Compare commits

..

177 Commits

Author SHA1 Message Date
a36ce6e442 [M108-LTS] Fix OOB write in BuildHuffmanTable.
M108 merge issues:
  dec/vp8l_dec.c:
    - Conflicting checks before ReadHuffmanCodeLengths() return statement;
    In 114, an assignment follows the check instead of a return.
    - ReadHuffmanCodes(): Conflict after the changed huffman_tables check,
    there's an assignment in 114 instead of the setter call.

First, BuildHuffmanTable is called to check if the data is valid.
If it is and the table is not big enough, more memory is allocated.

This will make sure that valid (but unoptimized because of unbalanced
codes) streams are still decodable.

Bug: chromium:1479274
Change-Id: I31c36dbf3aa78d35ecf38706b50464fd3d375741
(cherry picked from commit 902bc91903)
2023-09-12 09:30:11 +00:00
7366f7f394 Merge "lossless: fix crunch mode w/WEBP_REDUCE_SIZE" into main 2022-07-21 16:27:38 +00:00
84163d9d02 lossless: fix crunch mode w/WEBP_REDUCE_SIZE
WEBP_REDUCE_SIZE was introduced to bring down the library size by
removing cropping and scaling support. Previously WebPPictureView() was
only used with these two, but in
  ec178f2c Add progress hook granularity in lossless
an additional use was added in VP8LEncodeStream() when extra side
configurations are used in crunch mode (-mt, quality == 100 & method ==
6 or quality >= 75 & method == 5 with a palette present currently).

WebPPictureView() and, for coherency, WebPPictureIsView() are
restored in this configuration to avoid affecting the general encode
path.

Previously WebPPictureView() was assumed to always succeed in these
cases which could result in crashes with WEBP_REDUCE_SIZE defined.

Bug: chromium:1345547
Bug: chromium:1345595
Bug: chromium:1345772
Bug: chromium:1345804
Change-Id: Ifecde36a726a434510478a764514b1469942c684
2022-07-20 22:04:34 -07:00
d01c1eb309 webp-lossless-bitstream-spec,cosmetics: normalize capitalization
in section headings

Change-Id: I43b2208f5e0efa32029d519ac9805e871eb51ed3
2022-07-20 10:36:23 -07:00
8813ca8e69 Merge tag 'v1.2.3'
libwebp-1.2.3

- 6/30/2022: version 1.2.3
  This is a binary compatible release.
  * security fix for lossless encoder (#565, chromium:1313709)
  * improved progress granularity in WebPReportProgress() when using lossless
  * improved precision in Sharp YUV (-sharp_yuv) conversion
  * many corrections to webp-lossless-bitstream-spec.txt (#551)
  * crash/leak fixes on error/OOM and other bug fixes (#558, #563, #569, #573)

Bug: webp:568
Bug: b/230421671

* tag 'v1.2.3':
  update ChangeLog
  dsp/cpu.h: add missing extern "C"
  update ChangeLog
  vwebp: fix file name display in windows unicode build
  webpmux: fix -frame option in windows unicode build
  makefile.unix: add sharpyuv objects to clean target
  update NEWS
  bump version to 1.2.3
  update AUTHORS
  update .mailmap

Change-Id: I148041862bc930472e849d278471aa17ea12258b
2022-07-15 16:00:00 -07:00
3c4a0fbfbc update ChangeLog
Change-Id: I6c00a2c32e94d886f749fc09e2bdd71acfeb5402
2022-07-15 12:48:16 -07:00
56a480e80c dsp/cpu.h: add missing extern "C"
fixes linking of tests/fuzzer/animencoder_fuzzer on windows

Change-Id: I0bd14b0e8c7ecb261e861689c25cd4b7fdaecbfd
2022-07-08 15:44:39 -07:00
62b45bddcd update ChangeLog
Bug: webp:568
Change-Id: Icdb0657f9d19ba85e6235c6ce9577afa23e0ce21
2022-07-07 15:23:40 -07:00
8764ec7a07 Merge changes Idb037953,Id582e395 into 1.2.3
* changes:
  vwebp: fix file name display in windows unicode build
  webpmux: fix -frame option in windows unicode build
2022-07-07 22:18:26 +00:00
bcb872c31f vwebp: fix file name display in windows unicode build
glutBitmapCharacter() isn't limited to 8-bit characters; add
PrintStringW() to iterate through the file name. This may not fix all
cases, non-existent characters in the font used have no effect.

https://www.opengl.org/resources/libraries/glut/spec3/node76.html#SECTION000111000000000000000

Change-Id: Idb0379539d556a89ec694127f766eb662f09d597
2022-07-05 12:59:06 -07:00
67c44ac5db webpmux: fix -frame option in windows unicode build
-frame takes a file name parameter, use wargv[] like in other paths

Change-Id: Id582e395d3ff9b00bb7fcc0261b475211758f6d4
2022-07-05 11:48:56 -07:00
8278825aac makefile.unix: add sharpyuv objects to clean target
Change-Id: Iad9ac2530bd892681c055e5ae1bf82eb8782d2a2
2022-07-05 10:41:14 -07:00
14a49e018d update NEWS
Bug: webp:568
Change-Id: I0986c33910eba862ef6c1676d7dc58ea6df7ba3b
2022-06-30 19:30:31 -07:00
34b1dc336d bump version to 1.2.3
libwebp{,decoder} - 1.2.3
libwebp libtool - 8.4.1
libwebpdecoder libtool - 4.4.1

mux - 1.2.3
libtool - 3.4.0

demux - 1.2.3
libtool - 2.10.0

Bug: webp:568
Change-Id: I943bae1b7eacb445f6a4e13123e63170ac8bb142
2022-06-30 19:30:31 -07:00
0b397fda9d update AUTHORS
Bug: webp:568
Change-Id: I333e9679d1d9a9c33f94e214b7ab1723e063fe51
2022-06-30 19:30:27 -07:00
c16488ac4a update .mailmap
Bug: webp:568
Change-Id: I34df01bf958ef9de87345e5e43034fafd185f42a
2022-06-30 19:29:53 -07:00
5a2d929cd8 Merge "unicode.h: set console mode before using wprintf" into main 2022-07-01 01:03:01 +00:00
169f867f3c unicode.h: set console mode before using wprintf
This fixes incorrect character display in the file name
in e.g., stats output from cwebp.exe in visual studio builds.

In mingw further changes will be needed as using %s in wfprintf() for
wchar_t pointers is a Microsoft extension that doesn't seem to be
supported with gcc -fms-extensions. %ls works, but will require updating
format strings and wrapping concatenations with TO_W_CHAR() as visual
studio will reject merging string constants of different width.

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setmode

Change-Id: I57d24c3815f7b5aa3971ac315c65c4458258d706
2022-06-29 22:05:26 -07:00
a94b855c54 Merge "libsharpyuv: add version defines" into main 2022-06-28 09:49:56 +00:00
f83bdb5251 libsharpyuv: add version defines
Change-Id: I2dbe69d1ce5abaf7f5bd83daec99655520b5abad
2022-06-28 11:08:14 +02:00
bef0d79764 unicode_gif.h: fix -Wdeclaration-after-statement
when building for windows with _UNICODE defined

unicode_gif.h|49 col 3| warning: ISO C90 forbids mixed declarations and
code [-Wdeclaration-after-statement]

Change-Id: Ib9f0cc0eba036d6cd4221a4f70a078770dde01d0
2022-06-20 11:40:09 -07:00
404c1622f8 Rename Huffman coding to prefix coding in the bitstream spec
... since no guarantee of Huffman coding can be introduced at decoding
time and encoding didn't actually use Huffman coding in the first place

Bug: webp:551
Change-Id: I400466bb3b4a1d5506353eb3f287d658603164ee
2022-06-16 10:56:03 -07:00
8895f8a345 Merge "run_static_analysis.sh: fix scan-build archive path" into main 2022-06-16 17:27:52 +00:00
92a673d258 Merge "Add -fvisibility=hidden flag in CMakeLists." into main 2022-06-16 08:02:28 +00:00
67c1d72239 Merge "add WEBP_MSAN" into main 2022-06-16 05:11:26 +00:00
1124ff662d Add -fvisibility=hidden flag in CMakeLists.
This way, only functions marked with WEBP_EXTERN get exposed by the library.
This flag is already set in other build configs: configure.ac, makefile.unix,
Android.mk

Change-Id: Iafd8f160e539290e7ea46ceec764a090c6e626a9
2022-06-15 10:03:03 +02:00
e15b356014 add WEBP_MSAN
and use it to suppress a false positive related to data that passes
through RGBA32PackedToPlanar_16b_SSE41(). Current versions (tested with
clang 13.0.1, using -O0 and the build from oss-fuzz of enc_dec_fuzzer)
model shuffles incorrectly reporting use of uninitialized
data related to the alpha change that's removed when converting to YUV.
valgrind behaves correctly, however.

Bug: webp:573
Change-Id: If76997668dcdd436adf280a2e6dcffba766a2875
2022-06-14 21:49:46 -07:00
ec9e782a35 sharpyuv: remove minimum image size from sharpyuv library
libwebp still has a size threshold of 4 pixels in picture_csp_enc.c
but the sharpyuv library itself can handle any image size.

Change-Id: Ic1c78c8f8fae528395fa46a74f717f47cb13098e
2022-06-14 14:55:12 +02:00
7bd07f3b5d run_static_analysis.sh: fix scan-build archive path
move any error reports to the top-level of OUTPUT_DIR rather than
BUILD_DIR

Change-Id: Icb6677c42a89ef86d9d295a27b79a8a591672b87
2022-06-13 16:17:42 -07:00
5ecee06f7a Merge "sharpyuv: increase precision of gamma<->linear conversion" into main 2022-06-02 08:30:18 +00:00
f81dd7d63e Merge changes I3d17d529,I53026880,I1bd61639,I6bd4b25d,Icfec8fba into main
* changes:
  CMake: add src to webpinfo includes
  CMake: add WEBP_BUILD_WEBPINFO to list of checks for exampleutil
  CMake: add WEBP_BUILD_WEBPMUX to list of checks for exampleutil
  CMake: link imageioutil to exampleutil after defined
  WEBP_DEP_LIBRARIES: use Threads::Threads
2022-06-01 18:18:00 +00:00
2d607ee646 sharpyuv: increase precision of gamma<->linear conversion
Change-Id: I261bae3628315bda4ec0dafb8798c7512dd03a36
2022-06-01 15:38:44 +02:00
266cbbc511 sharpyuv: add 32bit version of SharpYuvFilterRow.
This allows increasing intermediate value precision from 10 bits to 14 bits.

Change-Id: I0fc33400d200a849bcc2c677ab8346215a9dbc3b
2022-06-01 13:42:29 +02:00
9fc12274ce CMake: add src to webpinfo includes
Fixes an include error with webp/types.h

Signed-off-by: Christopher Degawa <ccom@randomderp.com>
Change-Id: I3d17d529c904cdb4e5c8ae630e89ed3789791e79
2022-05-31 20:46:21 -05:00
7d18f40ac1 CMake: add WEBP_BUILD_WEBPINFO to list of checks for exampleutil
Signed-off-by: Christopher Degawa <ccom@randomderp.com>
Change-Id: I530268809468107fe29e0f04278791fe7c583208
2022-05-31 17:45:32 -05:00
11309aa54c CMake: add WEBP_BUILD_WEBPMUX to list of checks for exampleutil
Signed-off-by: Christopher Degawa <ccom@randomderp.com>
Change-Id: I1bd6163966d8cec9fc240fa46d41605f11d0c1ac
2022-05-31 17:45:30 -05:00
4bc762f729 CMake: link imageioutil to exampleutil after defined
Signed-off-by: Christopher Degawa <ccom@randomderp.com>
Change-Id: I6bd4b25d31a85839aadef57437faa04966085f52
2022-05-31 17:11:20 -05:00
0d1b9bc433 WEBP_DEP_LIBRARIES: use Threads::Threads
Signed-off-by: Christopher Degawa <ccom@randomderp.com>
Change-Id: Icfec8fba117cbf5668c6f4c7d46d05cbb17e3dea
2022-05-31 17:09:09 -05:00
20ef48f05a Merge "sharpyuv: add support for 10/12/16 bit rgb and 10/12 bit yuv." into main 2022-05-24 11:05:08 +00:00
93c5437115 sharpyuv: add support for 10/12/16 bit rgb and 10/12 bit yuv.
10bit+ input is truncated to 10bits for now.

Change-Id: I7ac00ca54c623d94c76ccd8954418e11095997d2
2022-05-23 20:48:44 +02:00
53cf2b4997 normalize WebPValidatePicture declaration w/definition
quiets a warning under visual studio:
src\enc\picture_enc.c(48) : warning C4028: formal parameter 1 different
from declaration

Change-Id: Ic3affbbb0e22ac8c43fa183e13506eee72e180dc
2022-05-17 09:46:51 -07:00
d3006f4b96 sharpyuv: slightly improve precision
- Remove SHALF constant so that we get back the original value when
  calling UpScale then downscale with rounding
- Make the linear->gamma precomputed table bigger (8 bits rather than 5)
- Round values in kLinearToGammaTabS

Change-Id: Ic9634d32cf93de321d2f6e9e4cad7f156d8d07df
2022-05-17 10:36:44 +02:00
ea967098a4 Merge changes Ia01bd397,Ibf3771af into main
* changes:
  Add an internal WebPValidatePicture.
  Some renamings for consistency.
2022-05-16 17:49:04 +00:00
11bc8410bd Merge changes I2d317c4b,I9e77f6db into main
* changes:
  webp-lossless-bitstream-spec,cosmetics: normalize range syntax
  webp-lossless-bitstream-spec,cosmetics: fix code typo
2022-05-16 17:17:22 +00:00
30453ea4e6 Add an internal WebPValidatePicture.
Change-Id: Ia01bd3975f7bd0d47eb0a1764807baed16f0d268
2022-05-16 17:37:20 +02:00
6c43219a5f Some renamings for consistency.
- pic->picture in public header
- match implementation to declaration in PictureImport, WebPPictureRescale, WebpBlendAlpha

Change-Id: Ibf3771af22d671bba6fd657684add618c6f32978
2022-05-16 17:33:49 +02:00
4f59fa7390 update .mailmap
Change-Id: I246d84d735bc0efada544a9051ddcb3c3a7ceabf
2022-05-14 20:57:41 -07:00
e74f8a62b2 webp-lossless-bitstream-spec,cosmetics: normalize range syntax
[N, M] -> [N..M] the latter is more common in this doc

Bug: webp:551
Change-Id: I2d317c4b8bb31d313123e981f93cd1feb346a98a
2022-05-14 20:51:43 -07:00
5a709ec0d7 webp-lossless-bitstream-spec,cosmetics: fix code typo
code_lengths -> code_length_code_lengths
after:
86f94ee0 Update lossless spec with Huffman codes.

Bug: webp:551
Change-Id: I9e77f6db0fca6fe8294cb31a3015e723050094b5
2022-05-14 20:51:34 -07:00
a2093acc4b webp-lossless-bitstream-spec: add amendment note
for recent changes to color transform, simple code length code, image
structure and details of decoding prefix codes

Bug: webp:551
Change-Id: I36a4d1ee3e25b8a56f5d926f4770374ace99bc2f
2022-05-13 18:50:55 -07:00
86c669303a webp-lossless-bitstream-spec: fix BNF
color cache info precedes the meta huffman info

Bug: webp:551
Change-Id: Ibb69b4ffad6bff5693015be3fe6c600c53fd06c0
2022-05-13 18:41:30 -07:00
232f22da5a webp-lossless-bitstream-spec: fix 'simple code' snippet
based on https://crbug.com/webp/551#c3 & https://crbug.com/webp/551#c4

Bug: webp:551
Change-Id: I4bcc19643b0bdda999247e9c3457d6954a49e35f
2022-05-13 18:41:20 -07:00
44dd765def webp-lossless-bitstream-spec: fix ColorTransform impl
and the corresponding InverseTransform(); the operations were swapped.
The forward transform subtracts the deltas, the inverse adds them.

Bug: webp:551
Change-Id: Ieb90a24f843cee7cdfe46cbb15ec7d716ca9d269
2022-05-13 18:33:16 -07:00
7a7e33e977 webp-lossless-bitstream-spec: fix TR-pixel right border note
the value of the TR-pixel on the right border is the leftmost pixel on
the current row, not the previous one

Bug: webp:551
Change-Id: I157e8c16ce43a9f52c36aa880be1be3bef19c063
2022-05-13 16:48:23 -07:00
86f94ee010 Update lossless spec with Huffman codes.
Bug: webp:551
Change-Id: I28b57c8e87a8023b727fe8359c2e2809cf92752d
2022-05-13 16:42:00 -07:00
a3927cc800 sharpyuv.c,cosmetics: fix indent
+ a few typos in sharpyuv_csp.c

Change-Id: I34b208d10d7808b42afb39b0618fb2e5d76633eb
2022-05-11 11:53:25 -07:00
6c45cef7ff Make sure the stride has a minimum value in the importer.
Bug: webp:569
Change-Id: Ia48d064dbb10e7179ae3da04ca8d769d1c447276
2022-05-10 10:18:46 +02:00
0c8b0e67a4 sharpyuv: cleanup/cosmetic changes
Remove unused constants.
Use ALL_CAPS for defines and kCamelCase for static const values.
Change some defines into static constants if they are not used in array sizes.

Change-Id: I036b0f99215fd0414a33f099bd6b809ff8ee4541
2022-05-09 15:10:14 +02:00
dc3841e077 {histogram,predictor}_enc: quiet int -> float warnings
after:
a19a25bb Replace doubles by floats in lossless misc cost estimations.

Change-Id: Idc5888b40ce5b591b72c6e51a188a9ab8c5d9823
2022-04-20 10:10:27 -07:00
a19a25bb03 Replace doubles by floats in lossless misc cost estimations.
Doubles are slower and use more RAM for no benefit.

Change-Id: I05b313576f9b33388c7c39d7fed8de84170c3753
2022-04-17 21:07:54 +02:00
42888f6c7c Add an option to enable static builds.
The build is not fully static but enough for certain usage.

Change-Id: I269fa40f332365873634b12ac54fd3c36beefd66
2022-04-12 17:50:19 +02:00
7efcf3cc26 Merge "Fix typo in color constants: Marix -> Matrix" into main 2022-04-12 05:08:08 +00:00
8f4b5c62b7 Fix typo in color constants: Marix -> Matrix
Change-Id: Ia5dc8b37ea7ddbb3dba923e24ef07633edb822eb
2022-04-11 14:54:43 -07:00
90084d84f9 Merge "demux,IsValidExtendedFormat: remove unused variable" into main 2022-04-11 20:29:24 +00:00
ed643f619d Merge changes I452d2485,Ic6d75475 into main
* changes:
  SharpYuvComputeConversionMatrix: quiet int->float warnings
  Makefile.vc: add sharpyuv_csp.obj to SHARPYUV_OBJS
2022-04-11 18:54:25 +00:00
8fa053d134 Rename SharpYUV to SharpYuv for consistency.
Change-Id: I21df96b4c8f8fa97bfd2ac9c806c7e5119b55691
2022-04-11 11:55:10 +02:00
99a8756201 SharpYuvComputeConversionMatrix: quiet int->float warnings
under some versions of visual studio:
sharpyuv\sharpyuv_csp.c(43): warning C4244: '=': conversion from 'int' to
'float', possible loss of data
sharpyuv\sharpyuv_csp.c(35): warning C4244: 'initializing': conversion from
'int' to 'float', possible loss of data

Change-Id: I452d24857b43b8a80fae0f339163b4b3965f2d9f
2022-04-09 11:07:09 -07:00
deb426becc Makefile.vc: add sharpyuv_csp.obj to SHARPYUV_OBJS
missed in:
01a05de1a libsharpyuv: add colorspace utilities

Change-Id: Ic6d754757a54dc098d5c761f03480a3766d60db6
2022-04-09 11:06:17 -07:00
779597d443 demux,IsValidExtendedFormat: remove unused variable
quiets -Wunused-but-set-variable

frame_count has been unused in this function since:
ab714b8a demux, Frame: remove is_fragment_ field

Change-Id: Ie6afda915c6b82736e05e7490eba0165c3dd37e4
2022-04-08 15:28:05 -07:00
40e8aa57f8 Merge "libsharpyuv: add colorspace utilities" into main 2022-04-08 09:06:23 +00:00
01a05de1a7 libsharpyuv: add colorspace utilities
Change-Id: I620c8593dc81f39e747de5ed354332adb7278bed
2022-04-08 10:07:22 +02:00
2de4b05a56 Merge changes Id9890a60,I376d81e6,I1c958838 into main
* changes:
  GetBackwardReferences: fail on alloc error
  BackwardReferencesHashChainDistanceOnly: fix segfault on OOM
  VP8LEncodeStream: fix segfault on OOM
2022-04-06 20:04:25 +00:00
b8bca81fb6 Merge "configure.ac: use LT_INIT if available" into main 2022-04-05 16:47:37 +00:00
e8e77b9c47 Merge changes I479bc487,I39864691,I5d486c2c,I186d13be into main
* changes:
  mux{edit,internal}: fix leaks on error
  ExUtilInitCommandLineArguments: fix leak on error
  anim_util: fix leaks on error
  gif2webp: fix segfault on OOM
2022-04-05 05:51:53 +00:00
7e7d5d503a Merge ".gitignore: add Android Studio & VS code dirs" into main 2022-04-04 22:27:07 +00:00
10c5084842 normalize label indent
1 space is most common in the source; this fixes some mixed cases within
lossless files, likely from clang-format

Change-Id: I504206d5bf418781d4131ee73570ecee4e0a69a1
2022-04-04 12:47:41 -07:00
89f774e61d mux{edit,internal}: fix leaks on error
several calls to ChunkSetHead() were unchecked, causing the chunk to
leak should the call fail due to OOM

Tested:
for i in `seq 1 1125`; do
  export MALLOC_FAIL_AT=$i
  ./examples/gif2webp gif_file
  ./examples/gif2webp -mixed gif_file
done
for i in `seq 1 171`; do
  export MALLOC_FAIL_AT=$i
  ./examples/img2webp jpeg_file -o /dev/null
  ./examples/img2webp -mixed jpeg_file -o /dev/null
done

Change-Id: I479bc487f61b493e5ce033872d353007055c172a
2022-04-04 11:26:25 -07:00
2d3293ad76 ExUtilInitCommandLineArguments: fix leak on error
argv_data would leak if the argv_ allocation failed or the MAX_ARGC cap
was hit

Tested:
for i in `seq 1 171`; do
  export MALLOC_FAIL_AT=$i
  ./examples/img2webp jpeg_file -o /dev/null
  ./examples/img2webp -mixed jpeg_file -o /dev/null
done

Change-Id: I39864691e96d5456f324d95a3653bba0f6d6a7be
2022-04-04 11:26:25 -07:00
ec34fd7023 anim_util: fix leaks on error
in ReadAnimatedWebP() & ReadAnimatedGIF() when AllocateFrames() fails
due to OOM

Tested:
for i in `seq 1 278`; do
  export MALLOC_FAIL_AT=$i
  ./examples/anim_diff webp1 webp2
  ./examples/anim_diff gif1 gif2
done

Change-Id: I5d486c2c2982ae088e34a25d8e3e0188df1a9b51
2022-04-04 11:26:25 -07:00
e471728754 gif2webp: fix segfault on OOM
previously calls to WebPPictureCopy() weren't checked, causing a crash
when the canvas copies were accessed later in the loop

Tested:
for i in `seq 1 1125`; do
  export MALLOC_FAIL_AT=$i
  ./examples/gif2webp gif_file
  ./examples/gif2webp -mixed gif_file
done

Change-Id: I186d13be0ec8f3b72b7d247a8482590c1b1be541
2022-04-04 11:26:12 -07:00
e3cfafaf71 GetBackwardReferences: fail on alloc error
previously failures in the call to
VP8LBackwardReferencesTraceBackwards() would be ignored which, though it
wouldn't result in a crash, would produce non-deterministic output

Change-Id: Id9890a60883c3270ec75e968506d46eea32b76d4
2022-04-04 11:24:06 -07:00
a828a59b49 BackwardReferencesHashChainDistanceOnly: fix segfault on OOM
change CostManager to calloc to avoid frees on undefined pointer
values in CostManagerClear() should the cost_model allocation succeed,
but the cost_manager allocation fail

since:
v0.5.0-93-g3e023c17 Speed-up BackwardReferencesHashChainDistanceOnly.

Tested:
for i in `seq 1 639`; do
  export MALLOC_FAIL_AT=$i
  ./examples/cwebp -m 6 -q 100 -lossless jpeg_file
done

Bug: webp:565
Change-Id: I376d81e6f41eb73529053e9e30c142b4b4f6b45b
2022-04-04 11:23:39 -07:00
fe153fae98 VP8LEncodeStream: fix segfault on OOM
initialize bw_side before calling EncoderAnalyze() & EncoderInit() which
may fail; previously this would cause a free of an invalid pointer in
VP8LBitWriterWipeOut().

since at least:
v0.6.0-120-gf8c2ac15 Multi-thread the lossless cruncher.

Tested:
for i in `seq 1 639`; do
  export MALLOC_FAIL_AT=$i
  ./examples/cwebp -m 6 -q 100 -lossless jpeg_file
done

Bug: webp:565
Change-Id: I1c95883834b6e4b13aee890568ce3bad0f4266f0
2022-04-04 11:21:30 -07:00
919acc0ef5 .gitignore: add Android Studio & VS code dirs
Change-Id: I0a8b8124f568df1a4e6bbf96e5a1144b2e7606a1
2022-04-04 10:28:06 -07:00
efa0731b9d configure.ac: use LT_INIT if available
AC_PROG_LIBTOOL is deprecated. quiets a warning from autoconf 2.71:
configure.ac:12: warning: The macro `AC_PROG_LIBTOOL' is obsolete.

Change-Id: I3b131f5ee636a8df48057862e600759f25ad7289
2022-04-04 10:25:26 -07:00
0957fd69ee tiffdec: add grayscale support
the file is always decoded to RGBA, so just the samples_per_px needed an
update

Bug: webp:563
Change-Id: I95d95c3b9e45dc8ecb2223f89f4ba791f0b21e8b
2022-03-31 21:43:29 -07:00
e685feef0c Merge "Make libsharpyuv self-contained by removing dependency on cpu.c" into main 2022-03-31 09:04:06 +00:00
841960b670 Make libsharpyuv self-contained by removing dependency on cpu.c
Change-Id: I2edac1afa38bfddf2a91e7829e38425bd3519feb
2022-03-30 15:04:35 +02:00
617cf03656 image_dec: add WebPGetEnabledInputFileFormats()
and use it to output the types supported in the examples

Change-Id: Ia6b8624a2146cf72c679129065a72f215644e1e9
2022-03-26 15:37:25 -07:00
7a68afaac5 Let SharpArgbToYuv caller pass in an RGB>YUV conversion matrix.
Change-Id: I4ed2dfc00ce63361abd49c693f31f307e0b0262f
2022-03-24 16:37:47 +01:00
34bb332ca1 man/cwebp.1: add note about crop/resize order
+ normalize help text in [cd]webp

Bug: webp:561
Change-Id: Id92ec4228d4933cd033b2bf68a43192532cef483
2022-03-17 16:08:34 -07:00
f0e9351cce webp-lossless-bitstream-spec,cosmetics: fix some typos
Bug: webp:551
Change-Id: I9ff90601b77deb9034ed7bef9cfd421d1f6e2e2b
2022-03-15 17:57:31 -07:00
5ccbd6ed8c vp8l_dec.c,cosmetics: fix a few typos
Change-Id: Ia2906883e7d19bd96f355b4ade98d29ac2efe8cc
2022-03-14 10:15:31 -07:00
c3d0c2d7d8 fix ios build scripts after sharpyuv dep added
in:
d55d447c Make libwebp depend on libsharpyuv.

Change-Id: I8efa679686b792da4cedf23f580152fecfe42275
2022-03-08 19:52:45 -08:00
d0d2292e1a Merge "Make libwebp depend on libsharpyuv." into main 2022-03-07 09:34:37 +00:00
03d1219055 alpha_processing_neon.c: fix 0x01... typo
one instance was overlong leading to a int64->uint32 conversion warning

Change-Id: I56d5ab75d89960c79293f62cd489d7ab519bbc34
2022-03-04 15:26:21 -08:00
d55d447c9a Make libwebp depend on libsharpyuv.
Change-Id: I6d8ebfe1f855024fc0694b1aa584f71fa27b83ae
2022-03-04 11:35:03 +01:00
e4cbcdd2b5 Fix lossless encoding for MIPS.
Bug: webp:558
Change-Id: I3d3ddb64ed26a8d8ff5664664c5f20f6eadfeb4f
2022-03-01 14:01:49 +01:00
924e7ca654 alpha_processing_neon.c: fix Dispatch/ExtractAlpha_NEON
the trailing width % 8 bytes would clear the upper bytes of
alpha_mask as they're done one at a time

since:
49d0280d NEON: implement several alpha-processing functions

Change-Id: Iff76c0af3094597285a6aa6ed032b345f9856aae
2022-02-28 13:57:23 -08:00
0fa0ea5488 Makefile.vc: use /MANIFEST:EMBED
this removes the mt.exe step and may fix some build failures if the
executable is locked after linking, e.g., by an antivirus program

Change-Id: I9a8184f3aaecb62a133a13d9ad3383667bc93fd3
2022-02-19 17:02:31 -08:00
29cc95ce4c Basic version of libsharpyuv in libwebp, in C.
It's self contained apart from a dependency on src/webp/types.h and src/dsp/cpu.h
For now it's only set up as an internal library, not an installable one.
Webp doesn't depend on it yet, the code is only duplicated.

Change-Id: I752799894f9d4105d0d296ddebd9f9641181a1ec
2022-02-18 14:52:44 +00:00
a30f219016 examples/webpmux.c: fix a couple of typos
in the code and help output; the man page is already correct

Change-Id: Id07d32cde24447cf61e1a2b3d55ab4a33549adde
2022-02-17 17:10:08 -08:00
66b3ce239e Fix bad overflow check in ReadTIFF()
See ImgIoUtilCheckSizeArgumentsOverflow() usage at line 199.

Change-Id: Iecad9278446a2f189e287e08512d26a794270a5a
2022-02-15 17:51:14 +01:00
54e61a3864 Markdownify libwebp docs and reorganize them.
Break the main README into into multiple pages in the doc/ directory,
except for the tests, swig and webp_js docs which are in the corresponding
directories.
The webp mux doc is merged into the API doc and the tools doc.

Change-Id: Ia407617dd88094f4662841d37947cfef80799914
2022-02-15 15:31:56 +00:00
b4533debd9 CMakeLists.txt,cosmetics: break long line
Change-Id: Ibe48516e858d4443d9ae43d8a5f6d074c7b07dd8
2022-02-14 10:06:03 -08:00
b9d2f9cd3b quant_enc.c: use WEBP_RESTRICT qualifier
results in code layout changes, a couple fewer instructions; some of the
smaller functions were unaffected as they were inlined, but are updated
for consistency. this mostly affects VP8Decimate(), ReconstructIntra16()
and ReconstructUV().

Change-Id: Icc2582278987a66ad1110bab683d1e0c21e6591a
2022-02-10 11:07:18 -08:00
ec178f2c7f Add progress hook granularity in lossless
A WebPPicture instance is necessary to call WebPReportProgress() which
sets WebPPicture::error_code so as well use WebPEncodingSetError() to
record errors too, instead of functions returning a WebPEncodingError.
However there must be one WebPPicture instance per thread, with error
codes merged at sync time. A mutex could simplify that but it is not
the objective of this change.

https://groups.google.com/a/webmproject.org/g/webp-discuss/c/yOiP8APubgc/m/vCTvxl6ODgAJ

Change-Id: Ia1a8f9d1199202e1c88484ce719b0180a80447ce
2022-02-07 11:00:09 +01:00
26139c7398 Rename MAX_COST to MAX_BIT_COST in histogram_enc.c
To differentiate it with the one in vp8i_enc.h

Change-Id: If4ecc40246cb1c6e42a2ae77328966c4069d441c
2022-02-03 09:57:30 +01:00
13b8281609 cmake: fix webpmux lib name for cmake linking
When using CMake the `<prefix>/usr/share/WebP/cmake/WebPConfig.cmake` gets
used to get the names of the libraries to link against.

Since version 1.2.1 of libwebp, libwebpmux is on by default.
This causes a linker error because the linker arg should be `-lwebpmux`
instead of `-llibwebpmux`.

This is fixable by renaming `libwebpmux` to `webpmux` in a few places.

This was identified after an update to 1.2.1 of libwebp in the OpenWrt
project:
  https://github.com/openwrt/packages/pull/16766

Internally in OpenWrt, this was patched here:
  https://github.com/openwrt/packages/pull/16784

Change-Id: I97501c62b1e97b133a62b04d6516261d6d7c7fd0
Signed-off-by: Alexandru Ardelean <ardeleanalex@gmail.com>
2022-01-31 14:38:16 +01:00
88b6a396f1 webp-container-spec.txt,cosmetics: normalize formatting
- prefer Exif to EXIF when not referring to the chunk
- normalize use of code format for canvas / frame width & height

Change-Id: I7fc9e87baeb5d8e719274680ce621dcb078a985f
2022-01-25 18:36:36 -08:00
6f49654024 Merge tag 'v1.2.2'
libwebp-1.2.2

- 1/11/2022: version 1.2.2
  This is a binary compatible release.
  * webpmux: add "-set bgcolor A,R,G,B"
  * add ARM64 NEON support for MSVC builds (#539)
  * fix duplicate include error in Xcode when using multiple XCFrameworks in a
    project (#542)
  * doc updates and bug fixes (#538, #544, #548, #550)

* tag 'v1.2.2':
  update ChangeLog
  libwebp: Fix VP8EncTokenLoop() progress
  BMP enc: fix the transparency case
  libwebp: do not destroy jpeg codec twice on error
  update ChangeLog
  update NEWS
  man/img2webp.1: update date
  Reword img2webp synopsis command line
  anim_decode: fix alpha blending with big-endian
  webpinfo: fix fourcc comparison w/big-endian
  update ChangeLog
  update NEWS
  bump version to 1.2.2
  update AUTHORS

Bug: webp:541, b/202302177
Change-Id: Iae875b6ec3084157837cc774c94088ca72e8dd91
2022-01-20 10:17:37 -08:00
4074acf873 dsp.h: bump msvc arm64 version requirement to 16.6
there was a bug in 16.4 causing compile failures with vtbl4_u8():

src\dsp\lossless_neon.c(105): error C2143: syntax error: missing ')'
before '{'
src\dsp\lossless_neon.c(105): error C2168: 'neon_tbl2_q8': too few
actual parameters for intrinsic function

https://developercommunity.visualstudio.com/t/cannot-compile-arm64-neon-vtbl4-u8-function-in-c-f/859331

Change-Id: I87c21850b3c597aa5cb41a8105b81e2135a9f890
2022-01-19 21:49:59 -08:00
b0a860891d update ChangeLog
Change-Id: I8a18162a178f1686cc8359ce48d90c1c7f65ec91
2022-01-19 15:35:26 -08:00
6db8248c01 libwebp: Fix VP8EncTokenLoop() progress
Encoding the image found in the user bug report below would result in
a progress rising up to 173% because of the extra 20% caused by each
of the 4 extra lossy passes. It happened at methods 3 to 6.

https://groups.google.com/a/webmproject.org/g/webp-discuss/c/yOiP8APubgc/m/FP3r5X2rDAAJ

Change-Id: I95318d0dc4df546044eb926c786c04bb7f915cbe
(cherry picked from commit db25f1b4ed)
2022-01-19 18:07:42 +00:00
827a307fec BMP enc: fix the transparency case
When transparency is present, it's not enough to just write 32bpp samples.
One need to use the full BITMAPV3INFOHEADER syntax and specify the
masks for BGRA.

 see https://en.wikipedia.org/wiki/BMP_file_format#Pixel_storage

Also remove the height-flip trick and write samples bottom-to-top instead.

Change-Id: If5d92c11453b96764b5bfbf19e9678e632bc911f
(cherry picked from commit 480cd51de6)
2022-01-19 18:07:17 +00:00
db25f1b4ed libwebp: Fix VP8EncTokenLoop() progress
Encoding the image found in the user bug report below would result in
a progress rising up to 173% because of the extra 20% caused by each
of the 4 extra lossy passes. It happened at methods 3 to 6.

https://groups.google.com/a/webmproject.org/g/webp-discuss/c/yOiP8APubgc/m/FP3r5X2rDAAJ

Change-Id: I95318d0dc4df546044eb926c786c04bb7f915cbe
2022-01-18 21:12:11 +00:00
286e7fceaa libwebp: do not destroy jpeg codec twice on error
WebPPictureImportRGB() can fail on memory allocation. In this case,
jpeg_destroy_decompress() was already called, so do not go to Error.
Free metadata as an error is returned.

Change-Id: I045b072090e9063d3ad10369ad18b0f08bdffe9f
(cherry picked from commit 6e8a4126f2)
2022-01-17 18:47:10 +00:00
6e8a4126f2 libwebp: do not destroy jpeg codec twice on error
WebPPictureImportRGB() can fail on memory allocation. In this case,
jpeg_destroy_decompress() was already called, so do not go to Error.
Free metadata as an error is returned.

Change-Id: I045b072090e9063d3ad10369ad18b0f08bdffe9f
2022-01-13 14:10:43 +00:00
faf219684c Merge "BMP enc: fix the transparency case" into main 2022-01-12 23:24:23 +00:00
480cd51de6 BMP enc: fix the transparency case
When transparency is present, it's not enough to just write 32bpp samples.
One need to use the full BITMAPV3INFOHEADER syntax and specify the
masks for BGRA.

 see https://en.wikipedia.org/wiki/BMP_file_format#Pixel_storage

Also remove the height-flip trick and write samples bottom-to-top instead.

Change-Id: If5d92c11453b96764b5bfbf19e9678e632bc911f
2022-01-12 07:48:01 +01:00
9195ea0538 update ChangeLog
Bug: webp:541
Change-Id: I6cfb9da3a3944f66efa681cffec7f3e6a84c8800
2022-01-11 18:46:37 -08:00
4acae017bd update NEWS
Bug: webp:541
Change-Id: I529210f8ecaa8f2e9a6fae2518ba71f7fd56a701
2022-01-11 18:45:55 -08:00
883f063397 man/img2webp.1: update date
after:
a80954a1 Reword img2webp synopsis command line

Change-Id: I0a5c18f7947d15fcd66dc32fab9b525186f7fcc5
(cherry picked from commit 1b0c15db02)
2022-01-11 02:03:24 +00:00
567e1f442b Reword img2webp synopsis command line
See https://bugs.chromium.org/p/webp/issues/detail?id=549

Change-Id: I75562d2ad021d8ec107eb4ced5b28e0abf373324
(cherry picked from commit a80954a1d9)
2022-01-11 02:02:57 +00:00
1b0c15db02 man/img2webp.1: update date
after:
a80954a1 Reword img2webp synopsis command line

Change-Id: I0a5c18f7947d15fcd66dc32fab9b525186f7fcc5
2022-01-10 10:57:55 -08:00
17bade381a Merge "Reword img2webp synopsis command line" into main 2022-01-05 12:04:26 +00:00
a80954a1d9 Reword img2webp synopsis command line
See https://bugs.chromium.org/p/webp/issues/detail?id=549

Change-Id: I75562d2ad021d8ec107eb4ced5b28e0abf373324
2022-01-05 10:15:28 +01:00
f084244d9f anim_decode: fix alpha blending with big-endian
images are decoded in RGBA/BGRA, but represented as uint32_t during the
blend process; this fixes the channel extraction

Bug: webp:548
Change-Id: Ie74aa43d8f87d3552d5afc0abba466335f5d1617
(cherry picked from commit e4886716d3)
2021-12-23 14:49:14 +00:00
b217b4fff7 webpinfo: fix fourcc comparison w/big-endian
store the recognized fourccs in little-endian order to match how the
fourcc is being read from the file

Bug: webp:548
Change-Id: I9de77db92208709d5e711846908a51e563102fa5
(cherry picked from commit e3cb052ca5)
2021-12-23 14:48:19 +00:00
ec497b7532 Merge "anim_decode: fix alpha blending with big-endian" into main 2021-12-23 02:36:32 +00:00
e4886716d3 anim_decode: fix alpha blending with big-endian
images are decoded in RGBA/BGRA, but represented as uint32_t during the
blend process; this fixes the channel extraction

Bug: webp:548
Change-Id: Ie74aa43d8f87d3552d5afc0abba466335f5d1617
2021-12-22 17:03:58 -08:00
e3cb052ca5 webpinfo: fix fourcc comparison w/big-endian
store the recognized fourccs in little-endian order to match how the
fourcc is being read from the file

Bug: webp:548
Change-Id: I9de77db92208709d5e711846908a51e563102fa5
2021-12-22 16:01:54 -08:00
a510fedb9a patch-check: detect duplicated files
Change-Id: Ia78425e7f8054d4b0b4e6b365ba0f5887cbcf2d1
Bug: b:185520507
2021-12-17 00:25:43 +00:00
f035d2e40d update ChangeLog
Bug: webp:541
Change-Id: Icd9d0bf1a011263108e899b561f7c8e93dc93e2f
2021-12-15 15:43:43 -08:00
7031946ad8 update NEWS
Change-Id: Id53e61bfb1551b04fe57fd095aa7ef860f60b248
2021-12-14 22:00:58 -08:00
973390b618 bump version to 1.2.2
libwebp{,decoder} - 1.2.2
libwebp libtool - 8.3.1
libwebpdecoder libtool - 4.3.1

mux - 1.2.2
libtool - 3.8.0

demux - 1.2.2
libtool - 2.9.0

Bug: webp:541
Change-Id: Ia9adda28f0320714335156552d0f5b563e1babb6
2021-12-14 19:58:29 -08:00
abd6664fee update AUTHORS
Bug: webp:541
Change-Id: I270b606a16d72dd5012253d932905375692b8eb7
2021-12-14 19:52:01 -08:00
5b7e79303a Merge "add missing USE_{MSA,NEON} checks in headers" into main 2021-12-14 23:39:18 +00:00
02ca04c348 add missing USE_{MSA,NEON} checks in headers
msa_macro.h
neon.h

allows the headers to be built / analyzed under different target
configurations

Change-Id: Ibbcfada210b54988aa5279674d53af8e21fd4a97
2021-12-14 22:21:57 +00:00
e94716e27c xcframeworkbuild.sh: place headers in a subdir
Headers/<framework> rather than Headers/ to avoid a Xcode error when
using multiple frameworks:
  error: Multiple commands produce
    '.../Build/Products/Debug-iphoneos/include/types.h'

WebPMux.xcframework/ios-arm64_i386_x86_64-simulator/Headers/WebPMux
WebPMux.xcframework/ios-arm64_armv7_armv7s/Headers/WebPMux
WebPMux.xcframework/macos-arm64_x86_64/Headers/WebPMux
WebPMux.xcframework/ios-arm64_x86_64-maccatalyst/Headers/WebPMux
WebPDecoder.xcframework/ios-arm64_i386_x86_64-simulator/Headers/WebPDecoder
WebPDecoder.xcframework/ios-arm64_armv7_armv7s/Headers/WebPDecoder
WebPDecoder.xcframework/macos-arm64_x86_64/Headers/WebPDecoder
WebPDecoder.xcframework/ios-arm64_x86_64-maccatalyst/Headers/WebPDecoder
WebPDemux.xcframework/ios-arm64_i386_x86_64-simulator/Headers/WebPDemux
WebPDemux.xcframework/ios-arm64_armv7_armv7s/Headers/WebPDemux
WebPDemux.xcframework/macos-arm64_x86_64/Headers/WebPDemux
WebPDemux.xcframework/ios-arm64_x86_64-maccatalyst/Headers/WebPDemux
WebP.xcframework/ios-arm64_i386_x86_64-simulator/Headers/WebP
WebP.xcframework/ios-arm64_armv7_armv7s/Headers/WebP
WebP.xcframework/macos-arm64_x86_64/Headers/WebP
WebP.xcframework/ios-arm64_x86_64-maccatalyst/Headers/WebP

Bug: webp:542
Change-Id: Ic7e03d85d2119597e422b9cf68b3ac5a892d494d
2021-12-10 19:44:36 -08:00
c846efd888 patch-check: commit subject length check
Change-Id: I7a1c7349f4f461c2384cbd1a62d1aa2e4e3be819
Bug: b:185520507
2021-12-08 18:57:13 +00:00
b6f756e82b update http links
- prefer https

- metadataworkinggroup.org/com seem to be offline; the web archive link
  was obtained from exiftool: https://exiftool.org/TagNames/MWG.html

- fix kramdown link, rubyforge has been gone a long time

- fix png/zlib links

Bug: webp:544
Bug: b/202302177
Change-Id: Id69de4553e7baf00393f12a2c1acb262443a1a93
2021-11-23 10:13:40 -08:00
8f5cb4c18e update rfc links
to https://datatracker.ietf.org/doc/html/... the http tools.ietf.org
links redirect here sometimes, in other cases they 404.

Bug: webp:544
Change-Id: I900972070d6c5659c45a86a89e78b870f42fe5bc
2021-11-17 11:03:35 -08:00
8ea81561d2 change VP8LPredictorFunc signature to avoid reading 'left'
... when it's not available. Even if the value was discarded and
never used, some msan config were complaining about reading it
and passing it around.

Change-Id: Iab8d24676c5bb58e607a829121e36c2862da397c
2021-11-05 16:22:31 +01:00
6b1d18c362 webpmux: fix the -bgcolor description
Change-Id: Iedb1865aec7b8c78c185a0eb17d97a5c9446a275
2021-11-04 22:51:48 +01:00
3368d8768a Merge "webpmux: add "-set bgcolor A,R,G,B"" into main 2021-11-04 19:00:36 +00:00
f213abf620 webpinfo: print the number of warnings
otherwise they can go un-noticed (unless you use -diag).

Change-Id: Ic6faaf09e7993002cdae3e998623764fde860351
2021-11-04 17:09:51 +01:00
50c97c301d webpmux: add "-set bgcolor A,R,G,B"
Similarly to "-set loop <>", this is useful to set
the parameter at global level and not just while assembling
the frames separately.

Change-Id: I79bcbe37f8ff50b9904e78d14011ccbac72f17a1
2021-11-04 15:45:44 +00:00
2c206aaf96 Remove CMakeLists.txt check in compile.sh
Bug: b:185520507
Change-Id: Id573423a9f6960360b9d96950c098ba488e2e9f3
2021-11-02 20:37:11 +00:00
96e3dfef26 Merge "infra/common.sh: add shard_should_run()" into main 2021-10-29 17:08:33 +00:00
0e0f74b7e3 infra/common.sh: add shard_should_run()
Detects whether test block should be run in the current test shard.

if shard_should_run; then
 ...
fi

Bug: b/185520507
Change-Id: I408d226651630a01c5e447dbff7d26b73426ce42
2021-10-28 17:13:11 -07:00
35b7436a21 Jenkins scripts port: update shell function comments
Review function comments style.
https://google.github.io/styleguide/shellguide.html#function-comments

Change-Id: I8c557fd6cb653744d93c28cd28caeef3e4bf10bc
Bug: b:185520507
2021-10-28 01:17:52 +00:00
21d24b4c08 webp-container-spec.txt: remove 'experimental' markers
unknown chunks as a group are well defined in the text

+ remove the Note about stable features as it matched the list given;
there are no WIP features for the format

Change-Id: I11a4de39f9d203b815879f0e9dea9c45b2ae6ff6
2021-10-22 12:17:59 -07:00
cdcf89020e Merge "Port Jenkins script: compile" into main 2021-10-22 04:41:53 +00:00
dc683cdef5 Jenkins scripts port: static analysis
From https://build.webmproject.org/jenkins/view/webp/job/libwebp__static_analysis/

Change-Id: I87846e14351632915a17ee086256dfebdbd656c9
Bug: b:185520507
2021-10-21 00:54:44 +00:00
0858494e96 Port Jenkins script: compile
https://build.webmproject.org/jenkins/view/webp/job/libwebp__compile/

Change-Id: I646e3048cf4e3d8672b66838e31c7ccc53ced60f
Bug: b:185520507
2021-10-21 00:46:57 +00:00
c2cf6a93b0 Jenkins scripts port: android compilation
Port script from https://build.webmproject.org/jenkins/job/libwebp__compile_android/
Change-Id: I4b3f7f15990b5c92971ec5faccc82dca815f92d2
Bug: b:185520507

Change-Id: Ic07f8191db7726e459ee56c04bf6e3776b30b1f7
2021-10-13 18:44:55 +00:00
df0e808fed presubmit: Add pylint-2.7 and .pylintrc
Added files to skip to prevent lint over generated code.

Change-Id: I62de5ec4fa7b6d764df1d8671c0263f668904e52
Bug: b:185520507
2021-10-12 01:01:14 +00:00
676c57dba4 patch-check: shfmt
shfmt is expected to be installed along with go.
GO111MODULE=on go install mvdan.cc/sh/v3/cmd/shfmt@latest

Change-Id: I27004e72f79f71df9405158f77df485f43b028bb
Bug: b:185520494
2021-10-08 05:05:01 +00:00
7bb7f7474e patch-check: Add shellcheck
Shellcheck is expected to be installed because depot_tools does not
provide the tool.

Change-Id: I9c8793cf7e2adedcb1e9f8244b886d6f2a54e2ae
Bug: b:185520494
2021-10-04 23:43:11 +00:00
abcd1797a1 Reformat docstrings and imports
Change-Id: Ie96a21779000a67c272f5e06d2bc11a64b4883f5
Bug: b:185520494
2021-10-04 23:42:35 +00:00
edaf08952d Port Jenkins scripts: compile js
Change-Id: I6d66de114758adccab782870e29a09b66a930ebc
Bug: b:185520507
2021-09-23 22:51:47 +00:00
b96220636b Set CheckPatchFormatted flags to fail on diffs
Change-Id: Ifb826860e27139bc43b4411575e4c2bebcc81239
Bug: b:185520494
2021-09-22 22:44:21 +00:00
e23cd5481c dsp.h: enable NEON w/VS2019+ ARM64 targets
Visual Studio added ARM64 support, but requires arm64_neon.h to be
included rather than arm_neon.h. Visual Studio 2019 addressed this so
we'll start with that version and leave a local adapter include for a
follow up.

Bug: webp:539
Change-Id: If975c029dafffba99210b3bb2d670035a83e8105
2021-09-13 19:56:19 -07:00
3875c7de07 CMakeLists.txt: set minimum version to 3.7
cmake/cpu.cmake (at least) requires 3.7 due to its use of GREATER_EQUAL:
https://cmake.org/cmake/help/latest/release/3.7.html

Bug: webp:538
Change-Id: I63511226a593218e1f4d3b1a7c4c998de3ba2ae1
2021-08-31 13:21:46 -07:00
1a8f0d45d3 Have a hard-coded value for memset in TrellisQuantizeBlock.
Change-Id: I1b842bb0cfec9e8559d0f11b3db8fa1bc1c9692f
2021-08-30 18:50:11 +02:00
934801604e Speed up TrellisQuantizeBlock
- only initialize variable when needed
- perform first loop outside the for loop
- perform computation only if know we are not already worse
- not adding base_score every time

Change-Id: I2cb8231fcaec1113b5902ed61b685f0ae3c78823
2021-08-30 17:07:42 +02:00
45eaacc939 Convert deprecated uint32 to uint32_t.
Change-Id: I057296a7ea90c3eeb9eaf251e08352a8491a591b
2021-08-30 16:06:53 +02:00
42592af875 webp,cmake: Remove unnecessary include dirs
Following crrev.com/c/webm/libwebp/+/3038647

Change-Id: Id43ed9b1cc02a7333bc64e82523122f483c9350a
2021-08-30 09:35:31 +02:00
e298e05f66 Add patch-check steps in PRESUBMIT.py
It substitutes patch-check and style-check by:

- man format checks and warnings
- long lines (max 80, except urls)
- trailing whitespaces
- tab indentation (except make)
- EOL

Change-Id: I33f391bac37c15e995182d735afdbd4efb5c7cae
Bug: b:185520507
2021-08-27 19:32:17 +00:00
29148919e0 Merge tag 'v1.2.1'
libwebp-1.2.1

- 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)

* tag 'v1.2.1':
  update ChangeLog
  fuzzer/*: normalize src/ includes
  fix indent
  update ChangeLog
  dsp/*: use WEBP_HAVE_* to determine Init availability
  update NEWS
  bump version to 1.2.1
  update AUTHORS

Bug: 521, b/188435220
Change-Id: Id6e6781d8da878413c2e57dcae5e2f2841174181
2021-08-13 16:43:13 -07:00
9ce5843dba update ChangeLog
Change-Id: I12c2b718e99087201a57f7ab7cc4c16374e205f6
2021-07-29 15:55:37 -07:00
d9191588ab fuzzer/*: normalize src/ includes
this uses the format introduced to some files in:
cc3577e9 fuzzer/*: use src/ based include paths

Change-Id: I9b5cbeadbb9d54d1e89f474a6e479a5eb3175ed7
(cherry picked from commit c5bc36243a)
2021-07-29 20:15:30 +00:00
c5bc36243a fuzzer/*: normalize src/ includes
this uses the format introduced to some files in:
cc3577e9 fuzzer/*: use src/ based include paths

Change-Id: I9b5cbeadbb9d54d1e89f474a6e479a5eb3175ed7
2021-07-28 13:32:19 -07:00
53b6f76209 fix indent
after:
277d3074 Fix size_t overflow in  WebPRescalerInit

Change-Id: I9adf7f01f28ddd54305512762e2ed28713282966
(cherry picked from commit d2caaba435)
2021-07-28 20:22:18 +00:00
d2caaba435 fix indent
after:
277d3074 Fix size_t overflow in  WebPRescalerInit

Change-Id: I9adf7f01f28ddd54305512762e2ed28713282966
2021-07-28 11:23:45 -07:00
1fe3162541 dsp/*: use WEBP_HAVE_* to determine Init availability
after:
  ece18e55 dsp.h: respect --disable-sse2/sse4.1/neon
WEBP_USE_* will be set when a module is targeting a particular
instruction set, e.g., sse4.1, and not overridden if WEBP_HAVE_SSE41 is
set, as previously this would ignore the case where the instruction set
was disabled via config.h and the HAVE macro was unset.

dsp.h not ensures WEBP_HAVE_* are set when WEBP_USE_* to cover cases
where the files are built without config.h.

Change-Id: Ia1c2dcf4100cc1081d968acb6e085e2a1768ece6
2021-07-24 10:19:30 -07:00
146 changed files with 6687 additions and 3352 deletions

2
.gitignore vendored
View File

@ -3,7 +3,9 @@
*.pc
.DS_Store
.deps
.idea
.libs
.vscode
/aclocal.m4
/ar-lib
/autom4te.cache

View File

@ -8,7 +8,11 @@ Vikas Arora <vikasa@google.com>
<vikasa@google.com> <vikaas.arora@gmail.com>
<slobodan.prijic@imgtec.com> <Slobodan.Prijic@imgtec.com>
<vrabaud@google.com> <vincent.rabaud@gmail.com>
Vincent Rabaud <vrabaud@google.com>
Tamar Levy <tamar.levy@intel.com>
<qrczak@google.com> <qrczak>
Hui Su <huisu@google.com>
James Zern <jzern@google.com>
Roberto Alanis <alanisbaez@google.com>
Brian Ledger <brianpl@google.com>
Maryla Ustarroz-Calonge <maryla@google.com>

441
.pylintrc Normal file
View 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
View File

@ -0,0 +1,2 @@
[style]
based_on_style = chromium

View File

@ -1,12 +1,15 @@
Contributors:
- Aidan O'Loan (aidanol at gmail dot com)
- Alan Browning (browning at google dot com)
- Alexandru Ardelean (ardeleanalex at gmail dot com)
- Brian Ledger (brianpl at google dot com)
- Charles Munger (clm at google dot com)
- Cheng Yi (cyi at google dot com)
- Christian Duvivier (cduvivier at google dot com)
- Christopher Degawa (ccom at randomderp dot com)
- Clement Courbet (courbet at google dot com)
- Djordje Pesut (djordje dot pesut at imgtec dot com)
- Frank Barchard (fbarchard at google dot com)
- Hui Su (huisu at google dot com)
- Ilya Kurdyukov (jpegqs at gmail dot com)
- Ingvar Stepanyan (rreverser at google dot com)
@ -22,6 +25,7 @@ Contributors:
- Mans Rullgard (mans at mansr dot com)
- Marcin Kowalczyk (qrczak at google dot com)
- Martin Olsson (mnemo at minimum dot se)
- Maryla Ustarroz-Calonge (maryla at google dot com)
- Mikołaj Zalewski (mikolajz at google dot com)
- Mislav Bradac (mislavm at google dot com)
- Nico Weber (thakis at chromium dot org)
@ -32,6 +36,7 @@ Contributors:
- Pascal Massimino (pascal dot massimino at gmail dot com)
- Paweł Hajdan, Jr (phajdan dot jr at chromium dot org)
- Pierre Joye (pierre dot php at gmail dot com)
- Roberto Alanis (alanisbaez at google dot com)
- Sam Clegg (sbc at chromium dot org)
- Scott Hancher (seh at google dot com)
- Scott LaVarnway (slavarnway at google dot com)

View File

@ -33,6 +33,14 @@ else
NEON := c
endif
sharpyuv_srcs := \
sharpyuv/sharpyuv.c \
sharpyuv/sharpyuv_csp.c \
sharpyuv/sharpyuv_dsp.c \
sharpyuv/sharpyuv_gamma.c \
sharpyuv/sharpyuv_neon.$(NEON) \
sharpyuv/sharpyuv_sse2.c \
dec_srcs := \
src/dec/alpha_dec.c \
src/dec/buffer_dec.c \
@ -204,6 +212,7 @@ endif # ENABLE_SHARED=1
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(sharpyuv_srcs) \
$(dsp_enc_srcs) \
$(enc_srcs) \
$(utils_enc_srcs) \

View File

@ -6,7 +6,7 @@
# 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.5)
cmake_minimum_required(VERSION 3.7)
if(POLICY CMP0072)
cmake_policy(SET CMP0072 NEW)
@ -15,6 +15,14 @@ endif()
project(WebP C)
# Options for coder / decoder executables.
if(BUILD_SHARED_LIBS)
set(WEBP_LINK_STATIC_DEFAULT OFF)
else()
set(WEBP_LINK_STATIC_DEFAULT ON)
endif()
option(WEBP_LINK_STATIC
"Link using static libraries. If OFF, use dynamic libraries."
${WEBP_LINK_STATIC_DEFAULT})
if(NOT EMSCRIPTEN)
# Disable SIMD on Emscripten by default, as it's a new unstable Wasm feature.
# Users can still explicitly opt-in to make a SIMD-enabled build.
@ -40,6 +48,18 @@ option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces."
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)
if(WEBP_LINK_STATIC)
if(WIN32)
SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
else()
SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
endif()
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# vwebp does not compile on Ubuntu with static libraries so disabling it for
# now.
set(WEBP_BUILD_VWEBP OFF)
endif()
# Option needed for handling Unicode file names on Windows.
if(WIN32)
option(WEBP_UNICODE "Build Unicode executables." ON)
@ -97,6 +117,8 @@ set(includedir "\$\{prefix\}/include")
set(PTHREAD_LIBS ${CMAKE_THREAD_LIBS_INIT})
set(INSTALLED_LIBRARIES)
set(CMAKE_C_VISIBILITY_PRESET hidden)
# ##############################################################################
# Android only.
if(ANDROID)
@ -211,6 +233,18 @@ function(libwebp_add_stub_file TARGET)
target_sources(${TARGET} PRIVATE ${stub_source_file})
endfunction()
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv "WEBP_SHARPYUV_SRCS"
"")
add_library(sharpyuv OBJECT ${WEBP_SHARPYUV_SRCS})
target_include_directories(sharpyuv
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(
sharpyuv
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/sharpyuv.h;\
${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/sharpyuv_csp.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
if(MSVC)
# avoid security warnings for e.g., fopen() used in the examples.
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
@ -275,6 +309,7 @@ target_include_directories(webputils
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
add_library(webp
$<TARGET_OBJECTS:sharpyuv>
$<TARGET_OBJECTS:webpdecode>
$<TARGET_OBJECTS:webpdsp>
$<TARGET_OBJECTS:webpencode>
@ -297,7 +332,8 @@ ${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
set_target_properties(sharpyuv
webpdecode
webpdspdecode
webputilsdecode
webpencode
@ -411,13 +447,14 @@ if(WEBP_BUILD_ANIM_UTILS
OR WEBP_BUILD_DWEBP
OR WEBP_BUILD_GIF2WEBP
OR WEBP_BUILD_IMG2WEBP
OR WEBP_BUILD_VWEBP)
OR WEBP_BUILD_VWEBP
OR WEBP_BUILD_WEBPMUX
OR WEBP_BUILD_WEBPINFO)
# Example utility library.
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "EXAMPLEUTIL_SRCS"
"example_util_[^ ]*")
list(APPEND EXAMPLEUTIL_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/examples/stopwatch.h)
add_library(exampleutil STATIC ${EXAMPLEUTIL_SRCS})
target_link_libraries(exampleutil imageioutil)
target_include_directories(
exampleutil
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
@ -426,6 +463,7 @@ if(WEBP_BUILD_ANIM_UTILS
"imageio_util_[^ ]*")
add_library(imageioutil STATIC ${IMAGEIOUTILS_SRCS})
target_link_libraries(imageioutil webp)
target_link_libraries(exampleutil imageioutil)
# Image-decoding utility library.
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEDEC_SRCS"
@ -471,19 +509,18 @@ 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
add_library(webpmux ${WEBP_MUX_SRCS})
target_link_libraries(webpmux webp)
target_include_directories(webpmux
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
set_version(mux/Makefile.am libwebpmux webpmux)
set_target_properties(libwebpmux
set_version(mux/Makefile.am webpmux webpmux)
set_target_properties(webpmux
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)
list(APPEND INSTALLED_LIBRARIES webpmux)
configure_pkg_config("src/mux/libwebpmux.pc")
endif()
@ -497,7 +534,7 @@ if(WEBP_BUILD_GIF2WEBP)
exampleutil
imageioutil
webp
libwebpmux
webpmux
${WEBP_DEP_GIF_LIBRARIES})
target_include_directories(gif2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
install(TARGETS gif2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
@ -514,7 +551,7 @@ if(WEBP_BUILD_IMG2WEBP)
imagedec
imageioutil
webp
libwebpmux)
webpmux)
target_include_directories(img2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
install(TARGETS img2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
@ -554,7 +591,9 @@ if(WEBP_BUILD_WEBPINFO)
"webpinfo")
add_executable(webpinfo ${WEBPINFO_SRCS})
target_link_libraries(webpinfo exampleutil imageioutil)
target_include_directories(webpinfo PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
target_include_directories(webpinfo
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/src)
install(TARGETS webpinfo RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
@ -562,10 +601,12 @@ 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})
add_executable(webpmux_app ${WEBPMUX_SRCS})
set_target_properties(webpmux_app PROPERTIES OUTPUT_NAME webpmux)
target_link_libraries(webpmux_app exampleutil imageioutil webpmux webp)
target_include_directories(webpmux_app
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
install(TARGETS webpmux_app RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(WEBP_BUILD_EXTRAS)
@ -575,29 +616,34 @@ if(WEBP_BUILD_EXTRAS)
parse_makefile_am(${EXTRAS_MAKEFILE} "WEBP_QUALITY_SRCS" "webp_quality")
parse_makefile_am(${EXTRAS_MAKEFILE} "VWEBP_SDL_SRCS" "vwebp_sdl")
# libextras
add_library(extras STATIC ${WEBP_EXTRAS_SRCS})
target_include_directories(extras
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src)
# get_disto
add_executable(get_disto ${GET_DISTO_SRCS})
target_link_libraries(get_disto imagedec)
target_include_directories(get_disto
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}/src)
# webp_quality
add_executable(webp_quality ${WEBP_QUALITY_SRCS} ${WEBP_EXTRAS_SRCS})
target_link_libraries(webp_quality exampleutil imagedec)
add_executable(webp_quality ${WEBP_QUALITY_SRCS})
target_link_libraries(webp_quality exampleutil imagedec extras)
target_include_directories(webp_quality
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR})
# vwebp_sdl
find_package(SDL)
if(SDL_FOUND)
if(WEBP_BUILD_VWEBP AND 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_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/src
${SDL_INCLUDE_DIR})

174
ChangeLog
View File

@ -1,4 +1,176 @@
56a480e8 dsp/cpu.h: add missing extern "C"
62b45bdd update ChangeLog (tag: v1.2.3-rc1)
8764ec7a Merge changes Idb037953,Id582e395 into 1.2.3
bcb872c3 vwebp: fix file name display in windows unicode build
67c44ac5 webpmux: fix -frame option in windows unicode build
8278825a makefile.unix: add sharpyuv objects to clean target
14a49e01 update NEWS
34b1dc33 bump version to 1.2.3
0b397fda update AUTHORS
c16488ac update .mailmap
5a2d929c Merge "unicode.h: set console mode before using wprintf" into main
169f867f unicode.h: set console mode before using wprintf
a94b855c Merge "libsharpyuv: add version defines" into main
f83bdb52 libsharpyuv: add version defines
bef0d797 unicode_gif.h: fix -Wdeclaration-after-statement
404c1622 Rename Huffman coding to prefix coding in the bitstream spec
8895f8a3 Merge "run_static_analysis.sh: fix scan-build archive path" into main
92a673d2 Merge "Add -fvisibility=hidden flag in CMakeLists." into main
67c1d722 Merge "add WEBP_MSAN" into main
1124ff66 Add -fvisibility=hidden flag in CMakeLists.
e15b3560 add WEBP_MSAN
ec9e782a sharpyuv: remove minimum image size from sharpyuv library
7bd07f3b run_static_analysis.sh: fix scan-build archive path
5ecee06f Merge "sharpyuv: increase precision of gamma<->linear conversion" into main
f81dd7d6 Merge changes I3d17d529,I53026880,I1bd61639,I6bd4b25d,Icfec8fba into main
2d607ee6 sharpyuv: increase precision of gamma<->linear conversion
266cbbc5 sharpyuv: add 32bit version of SharpYuvFilterRow.
9fc12274 CMake: add src to webpinfo includes
7d18f40a CMake: add WEBP_BUILD_WEBPINFO to list of checks for exampleutil
11309aa5 CMake: add WEBP_BUILD_WEBPMUX to list of checks for exampleutil
4bc762f7 CMake: link imageioutil to exampleutil after defined
0d1b9bc4 WEBP_DEP_LIBRARIES: use Threads::Threads
20ef48f0 Merge "sharpyuv: add support for 10/12/16 bit rgb and 10/12 bit yuv." into main
93c54371 sharpyuv: add support for 10/12/16 bit rgb and 10/12 bit yuv.
53cf2b49 normalize WebPValidatePicture declaration w/definition
d3006f4b sharpyuv: slightly improve precision
ea967098 Merge changes Ia01bd397,Ibf3771af into main
11bc8410 Merge changes I2d317c4b,I9e77f6db into main
30453ea4 Add an internal WebPValidatePicture.
6c43219a Some renamings for consistency.
4f59fa73 update .mailmap
e74f8a62 webp-lossless-bitstream-spec,cosmetics: normalize range syntax
5a709ec0 webp-lossless-bitstream-spec,cosmetics: fix code typo
a2093acc webp-lossless-bitstream-spec: add amendment note
86c66930 webp-lossless-bitstream-spec: fix BNF
232f22da webp-lossless-bitstream-spec: fix 'simple code' snippet
44dd765d webp-lossless-bitstream-spec: fix ColorTransform impl
7a7e33e9 webp-lossless-bitstream-spec: fix TR-pixel right border note
86f94ee0 Update lossless spec with Huffman codes.
a3927cc8 sharpyuv.c,cosmetics: fix indent
6c45cef7 Make sure the stride has a minimum value in the importer.
0c8b0e67 sharpyuv: cleanup/cosmetic changes
dc3841e0 {histogram,predictor}_enc: quiet int -> float warnings
a19a25bb Replace doubles by floats in lossless misc cost estimations.
42888f6c Add an option to enable static builds.
7efcf3cc Merge "Fix typo in color constants: Marix -> Matrix" into main
8f4b5c62 Fix typo in color constants: Marix -> Matrix
90084d84 Merge "demux,IsValidExtendedFormat: remove unused variable" into main
ed643f61 Merge changes I452d2485,Ic6d75475 into main
8fa053d1 Rename SharpYUV to SharpYuv for consistency.
99a87562 SharpYuvComputeConversionMatrix: quiet int->float warnings
deb426be Makefile.vc: add sharpyuv_csp.obj to SHARPYUV_OBJS
779597d4 demux,IsValidExtendedFormat: remove unused variable
40e8aa57 Merge "libsharpyuv: add colorspace utilities" into main
01a05de1 libsharpyuv: add colorspace utilities
2de4b05a Merge changes Id9890a60,I376d81e6,I1c958838 into main
b8bca81f Merge "configure.ac: use LT_INIT if available" into main
e8e77b9c Merge changes I479bc487,I39864691,I5d486c2c,I186d13be into main
7e7d5d50 Merge ".gitignore: add Android Studio & VS code dirs" into main
10c50848 normalize label indent
89f774e6 mux{edit,internal}: fix leaks on error
2d3293ad ExUtilInitCommandLineArguments: fix leak on error
ec34fd70 anim_util: fix leaks on error
e4717287 gif2webp: fix segfault on OOM
e3cfafaf GetBackwardReferences: fail on alloc error
a828a59b BackwardReferencesHashChainDistanceOnly: fix segfault on OOM
fe153fae VP8LEncodeStream: fix segfault on OOM
919acc0e .gitignore: add Android Studio & VS code dirs
efa0731b configure.ac: use LT_INIT if available
0957fd69 tiffdec: add grayscale support
e685feef Merge "Make libsharpyuv self-contained by removing dependency on cpu.c" into main
841960b6 Make libsharpyuv self-contained by removing dependency on cpu.c
617cf036 image_dec: add WebPGetEnabledInputFileFormats()
7a68afaa Let SharpArgbToYuv caller pass in an RGB>YUV conversion matrix.
34bb332c man/cwebp.1: add note about crop/resize order
f0e9351c webp-lossless-bitstream-spec,cosmetics: fix some typos
5ccbd6ed vp8l_dec.c,cosmetics: fix a few typos
c3d0c2d7 fix ios build scripts after sharpyuv dep added
d0d2292e Merge "Make libwebp depend on libsharpyuv." into main
03d12190 alpha_processing_neon.c: fix 0x01... typo
d55d447c Make libwebp depend on libsharpyuv.
e4cbcdd2 Fix lossless encoding for MIPS.
924e7ca6 alpha_processing_neon.c: fix Dispatch/ExtractAlpha_NEON
0fa0ea54 Makefile.vc: use /MANIFEST:EMBED
29cc95ce Basic version of libsharpyuv in libwebp, in C.
a30f2190 examples/webpmux.c: fix a couple of typos
66b3ce23 Fix bad overflow check in ReadTIFF()
54e61a38 Markdownify libwebp docs and reorganize them.
b4533deb CMakeLists.txt,cosmetics: break long line
b9d2f9cd quant_enc.c: use WEBP_RESTRICT qualifier
ec178f2c Add progress hook granularity in lossless
26139c73 Rename MAX_COST to MAX_BIT_COST in histogram_enc.c
13b82816 cmake: fix webpmux lib name for cmake linking
88b6a396 webp-container-spec.txt,cosmetics: normalize formatting
6f496540 Merge tag 'v1.2.2'
4074acf8 dsp.h: bump msvc arm64 version requirement to 16.6
b0a86089 update ChangeLog (tag: v1.2.2)
6db8248c libwebp: Fix VP8EncTokenLoop() progress
827a307f BMP enc: fix the transparency case
db25f1b4 libwebp: Fix VP8EncTokenLoop() progress
286e7fce libwebp: do not destroy jpeg codec twice on error
6e8a4126 libwebp: do not destroy jpeg codec twice on error
faf21968 Merge "BMP enc: fix the transparency case" into main
480cd51d BMP enc: fix the transparency case
9195ea05 update ChangeLog (tag: v1.2.2-rc2)
4acae017 update NEWS
883f0633 man/img2webp.1: update date
567e1f44 Reword img2webp synopsis command line
1b0c15db man/img2webp.1: update date
17bade38 Merge "Reword img2webp synopsis command line" into main
a80954a1 Reword img2webp synopsis command line
f084244d anim_decode: fix alpha blending with big-endian
b217b4ff webpinfo: fix fourcc comparison w/big-endian
ec497b75 Merge "anim_decode: fix alpha blending with big-endian" into main
e4886716 anim_decode: fix alpha blending with big-endian
e3cb052c webpinfo: fix fourcc comparison w/big-endian
a510fedb patch-check: detect duplicated files
f035d2e4 update ChangeLog (tag: v1.2.2-rc1)
7031946a update NEWS
973390b6 bump version to 1.2.2
abd6664f update AUTHORS
5b7e7930 Merge "add missing USE_{MSA,NEON} checks in headers" into main
02ca04c3 add missing USE_{MSA,NEON} checks in headers
e94716e2 xcframeworkbuild.sh: place headers in a subdir
c846efd8 patch-check: commit subject length check
b6f756e8 update http links
8f5cb4c1 update rfc links
8ea81561 change VP8LPredictorFunc signature to avoid reading 'left'
6b1d18c3 webpmux: fix the -bgcolor description
3368d876 Merge "webpmux: add "-set bgcolor A,R,G,B"" into main
f213abf6 webpinfo: print the number of warnings
50c97c30 webpmux: add "-set bgcolor A,R,G,B"
2c206aaf Remove CMakeLists.txt check in compile.sh
96e3dfef Merge "infra/common.sh: add shard_should_run()" into main
0e0f74b7 infra/common.sh: add shard_should_run()
35b7436a Jenkins scripts port: update shell function comments
21d24b4c webp-container-spec.txt: remove 'experimental' markers
cdcf8902 Merge "Port Jenkins script: compile" into main
dc683cde Jenkins scripts port: static analysis
0858494e Port Jenkins script: compile
c2cf6a93 Jenkins scripts port: android compilation
df0e808f presubmit: Add pylint-2.7 and .pylintrc
676c57db patch-check: shfmt
7bb7f747 patch-check: Add shellcheck
abcd1797 Reformat docstrings and imports
edaf0895 Port Jenkins scripts: compile js
b9622063 Set CheckPatchFormatted flags to fail on diffs
e23cd548 dsp.h: enable NEON w/VS2019+ ARM64 targets
3875c7de CMakeLists.txt: set minimum version to 3.7
1a8f0d45 Have a hard-coded value for memset in TrellisQuantizeBlock.
93480160 Speed up TrellisQuantizeBlock
45eaacc9 Convert deprecated uint32 to uint32_t.
42592af8 webp,cmake: Remove unnecessary include dirs
e298e05f Add patch-check steps in PRESUBMIT.py
29148919 Merge tag 'v1.2.1'
9ce5843d update ChangeLog (tag: v1.2.1)
d9191588 fuzzer/*: normalize src/ includes
c5bc3624 fuzzer/*: normalize src/ includes
53b6f762 fix indent
d2caaba4 fix indent
731246ba update ChangeLog (tag: v1.2.1-rc2)
d250f01d dsp/*: use WEBP_HAVE_* to determine Init availability
1fe31625 dsp/*: use WEBP_HAVE_* to determine Init availability
3a4d3ecd update NEWS
b2bc8093 bump version to 1.2.1
e542fc7a update AUTHORS
@ -170,7 +342,7 @@ a99078c1 remove call to MBAnalyzeBestIntra4Mode for method >= 5
6a0ff358 Enc: add a qmin / qmax range for quality factor
0fa56f30 Merge tag 'v1.1.0'
6cf504d0 PNM decoding: handle max_value != 255
d7844e97 update ChangeLog (tag: v1.1.0-rc2, tag: v1.1.0, origin/1.1.0)
d7844e97 update ChangeLog (tag: v1.1.0-rc2, tag: v1.1.0)
7f006436 Makefile.vc: fix webp_quality.exe link
cf047e83 Makefile.vc: fix webp_quality.exe link
c074c653 update NEWS

View File

@ -1,5 +1,5 @@
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src imageio man
SUBDIRS = sharpyuv src imageio man
EXTRA_DIST = COPYING autogen.sh
if BUILD_EXTRAS

View File

@ -31,12 +31,11 @@ CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG
CCDEBUG = cl.exe $(NOLOGO) /Od /Zi /D_DEBUG /RTC1
CFLAGS = /I. /Isrc $(NOLOGO) /W3 /EHsc /c
CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST /NXCOMPAT /DYNAMICBASE
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST:EMBED /NXCOMPAT /DYNAMICBASE
LDFLAGS = $(LDFLAGS) $(PLATFORM_LDFLAGS)
LNKDLL = link.exe /DLL $(NOLOGO)
LNKEXE = link.exe $(NOLOGO)
LNKLIB = lib.exe $(NOLOGO)
MT = mt.exe $(NOLOGO)
RCNODBG = rc.exe $(NOLOGO) /l"0x0409" # 0x409 = U.S. English
RCDEBUG = $(RCNODBG) /D_DEBUG
@ -82,6 +81,7 @@ OUTPUT_DIRS = $(DIRBIN) $(DIRINC) $(DIRLIB) \
$(DIROBJ)\extras \
$(DIROBJ)\imageio \
$(DIROBJ)\mux \
$(DIROBJ)\sharpyuv \
$(DIROBJ)\utils \
# Target configuration
@ -174,6 +174,14 @@ CFLAGS = $(CFLAGS) /D_UNICODE /DUNICODE
# A config was provided, so the library can be built.
#
SHARPYUV_OBJS = \
$(DIROBJ)\sharpyuv\sharpyuv.obj \
$(DIROBJ)\sharpyuv\sharpyuv_csp.obj \
$(DIROBJ)\sharpyuv\sharpyuv_dsp.obj \
$(DIROBJ)\sharpyuv\sharpyuv_gamma.obj \
$(DIROBJ)\sharpyuv\sharpyuv_neon.obj \
$(DIROBJ)\sharpyuv\sharpyuv_sse2.obj \
DEC_OBJS = \
$(DIROBJ)\dec\alpha_dec.obj \
$(DIROBJ)\dec\buffer_dec.obj \
@ -335,8 +343,8 @@ UTILS_ENC_OBJS = \
$(DIROBJ)\utils\quant_levels_utils.obj \
LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
$(UTILS_ENC_OBJS) $(DLL_OBJS)
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(SHARPYUV_OBJS) $(ENC_OBJS) \
$(DSP_ENC_OBJS) $(UTILS_ENC_OBJS) $(DLL_OBJS)
LIBWEBPMUX_OBJS = $(MUX_OBJS) $(LIBWEBPMUX_OBJS)
LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS) $(LIBWEBPDEMUX_OBJS)
@ -482,6 +490,8 @@ $(DIROBJ)\examples\gifdec.obj: examples\gifdec.c
$(CC) $(CFLAGS) /Fd$(DIROBJ)\extras\ /Fo$(DIROBJ)\extras\ $<
{imageio}.c{$(DIROBJ)\imageio}.obj::
$(CC) $(CFLAGS) /Fd$(DIROBJ)\imageio\ /Fo$(DIROBJ)\imageio\ $<
{sharpyuv}.c{$(DIROBJ)\sharpyuv}.obj::
$(CC) $(CFLAGS) /Fd$(DIROBJ)\sharpyuv\ /Fo$(DIROBJ)\sharpyuv\ $<
{src\dec}.c{$(DIROBJ)\dec}.obj::
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dec\ $<
{src\demux}.c{$(DIROBJ)\demux}.obj::
@ -502,13 +512,9 @@ LNKLIBS = $(LNKLIBS) Shell32.lib
{$(DIROBJ)\examples}.obj{$(DIRBIN)}.exe:
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS)
$(MT) -manifest $@.manifest -outputresource:$@;1
del $@.manifest
{$(DIROBJ)\extras}.obj{$(DIRBIN)}.exe:
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS)
$(MT) -manifest $@.manifest -outputresource:$@;1
del $@.manifest
clean::
@-erase /s $(DIROBJ)\*.dll 2> NUL

16
NEWS
View File

@ -1,3 +1,19 @@
- 6/30/2022: version 1.2.3
This is a binary compatible release.
* security fix for lossless encoder (#565, chromium:1313709)
* improved progress granularity in WebPReportProgress() when using lossless
* improved precision in Sharp YUV (-sharp_yuv) conversion
* many corrections to webp-lossless-bitstream-spec.txt (#551)
* crash/leak fixes on error/OOM and other bug fixes (#558, #563, #569, #573)
- 1/11/2022: version 1.2.2
This is a binary compatible release.
* webpmux: add "-set bgcolor A,R,G,B"
* add ARM64 NEON support for MSVC builds (#539)
* fix duplicate include error in Xcode when using multiple XCFrameworks in a
project (#542)
* doc updates and bug fixes (#538, #544, #548, #550)
- 7/20/2021: version 1.2.1
This is a binary compatible release.
* minor lossless encoder improvements and x86 color conversion speed up

245
PRESUBMIT.py Normal file
View File

@ -0,0 +1,245 @@
# 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 re
import subprocess2
USE_PYTHON3 = True
_BASH_INDENTATION = "2"
_GIT_COMMIT_SUBJECT_LENGTH = 65
_INCLUDE_BASH_FILES_ONLY = [r".*\.sh$"]
_INCLUDE_MAN_FILES_ONLY = [r"man/.+\.1$"]
_INCLUDE_SOURCE_FILES_ONLY = [r".*\.[ch]$"]
_LIBWEBP_MAX_LINE_LENGTH = 80
def _CheckCommitSubjectLength(input_api, output_api):
"""Ensures commit's subject length is no longer than 65 chars."""
name = "git-commit subject"
cmd = ["git", "log", "-1", "--pretty=%s"]
start = input_api.time.time()
proc = subprocess2.Popen(
cmd,
stderr=subprocess2.PIPE,
stdout=subprocess2.PIPE,
universal_newlines=True)
stdout, _ = proc.communicate()
duration = input_api.time.time() - start
if not re.match(r"^Revert",
stdout) and (len(stdout) - 1) > _GIT_COMMIT_SUBJECT_LENGTH:
failure_msg = (
"The commit subject: %s is too long (%d chars)\n"
"Try to keep this to 50 or less (up to 65 is permitted for "
"non-reverts).\n"
"https://www.git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-"
"Project#_commit_guidelines") % (stdout, len(stdout) - 1)
return output_api.PresubmitError("%s\n (%4.2fs) failed\n%s" %
(name, duration, failure_msg))
return output_api.PresubmitResult("%s\n (%4.2fs) success" % (name, duration))
def _CheckDuplicateFiles(input_api, output_api):
"""Ensures there are not repeated filenames."""
all_files = []
for f in input_api.change.AllFiles():
for include_file in _INCLUDE_SOURCE_FILES_ONLY:
if re.match(include_file, f):
all_files.append(f)
break
basename_to_path = {}
for f in all_files:
basename_file = input_api.basename(f)
if basename_file in basename_to_path:
basename_to_path[basename_file].append(f)
else:
basename_to_path[basename_file] = [f]
dupes = []
for files in basename_to_path.values():
if len(files) > 1:
dupes.extend(files)
if dupes:
return output_api.PresubmitError(
"Duplicate source files, rebase or rename some to make them unique:\n%s"
% dupes)
return output_api.PresubmitResult("No duplicates, success\n")
def _GetFilesToSkip(input_api):
return list(input_api.DEFAULT_FILES_TO_SKIP) + [
r"swig/.*\.py$",
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))
results.append(_CheckCommitSubjectLength(input_api, output_api))
results.append(_CheckDuplicateFiles(input_api, output_api))
source_file_filter = lambda x: input_api.FilterSourceFile(
x, files_to_skip=_GetFilesToSkip(input_api))
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

795
README
View File

@ -1,795 +0,0 @@
__ __ ____ ____ ____
/ \\/ \/ _ \/ _ )/ _ \
\ / __/ _ \ __/
\__\__/\____/\_____/__/ ____ ___
/ _/ / \ \ / _ \/ _/
/ \_/ / / \ \ __/ \__
\____/____/\_____/_____/____/v1.2.1
Description:
============
WebP codec: library to encode and decode images in WebP format. This package
contains the library that can be used in other programs to add WebP support,
as well as the command line tools 'cwebp' and 'dwebp'.
See http://developers.google.com/speed/webp
The latest source tree is available at
https://chromium.googlesource.com/webm/libwebp
It is released under the same license as the WebM project.
See http://www.webmproject.org/license/software/ or the
"COPYING" file for details. An additional intellectual
property rights grant can be found in the file PATENTS.
Building:
=========
Windows build:
--------------
By running:
nmake /f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output
the directory output\release-static\(x64|x86)\bin will contain the tools
cwebp.exe and dwebp.exe. The directory output\release-static\(x64|x86)\lib will
contain the libwebp static library.
The target architecture (x86/x64) is detected by Makefile.vc from the Visual
Studio compiler (cl.exe) available in the system path.
Unix build using makefile.unix:
-------------------------------
On platforms with GNU tools installed (gcc and make), running
make -f makefile.unix
will build the binaries examples/cwebp and examples/dwebp, along
with the static library src/libwebp.a. No system-wide installation
is supplied, as this is a simple alternative to the full installation
system based on the autoconf tools (see below).
Please refer to makefile.unix for additional details and customizations.
Using autoconf tools:
---------------------
Prerequisites:
A compiler (e.g., gcc), make, autoconf, automake, libtool.
On a Debian-like system the following should install everything you need for a
minimal build:
$ sudo apt-get install gcc make autoconf automake libtool
When building from git sources, you will need to run autogen.sh to generate the
configure script.
./configure
make
make install
should be all you need to have the following files
/usr/local/include/webp/decode.h
/usr/local/include/webp/encode.h
/usr/local/include/webp/types.h
/usr/local/lib/libwebp.*
/usr/local/bin/cwebp
/usr/local/bin/dwebp
installed.
Note: A decode-only library, libwebpdecoder, is available using the
'--enable-libwebpdecoder' flag. The encode library is built separately and can
be installed independently using a minor modification in the corresponding
Makefile.am configure files (see comments there). See './configure --help' for
more options.
Building for MIPS Linux:
------------------------
MIPS Linux toolchain stable available releases can be found at:
https://community.imgtec.com/developers/mips/tools/codescape-mips-sdk/available-releases/
# Add toolchain to PATH
export PATH=$PATH:/path/to/toolchain/bin
# 32-bit build for mips32r5 (p5600)
HOST=mips-mti-linux-gnu
MIPS_CFLAGS="-O3 -mips32r5 -mabi=32 -mtune=p5600 -mmsa -mfp64 \
-msched-weight -mload-store-pairs -fPIE"
MIPS_LDFLAGS="-mips32r5 -mabi=32 -mmsa -mfp64 -pie"
# 64-bit build for mips64r6 (i6400)
HOST=mips-img-linux-gnu
MIPS_CFLAGS="-O3 -mips64r6 -mabi=64 -mtune=i6400 -mmsa -mfp64 \
-msched-weight -mload-store-pairs -fPIE"
MIPS_LDFLAGS="-mips64r6 -mabi=64 -mmsa -mfp64 -pie"
./configure --host=${HOST} --build=`config.guess` \
CC="${HOST}-gcc -EL" \
CFLAGS="$MIPS_CFLAGS" \
LDFLAGS="$MIPS_LDFLAGS"
make
make install
CMake:
------
With CMake, you can compile libwebp, cwebp, dwebp, gif2webp, img2webp, webpinfo
and the JS bindings.
Prerequisites:
A compiler (e.g., gcc with autotools) and CMake.
On a Debian-like system the following should install everything you need for a
minimal build:
$ sudo apt-get install build-essential cmake
When building from git sources, you will need to run cmake to generate the
makefiles.
mkdir build && cd build && cmake ../
make
make install
If you also want any of the executables, you will need to enable them through
CMake, e.g.:
cmake -DWEBP_BUILD_CWEBP=ON -DWEBP_BUILD_DWEBP=ON ../
or through your favorite interface (like ccmake or cmake-qt-gui).
Use option -DWEBP_UNICODE=ON for Unicode support on Windows (with chcp 65001).
Finally, once installed, you can also use WebP in your CMake project by doing:
find_package(WebP)
which will define the CMake variables WebP_INCLUDE_DIRS and WebP_LIBRARIES.
Gradle:
-------
The support for Gradle is minimal: it only helps you compile libwebp, cwebp and
dwebp and webpmux_example.
Prerequisites:
A compiler (e.g., gcc with autotools) and gradle.
On a Debian-like system the following should install everything you need for a
minimal build:
$ sudo apt-get install build-essential gradle
When building from git sources, you will need to run the Gradle wrapper with the
appropriate target, e.g. :
./gradlew buildAllExecutables
SWIG bindings:
--------------
To generate language bindings from swig/libwebp.swig at least swig-1.3
(http://www.swig.org) is required.
Currently the following functions are mapped:
Decode:
WebPGetDecoderVersion
WebPGetInfo
WebPDecodeRGBA
WebPDecodeARGB
WebPDecodeBGRA
WebPDecodeBGR
WebPDecodeRGB
Encode:
WebPGetEncoderVersion
WebPEncodeRGBA
WebPEncodeBGRA
WebPEncodeRGB
WebPEncodeBGR
WebPEncodeLosslessRGBA
WebPEncodeLosslessBGRA
WebPEncodeLosslessRGB
WebPEncodeLosslessBGR
See swig/README for more detailed build instructions.
Java bindings:
To build the swig-generated JNI wrapper code at least JDK-1.5 (or equivalent)
is necessary for enum support. The output is intended to be a shared object /
DLL that can be loaded via System.loadLibrary("webp_jni").
Python bindings:
To build the swig-generated Python extension code at least Python 2.6 is
required. Python < 2.6 may build with some minor changes to libwebp.swig or the
generated code, but is untested.
Encoding tool:
==============
The examples/ directory contains tools for encoding (cwebp) and
decoding (dwebp) images.
The easiest use should look like:
cwebp input.png -q 80 -o output.webp
which will convert the input file to a WebP file using a quality factor of 80
on a 0->100 scale (0 being the lowest quality, 100 being the best. Default
value is 75).
You might want to try the -lossless flag too, which will compress the source
(in RGBA format) without any loss. The -q quality parameter will in this case
control the amount of processing time spent trying to make the output file as
small as possible.
A longer list of options is available using the -longhelp command line flag:
> cwebp -longhelp
Usage:
cwebp [-preset <...>] [options] in_file [-o out_file]
If input size (-s) for an image is not specified, it is
assumed to be a PNG, JPEG, TIFF or WebP file.
Note: Animated PNG and WebP files are not supported.
Options:
-h / -help ............. short help
-H / -longhelp ......... long help
-q <float> ............. quality factor (0:small..100:big), default=75
-alpha_q <int> ......... transparency-compression quality (0..100),
default=100
-preset <string> ....... preset setting, one of:
default, photo, picture,
drawing, icon, text
-preset must come first, as it overwrites other parameters
-z <int> ............... activates lossless preset with given
level in [0:fast, ..., 9:slowest]
-m <int> ............... compression method (0=fast, 6=slowest), default=4
-segments <int> ........ number of segments to use (1..4), default=4
-size <int> ............ target size (in bytes)
-psnr <float> .......... target PSNR (in dB. typically: 42)
-s <int> <int> ......... input size (width x height) for YUV
-sns <int> ............. spatial noise shaping (0:off, 100:max), default=50
-f <int> ............... filter strength (0=off..100), default=60
-sharpness <int> ....... filter sharpness (0:most .. 7:least sharp), default=0
-strong ................ use strong filter instead of simple (default)
-nostrong .............. use simple filter instead of strong
-sharp_yuv ............. use sharper (and slower) RGB->YUV conversion
-partition_limit <int> . limit quality to fit the 512k limit on
the first partition (0=no degradation ... 100=full)
-pass <int> ............ analysis pass number (1..10)
-qrange <min> <max> .... specifies the permissible quality range
(default: 0 100)
-crop <x> <y> <w> <h> .. crop picture with the given rectangle
-resize <w> <h> ........ resize picture (after any cropping)
-mt .................... use multi-threading if available
-low_memory ............ reduce memory usage (slower encoding)
-map <int> ............. print map of extra info
-print_psnr ............ prints averaged PSNR distortion
-print_ssim ............ prints averaged SSIM distortion
-print_lsim ............ prints local-similarity distortion
-d <file.pgm> .......... dump the compressed output (PGM file)
-alpha_method <int> .... transparency-compression method (0..1), default=1
-alpha_filter <string> . predictive filtering for alpha plane,
one of: none, fast (default) or best
-exact ................. preserve RGB values in transparent area, default=off
-blend_alpha <hex> ..... blend colors against background color
expressed as RGB values written in
hexadecimal, e.g. 0xc0e0d0 for red=0xc0
green=0xe0 and blue=0xd0
-noalpha ............... discard any transparency information
-lossless .............. encode image losslessly, default=off
-near_lossless <int> ... use near-lossless image
preprocessing (0..100=off), default=100
-hint <string> ......... specify image characteristics hint,
one of: photo, picture or graph
-metadata <string> ..... comma separated list of metadata to
copy from the input to the output if present.
Valid values: all, none (default), exif, icc, xmp
-short ................. condense printed message
-quiet ................. don't print anything
-version ............... print version number and exit
-noasm ................. disable all assembly optimizations
-v ..................... verbose, e.g. print encoding/decoding times
-progress .............. report encoding progress
Experimental Options:
-jpeg_like ............. roughly match expected JPEG size
-af .................... auto-adjust filter strength
-pre <int> ............. pre-processing filter
The main options you might want to try in order to further tune the
visual quality are:
-preset
-sns
-f
-m
Namely:
* 'preset' will set up a default encoding configuration targeting a
particular type of input. It should appear first in the list of options,
so that subsequent options can take effect on top of this preset.
Default value is 'default'.
* 'sns' will progressively turn on (when going from 0 to 100) some additional
visual optimizations (like: segmentation map re-enforcement). This option
will balance the bit allocation differently. It tries to take bits from the
"easy" parts of the picture and use them in the "difficult" ones instead.
Usually, raising the sns value (at fixed -q value) leads to larger files,
but with better quality.
Typical value is around '75'.
* 'f' option directly links to the filtering strength used by the codec's
in-loop processing. The higher the value, the smoother the
highly-compressed area will look. This is particularly useful when aiming
at very small files. Typical values are around 20-30. Note that using the
option -strong/-nostrong will change the type of filtering. Use "-f 0" to
turn filtering off.
* 'm' controls the trade-off between encoding speed and quality. Default is 4.
You can try -m 5 or -m 6 to explore more (time-consuming) encoding
possibilities. A lower value will result in faster encoding at the expense
of quality.
Decoding tool:
==============
There is a decoding sample in examples/dwebp.c which will take
a .webp file and decode it to a PNG image file (amongst other formats).
This is simply to demonstrate the use of the API. You can verify the
file test.webp decodes to exactly the same as test_ref.ppm by using:
cd examples
./dwebp test.webp -ppm -o test.ppm
diff test.ppm test_ref.ppm
The full list of options is available using -h:
> dwebp -h
Usage: dwebp in_file [options] [-o out_file]
Decodes the WebP image file to PNG format [Default].
Note: Animated WebP files are not supported.
Use following options to convert into alternate image formats:
-pam ......... save the raw RGBA samples as a color PAM
-ppm ......... save the raw RGB samples as a color PPM
-bmp ......... save as uncompressed BMP format
-tiff ........ save as uncompressed TIFF format
-pgm ......... save the raw YUV samples as a grayscale PGM
file with IMC4 layout
-yuv ......... save the raw YUV samples in flat layout
Other options are:
-version ..... print version number and exit
-nofancy ..... don't use the fancy YUV420 upscaler
-nofilter .... disable in-loop filtering
-nodither .... disable dithering
-dither <d> .. dithering strength (in 0..100)
-alpha_dither use alpha-plane dithering if needed
-mt .......... use multi-threading
-crop <x> <y> <w> <h> ... crop output with the given rectangle
-resize <w> <h> ......... scale the output (*after* any cropping)
-flip ........ flip the output vertically
-alpha ....... only save the alpha plane
-incremental . use incremental decoding (useful for tests)
-h ........... this help message
-v ........... verbose (e.g. print encoding/decoding times)
-quiet ....... quiet mode, don't print anything
-noasm ....... disable all assembly optimizations
WebP file analysis tool:
========================
'webpinfo' can be used to print out the chunk level structure and bitstream
header information of WebP files. It can also check if the files are of valid
WebP format.
Usage: webpinfo [options] in_files
Note: there could be multiple input files;
options must come before input files.
Options:
-version ........... Print version number and exit.
-quiet ............. Do not show chunk parsing information.
-diag .............. Show parsing error diagnosis.
-summary ........... Show chunk stats summary.
-bitstream_info .... Parse bitstream header.
Visualization tool:
===================
There's a little self-serve visualization tool called 'vwebp' under the
examples/ directory. It uses OpenGL to open a simple drawing window and show
a decoded WebP file. It's not yet integrated in the automake build system, but
you can try to manually compile it using the recommendations below.
Usage: vwebp in_file [options]
Decodes the WebP image file and visualize it using OpenGL
Options are:
-version ..... print version number and exit
-noicc ....... don't use the icc profile if present
-nofancy ..... don't use the fancy YUV420 upscaler
-nofilter .... disable in-loop filtering
-dither <int> dithering strength (0..100), default=50
-noalphadither disable alpha plane dithering
-usebgcolor .. display background color
-mt .......... use multi-threading
-info ........ print info
-h ........... this help message
Keyboard shortcuts:
'c' ................ toggle use of color profile
'b' ................ toggle background color display
'i' ................ overlay file information
'd' ................ disable blending & disposal (debug)
'q' / 'Q' / ESC .... quit
Building:
---------
Prerequisites:
1) OpenGL & OpenGL Utility Toolkit (GLUT)
Linux:
$ sudo apt-get install freeglut3-dev mesa-common-dev
Mac + Xcode:
- These libraries should be available in the OpenGL / GLUT frameworks.
Windows:
http://freeglut.sourceforge.net/index.php#download
2) (Optional) qcms (Quick Color Management System)
i. Download qcms from Mozilla / Chromium:
http://hg.mozilla.org/mozilla-central/file/0e7639e3bdfb/gfx/qcms
http://src.chromium.org/viewvc/chrome/trunk/src/third_party/qcms
ii. Build and archive the source files as libqcms.a / qcms.lib
iii. Update makefile.unix / Makefile.vc
a) Define WEBP_HAVE_QCMS
b) Update include / library paths to reference the qcms directory.
Build using makefile.unix / Makefile.vc:
$ make -f makefile.unix examples/vwebp
> nmake /f Makefile.vc CFG=release-static \
../obj/x64/release-static/bin/vwebp.exe
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 files can be converted to WebP files with animation using the
gif2webp utility available under examples/. The files can then be viewed using
vwebp.
Usage:
gif2webp [options] gif_file -o webp_file
Options:
-h / -help ............. this help
-lossy ................. encode image using lossy compression
-mixed ................. for each frame in the image, pick lossy
or lossless compression heuristically
-q <float> ............. quality factor (0:small..100:big)
-m <int> ............... compression method (0=fast, 6=slowest)
-min_size .............. minimize output size (default:off)
lossless compression by default; can be
combined with -q, -m, -lossy or -mixed
options
-kmin <int> ............ min distance between key frames
-kmax <int> ............ max distance between key frames
-f <int> ............... filter strength (0=off..100)
-metadata <string> ..... comma separated list of metadata to
copy from the input to the output if present
Valid values: all, none, icc, xmp (default)
-loop_compatibility .... use compatibility mode for Chrome
version prior to M62 (inclusive)
-mt .................... use multi-threading if available
-version ............... print version number and exit
-v ..................... verbose
-quiet ................. don't print anything
Building:
---------
With the libgif development files installed, gif2webp can be built using
makefile.unix:
$ make -f makefile.unix examples/gif2webp
or using autoconf:
$ ./configure --enable-everything
$ make
Comparison of animated images:
==============================
Test utility anim_diff under examples/ can be used to compare two animated
images (each can be GIF or WebP).
Usage: anim_diff <image1> <image2> [options]
Options:
-dump_frames <folder> dump decoded frames in PAM format
-min_psnr <float> ... minimum per-frame PSNR
-raw_comparison ..... if this flag is not used, RGB is
premultiplied before comparison
-max_diff <int> ..... maximum allowed difference per channel
between corresponding pixels in subsequent
frames
-h .................. this help
-version ............ print version number and exit
Building:
---------
With the libgif development files and a C++ compiler installed, anim_diff can
be built using makefile.unix:
$ make -f makefile.unix examples/anim_diff
or using autoconf:
$ ./configure --enable-everything
$ make
Encoding API:
=============
The main encoding functions are available in the header src/webp/encode.h
The ready-to-use ones are:
size_t WebPEncodeRGB(const uint8_t* rgb, int width, int height, int stride,
float quality_factor, uint8_t** output);
size_t WebPEncodeBGR(const uint8_t* bgr, int width, int height, int stride,
float quality_factor, uint8_t** output);
size_t WebPEncodeRGBA(const uint8_t* rgba, int width, int height, int stride,
float quality_factor, uint8_t** output);
size_t WebPEncodeBGRA(const uint8_t* bgra, int width, int height, int stride,
float quality_factor, uint8_t** output);
They will convert raw RGB samples to a WebP data. The only control supplied
is the quality factor.
There are some variants for using the lossless format:
size_t WebPEncodeLosslessRGB(const uint8_t* rgb, int width, int height,
int stride, uint8_t** output);
size_t WebPEncodeLosslessBGR(const uint8_t* bgr, int width, int height,
int stride, uint8_t** output);
size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, int width, int height,
int stride, uint8_t** output);
size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, int width, int height,
int stride, uint8_t** output);
Of course in this case, no quality factor is needed since the compression
occurs without loss of the input values, at the expense of larger output sizes.
Advanced encoding API:
----------------------
A more advanced API is based on the WebPConfig and WebPPicture structures.
WebPConfig contains the encoding settings and is not tied to a particular
picture.
WebPPicture contains input data, on which some WebPConfig will be used for
compression.
The encoding flow looks like:
-------------------------------------- BEGIN PSEUDO EXAMPLE
#include <webp/encode.h>
// Setup a config, starting form a preset and tuning some additional
// parameters
WebPConfig config;
if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) {
return 0; // version error
}
// ... additional tuning
config.sns_strength = 90;
config.filter_sharpness = 6;
config_error = WebPValidateConfig(&config); // not mandatory, but useful
// Setup the input data
WebPPicture pic;
if (!WebPPictureInit(&pic)) {
return 0; // version error
}
pic.width = width;
pic.height = height;
// allocated picture of dimension width x height
if (!WebPPictureAlloc(&pic)) {
return 0; // memory error
}
// at this point, 'pic' has been initialized as a container,
// and can receive the Y/U/V samples.
// Alternatively, one could use ready-made import functions like
// WebPPictureImportRGB(), which will take care of memory allocation.
// In any case, past this point, one will have to call
// WebPPictureFree(&pic) to reclaim memory.
// Set up a byte-output write method. WebPMemoryWriter, for instance.
WebPMemoryWriter wrt;
WebPMemoryWriterInit(&wrt); // initialize 'wrt'
pic.writer = MyFileWriter;
pic.custom_ptr = my_opaque_structure_to_make_MyFileWriter_work;
// Compress!
int ok = WebPEncode(&config, &pic); // ok = 0 => error occurred!
WebPPictureFree(&pic); // must be called independently of the 'ok' result.
// output data should have been handled by the writer at that point.
// -> compressed data is the memory buffer described by wrt.mem / wrt.size
// deallocate the memory used by compressed data
WebPMemoryWriterClear(&wrt);
-------------------------------------- END PSEUDO EXAMPLE
Decoding API:
=============
This is mainly just one function to call:
#include "webp/decode.h"
uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size,
int* width, int* height);
Please have a look at the file src/webp/decode.h for the details.
There are variants for decoding in BGR/RGBA/ARGB/BGRA order, along with
decoding to raw Y'CbCr samples. One can also decode the image directly into a
pre-allocated buffer.
To detect a WebP file and gather the picture's dimensions, the function:
int WebPGetInfo(const uint8_t* data, size_t data_size,
int* width, int* height);
is supplied. No decoding is involved when using it.
Incremental decoding API:
=========================
In the case when data is being progressively transmitted, pictures can still
be incrementally decoded using a slightly more complicated API. Decoder state
is stored into an instance of the WebPIDecoder object. This object can be
created with the purpose of decoding either RGB or Y'CbCr samples.
For instance:
WebPDecBuffer buffer;
WebPInitDecBuffer(&buffer);
buffer.colorspace = MODE_BGR;
...
WebPIDecoder* idec = WebPINewDecoder(&buffer);
As data is made progressively available, this incremental-decoder object
can be used to decode the picture further. There are two (mutually exclusive)
ways to pass freshly arrived data:
either by appending the fresh bytes:
WebPIAppend(idec, fresh_data, size_of_fresh_data);
or by just mentioning the new size of the transmitted data:
WebPIUpdate(idec, buffer, size_of_transmitted_buffer);
Note that 'buffer' can be modified between each call to WebPIUpdate, in
particular when the buffer is resized to accommodate larger data.
These functions will return the decoding status: either VP8_STATUS_SUSPENDED if
decoding is not finished yet or VP8_STATUS_OK when decoding is done. Any other
status is an error condition.
The 'idec' object must always be released (even upon an error condition) by
calling: WebPDelete(idec).
To retrieve partially decoded picture samples, one must use the corresponding
method: WebPIDecGetRGB or WebPIDecGetYUVA.
It will return the last displayable pixel row.
Lastly, note that decoding can also be performed into a pre-allocated pixel
buffer. This buffer must be passed when creating a WebPIDecoder, calling
WebPINewRGB() or WebPINewYUVA().
Please have a look at the src/webp/decode.h header for further details.
Advanced Decoding API:
======================
WebP decoding supports an advanced API which provides on-the-fly cropping and
rescaling, something of great usefulness on memory-constrained environments like
mobile phones. Basically, the memory usage will scale with the output's size,
not the input's, when one only needs a quick preview or a zoomed in portion of
an otherwise too-large picture. Some CPU can be saved too, incidentally.
-------------------------------------- BEGIN PSEUDO EXAMPLE
// A) Init a configuration object
WebPDecoderConfig config;
CHECK(WebPInitDecoderConfig(&config));
// B) optional: retrieve the bitstream's features.
CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
// C) Adjust 'config' options, if needed
config.options.no_fancy_upsampling = 1;
config.options.use_scaling = 1;
config.options.scaled_width = scaledWidth();
config.options.scaled_height = scaledHeight();
// etc.
// D) Specify 'config' output options for specifying output colorspace.
// Optionally the external image decode buffer can also be specified.
config.output.colorspace = MODE_BGRA;
// Optionally, the config.output can be pointed to an external buffer as
// well for decoding the image. This externally supplied memory buffer
// should be big enough to store the decoded picture.
config.output.u.RGBA.rgba = (uint8_t*) memory_buffer;
config.output.u.RGBA.stride = scanline_stride;
config.output.u.RGBA.size = total_size_of_the_memory_buffer;
config.output.is_external_memory = 1;
// E) Decode the WebP image. There are two variants w.r.t decoding image.
// The first one (E.1) decodes the full image and the second one (E.2) is
// used to incrementally decode the image using small input buffers.
// Any one of these steps can be used to decode the WebP image.
// E.1) Decode full image.
CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK);
// E.2) Decode image incrementally.
WebPIDecoder* const idec = WebPIDecode(NULL, NULL, &config);
CHECK(idec != NULL);
while (bytes_remaining > 0) {
VP8StatusCode status = WebPIAppend(idec, input, bytes_read);
if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) {
bytes_remaining -= bytes_read;
} else {
break;
}
}
WebPIDelete(idec);
// F) Decoded image is now in config.output (and config.output.u.RGBA).
// It can be saved, displayed or otherwise processed.
// G) Reclaim memory allocated in config's object. It's safe to call
// this function even if the memory is external and wasn't allocated
// by WebPDecode().
WebPFreeDecBuffer(&config.output);
-------------------------------------- END PSEUDO EXAMPLE
Bugs:
=====
Please report all bugs to the issue tracker:
https://bugs.chromium.org/p/webp
Patches welcome! See this page to get started:
http://www.webmproject.org/code/contribute/submitting-patches/
Discuss:
========
Email: webp-discuss@webmproject.org
Web: http://groups.google.com/a/webmproject.org/group/webp-discuss

53
README.md Normal file
View File

@ -0,0 +1,53 @@
# WebP Codec
```
__ __ ____ ____ ____
/ \\/ \/ _ \/ _ )/ _ \
\ / __/ _ \ __/
\__\__/\____/\_____/__/ ____ ___
/ _/ / \ \ / _ \/ _/
/ \_/ / / \ \ __/ \__
\____/____/\_____/_____/____/v1.2.3
```
WebP codec is a library to encode and decode images in WebP format. This package
contains the library that can be used in other programs to add WebP support, as
well as the command line tools 'cwebp' and 'dwebp' to compress and decompress
images respectively.
See https://developers.google.com/speed/webp for details on the image format.
The latest source tree is available at
https://chromium.googlesource.com/webm/libwebp
It is released under the same license as the WebM project. See
https://www.webmproject.org/license/software/ or the "COPYING" file for details.
An additional intellectual property rights grant can be found in the file
PATENTS.
## Building
See the [building documentation](doc/building.md).
## Encoding and Decoding Tools
The examples/ directory contains tools to encode and decode images and
animations, view information about WebP images, and more. See the
[tools documentation](doc/tools.md).
## APIs
See the [APIs documentation](doc/api.md), and API usage examples in the
`examples/` directory.
## Bugs
Please report all bugs to the issue tracker: https://bugs.chromium.org/p/webp
Patches welcome! See [how to contribute](CONTRIBUTING.md).
## Discuss
Email: webp-discuss@webmproject.org
Web: https://groups.google.com/a/webmproject.org/group/webp-discuss

View File

@ -1,257 +0,0 @@
 __ __ ____ ____ ____ __ __ _ __ __
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
\ / __/ _ \ __/ / / (_/ /__
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v1.2.1
Description:
============
WebPMux: set of two libraries 'Mux' and 'Demux' for creation, extraction and
manipulation of an extended format WebP file, which can have features like
color profile, metadata and animation. Reference command-line tools 'webpmux'
and 'vwebp' as well as the WebP container specification
'doc/webp-container-spec.txt' are also provided in this package.
WebP Mux tool:
==============
The examples/ directory contains a tool (webpmux) for manipulating WebP
files. The webpmux tool can be used to create an extended format WebP file and
also to extract or strip relevant data from such a file.
A list of options is available using the -help command line flag:
> webpmux -help
Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT
webpmux -set SET_OPTIONS INPUT -o OUTPUT
webpmux -duration DURATION_OPTIONS [-duration ...]
INPUT -o OUTPUT
webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT
webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]
[-bgcolor BACKGROUND_COLOR] -o OUTPUT
webpmux -info INPUT
webpmux [-h|-help]
webpmux -version
webpmux argument_file_name
GET_OPTIONS:
Extract relevant data:
icc get ICC profile
exif get EXIF metadata
xmp get XMP metadata
frame n get nth frame
SET_OPTIONS:
Set color profile/metadata:
loop LOOP_COUNT set the loop count
icc file.icc set ICC profile
exif file.exif set EXIF metadata
xmp file.xmp set XMP metadata
where: 'file.icc' contains the ICC profile to be set,
'file.exif' contains the EXIF metadata to be set
'file.xmp' contains the XMP metadata to be set
DURATION_OPTIONS:
Set duration of selected frames:
duration set duration for each frames
duration,frame set duration of a particular frame
duration,start,end set duration of frames in the
interval [start,end])
where: 'duration' is the duration in milliseconds
'start' is the start frame index
'end' is the inclusive end frame index
The special 'end' value '0' means: last frame.
STRIP_OPTIONS:
Strip color profile/metadata:
icc strip ICC profile
exif strip EXIF metadata
xmp strip XMP metadata
FRAME_OPTIONS(i):
Create animation:
file_i +di+[xi+yi[+mi[bi]]]
where: 'file_i' is the i'th animation frame (WebP format),
'di' is the pause duration before next frame,
'xi','yi' specify the image offset for this frame,
'mi' is the dispose method for this frame (0 or 1),
'bi' is the blending method for this frame (+b or -b)
LOOP_COUNT:
Number of times to repeat the animation.
Valid range is 0 to 65535 [Default: 0 (infinite)].
BACKGROUND_COLOR:
Background color of the canvas.
A,R,G,B
where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying
the Alpha, Red, Green and Blue component values respectively
[Default: 255,255,255,255]
INPUT & OUTPUT are in WebP format.
Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be
valid.
Note: if a single file name is passed as the argument, the arguments will be
tokenized from this file. The file name must not start with the character '-'.
Visualization tool:
===================
The examples/ directory also contains a tool (vwebp) for viewing WebP files.
It decodes the image and visualizes it using OpenGL. See the libwebp README
for details on building and running this program.
Mux API:
========
The Mux API contains methods for adding data to and reading data from WebP
files. This API currently supports XMP/EXIF metadata, ICC profile and animation.
Other features may be added in subsequent releases.
Example#1 (pseudo code): Creating a WebPMux object with image data, color
profile and XMP metadata.
int copy_data = 0;
WebPMux* mux = WebPMuxNew();
// ... (Prepare image data).
WebPMuxSetImage(mux, &image, copy_data);
// ... (Prepare ICC profile data).
WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data);
// ... (Prepare XMP metadata).
WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data);
// Get data from mux in WebP RIFF format.
WebPMuxAssemble(mux, &output_data);
WebPMuxDelete(mux);
// ... (Consume output_data; e.g. write output_data.bytes to file).
WebPDataClear(&output_data);
Example#2 (pseudo code): Get image and color profile data from a WebP file.
int copy_data = 0;
// ... (Read data from file).
WebPMux* mux = WebPMuxCreate(&data, copy_data);
WebPMuxGetFrame(mux, 1, &image);
// ... (Consume image; e.g. call WebPDecode() to decode the data).
WebPMuxGetChunk(mux, "ICCP", &icc_profile);
// ... (Consume icc_profile).
WebPMuxDelete(mux);
free(data);
For a detailed Mux API reference, please refer to the header file
(src/webp/mux.h).
Demux API:
==========
The Demux API enables extraction of images and extended format data from
WebP files. This API currently supports reading of XMP/EXIF metadata, ICC
profile and animated images. Other features may be added in subsequent
releases.
Code example: Demuxing WebP data to extract all the frames, ICC profile
and EXIF/XMP metadata.
WebPDemuxer* demux = WebPDemux(&webp_data);
uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
// ... (Get information about the features present in the WebP file).
uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS);
// ... (Iterate over all frames).
WebPIterator iter;
if (WebPDemuxGetFrame(demux, 1, &iter)) {
do {
// ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(),
// ... and get other frame properties like width, height, offsets etc.
// ... see 'struct WebPIterator' below for more info).
} while (WebPDemuxNextFrame(&iter));
WebPDemuxReleaseIterator(&iter);
}
// ... (Extract metadata).
WebPChunkIterator chunk_iter;
if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter);
// ... (Consume the ICC profile in 'chunk_iter.chunk').
WebPDemuxReleaseChunkIterator(&chunk_iter);
if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter);
// ... (Consume the EXIF metadata in 'chunk_iter.chunk').
WebPDemuxReleaseChunkIterator(&chunk_iter);
if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter);
// ... (Consume the XMP metadata in 'chunk_iter.chunk').
WebPDemuxReleaseChunkIterator(&chunk_iter);
WebPDemuxDelete(demux);
For a detailed Demux API reference, please refer to the header file
(src/webp/demux.h).
AnimEncoder API:
================
The AnimEncoder API can be used to create animated WebP images.
Code example:
WebPAnimEncoderOptions enc_options;
WebPAnimEncoderOptionsInit(&enc_options);
// ... (Tune 'enc_options' as needed).
WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options);
while(<there are more frames>) {
WebPConfig config;
WebPConfigInit(&config);
// ... (Tune 'config' as needed).
WebPAnimEncoderAdd(enc, frame, duration, &config);
}
WebPAnimEncoderAssemble(enc, webp_data);
WebPAnimEncoderDelete(enc);
// ... (Write the 'webp_data' to a file, or re-mux it further).
For a detailed AnimEncoder API reference, please refer to the header file
(src/webp/mux.h).
AnimDecoder API:
================
This AnimDecoder API allows decoding (possibly) animated WebP images.
Code Example:
WebPAnimDecoderOptions dec_options;
WebPAnimDecoderOptionsInit(&dec_options);
// Tune 'dec_options' as needed.
WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options);
WebPAnimInfo anim_info;
WebPAnimDecoderGetInfo(dec, &anim_info);
for (uint32_t i = 0; i < anim_info.loop_count; ++i) {
while (WebPAnimDecoderHasMoreFrames(dec)) {
uint8_t* buf;
int timestamp;
WebPAnimDecoderGetNext(dec, &buf, &timestamp);
// ... (Render 'buf' based on 'timestamp').
// ... (Do NOT free 'buf', as it is owned by 'dec').
}
WebPAnimDecoderReset(dec);
}
const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec);
// ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data).
WebPAnimDecoderDelete(dec);
For a detailed AnimDecoder API reference, please refer to the header file
(src/webp/demux.h).
Bugs:
=====
Please report all bugs to the issue tracker:
https://bugs.chromium.org/p/webp
Patches welcome! See this page to get started:
http://www.webmproject.org/code/contribute/submitting-patches/
Discuss:
========
Email: webp-discuss@webmproject.org
Web: http://groups.google.com/a/webmproject.org/group/webp-discuss

View File

@ -1,75 +0,0 @@
__ __ ____ ____ ____ __ ____
/ \\/ \ _ \ _ \ _ \ (__)/ __\
\ / __/ _ \ __/ _) \_ \
\__\__/_____/____/_/ /____/____/
Description:
============
This file describes the compilation of libwebp into a JavaScript decoder
using Emscripten and CMake.
- install the Emscripten SDK following the procedure described at:
https://emscripten.org/docs/getting_started/downloads.html#installation-instructions-using-the-emsdk-recommended
After installation, you should have some global variable positioned to the
location of the SDK. In particular, $EMSDK should point to the
top-level directory containing Emscripten tools.
- configure the project 'WEBP_JS' with CMake using:
cd webp_js && \
emcmake cmake -DWEBP_BUILD_WEBP_JS=ON \
../
- compile webp.js using 'emmake make'.
- that's it! Upon completion, you should have the webp.js and
webp.wasm files generated.
The callable JavaScript function is WebPToSDL(), which decodes a raw WebP
bitstream into a canvas. See webp_js/index.html for a simple usage sample
(see below for instructions).
Demo HTML page:
===============
The HTML page webp_js/index.html requires an HTTP server to serve the WebP
image example. It's easy to just use Python for that.
cd webp_js && python -m SimpleHTTPServer 8080
and then navigate to http://localhost:8080 in your favorite browser.
Web-Assembly (WASM) version:
============================
CMakeLists.txt is configured to build the WASM version when using
the option WEBP_BUILD_WEBP_JS=ON. The compilation step will assemble
the files 'webp_wasm.js', 'webp_wasm.wasm' in the webp_js/ directory.
See webp_js/index_wasm.html for a simple demo page using the WASM version
of the library.
You will need a fairly recent version of Emscripten (at least 2.0.18,
latest-upstream is recommended) and of your WASM-enabled browser to run this
version.
Caveat:
=======
- First decoding using the library is usually slower, due to just-in-time
compilation.
- Some versions of llvm produce the following compile error when SSE2 is
enabled.
"Unsupported: %516 = bitcast <8 x i16> %481 to i128
LLVM ERROR: BitCast Instruction not yet supported for integer types larger than 64 bits"
The corresponding Emscripten bug is at:
https://github.com/kripken/emscripten/issues/3788
Therefore, SSE2 optimization is currently disabled in CMakeLists.txt.
- If WEBP_ENABLE_SIMD is set to 1 the JavaScript version (webp.js) will be
disabled as wasm2js does not support SIMD.

View File

@ -105,6 +105,13 @@ model {
sources {
c {
source {
srcDir "sharpyuv"
include "sharpyuv.c"
include "sharpyuv_csp.c"
include "sharpyuv_dsp.c"
include "sharpyuv_gamma.c"
include "sharpyuv_neon.c"
include "sharpyuv_sse2.c"
srcDir "src/dec"
include "alpha_dec.c"
include "buffer_dec.c"

View File

@ -45,7 +45,7 @@ if(WEBP_USE_THREAD)
}
" FLAG_HAVE_PTHREAD_PRIO_INHERIT)
set(HAVE_PTHREAD_PRIO_INHERIT ${FLAG_HAVE_PTHREAD_PRIO_INHERIT})
list(APPEND WEBP_DEP_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
list(APPEND WEBP_DEP_LIBRARIES Threads::Threads)
endif()
set(WEBP_USE_THREAD ${Threads_FOUND})
endif()
@ -74,6 +74,11 @@ endif()
set(WEBP_DEP_IMG_LIBRARIES)
set(WEBP_DEP_IMG_INCLUDE_DIRS)
foreach(I_LIB PNG JPEG TIFF)
# Disable tiff when compiling in static mode as it is failing on Ubuntu.
if(WEBP_LINK_STATIC AND ${I_LIB} STREQUAL "TIFF")
message("TIFF is disabled when statically linking.")
continue()
endif()
find_package(${I_LIB})
set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND})
if(${I_LIB}_FOUND)

View File

@ -1,6 +1,6 @@
AC_INIT([libwebp], [1.2.1],
AC_INIT([libwebp], [1.2.3],
[https://bugs.chromium.org/p/webp],,
[http://developers.google.com/speed/webp])
[https://developers.google.com/speed/webp])
AC_CANONICAL_HOST
AC_PREREQ([2.60])
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
@ -9,7 +9,8 @@ dnl === automake >= 1.12 requires this for 'unusual archivers' support.
dnl === it must occur before LT_INIT (AC_PROG_LIBTOOL).
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AC_PROG_LIBTOOL
dnl === AC_PROG_LIBTOOL is deprecated.
m4_ifdef([LT_INIT], [LT_INIT], [AC_PROG_LIBTOOL])
AC_PROG_SED
AM_PROG_CC_C_O
@ -27,7 +28,8 @@ AC_ARG_ENABLE([everything],
AS_HELP_STRING([--enable-everything],
[Enable all optional targets. These can still be
disabled with --disable-target]),
[SET_IF_UNSET([enable_libwebpdecoder], [$enableval])
[SET_IF_UNSET([enable_libsharpyuv], [$enableval])
SET_IF_UNSET([enable_libwebpdecoder], [$enableval])
SET_IF_UNSET([enable_libwebpdemux], [$enableval])
SET_IF_UNSET([enable_libwebpextras], [$enableval])
SET_IF_UNSET([enable_libwebpmux], [$enableval])])
@ -751,6 +753,7 @@ AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([src/webp/config.h])
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile \
examples/Makefile extras/Makefile imageio/Makefile \
sharpyuv/Makefile \
src/dec/Makefile src/enc/Makefile src/dsp/Makefile \
src/demux/Makefile src/mux/Makefile \
src/utils/Makefile \

View File

@ -1,29 +0,0 @@
Generate libwebp Container Spec Docs from Text Source
=====================================================
HTML generation requires kramdown [1], easily installed as a
rubygem [2]. Rubygems installation should satisfy dependencies
automatically.
[1]: http://kramdown.rubyforge.org/
[2]: http://rubygems.org/
HTML generation can then be done from the project root:
$ kramdown doc/webp-container-spec.txt --template doc/template.html > \
doc/output/webp-container-spec.html
kramdown can optionally syntax highlight code blocks, using CodeRay [3],
a dependency of kramdown that rubygems will install automatically. The
following will apply inline CSS styling; an external stylesheet is not
needed.
$ kramdown doc/webp-lossless-bitstream-spec.txt --template \
doc/template.html --coderay-css style --coderay-line-numbers ' ' \
--coderay-default-lang c > \
doc/output/webp-lossless-bitstream-spec.html
Optimally, use kramdown 0.13.7 or newer if syntax highlighting desired.
[3]: http://coderay.rubychan.de/

385
doc/api.md Normal file
View File

@ -0,0 +1,385 @@
# WebP APIs
## Encoding API
The main encoding functions are available in the header src/webp/encode.h
The ready-to-use ones are:
```c
size_t WebPEncodeRGB(const uint8_t* rgb, int width, int height, int stride,
float quality_factor, uint8_t** output);
size_t WebPEncodeBGR(const uint8_t* bgr, int width, int height, int stride,
float quality_factor, uint8_t** output);
size_t WebPEncodeRGBA(const uint8_t* rgba, int width, int height, int stride,
float quality_factor, uint8_t** output);
size_t WebPEncodeBGRA(const uint8_t* bgra, int width, int height, int stride,
float quality_factor, uint8_t** output);
```
They will convert raw RGB samples to a WebP data. The only control supplied is
the quality factor.
There are some variants for using the lossless format:
```c
size_t WebPEncodeLosslessRGB(const uint8_t* rgb, int width, int height,
int stride, uint8_t** output);
size_t WebPEncodeLosslessBGR(const uint8_t* bgr, int width, int height,
int stride, uint8_t** output);
size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, int width, int height,
int stride, uint8_t** output);
size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, int width, int height,
int stride, uint8_t** output);
```
Of course in this case, no quality factor is needed since the compression occurs
without loss of the input values, at the expense of larger output sizes.
### Advanced encoding API
A more advanced API is based on the WebPConfig and WebPPicture structures.
WebPConfig contains the encoding settings and is not tied to a particular
picture. WebPPicture contains input data, on which some WebPConfig will be used
for compression. The encoding flow looks like:
```c
#include <webp/encode.h>
// Setup a config, starting form a preset and tuning some additional
// parameters
WebPConfig config;
if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) {
return 0; // version error
}
// ... additional tuning
config.sns_strength = 90;
config.filter_sharpness = 6;
config_error = WebPValidateConfig(&config); // not mandatory, but useful
// Setup the input data
WebPPicture pic;
if (!WebPPictureInit(&pic)) {
return 0; // version error
}
pic.width = width;
pic.height = height;
// allocated picture of dimension width x height
if (!WebPPictureAlloc(&pic)) {
return 0; // memory error
}
// at this point, 'pic' has been initialized as a container,
// and can receive the Y/U/V samples.
// Alternatively, one could use ready-made import functions like
// WebPPictureImportRGB(), which will take care of memory allocation.
// In any case, past this point, one will have to call
// WebPPictureFree(&pic) to reclaim memory.
// Set up a byte-output write method. WebPMemoryWriter, for instance.
WebPMemoryWriter wrt;
WebPMemoryWriterInit(&wrt); // initialize 'wrt'
pic.writer = MyFileWriter;
pic.custom_ptr = my_opaque_structure_to_make_MyFileWriter_work;
// Compress!
int ok = WebPEncode(&config, &pic); // ok = 0 => error occurred!
WebPPictureFree(&pic); // must be called independently of the 'ok' result.
// output data should have been handled by the writer at that point.
// -> compressed data is the memory buffer described by wrt.mem / wrt.size
// deallocate the memory used by compressed data
WebPMemoryWriterClear(&wrt);
```
## Decoding API
This is mainly just one function to call:
```c
#include "webp/decode.h"
uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size,
int* width, int* height);
```
Please have a look at the file src/webp/decode.h for the details. There are
variants for decoding in BGR/RGBA/ARGB/BGRA order, along with decoding to raw
Y'CbCr samples. One can also decode the image directly into a pre-allocated
buffer.
To detect a WebP file and gather the picture's dimensions, the function:
```c
int WebPGetInfo(const uint8_t* data, size_t data_size,
int* width, int* height);
```
is supplied. No decoding is involved when using it.
### Incremental decoding API
In the case when data is being progressively transmitted, pictures can still be
incrementally decoded using a slightly more complicated API. Decoder state is
stored into an instance of the WebPIDecoder object. This object can be created
with the purpose of decoding either RGB or Y'CbCr samples. For instance:
```c
WebPDecBuffer buffer;
WebPInitDecBuffer(&buffer);
buffer.colorspace = MODE_BGR;
...
WebPIDecoder* idec = WebPINewDecoder(&buffer);
```
As data is made progressively available, this incremental-decoder object can be
used to decode the picture further. There are two (mutually exclusive) ways to
pass freshly arrived data:
either by appending the fresh bytes:
```c
WebPIAppend(idec, fresh_data, size_of_fresh_data);
```
or by just mentioning the new size of the transmitted data:
```c
WebPIUpdate(idec, buffer, size_of_transmitted_buffer);
```
Note that 'buffer' can be modified between each call to WebPIUpdate, in
particular when the buffer is resized to accommodate larger data.
These functions will return the decoding status: either VP8_STATUS_SUSPENDED if
decoding is not finished yet or VP8_STATUS_OK when decoding is done. Any other
status is an error condition.
The 'idec' object must always be released (even upon an error condition) by
calling: WebPDelete(idec).
To retrieve partially decoded picture samples, one must use the corresponding
method: WebPIDecGetRGB or WebPIDecGetYUVA. It will return the last displayable
pixel row.
Lastly, note that decoding can also be performed into a pre-allocated pixel
buffer. This buffer must be passed when creating a WebPIDecoder, calling
WebPINewRGB() or WebPINewYUVA().
Please have a look at the src/webp/decode.h header for further details.
### Advanced Decoding API
WebP decoding supports an advanced API which provides on-the-fly cropping and
rescaling, something of great usefulness on memory-constrained environments like
mobile phones. Basically, the memory usage will scale with the output's size,
not the input's, when one only needs a quick preview or a zoomed in portion of
an otherwise too-large picture. Some CPU can be saved too, incidentally.
```c
// A) Init a configuration object
WebPDecoderConfig config;
CHECK(WebPInitDecoderConfig(&config));
// B) optional: retrieve the bitstream's features.
CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
// C) Adjust 'config' options, if needed
config.options.no_fancy_upsampling = 1;
config.options.use_scaling = 1;
config.options.scaled_width = scaledWidth();
config.options.scaled_height = scaledHeight();
// etc.
// D) Specify 'config' output options for specifying output colorspace.
// Optionally the external image decode buffer can also be specified.
config.output.colorspace = MODE_BGRA;
// Optionally, the config.output can be pointed to an external buffer as
// well for decoding the image. This externally supplied memory buffer
// should be big enough to store the decoded picture.
config.output.u.RGBA.rgba = (uint8_t*) memory_buffer;
config.output.u.RGBA.stride = scanline_stride;
config.output.u.RGBA.size = total_size_of_the_memory_buffer;
config.output.is_external_memory = 1;
// E) Decode the WebP image. There are two variants w.r.t decoding image.
// The first one (E.1) decodes the full image and the second one (E.2) is
// used to incrementally decode the image using small input buffers.
// Any one of these steps can be used to decode the WebP image.
// E.1) Decode full image.
CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK);
// E.2) Decode image incrementally.
WebPIDecoder* const idec = WebPIDecode(NULL, NULL, &config);
CHECK(idec != NULL);
while (bytes_remaining > 0) {
VP8StatusCode status = WebPIAppend(idec, input, bytes_read);
if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) {
bytes_remaining -= bytes_read;
} else {
break;
}
}
WebPIDelete(idec);
// F) Decoded image is now in config.output (and config.output.u.RGBA).
// It can be saved, displayed or otherwise processed.
// G) Reclaim memory allocated in config's object. It's safe to call
// this function even if the memory is external and wasn't allocated
// by WebPDecode().
WebPFreeDecBuffer(&config.output);
```
## Webp Mux
WebPMux is a set of two libraries 'Mux' and 'Demux' for creation, extraction and
manipulation of an extended format WebP file, which can have features like color
profile, metadata and animation. Reference command-line tools `webpmux` and
`vwebp` as well as the WebP container specification
'doc/webp-container-spec.txt' are also provided in this package, see the
[tools documentation](tools.md).
### Mux API
The Mux API contains methods for adding data to and reading data from WebP
files. This API currently supports XMP/EXIF metadata, ICC profile and animation.
Other features may be added in subsequent releases.
Example#1 (pseudo code): Creating a WebPMux object with image data, color
profile and XMP metadata.
```c
int copy_data = 0;
WebPMux* mux = WebPMuxNew();
// ... (Prepare image data).
WebPMuxSetImage(mux, &image, copy_data);
// ... (Prepare ICC profile data).
WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data);
// ... (Prepare XMP metadata).
WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data);
// Get data from mux in WebP RIFF format.
WebPMuxAssemble(mux, &output_data);
WebPMuxDelete(mux);
// ... (Consume output_data; e.g. write output_data.bytes to file).
WebPDataClear(&output_data);
```
Example#2 (pseudo code): Get image and color profile data from a WebP file.
```c
int copy_data = 0;
// ... (Read data from file).
WebPMux* mux = WebPMuxCreate(&data, copy_data);
WebPMuxGetFrame(mux, 1, &image);
// ... (Consume image; e.g. call WebPDecode() to decode the data).
WebPMuxGetChunk(mux, "ICCP", &icc_profile);
// ... (Consume icc_profile).
WebPMuxDelete(mux);
free(data);
```
For a detailed Mux API reference, please refer to the header file
(src/webp/mux.h).
### Demux API
The Demux API enables extraction of images and extended format data from WebP
files. This API currently supports reading of XMP/EXIF metadata, ICC profile and
animated images. Other features may be added in subsequent releases.
Code example: Demuxing WebP data to extract all the frames, ICC profile and
EXIF/XMP metadata.
```c
WebPDemuxer* demux = WebPDemux(&webp_data);
uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
// ... (Get information about the features present in the WebP file).
uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS);
// ... (Iterate over all frames).
WebPIterator iter;
if (WebPDemuxGetFrame(demux, 1, &iter)) {
do {
// ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(),
// ... and get other frame properties like width, height, offsets etc.
// ... see 'struct WebPIterator' below for more info).
} while (WebPDemuxNextFrame(&iter));
WebPDemuxReleaseIterator(&iter);
}
// ... (Extract metadata).
WebPChunkIterator chunk_iter;
if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter);
// ... (Consume the ICC profile in 'chunk_iter.chunk').
WebPDemuxReleaseChunkIterator(&chunk_iter);
if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter);
// ... (Consume the EXIF metadata in 'chunk_iter.chunk').
WebPDemuxReleaseChunkIterator(&chunk_iter);
if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter);
// ... (Consume the XMP metadata in 'chunk_iter.chunk').
WebPDemuxReleaseChunkIterator(&chunk_iter);
WebPDemuxDelete(demux);
```
For a detailed Demux API reference, please refer to the header file
(src/webp/demux.h).
## AnimEncoder API
The AnimEncoder API can be used to create animated WebP images.
Code example:
```c
WebPAnimEncoderOptions enc_options;
WebPAnimEncoderOptionsInit(&enc_options);
// ... (Tune 'enc_options' as needed).
WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options);
while(<there are more frames>) {
WebPConfig config;
WebPConfigInit(&config);
// ... (Tune 'config' as needed).
WebPAnimEncoderAdd(enc, frame, duration, &config);
}
WebPAnimEncoderAssemble(enc, webp_data);
WebPAnimEncoderDelete(enc);
// ... (Write the 'webp_data' to a file, or re-mux it further).
```
For a detailed AnimEncoder API reference, please refer to the header file
(src/webp/mux.h).
## AnimDecoder API
This AnimDecoder API allows decoding (possibly) animated WebP images.
Code Example:
```c
WebPAnimDecoderOptions dec_options;
WebPAnimDecoderOptionsInit(&dec_options);
// Tune 'dec_options' as needed.
WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options);
WebPAnimInfo anim_info;
WebPAnimDecoderGetInfo(dec, &anim_info);
for (uint32_t i = 0; i < anim_info.loop_count; ++i) {
while (WebPAnimDecoderHasMoreFrames(dec)) {
uint8_t* buf;
int timestamp;
WebPAnimDecoderGetNext(dec, &buf, &timestamp);
// ... (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).

213
doc/building.md Normal file
View File

@ -0,0 +1,213 @@
# Building
## Windows build
By running:
```batch
nmake /f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output
```
the directory `output\release-static\(x64|x86)\bin` will contain the tools
cwebp.exe and dwebp.exe. The directory `output\release-static\(x64|x86)\lib`
will contain the libwebp static library. The target architecture (x86/x64) is
detected by Makefile.vc from the Visual Studio compiler (cl.exe) available in
the system path.
## Unix build using makefile.unix
On platforms with GNU tools installed (gcc and make), running
```shell
make -f makefile.unix
```
will build the binaries examples/cwebp and examples/dwebp, along with the static
library src/libwebp.a. No system-wide installation is supplied, as this is a
simple alternative to the full installation system based on the autoconf tools
(see below). Please refer to makefile.unix for additional details and
customizations.
## Using autoconf tools
Prerequisites: a compiler (e.g., gcc), make, autoconf, automake, libtool.
On a Debian-like system the following should install everything you need for a
minimal build:
```shell
$ sudo apt-get install gcc make autoconf automake libtool
```
When building from git sources, you will need to run autogen.sh to generate the
configure script.
```shell
./configure
make
make install
```
should be all you need to have the following files
```
/usr/local/include/webp/decode.h
/usr/local/include/webp/encode.h
/usr/local/include/webp/types.h
/usr/local/lib/libwebp.*
/usr/local/bin/cwebp
/usr/local/bin/dwebp
```
installed.
Note: A decode-only library, libwebpdecoder, is available using the
`--enable-libwebpdecoder` flag. The encode library is built separately and can
be installed independently using a minor modification in the corresponding
Makefile.am configure files (see comments there). See `./configure --help` for
more options.
## Building for MIPS Linux
MIPS Linux toolchain stable available releases can be found at:
https://community.imgtec.com/developers/mips/tools/codescape-mips-sdk/available-releases/
```shell
# Add toolchain to PATH
export PATH=$PATH:/path/to/toolchain/bin
# 32-bit build for mips32r5 (p5600)
HOST=mips-mti-linux-gnu
MIPS_CFLAGS="-O3 -mips32r5 -mabi=32 -mtune=p5600 -mmsa -mfp64 \
-msched-weight -mload-store-pairs -fPIE"
MIPS_LDFLAGS="-mips32r5 -mabi=32 -mmsa -mfp64 -pie"
# 64-bit build for mips64r6 (i6400)
HOST=mips-img-linux-gnu
MIPS_CFLAGS="-O3 -mips64r6 -mabi=64 -mtune=i6400 -mmsa -mfp64 \
-msched-weight -mload-store-pairs -fPIE"
MIPS_LDFLAGS="-mips64r6 -mabi=64 -mmsa -mfp64 -pie"
./configure --host=${HOST} --build=`config.guess` \
CC="${HOST}-gcc -EL" \
CFLAGS="$MIPS_CFLAGS" \
LDFLAGS="$MIPS_LDFLAGS"
make
make install
```
## CMake
With CMake, you can compile libwebp, cwebp, dwebp, gif2webp, img2webp, webpinfo
and the JS bindings.
Prerequisites: a compiler (e.g., gcc with autotools) and CMake.
On a Debian-like system the following should install everything you need for a
minimal build:
```shell
$ sudo apt-get install build-essential cmake
```
When building from git sources, you will need to run cmake to generate the
makefiles.
```shell
mkdir build && cd build && cmake ../
make
make install
```
If you also want any of the executables, you will need to enable them through
CMake, e.g.:
```shell
cmake -DWEBP_BUILD_CWEBP=ON -DWEBP_BUILD_DWEBP=ON ../
```
or through your favorite interface (like ccmake or cmake-qt-gui).
Use option `-DWEBP_UNICODE=ON` for Unicode support on Windows (with chcp 65001).
Finally, once installed, you can also use WebP in your CMake project by doing:
```cmake
find_package(WebP)
```
which will define the CMake variables WebP_INCLUDE_DIRS and WebP_LIBRARIES.
## Gradle
The support for Gradle is minimal: it only helps you compile libwebp, cwebp and
dwebp and webpmux_example.
Prerequisites: a compiler (e.g., gcc with autotools) and gradle.
On a Debian-like system the following should install everything you need for a
minimal build:
```shell
$ sudo apt-get install build-essential gradle
```
When building from git sources, you will need to run the Gradle wrapper with the
appropriate target, e.g. :
```shell
./gradlew buildAllExecutables
```
## SWIG bindings
To generate language bindings from swig/libwebp.swig at least swig-1.3
(http://www.swig.org) is required.
Currently the following functions are mapped:
Decode:
```
WebPGetDecoderVersion
WebPGetInfo
WebPDecodeRGBA
WebPDecodeARGB
WebPDecodeBGRA
WebPDecodeBGR
WebPDecodeRGB
```
Encode:
```
WebPGetEncoderVersion
WebPEncodeRGBA
WebPEncodeBGRA
WebPEncodeRGB
WebPEncodeBGR
WebPEncodeLosslessRGBA
WebPEncodeLosslessBGRA
WebPEncodeLosslessRGB
WebPEncodeLosslessBGR
```
See also the [swig documentation](../swig/README.md) for more detailed build
instructions and usage examples.
### Java bindings
To build the swig-generated JNI wrapper code at least JDK-1.5 (or equivalent) is
necessary for enum support. The output is intended to be a shared object / DLL
that can be loaded via `System.loadLibrary("webp_jni")`.
### Python bindings
To build the swig-generated Python extension code at least Python 2.6 is
required. Python < 2.6 may build with some minor changes to libwebp.swig or the
generated code, but is untested.
## Javascript decoder
Libwebp can be compiled into a JavaScript decoder using Emscripten and CMake.
See the [corresponding documentation](../README.md)

26
doc/specs_generation.md Normal file
View File

@ -0,0 +1,26 @@
# Generate libwebp Container Spec Docs from Text Source
HTML generation requires [kramdown](https://kramdown.gettalong.org/), easily
installed as a [rubygem](https://rubygems.org/). Rubygems installation should
satisfy dependencies automatically.
HTML generation can then be done from the project root:
```shell
$ kramdown doc/webp-container-spec.txt --template doc/template.html > \
doc/output/webp-container-spec.html
```
kramdown can optionally syntax highlight code blocks, using
[CodeRay](https://github.com/rubychan/coderay), a dependency of kramdown that
rubygems will install automatically. The following will apply inline CSS
styling; an external stylesheet is not needed.
```shell
$ kramdown doc/webp-lossless-bitstream-spec.txt --template \
doc/template.html --coderay-css style --coderay-line-numbers ' ' \
--coderay-default-lang c > \
doc/output/webp-lossless-bitstream-spec.html
```
Optimally, use kramdown 0.13.7 or newer if syntax highlighting desired.

512
doc/tools.md Normal file
View File

@ -0,0 +1,512 @@
# WebP tools
## Encoding tool
The examples/ directory contains tools for encoding (cwebp) and decoding (dwebp)
images.
The easiest use should look like:
```shell
cwebp input.png -q 80 -o output.webp
```
which will convert the input file to a WebP file using a quality factor of 80 on
a 0->100 scale (0 being the lowest quality, 100 being the best. Default value is
75).
You might want to try the `-lossless` flag too, which will compress the source
(in RGBA format) without any loss. The `-q` quality parameter will in this case
control the amount of processing time spent trying to make the output file as
small as possible.
A longer list of options is available using the `-longhelp` command line flag:
```shell
> cwebp -longhelp
Usage:
cwebp [-preset <...>] [options] in_file [-o out_file]
```
If input size (-s) for an image is not specified, it is assumed to be a PNG,
JPEG, TIFF or WebP file. Note: Animated PNG and WebP files are not supported.
Options:
```
-h / -help ............. short help
-H / -longhelp ......... long help
-q <float> ............. quality factor (0:small..100:big), default=75
-alpha_q <int> ......... transparency-compression quality (0..100),
default=100
-preset <string> ....... preset setting, one of:
default, photo, picture,
drawing, icon, text
-preset must come first, as it overwrites other parameters
-z <int> ............... activates lossless preset with given
level in [0:fast, ..., 9:slowest]
-m <int> ............... compression method (0=fast, 6=slowest), default=4
-segments <int> ........ number of segments to use (1..4), default=4
-size <int> ............ target size (in bytes)
-psnr <float> .......... target PSNR (in dB. typically: 42)
-s <int> <int> ......... input size (width x height) for YUV
-sns <int> ............. spatial noise shaping (0:off, 100:max), default=50
-f <int> ............... filter strength (0=off..100), default=60
-sharpness <int> ....... filter sharpness (0:most .. 7:least sharp), default=0
-strong ................ use strong filter instead of simple (default)
-nostrong .............. use simple filter instead of strong
-sharp_yuv ............. use sharper (and slower) RGB->YUV conversion
-partition_limit <int> . limit quality to fit the 512k limit on
the first partition (0=no degradation ... 100=full)
-pass <int> ............ analysis pass number (1..10)
-qrange <min> <max> .... specifies the permissible quality range
(default: 0 100)
-crop <x> <y> <w> <h> .. crop picture with the given rectangle
-resize <w> <h> ........ resize picture (*after* any cropping)
-mt .................... use multi-threading if available
-low_memory ............ reduce memory usage (slower encoding)
-map <int> ............. print map of extra info
-print_psnr ............ prints averaged PSNR distortion
-print_ssim ............ prints averaged SSIM distortion
-print_lsim ............ prints local-similarity distortion
-d <file.pgm> .......... dump the compressed output (PGM file)
-alpha_method <int> .... transparency-compression method (0..1), default=1
-alpha_filter <string> . predictive filtering for alpha plane,
one of: none, fast (default) or best
-exact ................. preserve RGB values in transparent area, default=off
-blend_alpha <hex> ..... blend colors against background color
expressed as RGB values written in
hexadecimal, e.g. 0xc0e0d0 for red=0xc0
green=0xe0 and blue=0xd0
-noalpha ............... discard any transparency information
-lossless .............. encode image losslessly, default=off
-near_lossless <int> ... use near-lossless image
preprocessing (0..100=off), default=100
-hint <string> ......... specify image characteristics hint,
one of: photo, picture or graph
-metadata <string> ..... comma separated list of metadata to
copy from the input to the output if present.
Valid values: all, none (default), exif, icc, xmp
-short ................. condense printed message
-quiet ................. don't print anything
-version ............... print version number and exit
-noasm ................. disable all assembly optimizations
-v ..................... verbose, e.g. print encoding/decoding times
-progress .............. report encoding progress
```
Experimental Options:
```
-jpeg_like ............. roughly match expected JPEG size
-af .................... auto-adjust filter strength
-pre <int> ............. pre-processing filter
```
The main options you might want to try in order to further tune the visual
quality are:
-preset -sns -f -m
Namely:
* `preset` will set up a default encoding configuration targeting a particular
type of input. It should appear first in the list of options, so that
subsequent options can take effect on top of this preset. Default value is
'default'.
* `sns` will progressively turn on (when going from 0 to 100) some additional
visual optimizations (like: segmentation map re-enforcement). This option
will balance the bit allocation differently. It tries to take bits from the
"easy" parts of the picture and use them in the "difficult" ones instead.
Usually, raising the sns value (at fixed -q value) leads to larger files,
but with better quality. Typical value is around '75'.
* `f` option directly links to the filtering strength used by the codec's
in-loop processing. The higher the value, the smoother the highly-compressed
area will look. This is particularly useful when aiming at very small files.
Typical values are around 20-30. Note that using the option
-strong/-nostrong will change the type of filtering. Use "-f 0" to turn
filtering off.
* `m` controls the trade-off between encoding speed and quality. Default is 4.
You can try -m 5 or -m 6 to explore more (time-consuming) encoding
possibilities. A lower value will result in faster encoding at the expense
of quality.
## Decoding tool
There is a decoding sample in examples/dwebp.c which will take a .webp file and
decode it to a PNG image file (amongst other formats). This is simply to
demonstrate the use of the API. You can verify the file test.webp decodes to
exactly the same as test_ref.ppm by using:
```shell
cd examples
./dwebp test.webp -ppm -o test.ppm
diff test.ppm test_ref.ppm
```
The full list of options is available using -h:
```shell
> dwebp -h
Usage: dwebp in_file [options] [-o out_file]
```
Decodes the WebP image file to PNG format [Default]. Note: Animated WebP files
are not supported.
Use following options to convert into alternate image formats:
```
-pam ......... save the raw RGBA samples as a color PAM
-ppm ......... save the raw RGB samples as a color PPM
-bmp ......... save as uncompressed BMP format
-tiff ........ save as uncompressed TIFF format
-pgm ......... save the raw YUV samples as a grayscale PGM
file with IMC4 layout
-yuv ......... save the raw YUV samples in flat layout
```
Other options are:
```
-version ..... print version number and exit
-nofancy ..... don't use the fancy YUV420 upscaler
-nofilter .... disable in-loop filtering
-nodither .... disable dithering
-dither <d> .. dithering strength (in 0..100)
-alpha_dither use alpha-plane dithering if needed
-mt .......... use multi-threading
-crop <x> <y> <w> <h> ... crop output with the given rectangle
-resize <w> <h> ......... resize output (*after* any cropping)
-flip ........ flip the output vertically
-alpha ....... only save the alpha plane
-incremental . use incremental decoding (useful for tests)
-h ........... this help message
-v ........... verbose (e.g. print encoding/decoding times)
-quiet ....... quiet mode, don't print anything
-noasm ....... disable all assembly optimizations
```
## WebP file analysis tool
`webpinfo` can be used to print out the chunk level structure and bitstream
header information of WebP files. It can also check if the files are of valid
WebP format.
Usage:
```shell
webpinfo [options] in_files
```
Note: there could be multiple input files; options must come before input files.
Options:
```
-version ........... Print version number and exit.
-quiet ............. Do not show chunk parsing information.
-diag .............. Show parsing error diagnosis.
-summary ........... Show chunk stats summary.
-bitstream_info .... Parse bitstream header.
```
## Visualization tool
There's a little self-serve visualization tool called 'vwebp' under the
examples/ directory. It uses OpenGL to open a simple drawing window and show a
decoded WebP file. It's not yet integrated in the automake build system, but you
can try to manually compile it using the recommendations below.
Usage:
```shell
vwebp in_file [options]
```
Decodes the WebP image file and visualize it using OpenGL
Options are:
```
-version ..... print version number and exit
-noicc ....... don't use the icc profile if present
-nofancy ..... don't use the fancy YUV420 upscaler
-nofilter .... disable in-loop filtering
-dither <int> dithering strength (0..100), default=50
-noalphadither disable alpha plane dithering
-usebgcolor .. display background color
-mt .......... use multi-threading
-info ........ print info
-h ........... this help message
```
Keyboard shortcuts:
```
'c' ................ toggle use of color profile
'b' ................ toggle background color display
'i' ................ overlay file information
'd' ................ disable blending & disposal (debug)
'q' / 'Q' / ESC .... quit
```
### Building
Prerequisites:
1. OpenGL & OpenGL Utility Toolkit (GLUT)
Linux: `sudo apt-get install freeglut3-dev mesa-common-dev`
Mac + Xcode: These libraries should be available in the OpenGL / GLUT
frameworks.
Windows: http://freeglut.sourceforge.net/index.php#download
2. (Optional) qcms (Quick Color Management System)
1. Download qcms from Mozilla / Chromium:
https://hg.mozilla.org/mozilla-central/file/0e7639e3bdfb/gfx/qcms
https://source.chromium.org/chromium/chromium/src/+/main:third_party/qcms/;drc=d4a2f8e1ed461d8fc05ed88d1ae2dc94c9773825
2. Build and archive the source files as libqcms.a / qcms.lib
3. Update makefile.unix / Makefile.vc
1. Define WEBP_HAVE_QCMS
2. Update include / library paths to reference the qcms directory.
Build using makefile.unix / Makefile.vc:
```shell
$ make -f makefile.unix examples/vwebp
> nmake /f Makefile.vc CFG=release-static \
../obj/x64/release-static/bin/vwebp.exe
```
## Animation creation tool
The utility `img2webp` can turn a sequence of input images (PNG, JPEG, ...) into
an animated WebP file. It offers fine control over duration, encoding modes,
etc.
Usage:
```shell
img2webp [file_options] [[frame_options] frame_file]...
```
File-level options (only used at the start of compression):
```
-min_size ............ minimize size
-loop <int> .......... loop count (default: 0, = infinite loop)
-kmax <int> .......... maximum number of frame between key-frames
(0=only keyframes)
-kmin <int> .......... minimum number of frame between key-frames
(0=disable key-frames altogether)
-mixed ............... use mixed lossy/lossless automatic mode
-v ................... verbose mode
-h ................... this help
-version ............. print version number and exit
```
Per-frame options (only used for subsequent images input):
```
-d <int> ............. frame duration in ms (default: 100)
-lossless ........... use lossless mode (default)
-lossy ... ........... use lossy mode
-q <float> ........... quality
-m <int> ............. method to use
```
example: `img2webp -loop 2 in0.png -lossy in1.jpg -d 80 in2.tiff -o out.webp`
Note: if a single file name is passed as the argument, the arguments will be
tokenized from this file. The file name must not start with the character '-'.
## Animated GIF conversion
Animated GIF files can be converted to WebP files with animation using the
gif2webp utility available under examples/. The files can then be viewed using
vwebp.
Usage:
```shell
gif2webp [options] gif_file -o webp_file
```
Options:
```
-h / -help ............. this help
-lossy ................. encode image using lossy compression
-mixed ................. for each frame in the image, pick lossy
or lossless compression heuristically
-q <float> ............. quality factor (0:small..100:big)
-m <int> ............... compression method (0=fast, 6=slowest)
-min_size .............. minimize output size (default:off)
lossless compression by default; can be
combined with -q, -m, -lossy or -mixed
options
-kmin <int> ............ min distance between key frames
-kmax <int> ............ max distance between key frames
-f <int> ............... filter strength (0=off..100)
-metadata <string> ..... comma separated list of metadata to
copy from the input to the output if present
Valid values: all, none, icc, xmp (default)
-loop_compatibility .... use compatibility mode for Chrome
version prior to M62 (inclusive)
-mt .................... use multi-threading if available
-version ............... print version number and exit
-v ..................... verbose
-quiet ................. don't print anything
```
### Building
With the libgif development files installed, gif2webp can be built using
makefile.unix:
```shell
$ make -f makefile.unix examples/gif2webp
```
or using autoconf:
```shell
$ ./configure --enable-everything
$ make
```
## Comparison of animated images
Test utility anim_diff under examples/ can be used to compare two animated
images (each can be GIF or WebP).
Usage:
```shell
anim_diff <image1> <image2> [options]
```
Options:
```
-dump_frames <folder> dump decoded frames in PAM format
-min_psnr <float> ... minimum per-frame PSNR
-raw_comparison ..... if this flag is not used, RGB is
premultiplied before comparison
-max_diff <int> ..... maximum allowed difference per channel
between corresponding pixels in subsequent
frames
-h .................. this help
-version ............ print version number and exit
```
### Building
With the libgif development files installed, anim_diff can be built using
makefile.unix:
```shell
$ make -f makefile.unix examples/anim_diff
```
or using autoconf:
```shell
$ ./configure --enable-everything
$ make
```
## WebP Mux tool
The examples/ directory contains a tool (webpmux) for manipulating WebP files.
The webpmux tool can be used to create an extended format WebP file and also to
extract or strip relevant data from such a file.
A list of options is available using the -help command line flag:
```shell
> webpmux -help
Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT
webpmux -set SET_OPTIONS INPUT -o OUTPUT
webpmux -duration DURATION_OPTIONS [-duration ...]
INPUT -o OUTPUT
webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT
webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]
[-bgcolor BACKGROUND_COLOR] -o OUTPUT
webpmux -info INPUT
webpmux [-h|-help]
webpmux -version
webpmux argument_file_name
GET_OPTIONS:
Extract relevant data:
icc get ICC profile
exif get EXIF metadata
xmp get XMP metadata
frame n get nth frame
SET_OPTIONS:
Set color profile/metadata/parameters:
loop LOOP_COUNT set the loop count
bgcolor BACKGROUND_COLOR set the animation background color
icc file.icc set ICC profile
exif file.exif set EXIF metadata
xmp file.xmp set XMP metadata
where: 'file.icc' contains the ICC profile to be set,
'file.exif' contains the EXIF metadata to be set
'file.xmp' contains the XMP metadata to be set
DURATION_OPTIONS:
Set duration of selected frames:
duration set duration for all frames
duration,frame set duration of a particular frame
duration,start,end set duration of frames in the
interval [start,end])
where: 'duration' is the duration in milliseconds
'start' is the start frame index
'end' is the inclusive end frame index
The special 'end' value '0' means: last frame.
STRIP_OPTIONS:
Strip color profile/metadata:
icc strip ICC profile
exif strip EXIF metadata
xmp strip XMP metadata
FRAME_OPTIONS(i):
Create animation:
file_i +di[+xi+yi[+mi[bi]]]
where: 'file_i' is the i'th animation frame (WebP format),
'di' is the pause duration before next frame,
'xi','yi' specify the image offset for this frame,
'mi' is the dispose method for this frame (0 or 1),
'bi' is the blending method for this frame (+b or -b)
LOOP_COUNT:
Number of times to repeat the animation.
Valid range is 0 to 65535 [Default: 0 (infinite)].
BACKGROUND_COLOR:
Background color of the canvas.
A,R,G,B
where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying
the Alpha, Red, Green and Blue component values respectively
[Default: 255,255,255,255]
INPUT & OUTPUT are in WebP format.
Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be
valid.
Note: if a single file name is passed as the argument, the arguments will be
tokenized from this file. The file name must not start with the character '-'.
```

View File

@ -2,10 +2,10 @@
Although you may be viewing an alternate representation, this document
is sourced in Markdown, a light-duty markup scheme, and is optimized for
the [kramdown](http://kramdown.rubyforge.org/) transformer.
the [kramdown](https://kramdown.gettalong.org/) transformer.
See the accompanying README. External link targets are referenced at the
end of this file.
See the accompanying specs_generation.md. External link targets are referenced
at the end of this file.
-->
@ -36,7 +36,7 @@ for:
* **Lossless compression.** An image can be losslessly compressed, using the
WebP Lossless Format.
* **Metadata.** An image may have metadata stored in EXIF or XMP formats.
* **Metadata.** An image may have metadata stored in Exif or XMP formats.
* **Transparency.** An image may have transparency, i.e., an alpha channel.
@ -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
('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 &amp; Basics
------------------------
@ -98,7 +94,7 @@ _1-based_
RIFF File Format
----------------
The WebP file format is based on the RIFF (resource interchange file format)
The WebP file format is based on the RIFF (Resource Interchange File Format)
document format.
The basic element of a RIFF file is a _chunk_. It consists of:
@ -265,11 +261,11 @@ An extended format file consists of:
* Image data.
* An optional 'EXIF' chunk with EXIF metadata.
* An optional 'EXIF' chunk with Exif metadata.
* An optional 'XMP ' chunk with XMP metadata.
* An optional 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
up of:
@ -321,9 +317,9 @@ Alpha (L): 1 bit
: Set if any of the frames of the image contain transparency information
("alpha").
EXIF metadata (E): 1 bit
Exif metadata (E): 1 bit
: Set if the file contains EXIF metadata.
: Set if the file contains Exif metadata.
XMP metadata (X): 1 bit
@ -345,12 +341,12 @@ Reserved: 24 bits
Canvas Width Minus One: 24 bits
: _1-based_ width of the canvas in pixels.
The actual canvas width is '1 + Canvas Width Minus One'
The actual canvas width is `1 + Canvas Width Minus One`.
Canvas Height Minus One: 24 bits
: _1-based_ height of the canvas in pixels.
The actual canvas height is '1 + Canvas Height Minus One'
The actual canvas height is `1 + Canvas Height Minus One`.
The product of _Canvas Width_ and _Canvas Height_ MUST be at most `2^32 - 1`.
@ -427,21 +423,21 @@ If the _Animation flag_ is not set, then this chunk SHOULD NOT be present.
Frame X: 24 bits (_uint24_)
: The X coordinate of the upper left corner of the frame is `Frame X * 2`
: The X coordinate of the upper left corner of the frame is `Frame X * 2`.
Frame Y: 24 bits (_uint24_)
: The Y coordinate of the upper left corner of the frame is `Frame Y * 2`
: The Y coordinate of the upper left corner of the frame is `Frame Y * 2`.
Frame Width Minus One: 24 bits (_uint24_)
: The _1-based_ width of the frame.
The frame width is `1 + Frame Width Minus One`
The frame width is `1 + Frame Width Minus One`.
Frame Height Minus One: 24 bits (_uint24_)
: The _1-based_ height of the frame.
The frame height is `1 + Frame Height Minus One`
The frame height is `1 + Frame Height Minus One`.
Frame Duration: 24 bits (_uint24_)
@ -681,12 +677,12 @@ EXIF chunk:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('EXIF') |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| EXIF Metadata |
| Exif Metadata |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
EXIF Metadata: _Chunk Size_ bytes
Exif Metadata: _Chunk Size_ bytes
: image metadata in EXIF format.
: image metadata in Exif format.
XMP chunk:
@ -705,7 +701,7 @@ XMP Metadata: _Chunk Size_ bytes
Additional guidance about handling metadata can be found in the
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
tag_ is different from any of the chunks described in this document, is
@ -802,7 +798,7 @@ RIFF/WEBP
+- XMP (metadata)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An animated image with EXIF metadata may look as follows:
An animated image with Exif metadata may look as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RIFF/WEBP
@ -815,9 +811,9 @@ RIFF/WEBP
+- EXIF (metadata)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[vp8spec]: http://tools.ietf.org/html/rfc6386
[vp8spec]: https://datatracker.ietf.org/doc/html/rfc6386
[webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/webp-lossless-bitstream-spec.txt
[iccspec]: http://www.color.org/icc_specs2.xalter
[metadata]: http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
[rfc 1166]: http://tools.ietf.org/html/rfc1166
[rfc 2119]: http://tools.ietf.org/html/rfc2119
[iccspec]: https://www.color.org/icc_specs2.xalter
[metadata]: https://web.archive.org/web/20180919181934/http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
[rfc 1166]: https://datatracker.ietf.org/doc/html/rfc1166
[rfc 2119]: https://datatracker.ietf.org/doc/html/rfc2119

View File

@ -2,10 +2,10 @@
Although you may be viewing an alternate representation, this document
is sourced in Markdown, a light-duty markup scheme, and is optimized for
the [kramdown](http://kramdown.rubyforge.org/) transformer.
the [kramdown](https://kramdown.gettalong.org/) transformer.
See the accompanying README. External link targets are referenced at the
end of this file.
See the accompanying specs_generation.md. External link targets are referenced
at the end of this file.
-->
@ -16,6 +16,8 @@ _Jyrki Alakuijala, Ph.D., Google, Inc., 2012-06-19_
Paragraphs marked as \[AMENDED\] were amended on 2014-09-16.
Paragraphs marked as \[AMENDED2\] were amended on 2022-05-13.
Abstract
--------
@ -25,7 +27,7 @@ exactly, including the color values for zero alpha pixels. The
format uses subresolution images, recursively embedded into the format
itself, for storing statistical data about the images, such as the used
entropy codes, spatial predictors, color space conversion, and color
table. LZ77, Huffman coding, and a color cache are used for compression
table. LZ77, prefix coding, and a color cache are used for compression
of the bulk data. Decoding speeds faster than PNG have been
demonstrated, as well as 25% denser compression than can be achieved
using today's PNG format.
@ -63,9 +65,9 @@ distance mapping
entropy image
: A two-dimensional subresolution image indicating which entropy coding
should be used in a respective square in the image, i.e., each pixel
is a meta Huffman code.
is a meta prefix code.
Huffman code
prefix code
: A classic way to do entropy coding where a smaller number of bits are
used for more frequent codes.
@ -73,9 +75,9 @@ LZ77
: Dictionary-based sliding window compression algorithm that either
emits symbols or describes them as sequences of past symbols.
meta Huffman code
meta prefix code
: A small integer (up to 16 bits) that indexes an element in the meta
Huffman table.
prefix table.
predictor image
: A two-dimensional subresolution image indicating which spatial
@ -235,7 +237,7 @@ transform, the current pixel value is predicted from the pixels already
decoded (in scan-line order) and only the residual value (actual -
predicted) is encoded. The _prediction mode_ determines the type of
prediction to use. We divide the image into squares and all the pixels
in a square use same prediction mode.
in a square use the same prediction mode.
The first 3 bits of prediction data define the block width and height in
number of bits. The number of block columns, `block_xsize`, is used in
@ -367,15 +369,17 @@ the predicted value for the left-topmost pixel of the image is
0xff000000, L-pixel for all pixels on the top row, and T-pixel for all
pixels on the leftmost column.
\[AMENDED2\]
Addressing the TR-pixel for pixels on the rightmost column is
exceptional. The pixels on the rightmost column are predicted by using
the modes \[0..13\] just like pixels not on border, but by using the
leftmost pixel on the same row as the current TR-pixel. The TR-pixel
offset in memory is the same for border and non-border pixels.
the modes \[0..13\] just like pixels not on the border, but the leftmost pixel
on the same row as the current pixel is instead used as the TR-pixel.
### Color Transform
\[AMENDED2\]
The goal of the color transform is to decorrelate the R, G and B values
of each pixel. Color transform keeps the green (G) value as it is,
transforms red (R) based on green and transforms blue (B) based on green
@ -396,8 +400,8 @@ typedef struct {
The actual color transformation is done by defining a color transform
delta. The color transform delta depends on the `ColorTransformElement`,
which is the same for all the pixels in a particular block. The delta is
added during color transform. The inverse color transform then is just
subtracting those deltas.
subtracted during color transform. The inverse color transform then is just
adding those deltas.
The color transform function is defined as follows:
@ -406,13 +410,13 @@ void ColorTransform(uint8 red, uint8 blue, uint8 green,
ColorTransformElement *trans,
uint8 *new_red, uint8 *new_blue) {
// Transformed values of red and blue components
uint32 tmp_red = red;
uint32 tmp_blue = blue;
int tmp_red = red;
int tmp_blue = blue;
// Applying transform is just adding the transform deltas
tmp_red += ColorTransformDelta(trans->green_to_red, green);
tmp_blue += ColorTransformDelta(trans->green_to_blue, green);
tmp_blue += ColorTransformDelta(trans->red_to_blue, red);
// Applying the transform is just subtracting the transform deltas
tmp_red -= ColorTransformDelta(p->green_to_red_, green);
tmp_blue -= ColorTransformDelta(p->green_to_blue_, green);
tmp_blue -= ColorTransformDelta(p->red_to_blue_, red);
*new_red = tmp_red & 0xff;
*new_blue = tmp_blue & 0xff;
@ -430,7 +434,7 @@ 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().
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).
@ -468,14 +472,18 @@ channels.
void InverseTransform(uint8 red, uint8 green, uint8 blue,
ColorTransformElement *p,
uint8 *new_red, uint8 *new_blue) {
// Applying inverse transform is just subtracting the
// color transform deltas
red -= ColorTransformDelta(p->green_to_red_, green);
blue -= ColorTransformDelta(p->green_to_blue_, green);
blue -= ColorTransformDelta(p->red_to_blue_, red & 0xff);
// Transformed values of red and blue components
int tmp_red = red;
int tmp_blue = blue;
*new_red = red & 0xff;
*new_blue = blue & 0xff;
// Applying inverse transform is just adding the
// color transform deltas
tmp_red += ColorTransformDelta(trans->green_to_red, green);
tmp_blue += ColorTransformDelta(trans->green_to_blue, green);
tmp_blue += ColorTransformDelta(trans->red_to_blue, tmp_red & 0xff);
*new_red = tmp_red & 0xff;
*new_blue = tmp_blue & 0xff;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -590,12 +598,12 @@ The values are packed into the green component as follows:
4 most-significant bits of the green value at x / 2.
* `width_bits` = 2: for every x value where x ≡ 0 (mod 4), a green
value at x is positioned into the 2 least-significant bits of the
green value at x / 4, green values at x + 1 to x + 3 in order to the
more significant bits of the green value at x / 4.
green value at x / 4, green values at x + 1 to x + 3 are positioned in order
to the more significant bits of the green value at x / 4.
* `width_bits` = 3: for every x value where x ≡ 0 (mod 8), a green
value at x is positioned into the least-significant bit of the green
value at x / 8, green values at x + 1 to x + 7 in order to the more
significant bits of the green value at x / 8.
value at x / 8, green values at x + 1 to x + 7 are positioned in order to
the more significant bits of the green value at x / 8.
4 Image Data
@ -609,8 +617,8 @@ We use image data in five different roles:
1. ARGB image: Stores the actual pixels of the image.
1. Entropy image: Stores the
[meta Huffman codes](#decoding-of-meta-huffman-codes). The red and green
components of a pixel define the meta Huffman code used in a particular
[meta prefix codes](#decoding-of-meta-prefix-codes). The red and green
components of a pixel define the meta prefix code used in a particular
block of the ARGB image.
1. Predictor image: Stores the metadata for [Predictor
Transform](#predictor-transform). The green component of a pixel defines
@ -621,12 +629,12 @@ We use image data in five different roles:
the image. Each `ColorTransformElement` `'cte'` is treated as a pixel whose
alpha component is `255`, red component is `cte.red_to_blue`, green
component is `cte.green_to_blue` and blue component is `cte.green_to_red`.
1. Color indexing image: An array of of size `color_table_size` (up to 256
1. Color indexing image: An array of size `color_table_size` (up to 256
ARGB values) storing the metadata for the
[Color Indexing Transform](#color-indexing-transform). This is stored as an
image of width `color_table_size` and height `1`.
### 4.2 Encoding of Image data
### 4.2 Encoding of Image Data
The encoding of image data is independent of its role.
@ -643,7 +651,7 @@ the image.
Each pixel is encoded using one of the three possible methods:
1. Huffman coded literal: each channel (green, red, blue and alpha) is
1. prefix coded literal: each channel (green, red, blue and alpha) is
entropy-coded independently;
2. LZ77 backward reference: a sequence of pixels are copied from elsewhere
in the image; or
@ -652,9 +660,9 @@ Each pixel is encoded using one of the three possible methods:
The following sub-sections describe each of these in detail.
#### 4.2.1 Huffman Coded Literals
#### 4.2.1 Prefix Coded Literals
The pixel is stored as Huffman coded values of green, red, blue and alpha (in
The pixel is stored as prefix coded values of green, red, blue and alpha (in
that order). See [this section](#decoding-entropy-coded-image-data) for details.
#### 4.2.2 LZ77 Backward Reference
@ -678,7 +686,7 @@ very few values in the image. Thus, this approach results in a better
compression overall.
The following table denotes the prefix codes and extra bits used for storing
different range of values.
different ranges of values.
Note: The maximum backward reference length is limited to 4096. Hence, only the
first 24 prefix codes (with the respective extra bits) are meaningful for length
@ -753,13 +761,13 @@ The mapping between distance code `i` and the neighboring pixel offset
(-6, 7), (7, 6), (-7, 6), (8, 5), (7, 7), (-7, 7), (8, 6), (8, 7)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For example, distance code `1` indicates offset of `(0, 1)` for the neighboring
pixel, that is, the pixel above the current pixel (0-pixel difference in
X-direction and 1 pixel difference in Y-direction). Similarly, distance code
`3` indicates left-top pixel.
For example, distance code `1` indicates an offset of `(0, 1)` for the
neighboring pixel, that is, the pixel above the current pixel (0 pixel
difference in X-direction and 1 pixel difference in Y-direction). Similarly,
distance code `3` indicates left-top pixel.
The decoder can convert a distances code 'i' to a scan-line order distance
'dist' as follows:
The decoder can convert a distance code `i` to a scan-line order distance
`dist` as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(xi, yi) = distance_map[i]
@ -769,21 +777,22 @@ if (dist < 1) {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
where 'distance_map' is the mapping noted above and `xsize` is the width of the
where `distance_map` is the mapping noted above and `xsize` is the width of the
image in pixels.
#### 4.2.3 Color Cache Coding
{:#color-cache-code}
Color cache stores a set of colors that have been recently used in the image.
**Rationale:** This way, the recently used colors can sometimes be referred to
more efficiently than emitting them using other two methods (described in
[4.2.1](#huffman-coded-literals) and [4.2.2](#lz77-backward-reference)).
more efficiently than emitting them using the other two methods (described in
[4.2.1](#prefix-coded-literals) and [4.2.2](#lz77-backward-reference)).
Color cache codes are stored as follows. First, there is a 1-bit value that
indicates if the color cache is used. If this bit is 0, no color cache codes
exist, and they are not transmitted in the Huffman code that decodes the green
exist, and they are not transmitted in the prefix code that decodes the green
symbols and the length prefix codes. However, if this bit is 1, the color cache
size is read next:
@ -814,130 +823,245 @@ literals, into the cache in the order they appear in the stream.
### 5.1 Overview
Most of the data is coded using [canonical Huffman code][canonical_huff]. Hence,
the codes are transmitted by sending the _Huffman code lengths_, as opposed to
the actual _Huffman codes_.
Most of the data is coded using a [canonical prefix code][canonical_huff].
Hence, the codes are transmitted by sending the _prefix code lengths_, as
opposed to the actual _prefix codes_.
In particular, the format uses **spatially-variant Huffman coding**. In other
In particular, the format uses **spatially-variant prefix coding**. In other
words, different blocks of the image can potentially use different entropy
codes.
**Rationale**: Different areas of the image may have different characteristics. So, allowing them to use different entropy codes provides more flexibility and
potentially a better compression.
**Rationale**: Different areas of the image may have different characteristics.
So, allowing them to use different entropy codes provides more flexibility and
potentially better compression.
### 5.2 Details
The encoded image data consists of two parts:
The encoded image data consists of several parts:
1. Meta Huffman codes
1. Decoding and building the prefix codes \[AMENDED2\]
1. Meta prefix codes
1. Entropy-coded image data
#### 5.2.1 Decoding of Meta Huffman Codes
#### 5.2.1 Decoding and Building the Prefix Codes
As noted earlier, the format allows the use of different Huffman codes for
different blocks of the image. _Meta Huffman codes_ are indexes identifying
which Huffman codes to use in different parts of the image.
There are several steps in decoding the prefix codes.
Meta Huffman codes may be used _only_ when the image is being used in the
**Decoding the Code Lengths:**
{:#decoding-the-code-lengths}
This section describes how to read the prefix code lengths from the bitstream.
The prefix code lengths can be coded in two ways. The method used is specified
by a 1-bit value.
* If this bit is 1, it is a _simple code length code_, and
* If this bit is 0, it is a _normal code length code_.
In both cases, there can be unused code lengths that are still part of the
stream. This may be inefficient, but it is allowed by the format.
**(i) Simple Code Length Code:**
\[AMENDED2\]
This variant is used in the special case when only 1 or 2 prefix symbols are
in the range \[0..255\] with code length `1`. All other prefix code lengths
are implicitly zeros.
The first bit indicates the number of symbols:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int num_symbols = ReadBits(1) + 1;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Following are the symbol values.
This first symbol is coded using 1 or 8 bits depending on the value of
`is_first_8bits`. The range is \[0..1\] or \[0..255\], respectively.
The second symbol, if present, is always assumed to be in the range \[0..255\]
and coded using 8 bits.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int is_first_8bits = ReadBits(1);
symbol0 = ReadBits(1 + 7 * is_first_8bits);
code_lengths[symbol0] = 1;
if (num_symbols == 2) {
symbol1 = ReadBits(8);
code_lengths[symbol1] = 1;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Note:** Another special case is when _all_ prefix code lengths are _zeros_
(an empty prefix code). For example, a prefix code for distance can be empty
if there are no backward references. Similarly, prefix codes for alpha, red,
and blue can be empty if all pixels within the same meta prefix code are
produced using the color cache. However, this case doesn't need a special
handling, as empty prefix codes can be coded as those containing a single
symbol `0`.
**(ii) Normal Code Length Code:**
The code lengths of the prefix code fit in 8 bits and are read as follows.
First, `num_code_lengths` specifies the number of code lengths.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int num_code_lengths = 4 + ReadBits(4);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If `num_code_lengths` is > 18, the bitstream is invalid.
The code lengths are themselves encoded using prefix codes: lower level code
lengths `code_length_code_lengths` first have to be read. The rest of those
`code_length_code_lengths` (according to the order in `kCodeLengthCodeOrder`)
are zeros.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int kCodeLengthCodes = 19;
int kCodeLengthCodeOrder[kCodeLengthCodes] = {
17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
int code_length_code_lengths[kCodeLengthCodes] = { 0 }; // All zeros.
for (i = 0; i < num_code_lengths; ++i) {
code_length_code_lengths[kCodeLengthCodeOrder[i]] = ReadBits(3);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Next, if `ReadBits(1) == 0`, the maximum number of different read symbols is
`num_code_lengths`. Otherwise, it is defined as:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int length_nbits = 2 + 2 * ReadBits(3);
int max_symbol = 2 + ReadBits(length_nbits);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A prefix table is then built from `code_length_code_lengths` and used to read
up to `max_symbol` code lengths.
* Code \[0..15\] indicates literal code lengths.
* Value 0 means no symbols have been coded.
* Values \[1..15\] indicate the bit length of the respective code.
* Code 16 repeats the previous non-zero value \[3..6\] times, i.e.,
`3 + ReadBits(2)` times. If code 16 is used before a non-zero
value has been emitted, a value of 8 is repeated.
* Code 17 emits a streak of zeros \[3..10\], i.e., `3 + ReadBits(3)`
times.
* Code 18 emits a streak of zeros of length \[11..138\], i.e.,
`11 + ReadBits(7)` times.
Once code lengths are read, a prefix code for each symbol type (A, R, G, B,
distance) is formed using their respective alphabet sizes:
* G channel: 256 + 24 + `color_cache_size`
* other literals (A,R,B): 256
* distance code: 40
#### 5.2.2 Decoding of Meta Prefix Codes
As noted earlier, the format allows the use of different prefix codes for
different blocks of the image. _Meta prefix codes_ are indexes identifying
which prefix codes to use in different parts of the image.
Meta prefix codes may be used _only_ when the image is being used in the
[role](#roles-of-image-data) of an _ARGB image_.
There are two possibilities for the meta Huffman codes, indicated by a 1-bit
There are two possibilities for the meta prefix codes, indicated by a 1-bit
value:
* If this bit is zero, there is only one meta Huffman code used everywhere in
* If this bit is zero, there is only one meta prefix code used everywhere in
the image. No more data is stored.
* If this bit is one, the image uses multiple meta Huffman codes. These meta
Huffman codes are stored as an _entropy image_ (described below).
* If this bit is one, the image uses multiple meta prefix codes. These meta
prefix codes are stored as an _entropy image_ (described below).
**Entropy image:**
The entropy image defines which Huffman codes are used in different parts of the
The entropy image defines which prefix codes are used in different parts of the
image, as described below.
The first 3-bits contain the `huffman_bits` value. The dimensions of the entropy
image are derived from 'huffman_bits'.
The first 3-bits contain the `prefix_bits` value. The dimensions of the entropy
image are derived from 'prefix_bits'.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int huffman_bits = ReadBits(3) + 2;
int huffman_xsize = DIV_ROUND_UP(xsize, 1 << huffman_bits);
int huffman_ysize = DIV_ROUND_UP(ysize, 1 << huffman_bits);
int prefix_bits = ReadBits(3) + 2;
int prefix_xsize = DIV_ROUND_UP(xsize, 1 << prefix_bits);
int prefix_ysize = DIV_ROUND_UP(ysize, 1 << prefix_bits);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
where `DIV_ROUND_UP` is as defined [earlier](#predictor-transform).
Next bits contain an entropy image of width `huffman_xsize` and height
`huffman_ysize`.
The next bits contain an entropy image of width `prefix_xsize` and height
`prefix_ysize`.
**Interpretation of Meta Huffman Codes:**
**Interpretation of Meta Prefix Codes:**
For any given pixel (x, y), there is a set of five Huffman codes associated with
For any given pixel (x, y), there is a set of five prefix codes associated with
it. These codes are (in bitstream order):
* **Huffman code #1**: used for green channel, backward-reference length and
* **prefix code #1**: used for green channel, backward-reference length and
color cache
* **Huffman code #2, #3 and #4**: used for red, blue and alpha channels
* **prefix code #2, #3 and #4**: used for red, blue and alpha channels
respectively.
* **Huffman code #5**: used for backward-reference distance.
* **prefix code #5**: used for backward-reference distance.
From here on, we refer to this set as a **Huffman code group**.
From here on, we refer to this set as a **prefix code group**.
The number of Huffman code groups in the ARGB image can be obtained by finding
the _largest meta Huffman code_ from the entropy image:
The number of prefix code groups in the ARGB image can be obtained by finding
the _largest meta prefix code_ from the entropy image:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int num_huff_groups = max(entropy image) + 1;
int num_prefix_groups = max(entropy image) + 1;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
where `max(entropy image)` indicates the largest Huffman code stored in the
where `max(entropy image)` indicates the largest prefix code stored in the
entropy image.
As each Huffman code groups contains five Huffman codes, the total number of
Huffman codes is:
As each prefix code group contains five prefix codes, the total number of
prefix codes is:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int num_huff_codes = 5 * num_huff_groups;
int num_prefix_codes = 5 * num_prefix_groups;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Given a pixel (x, y) in the ARGB image, we can obtain the corresponding Huffman
Given a pixel (x, y) in the ARGB image, we can obtain the corresponding prefix
codes to be used as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int position = (y >> huffman_bits) * huffman_xsize + (x >> huffman_bits);
int meta_huff_code = (entropy_image[pos] >> 8) & 0xffff;
HuffmanCodeGroup huff_group = huffman_code_groups[meta_huff_code];
int position = (y >> prefix_bits) * prefix_xsize + (x >> prefix_bits);
int meta_prefix_code = (entropy_image[pos] >> 8) & 0xffff;
PrefixCodeGroup prefix_group = prefix_code_groups[meta_prefix_code];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
where, we have assumed the existence of `HuffmanCodeGroup` structure, which
represents a set of five Huffman codes. Also, `huffman_code_groups` is an array
of `HuffmanCodeGroup` (of size `num_huff_groups`).
where, we have assumed the existence of `PrefixCodeGroup` structure, which
represents a set of five prefix codes. Also, `prefix_code_groups` is an array
of `PrefixCodeGroup` (of size `num_prefix_groups`).
The decoder then uses Huffman code group `huff_group` to decode the pixel
The decoder then uses prefix code group `prefix_group` to decode the pixel
(x, y) as explained in the [next section](#decoding-entropy-coded-image-data).
#### 5.2.2 Decoding Entropy-coded Image Data
#### 5.2.3 Decoding Entropy-coded Image Data
\[AMENDED2\]
For the current position (x, y) in the image, the decoder first identifies the
corresponding Huffman code group (as explained in the last section). Given the
Huffman code group, the pixel is read and decoded as follows:
corresponding prefix code group (as explained in the last section). Given the
prefix code group, the pixel is read and decoded as follows:
Read next symbol S from the bitstream using Huffman code #1. \[See
[next section](#decoding-the-code-lengths) for details on decoding the Huffman
code lengths\]. Note that S is any integer in the range `0` to
`(256 + 24 + ` [`color_cache_size`](#color-cache-code)`- 1)`.
Read next symbol S from the bitstream using prefix code #1. Note that S is any
integer in the range `0` to
`(256 + 24 + ` [`color_cache_size`](#color-cache-code)` - 1)`.
The interpretation of S depends on its value:
1. if S < 256
1. Use S as the green component
1. Read red from the bitstream using Huffman code #2
1. Read blue from the bitstream using Huffman code #3
1. Read alpha from the bitstream using Huffman code #4
1. if S < 256 + 24
1. Use S - 256 as a length prefix code
1. Read extra bits for length from the bitstream
1. Use S as the green component.
1. Read red from the bitstream using prefix code #2.
1. Read blue from the bitstream using prefix code #3.
1. Read alpha from the bitstream using prefix code #4.
1. if S >= 256 && S < 256 + 24
1. Use S - 256 as a length prefix code.
1. Read extra bits for length from the bitstream.
1. Determine backward-reference length L from length prefix code and the
extra bits read.
1. Read distance prefix code from the bitstream using Huffman code #5
1. Read extra bits for distance from the bitstream
1. Read distance prefix code from the bitstream using prefix code #5.
1. Read extra bits for distance from the bitstream.
1. Determine backward-reference distance D from distance prefix code and
the extra bits read.
1. Copy the L pixels (in scan-line order) from the sequence of pixels
@ -947,80 +1071,6 @@ The interpretation of S depends on its value:
1. Get ARGB color from the color cache at that index.
**Decoding the Code Lengths:**
{:#decoding-the-code-lengths}
This section describes the details about reading a symbol from the bitstream by
decoding the Huffman code length.
The Huffman code lengths can be coded in two ways. The method used is specified
by a 1-bit value.
* If this bit is 1, it is a _simple code length code_, and
* If this bit is 0, it is a _normal code length code_.
**(i) Simple Code Length Code:**
This variant is used in the special case when only 1 or 2 Huffman code lengths
are non-zero, and are in the range of \[0, 255\]. All other Huffman code lengths
are implicitly zeros.
The first bit indicates the number of non-zero code lengths:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int num_code_lengths = ReadBits(1) + 1;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The first code length is stored either using a 1-bit code for values of 0 and 1,
or using an 8-bit code for values in range \[0, 255\]. The second code length,
when present, is coded as an 8-bit code.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int is_first_8bits = ReadBits(1);
code_lengths[0] = ReadBits(1 + 7 * is_first_8bits);
if (num_code_lengths == 2) {
code_lengths[1] = ReadBits(8);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Note:** Another special case is when _all_ Huffman code lengths are _zeros_
(an empty Huffman code). For example, a Huffman code for distance can be empty
if there are no backward references. Similarly, Huffman codes for alpha, red,
and blue can be empty if all pixels within the same meta Huffman code are
produced using the color cache. However, this case doesn't need a special
handling, as empty Huffman codes can be coded as those containing a single
symbol `0`.
**(ii) Normal Code Length Code:**
The code lengths of a Huffman code are read as follows: `num_code_lengths`
specifies the number of code lengths; the rest of the code lengths
(according to the order in `kCodeLengthCodeOrder`) are zeros.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int kCodeLengthCodes = 19;
int kCodeLengthCodeOrder[kCodeLengthCodes] = {
17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
int code_lengths[kCodeLengthCodes] = { 0 }; // All zeros.
int num_code_lengths = 4 + ReadBits(4);
for (i = 0; i < num_code_lengths; ++i) {
code_lengths[kCodeLengthCodeOrder[i]] = ReadBits(3);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Code length code \[0..15\] indicates literal code lengths.
* Value 0 means no symbols have been coded.
* Values \[1..15\] indicate the bit length of the respective code.
* Code 16 repeats the previous non-zero value \[3..6\] times, i.e.,
3 + `ReadBits(2)` times. If code 16 is used before a non-zero
value has been emitted, a value of 8 is repeated.
* Code 17 emits a streak of zeros \[3..10\], i.e., 3 + `ReadBits(3)`
times.
* Code 18 emits a streak of zeros of length \[11..138\], i.e.,
11 + `ReadBits(7)` times.
6 Overall Structure of the Format
---------------------------------
@ -1056,23 +1106,26 @@ of pixels (xsize * ysize).
#### Structure of the Image Data
\[AMENDED2\]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<spatially-coded image> ::= <meta huffman><entropy-coded image>
<entropy-coded image> ::= <color cache info><huffman codes><lz77-coded image>
<meta huffman> ::= 1-bit value 0 |
(1-bit value 1; <entropy image>)
<entropy image> ::= 3-bit subsample value; <entropy-coded image>
<spatially-coded image> ::= <color cache info><meta prefix><data>
<entropy-coded image> ::= <color cache info><data>
<color cache info> ::= 1 bit value 0 |
(1-bit value 1; 4-bit value for color cache size)
<huffman codes> ::= <huffman code group> | <huffman code group><huffman codes>
<huffman code group> ::= <huffman code><huffman code><huffman code>
<huffman code><huffman code>
See "Interpretation of Meta Huffman codes" to
understand what each of these five Huffman codes are
for.
<huffman code> ::= <simple huffman code> | <normal huffman code>
<simple huffman code> ::= see "Simple code length code" for details
<normal huffman code> ::= <code length code>; encoded code lengths
<meta prefix> ::= 1-bit value 0 |
(1-bit value 1; <entropy image>)
<data> ::= <prefix codes><lz77-coded image>
<entropy image> ::= 3-bit subsample value; <entropy-coded image>
<prefix codes> ::= <prefix code group> | <prefix code group><prefix codes>
<prefix code group> ::= <prefix code><prefix code><prefix code>
<prefix code><prefix code>
See "Interpretation of Meta Prefix Codes" to
understand what each of these five prefix codes are
for.
<prefix code> ::= <simple prefix code> | <normal prefix code>
<simple prefix code> ::= see "Simple code length code" for details
<normal prefix code> ::= <code length code>; encoded code lengths
<code length code> ::= see section "Normal code length code"
<lz77-coded image> ::= ((<argb-pixel> | <lz77-copy> | <color-cache-code>)
<lz77-coded image>) | ""
@ -1082,9 +1135,8 @@ A possible example sequence:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<RIFF header><image size>1-bit value 1<subtract-green-tx>
1-bit value 1<predictor-tx>1-bit value 0<meta huffman>
<color cache info><huffman codes>
<lz77-coded image>
1-bit value 1<predictor-tx>1-bit value 0<color cache info>1-bit value 0
<prefix codes><lz77-coded image>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[canonical_huff]: http://en.wikipedia.org/wiki/Canonical_Huffman_code
[canonical_huff]: https://en.wikipedia.org/wiki/Canonical_Huffman_code

View File

@ -241,7 +241,7 @@ static int ReadAnimatedWebP(const char filename[],
image->bgcolor = anim_info.bgcolor;
// Allocate frames.
if (!AllocateFrames(image, anim_info.frame_count)) return 0;
if (!AllocateFrames(image, anim_info.frame_count)) goto End;
// Decode frames.
while (WebPAnimDecoderHasMoreFrames(dec)) {
@ -558,7 +558,10 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
}
}
// Allocate frames.
AllocateFrames(image, frame_count);
if (!AllocateFrames(image, frame_count)) {
DGifCloseFile(gif, NULL);
return 0;
}
canvas_width = image->canvas_width;
canvas_height = image->canvas_height;

View File

@ -571,7 +571,7 @@ static void HelpLong(void) {
printf(" -qrange <min> <max> .... specifies the permissible quality range\n"
" (default: 0 100)\n");
printf(" -crop <x> <y> <w> <h> .. crop picture with the given rectangle\n");
printf(" -resize <w> <h> ........ resize picture (after any cropping)\n");
printf(" -resize <w> <h> ........ resize picture (*after* any cropping)\n");
printf(" -mt .................... use multi-threading if available\n");
printf(" -low_memory ............ reduce memory usage (slower encoding)\n");
printf(" -map <int> ............. print map of extra info\n");
@ -620,6 +620,7 @@ static void HelpLong(void) {
printf(" -af .................... auto-adjust filter strength\n");
printf(" -pre <int> ............. pre-processing filter\n");
printf("\n");
printf("Supported input formats:\n %s\n", WebPGetEnabledInputFileFormats());
}
//------------------------------------------------------------------------------

View File

@ -96,7 +96,7 @@ static void Help(void) {
" -alpha_dither use alpha-plane dithering if needed\n"
" -mt .......... use multi-threading\n"
" -crop <x> <y> <w> <h> ... crop output with the given rectangle\n"
" -resize <w> <h> ......... scale the output (*after* any cropping)\n"
" -resize <w> <h> ......... resize output (*after* any cropping)\n"
" -flip ........ flip the output vertically\n"
" -alpha ....... only save the alpha plane\n"
" -incremental . use incremental decoding (useful for tests)\n"

View File

@ -103,7 +103,10 @@ int ExUtilInitCommandLineArguments(int argc, const char* argv[],
}
args->own_argv_ = 1;
args->argv_ = (const char**)WebPMalloc(MAX_ARGC * sizeof(*args->argv_));
if (args->argv_ == NULL) return 0;
if (args->argv_ == NULL) {
ExUtilDeleteCommandLineArguments(args);
return 0;
}
argc = 0;
for (cur = strtok((char*)args->argv_data_.bytes, sep);
@ -111,6 +114,7 @@ int ExUtilInitCommandLineArguments(int argc, const char* argv[],
cur = strtok(NULL, sep)) {
if (argc == MAX_ARGC) {
fprintf(stderr, "ERROR: Arguments limit %d reached\n", MAX_ARGC);
ExUtilDeleteCommandLineArguments(args);
return 0;
}
assert(strlen(cur) != 0);

View File

@ -314,8 +314,11 @@ int main(int argc, const char* argv[]) {
frame.use_argb = 1;
if (!WebPPictureAlloc(&frame)) goto End;
GIFClearPic(&frame, NULL);
WebPPictureCopy(&frame, &curr_canvas);
WebPPictureCopy(&frame, &prev_canvas);
if (!(WebPPictureCopy(&frame, &curr_canvas) &&
WebPPictureCopy(&frame, &prev_canvas))) {
fprintf(stderr, "Error allocating canvas.\n");
goto End;
}
// Background color.
GIFGetBackgroundColor(gif->SColorMap, gif->SBackGroundColor,

View File

@ -35,8 +35,7 @@
static void Help(void) {
printf("Usage:\n\n");
printf(" img2webp [file-level options] [image files...] "
"[per-frame options...]\n");
printf(" img2webp [file_options] [[frame_options] frame_file]...\n");
printf("\n");
printf("File-level options (only used at the start of compression):\n");
@ -66,6 +65,8 @@ static void Help(void) {
"arguments will be\n");
printf("tokenized from this file. The file name must not start with "
"the character '-'.\n");
printf("\nSupported input formats:\n %s\n",
WebPGetEnabledInputFileFormats());
}
//------------------------------------------------------------------------------
@ -187,7 +188,7 @@ int main(int argc, const char* argv[]) {
verbose = 1;
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
goto End;
FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-version")) {
const int enc_version = WebPGetEncoderVersion();
const int mux_version = WebPGetMuxVersion();

View File

@ -16,11 +16,15 @@
#ifndef WEBP_EXAMPLES_UNICODE_H_
#define WEBP_EXAMPLES_UNICODE_H_
#include <stdio.h>
#if defined(_WIN32) && defined(_UNICODE)
// wchar_t is used instead of TCHAR because we only perform additional work when
// Unicode is enabled and because the output of CommandLineToArgvW() is wchar_t.
#include <fcntl.h>
#include <io.h>
#include <wchar.h>
#include <windows.h>
#include <shellapi.h>
@ -55,8 +59,16 @@
#define WFOPEN(ARG, OPT) _wfopen((const W_CHAR*)ARG, TO_W_CHAR(OPT))
#define WPRINTF(STR, ...) wprintf(TO_W_CHAR(STR), __VA_ARGS__)
#define WFPRINTF(STDERR, STR, ...) fwprintf(STDERR, TO_W_CHAR(STR), __VA_ARGS__)
#define WFPRINTF(STREAM, STR, ...) \
do { \
int prev_mode; \
fflush(STREAM); \
prev_mode = _setmode(_fileno(STREAM), _O_U8TEXT); \
fwprintf(STREAM, TO_W_CHAR(STR), __VA_ARGS__); \
fflush(STREAM); \
(void)_setmode(_fileno(STREAM), prev_mode); \
} while (0)
#define WPRINTF(STR, ...) WFPRINTF(stdout, STR, __VA_ARGS__)
#define WSTRLEN(FILENAME) wcslen((const W_CHAR*)FILENAME)
#define WSTRCMP(FILENAME, STR) wcscmp((const W_CHAR*)FILENAME, TO_W_CHAR(STR))
@ -65,6 +77,8 @@
#else
#include <string.h>
// Unicode file paths work as is on Unix platforms, and no extra work is done on
// Windows either if Unicode is disabled.
@ -83,7 +97,7 @@
#define WFOPEN(ARG, OPT) fopen(ARG, OPT)
#define WPRINTF(STR, ...) printf(STR, __VA_ARGS__)
#define WFPRINTF(STDERR, STR, ...) fprintf(STDERR, STR, __VA_ARGS__)
#define WFPRINTF(STREAM, STR, ...) fprintf(STREAM, STR, __VA_ARGS__)
#define WSTRLEN(FILENAME) strlen(FILENAME)
#define WSTRCMP(FILENAME, STR) strcmp(FILENAME, STR)

View File

@ -45,18 +45,19 @@ static GifFileType* DGifOpenFileUnicode(const W_CHAR* file_name, int* error) {
}
#if defined(_WIN32) && defined(_UNICODE)
int file_handle = _wopen(file_name, _O_RDONLY | _O_BINARY);
if (file_handle == -1) {
if (error != NULL) *error = D_GIF_ERR_OPEN_FAILED;
return NULL;
}
{
int file_handle = _wopen(file_name, _O_RDONLY | _O_BINARY);
if (file_handle == -1) {
if (error != NULL) *error = D_GIF_ERR_OPEN_FAILED;
return NULL;
}
#if LOCAL_GIF_PREREQ(5, 0)
return DGifOpenFileHandle(file_handle, error);
return DGifOpenFileHandle(file_handle, error);
#else
return DGifOpenFileHandle(file_handle);
return DGifOpenFileHandle(file_handle);
#endif
}
#else

View File

@ -292,6 +292,19 @@ static void PrintString(const char* const text) {
}
}
static void PrintStringW(const char* const text) {
#if defined(_WIN32) && defined(_UNICODE)
void* const font = GLUT_BITMAP_9_BY_15;
const W_CHAR* const wtext = (const W_CHAR*)text;
int i;
for (i = 0; wtext[i]; ++i) {
glutBitmapCharacter(font, wtext[i]);
}
#else
PrintString(text);
#endif
}
static float GetColorf(uint32_t color, int shift) {
return ((color >> shift) & 0xff) / 255.f;
}
@ -396,7 +409,7 @@ static void HandleDisplay(void) {
glColor4f(0.90f, 0.0f, 0.90f, 1.0f);
glRasterPos2f(-0.95f, 0.90f);
PrintString(kParams.file_name);
PrintStringW(kParams.file_name);
snprintf(tmp, sizeof(tmp), "Dimension:%d x %d", pic->width, pic->height);
glColor4f(0.90f, 0.0f, 0.90f, 1.0f);

View File

@ -41,6 +41,7 @@
if (webp_info->show_diagnosis_) { \
fprintf(stderr, "Warning: %s\n", MESSAGE); \
} \
++webp_info->num_warnings_; \
} while (0)
static const char* const kFormats[3] = {
@ -116,6 +117,7 @@ typedef struct WebPInfo {
int is_processing_anim_frame_, seen_alpha_subchunk_, seen_image_subchunk_;
// Print output control.
int quiet_, show_diagnosis_, show_summary_;
int num_warnings_;
int parse_bitstream_;
} WebPInfo;
@ -123,16 +125,16 @@ static void WebPInfoInit(WebPInfo* const webp_info) {
memset(webp_info, 0, sizeof(*webp_info));
}
static const char kWebPChunkTags[CHUNK_TYPES][4] = {
{ 'V', 'P', '8', ' ' },
{ 'V', 'P', '8', 'L' },
{ 'V', 'P', '8', 'X' },
{ 'A', 'L', 'P', 'H' },
{ 'A', 'N', 'I', 'M' },
{ 'A', 'N', 'M', 'F' },
{ 'I', 'C', 'C', 'P' },
{ 'E', 'X', 'I', 'F' },
{ 'X', 'M', 'P', ' ' },
static const uint32_t kWebPChunkTags[CHUNK_TYPES] = {
MKFOURCC('V', 'P', '8', ' '),
MKFOURCC('V', 'P', '8', 'L'),
MKFOURCC('V', 'P', '8', 'X'),
MKFOURCC('A', 'L', 'P', 'H'),
MKFOURCC('A', 'N', 'I', 'M'),
MKFOURCC('A', 'N', 'M', 'F'),
MKFOURCC('I', 'C', 'C', 'P'),
MKFOURCC('E', 'X', 'I', 'F'),
MKFOURCC('X', 'M', 'P', ' '),
};
// -----------------------------------------------------------------------------
@ -580,7 +582,7 @@ static WebPInfoStatus ParseAlphaHeader(const ChunkData* const chunk_data,
// -----------------------------------------------------------------------------
// Chunk parsing.
static WebPInfoStatus ParseRIFFHeader(const WebPInfo* const webp_info,
static WebPInfoStatus ParseRIFFHeader(WebPInfo* const webp_info,
MemBuffer* const mem) {
const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE;
size_t riff_size;
@ -642,7 +644,7 @@ static WebPInfoStatus ParseChunk(const WebPInfo* const webp_info,
return WEBP_INFO_TRUNCATED_DATA;
}
for (i = 0; i < CHUNK_TYPES; ++i) {
if (!memcmp(kWebPChunkTags[i], &fourcc, TAG_SIZE)) break;
if (kWebPChunkTags[i] == fourcc) break;
}
chunk_data->offset_ = chunk_start_offset;
chunk_data->size_ = chunk_size;
@ -937,7 +939,13 @@ static WebPInfoStatus ProcessChunk(const ChunkData* const chunk_data,
LOG_WARN(error_message);
} else {
if (!webp_info->quiet_) {
const char* tag = kWebPChunkTags[chunk_data->id_];
char tag[4];
uint32_t fourcc = kWebPChunkTags[chunk_data->id_];
#ifdef WORDS_BIGENDIAN
fourcc = (fourcc >> 24) | ((fourcc >> 8) & 0xff00) |
((fourcc << 8) & 0xff0000) | (fourcc << 24);
#endif
memcpy(tag, &fourcc, sizeof(tag));
printf("Chunk %c%c%c%c at offset %6d, length %6d\n",
tag[0], tag[1], tag[2], tag[3], (int)chunk_data->offset_,
(int)chunk_data->size_);
@ -988,7 +996,7 @@ static WebPInfoStatus ProcessChunk(const ChunkData* const chunk_data,
return status;
}
static WebPInfoStatus Validate(const WebPInfo* const webp_info) {
static WebPInfoStatus Validate(WebPInfo* const webp_info) {
if (webp_info->num_frames_ < 1) {
LOG_ERROR("No image/frame detected.");
return WEBP_INFO_MISSING_DATA;
@ -1093,16 +1101,14 @@ static WebPInfoStatus AnalyzeWebP(WebPInfo* const webp_info,
} else {
printf("Errors detected.\n");
}
if (webp_info->num_warnings_ > 0) {
printf("There were %d warning(s).\n", webp_info->num_warnings_);
}
}
return webp_info_status;
}
static void HelpShort(void) {
printf("Usage: webpinfo [options] in_files\n"
"Try -longhelp for an exhaustive list of options.\n");
}
static void HelpLong(void) {
static void Help(void) {
printf("Usage: webpinfo [options] in_files\n"
"Note: there could be multiple input files;\n"
" options must come before input files.\n"
@ -1123,17 +1129,15 @@ int main(int argc, const char* argv[]) {
INIT_WARGV(argc, argv);
if (argc == 1) {
HelpShort();
Help();
FREE_WARGV_AND_RETURN(WEBP_INFO_OK);
}
// Parse command-line input.
for (c = 1; c < argc; ++c) {
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
HelpShort();
FREE_WARGV_AND_RETURN(WEBP_INFO_OK);
} else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
HelpLong();
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help") ||
!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
Help();
FREE_WARGV_AND_RETURN(WEBP_INFO_OK);
} else if (!strcmp(argv[c], "-quiet")) {
quiet = 1;
@ -1154,7 +1158,7 @@ int main(int argc, const char* argv[]) {
}
if (c == argc) {
HelpShort();
Help();
FREE_WARGV_AND_RETURN(WEBP_INFO_INVALID_COMMAND);
}

View File

@ -99,6 +99,7 @@ typedef enum {
FEATURE_ANMF,
FEATURE_DURATION,
FEATURE_LOOP,
FEATURE_BGCOLOR,
LAST_FEATURE
} FeatureType;
@ -315,11 +316,12 @@ static void PrintHelp(void) {
printf("\n");
printf("SET_OPTIONS:\n");
printf(" Set color profile/metadata:\n");
printf(" loop LOOP_COUNT set the loop count\n");
printf(" icc file.icc set ICC profile\n");
printf(" exif file.exif set EXIF metadata\n");
printf(" xmp file.xmp set XMP metadata\n");
printf(" Set color profile/metadata/parameters:\n");
printf(" loop LOOP_COUNT set the loop count\n");
printf(" bgcolor BACKGROUND_COLOR set the animation background color\n");
printf(" icc file.icc set ICC profile\n");
printf(" exif file.exif set EXIF metadata\n");
printf(" xmp file.xmp set XMP metadata\n");
printf(" where: 'file.icc' contains the ICC profile to be set,\n");
printf(" 'file.exif' contains the EXIF metadata to be set\n");
printf(" 'file.xmp' contains the XMP metadata to be set\n");
@ -327,7 +329,7 @@ static void PrintHelp(void) {
printf("\n");
printf("DURATION_OPTIONS:\n");
printf(" Set duration of selected frames:\n");
printf(" duration set duration for each frames\n");
printf(" duration set duration for all frames\n");
printf(" duration,frame set duration of a particular frame\n");
printf(" duration,start,end set duration of frames in the\n");
printf(" interval [start,end])\n");
@ -346,7 +348,7 @@ static void PrintHelp(void) {
printf("\n");
printf("FRAME_OPTIONS(i):\n");
printf(" Create animation:\n");
printf(" file_i +di+[xi+yi[+mi[bi]]]\n");
printf(" file_i +di[+xi+yi[+mi[bi]]]\n");
printf(" where: 'file_i' is the i'th animation frame (WebP format),\n");
printf(" 'di' is the pause duration before next frame,\n");
printf(" 'xi','yi' specify the image offset for this frame,\n");
@ -458,7 +460,8 @@ static WebPMux* DuplicateMuxHeader(const WebPMux* const mux) {
if (err == WEBP_MUX_OK && metadata.size > 0) {
err = WebPMuxSetChunk(new_mux, kFourccList[i], &metadata, 1);
if (err != WEBP_MUX_OK) {
ERROR_GOTO1("Error transferring metadata in DuplicateMux().", End);
ERROR_GOTO1("Error transferring metadata in DuplicateMuxHeader().",
End);
}
}
}
@ -682,7 +685,7 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
}
arg->subtype_ = SUBTYPE_ANMF;
arg->filename_ = argv[i + 1];
arg->filename_ = wargv[i + 1];
arg->params_ = argv[i + 2];
++feature_arg_index;
i += 3;
@ -778,6 +781,13 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
arg->params_ = argv[i + 1];
++feature_arg_index;
i += 2;
} else if (!strcmp(argv[i], "bgcolor") &&
(config->action_type_ == ACTION_SET)) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
config->type_ = FEATURE_BGCOLOR;
arg->params_ = argv[i + 1];
++feature_arg_index;
i += 2;
} else { // Assume input file.
if (config->input_ == NULL) {
config->input_ = wargv[i];
@ -1053,6 +1063,30 @@ static int Process(const Config* config) {
}
break;
}
case FEATURE_BGCOLOR: {
WebPMuxAnimParams params = { 0xFFFFFFFF, 0 };
uint32_t bgcolor;
ok = ParseBgcolorArgs(config->args_[0].params_, &bgcolor);
if (!ok) {
ERROR_GOTO1("ERROR: Could not parse the background color.\n",
Err2);
}
ok = CreateMux(config->input_, &mux);
if (!ok) goto Err2;
ok = (WebPMuxGetAnimationParams(mux, &params) == WEBP_MUX_OK);
if (!ok) {
ERROR_GOTO1("ERROR: input file does not seem to be an animation.\n",
Err2);
}
params.bgcolor = bgcolor;
err = WebPMuxSetAnimationParams(mux, &params);
ok = (err == WEBP_MUX_OK);
if (!ok) {
ERROR_GOTO2("ERROR (%s): Could not set animation parameters.\n",
ErrorString(err), Err2);
}
break;
}
default: {
ERROR_GOTO1("ERROR: Invalid feature for action 'set'.\n", Err2);
break;

View File

@ -19,7 +19,7 @@
#define XTRA_MAJ_VERSION 1
#define XTRA_MIN_VERSION 2
#define XTRA_REV_VERSION 1
#define XTRA_REV_VERSION 3
//------------------------------------------------------------------------------

View File

@ -223,7 +223,8 @@ static void Help(void) {
" -o <file> . save the diff map as a WebP lossless file\n"
" -scale .... scale the difference map to fit [0..255] range\n"
" -gray ..... use grayscale for difference map (-scale)\n"
" Also handles PNG, JPG and TIFF files, in addition to WebP.\n");
"\nSupported input formats:\n %s\n",
WebPGetEnabledInputFileFormats());
}
int main(int argc, const char* argv[]) {

View File

@ -11,6 +11,24 @@
#include "./image_dec.h"
const char* WebPGetEnabledInputFileFormats(void) {
return "WebP"
#ifdef WEBP_HAVE_JPEG
", JPEG"
#endif
#ifdef WEBP_HAVE_PNG
", PNG"
#endif
", PNM (PGM, PPM, PAM)"
#ifdef WEBP_HAVE_TIFF
", TIFF"
#endif
#ifdef HAVE_WINCODEC_H
", Windows Imaging Component (WIC)"
#endif
"";
}
static WEBP_INLINE uint32_t GetBE32(const uint8_t buf[]) {
return ((uint32_t)buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
}

View File

@ -41,6 +41,9 @@ typedef enum {
WEBP_UNSUPPORTED_FORMAT
} WebPInputFileFormat;
// Returns a comma separated list of enabled input formats.
const char* WebPGetEnabledInputFileFormats(void);
// Try to infer the image format. 'data_size' should be larger than 12.
// Returns WEBP_UNSUPPORTED_FORMAT if format can't be guess safely.
WebPInputFileFormat WebPGuessImageType(const uint8_t* const data,

View File

@ -280,7 +280,7 @@ int WebPWrite16bAsPGM(FILE* fout, const WebPDecBuffer* const buffer) {
}
//------------------------------------------------------------------------------
// BMP
// BMP (see https://en.wikipedia.org/wiki/BMP_file_format#Pixel_storage)
static void PutLE16(uint8_t* const dst, uint32_t value) {
dst[0] = (value >> 0) & 0xff;
@ -293,8 +293,11 @@ static void PutLE32(uint8_t* const dst, uint32_t value) {
}
#define BMP_HEADER_SIZE 54
#define BMP_HEADER_ALPHA_EXTRA_SIZE 16 // for alpha info
int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
const int header_size =
BMP_HEADER_SIZE + (has_alpha ? BMP_HEADER_ALPHA_EXTRA_SIZE : 0);
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
const uint8_t* rgba = buffer->u.RGBA.rgba;
@ -303,8 +306,9 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
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 };
const uint32_t image_size = bmp_stride * height;
const uint32_t total_size = image_size + header_size;
uint8_t bmp_header[BMP_HEADER_SIZE + BMP_HEADER_ALPHA_EXTRA_SIZE] = { 0 };
if (fout == NULL || buffer == NULL || rgba == NULL) return 0;
@ -312,30 +316,37 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
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
PutLE32(bmp_header + 10, header_size); // offset to pixel array
// bitmap info header
PutLE32(bmp_header + 14, 40); // DIB header size
PutLE32(bmp_header + 14, header_size - 14); // DIB header size
PutLE32(bmp_header + 18, width); // dimensions
PutLE32(bmp_header + 22, -(int)height); // vertical flip!
PutLE32(bmp_header + 22, height); // no 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 + 30, has_alpha ? 3 : 0); // BI_BITFIELDS or BI_RGB
PutLE32(bmp_header + 34, image_size);
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
if (has_alpha) { // BITMAPV3INFOHEADER complement
PutLE32(bmp_header + 54, 0x00ff0000); // red mask
PutLE32(bmp_header + 58, 0x0000ff00); // green mask
PutLE32(bmp_header + 62, 0x000000ff); // blue mask
PutLE32(bmp_header + 66, 0xff000000); // alpha mask
}
// TODO(skal): color profile
// write header
if (fwrite(bmp_header, sizeof(bmp_header), 1, fout) != 1) {
if (fwrite(bmp_header, header_size, 1, fout) != 1) {
return 0;
}
// write pixel array
// write pixel array, bottom to top
for (y = 0; y < height; ++y) {
if (fwrite(rgba, line_size, 1, fout) != 1) {
const uint8_t* const src = &rgba[(uint64_t)(height - 1 - y) * stride];
if (fwrite(src, line_size, 1, fout) != 1) {
return 0;
}
// write padding zeroes
@ -345,11 +356,11 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
return 0;
}
}
rgba += stride;
}
return 1;
}
#undef BMP_HEADER_SIZE
#undef BMP_HEADER_ALPHA_EXTRA_SIZE
//------------------------------------------------------------------------------
// TIFF

View File

@ -79,7 +79,7 @@ int WebPWriteTIFF(FILE* fout, const struct WebPDecBuffer* const buffer);
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.
// See: https://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);

View File

@ -336,7 +336,11 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
pic->width = width;
pic->height = height;
ok = WebPPictureImportRGB(pic, rgb, (int)stride);
if (!ok) goto Error;
if (!ok) {
pic->width = 0; // WebPPictureImportRGB() barely touches 'pic' on failure.
pic->height = 0; // Just reset dimensions but keep any 'custom_ptr' etc.
MetadataFree(metadata); // In case the caller forgets to free it on error.
}
End:
free(rgb);

View File

@ -133,7 +133,7 @@ static const struct {
MetadataPayload* const payload);
size_t storage_offset;
} kPNGMetadataMap[] = {
// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PNG.html#TextualData
// https://exiftool.org/TagNames/PNG.html#TextualData
// See also: ExifTool on CPAN.
{ "Raw profile type exif", ProcessRawProfile, METADATA_OFFSET(exif) },
{ "Raw profile type xmp", ProcessRawProfile, METADATA_OFFSET(xmp) },

View File

@ -46,7 +46,7 @@ static int ExtractMetadataFromTIFF(TIFF* const tif, Metadata* const metadata) {
(MetadataPayload*)((uint8_t*)metadata +
kTIFFMetadataMap[i].storage_offset);
void* tag_data;
uint32 tag_data_len;
uint32_t tag_data_len;
if (TIFFGetField(tif, kTIFFMetadataMap[i].tag, &tag_data_len, &tag_data) &&
!MetadataCopy((const char*)tag_data, tag_data_len, payload)) {
@ -188,7 +188,9 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
fprintf(stderr, "Error! Cannot retrieve TIFF samples-per-pixel info.\n");
goto End;
}
if (samples_per_px < 3 || samples_per_px > 4) goto End; // not supported
if (!(samples_per_px == 1 || samples_per_px == 3 || samples_per_px == 4)) {
goto End; // not supported
}
if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &image_width) &&
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &image_height))) {
@ -212,7 +214,7 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height)) {
if ((tile_width > 32 && tile_width / 2 > image_width) ||
(tile_height > 32 && tile_height / 2 > image_height) ||
ImgIoUtilCheckSizeArgumentsOverflow(
!ImgIoUtilCheckSizeArgumentsOverflow(
(uint64_t)tile_width * sizeof(*raster), tile_height)) {
fprintf(stderr, "Error! TIFF tile dimension (%d x %d) is too large.\n",
tile_width, tile_height);
@ -230,7 +232,7 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
alloc_size = (int64_t)(stride * image_height);
if (alloc_size < 0 || alloc_size != (tsize_t)alloc_size) goto End;
raster = (uint32*)_TIFFmalloc((tsize_t)alloc_size);
raster = (uint32_t*)_TIFFmalloc((tsize_t)alloc_size);
if (raster != NULL) {
if (TIFFReadRGBAImageOriented(tif, image_width, image_height, raster,
ORIENTATION_TOPLEFT, 1)) {

106
infra/common.sh Normal file
View 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
View 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
View 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
View 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
View 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}")/"* "${OUTPUT_DIR}"
else
# make a empty report to wipe out any old bug reports.
cat << EOT > "${OUTPUT_DIR}/index.html"
<html>
<body>
No bugs reported.
</body>
</html>
EOT
fi

View File

@ -9,7 +9,7 @@
# (the previous build will be erased if it exists).
#
# 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/).
# (https://www.ioncannon.net/programming/1483/using-webp-to-reduce-native-ios-app-size/).
set -e
@ -86,7 +86,7 @@ if [[ ! -e ${SRCDIR}/configure ]]; then
Error creating configure script!
This script requires the autoconf/automake and libtool to build. MacPorts can
be used to obtain these:
http://www.macports.org/install.php
https://www.macports.org/install.php
EOF
exit 1
fi
@ -133,10 +133,9 @@ for PLATFORM in ${PLATFORMS}; do
CFLAGS="${CFLAGS}"
set +x
# run make only in the src/ directory to create libwebp.a/libwebpdecoder.a
cd src/
make V=0
make install
# Build only the libraries, skip the examples.
make V=0 -C sharpyuv
make V=0 -C src install
LIBLIST+=" ${ROOTDIR}/lib/libwebp.a"
DECLIBLIST+=" ${ROOTDIR}/lib/libwebpdecoder.a"
@ -144,7 +143,6 @@ for PLATFORM in ${PLATFORMS}; do
DEMUXLIBLIST+=" ${ROOTDIR}/lib/libwebpdemux.a"
make clean
cd ..
export PATH=${OLDPATH}
done

View File

@ -47,7 +47,7 @@ else
endif
# To install libraries on Mac OS X:
# 1. Install MacPorts (http://www.macports.org/install.php)
# 1. Install MacPorts (https://www.macports.org/install.php)
# 2. Run "sudo port install jpeg"
# 3. Run "sudo port install libpng"
# 4. Run "sudo port install tiff"
@ -125,6 +125,14 @@ endif
ANIM_UTIL_OBJS = \
examples/anim_util.o \
SHARPYUV_OBJS = \
sharpyuv/sharpyuv.o \
sharpyuv/sharpyuv_csp.o \
sharpyuv/sharpyuv_dsp.o \
sharpyuv/sharpyuv_gamma.o \
sharpyuv/sharpyuv_neon.o \
sharpyuv/sharpyuv_sse2.o \
DEC_OBJS = \
src/dec/alpha_dec.o \
src/dec/buffer_dec.o \
@ -282,8 +290,8 @@ EXTRA_OBJS = \
extras/quality_estimate.o \
LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
$(UTILS_ENC_OBJS)
LIBWEBP_OBJS = $(SHARPYUV_OBJS) $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) \
$(DSP_ENC_OBJS) $(UTILS_ENC_OBJS)
LIBWEBPMUX_OBJS = $(MUX_OBJS)
LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS)
LIBWEBPEXTRA_OBJS = $(EXTRA_OBJS)
@ -304,6 +312,7 @@ HDRS = \
src/dec/vp8li_dec.h \
src/dec/webpi_dec.h \
src/dsp/common_sse2.h \
src/dsp/cpu.h \
src/dsp/dsp.h \
src/dsp/lossless.h \
src/dsp/lossless_common.h \
@ -489,6 +498,7 @@ clean:
examples/*.o examples/*~ \
extras/*.o extras/*~ \
imageio/*.o imageio/*~ \
sharpyuv/*.o sharpyuv/*~ \
src/dec/*.o src/dec/*~ \
src/demux/*.o src/demux/*~ \
src/dsp/*.o src/dsp/*~ \

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH CWEBP 1 "November 19, 2020"
.TH CWEBP 1 "March 17, 2022"
.SH NAME
cwebp \- compress an image file to a WebP file
.SH SYNOPSIS
@ -90,15 +90,17 @@ additional encoding possibilities and decide on the quality gain.
Lower value can result in faster processing time at the expense of
larger file size and lower compression quality.
.TP
.BI \-resize " width height
Resize the source to a rectangle with size \fBwidth\fP x \fBheight\fP.
If either (but not both) of the \fBwidth\fP or \fBheight\fP parameters is 0,
the value will be calculated preserving the aspect\-ratio.
.TP
.BI \-crop " x_position y_position width height
Crop the source to a rectangle with top\-left corner at coordinates
(\fBx_position\fP, \fBy_position\fP) and size \fBwidth\fP x \fBheight\fP.
This cropping area must be fully contained within the source rectangle.
Note: the cropping is applied \fIbefore\fP any scaling.
.TP
.BI \-resize " width height
Resize the source to a rectangle with size \fBwidth\fP x \fBheight\fP.
If either (but not both) of the \fBwidth\fP or \fBheight\fP parameters is 0,
the value will be calculated preserving the aspect\-ratio. Note: scaling
is applied \fIafter\fP cropping.
.TP
.B \-mt
Use multi\-threading for encoding, if possible.
@ -222,7 +224,7 @@ Compute and report average PSNR (Peak\-Signal\-To\-Noise ratio).
.TP
.B \-print_ssim
Compute and report average SSIM (structural similarity
metric, see http://en.wikipedia.org/wiki/SSIM for additional details).
metric, see https://en.wikipedia.org/wiki/SSIM for additional details).
.TP
.B \-print_lsim
Compute and report local similarity metric (sum of lowest error amongst the
@ -298,7 +300,7 @@ 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/
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXAMPLES
cwebp \-q 50 -lossless picture.png \-o picture_lossless.webp
@ -322,5 +324,5 @@ for the Debian project (and may be used by others).
.BR dwebp (1),
.BR gif2webp (1)
.br
Please refer to http://developers.google.com/speed/webp/ for additional
Please refer to https://developers.google.com/speed/webp/ for additional
information.

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH DWEBP 1 "November 19, 2020"
.TH DWEBP 1 "November 17, 2021"
.SH NAME
dwebp \- decompress a WebP file to an image file
.SH SYNOPSIS
@ -113,7 +113,7 @@ 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/
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXAMPLES
dwebp picture.webp \-o output.png
@ -138,7 +138,7 @@ for the Debian project (and may be used by others).
.BR gif2webp (1),
.BR webpmux (1)
.br
Please refer to http://developers.google.com/speed/webp/ for additional
Please refer to https://developers.google.com/speed/webp/ for additional
information.
.SS Output file format details
PAM: http://netpbm.sourceforge.net/doc/pam.html

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH GIF2WEBP 1 "May 1, 2020"
.TH GIF2WEBP 1 "November 17, 2021"
.SH NAME
gif2webp \- Convert a GIF image to WebP
.SH SYNOPSIS
@ -131,7 +131,7 @@ 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/
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXAMPLES
gif2webp picture.gif \-o picture.webp
@ -160,5 +160,5 @@ Debian project (and may be used by others).
.BR dwebp (1),
.BR webpmux (1)
.br
Please refer to http://developers.google.com/speed/webp/ for additional
Please refer to https://developers.google.com/speed/webp/ for additional
information.

View File

@ -1,10 +1,10 @@
.\" Hey, EMACS: -*- nroff -*-
.TH IMG2WEBP 1 "May 1, 2020"
.TH IMG2WEBP 1 "January 5, 2022"
.SH NAME
img2webp \- create animated WebP file from a sequence of input images.
.SH SYNOPSIS
.B img2webp
[file_level_options] [files] [per_frame_options...]
[file_options] [[frame_options] frame_file]...
.br
.B img2webp argument_file_name
.br
@ -86,7 +86,7 @@ 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/
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH AUTHORS
\fBimg2webp\fP is a part of libwebp and was written by the WebP team.
@ -101,5 +101,5 @@ for the Debian project (and may be used by others).
.BR webpmux (1),
.BR gif2webp (1)
.br
Please refer to http://developers.google.com/speed/webp/ for additional
Please refer to https://developers.google.com/speed/webp/ for additional
information.

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH VWEBP 1 "June 5, 2019"
.TH VWEBP 1 "November 17, 2021"
.SH NAME
vwebp \- decompress a WebP file and display it in a window
.SH SYNOPSIS
@ -77,7 +77,7 @@ 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/
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXAMPLES
vwebp picture.webp
@ -97,5 +97,5 @@ This manual page was written for the Debian project (and may be used by others).
.SH SEE ALSO
.BR dwebp (1)
.br
Please refer to http://developers.google.com/speed/webp/ for additional
Please refer to https://developers.google.com/speed/webp/ for additional
information.

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH WEBPINFO 1 "November 24, 2017"
.TH WEBPINFO 1 "November 17, 2021"
.SH NAME
webpinfo \- print out the chunk level structure of WebP files
along with basic integrity checks.
@ -52,7 +52,7 @@ 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/
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXAMPLES
.br
@ -76,5 +76,5 @@ 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
Please refer to https://developers.google.com/speed/webp/ for additional
information.

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH WEBPMUX 1 "December 12, 2020"
.TH WEBPMUX 1 "November 17, 2021"
.SH NAME
webpmux \- create animated WebP files from non\-animated WebP images, extract
frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
@ -82,6 +82,12 @@ 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
Set ICC profile.
.P
@ -185,7 +191,7 @@ 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/
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXAMPLES
.P
@ -261,5 +267,5 @@ for the Debian project (and may be used by others).
.BR dwebp (1),
.BR gif2webp (1)
.br
Please refer to http://developers.google.com/speed/webp/ for additional
Please refer to https://developers.google.com/speed/webp/ for additional
information.

34
sharpyuv/Makefile.am Normal file
View File

@ -0,0 +1,34 @@
AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir)
AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src
noinst_LTLIBRARIES =
noinst_LTLIBRARIES += libsharpyuv.la
noinst_LTLIBRARIES += libsharpyuv_sse2.la
noinst_LTLIBRARIES += libsharpyuv_neon.la
noinst_HEADERS =
noinst_HEADERS += ../src/webp/types.h
noinst_HEADERS += ../src/dsp/cpu.h
libsharpyuv_sse2_la_SOURCES =
libsharpyuv_sse2_la_SOURCES += sharpyuv_sse2.c
libsharpyuv_sse2_la_CPPFLAGS = $(libsharpyuv_la_CPPFLAGS)
libsharpyuv_sse2_la_CFLAGS = $(AM_CFLAGS) $(SSE2_FLAGS)
libsharpyuv_neon_la_SOURCES =
libsharpyuv_neon_la_SOURCES += sharpyuv_neon.c
libsharpyuv_neon_la_CPPFLAGS = $(libsharpyuv_la_CPPFLAGS)
libsharpyuv_neon_la_CFLAGS = $(AM_CFLAGS) $(NEON_FLAGS)
libsharpyuv_la_SOURCES =
libsharpyuv_la_SOURCES += sharpyuv_csp.c sharpyuv_csp.h
libsharpyuv_la_SOURCES += sharpyuv_dsp.c sharpyuv_dsp.h
libsharpyuv_la_SOURCES += sharpyuv_gamma.c sharpyuv_gamma.h
libsharpyuv_la_SOURCES += sharpyuv.c sharpyuv.h
libsharpyuv_la_CPPFLAGS = $(AM_CPPFLAGS)
libsharpyuv_la_LDFLAGS =
libsharpyuv_la_LIBADD =
libsharpyuv_la_LIBADD += libsharpyuv_sse2.la
libsharpyuv_la_LIBADD += libsharpyuv_neon.la
noinst_PROGRAMS =

498
sharpyuv/sharpyuv.c Normal file
View File

@ -0,0 +1,498 @@
// Copyright 2022 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Sharp RGB to YUV conversion.
//
// Author: Skal (pascal.massimino@gmail.com)
#include "sharpyuv/sharpyuv.h"
#include <assert.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "src/webp/types.h"
#include "src/dsp/cpu.h"
#include "sharpyuv/sharpyuv_dsp.h"
#include "sharpyuv/sharpyuv_gamma.h"
//------------------------------------------------------------------------------
// Sharp RGB->YUV conversion
static const int kNumIterations = 4;
#define YUV_FIX 16 // fixed-point precision for RGB->YUV
static const int kYuvHalf = 1 << (YUV_FIX - 1);
// Max bit depth so that intermediate calculations fit in 16 bits.
static const int kMaxBitDepth = 14;
// Returns the precision shift to use based on the input rgb_bit_depth.
static int GetPrecisionShift(int rgb_bit_depth) {
// Try to add 2 bits of precision if it fits in kMaxBitDepth. Otherwise remove
// bits if needed.
return ((rgb_bit_depth + 2) <= kMaxBitDepth) ? 2
: (kMaxBitDepth - rgb_bit_depth);
}
typedef int16_t fixed_t; // signed type with extra precision for UV
typedef uint16_t fixed_y_t; // unsigned type with extra precision for W
//------------------------------------------------------------------------------
static uint8_t clip_8b(fixed_t v) {
return (!(v & ~0xff)) ? (uint8_t)v : (v < 0) ? 0u : 255u;
}
static uint16_t clip(fixed_t v, int max) {
return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v;
}
static fixed_y_t clip_bit_depth(int y, int bit_depth) {
const int max = (1 << bit_depth) - 1;
return (!(y & ~max)) ? (fixed_y_t)y : (y < 0) ? 0 : max;
}
//------------------------------------------------------------------------------
static int RGBToGray(int64_t r, int64_t g, int64_t b) {
const int64_t luma = 13933 * r + 46871 * g + 4732 * b + kYuvHalf;
return (int)(luma >> YUV_FIX);
}
static uint32_t ScaleDown(uint16_t a, uint16_t b, uint16_t c, uint16_t d,
int rgb_bit_depth) {
const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth);
const uint32_t A = SharpYuvGammaToLinear(a, bit_depth);
const uint32_t B = SharpYuvGammaToLinear(b, bit_depth);
const uint32_t C = SharpYuvGammaToLinear(c, bit_depth);
const uint32_t D = SharpYuvGammaToLinear(d, bit_depth);
return SharpYuvLinearToGamma((A + B + C + D + 2) >> 2, bit_depth);
}
static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int w,
int rgb_bit_depth) {
const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth);
int i;
for (i = 0; i < w; ++i) {
const uint32_t R = SharpYuvGammaToLinear(src[0 * w + i], bit_depth);
const uint32_t G = SharpYuvGammaToLinear(src[1 * w + i], bit_depth);
const uint32_t B = SharpYuvGammaToLinear(src[2 * w + i], bit_depth);
const uint32_t Y = RGBToGray(R, G, B);
dst[i] = (fixed_y_t)SharpYuvLinearToGamma(Y, bit_depth);
}
}
static void UpdateChroma(const fixed_y_t* src1, const fixed_y_t* src2,
fixed_t* dst, int uv_w, int rgb_bit_depth) {
int i;
for (i = 0; i < uv_w; ++i) {
const int r =
ScaleDown(src1[0 * uv_w + 0], src1[0 * uv_w + 1], src2[0 * uv_w + 0],
src2[0 * uv_w + 1], rgb_bit_depth);
const int g =
ScaleDown(src1[2 * uv_w + 0], src1[2 * uv_w + 1], src2[2 * uv_w + 0],
src2[2 * uv_w + 1], rgb_bit_depth);
const int b =
ScaleDown(src1[4 * uv_w + 0], src1[4 * uv_w + 1], src2[4 * uv_w + 0],
src2[4 * uv_w + 1], rgb_bit_depth);
const int W = RGBToGray(r, g, b);
dst[0 * uv_w] = (fixed_t)(r - W);
dst[1 * uv_w] = (fixed_t)(g - W);
dst[2 * uv_w] = (fixed_t)(b - W);
dst += 1;
src1 += 2;
src2 += 2;
}
}
static void StoreGray(const fixed_y_t* rgb, fixed_y_t* y, int w) {
int i;
assert(w > 0);
for (i = 0; i < w; ++i) {
y[i] = RGBToGray(rgb[0 * w + i], rgb[1 * w + i], rgb[2 * w + i]);
}
}
//------------------------------------------------------------------------------
static WEBP_INLINE fixed_y_t Filter2(int A, int B, int W0, int bit_depth) {
const int v0 = (A * 3 + B + 2) >> 2;
return clip_bit_depth(v0 + W0, bit_depth);
}
//------------------------------------------------------------------------------
static WEBP_INLINE int Shift(int v, int shift) {
return (shift >= 0) ? (v << shift) : (v >> -shift);
}
static void ImportOneRow(const uint8_t* const r_ptr,
const uint8_t* const g_ptr,
const uint8_t* const b_ptr,
int rgb_step,
int rgb_bit_depth,
int pic_width,
fixed_y_t* const dst) {
// Convert the rgb_step from a number of bytes to a number of uint8_t or
// uint16_t values depending the bit depth.
const int step = (rgb_bit_depth > 8) ? rgb_step / 2 : rgb_step;
int i;
const int w = (pic_width + 1) & ~1;
for (i = 0; i < pic_width; ++i) {
const int off = i * step;
const int shift = GetPrecisionShift(rgb_bit_depth);
if (rgb_bit_depth == 8) {
dst[i + 0 * w] = Shift(r_ptr[off], shift);
dst[i + 1 * w] = Shift(g_ptr[off], shift);
dst[i + 2 * w] = Shift(b_ptr[off], shift);
} else {
dst[i + 0 * w] = Shift(((uint16_t*)r_ptr)[off], shift);
dst[i + 1 * w] = Shift(((uint16_t*)g_ptr)[off], shift);
dst[i + 2 * w] = Shift(((uint16_t*)b_ptr)[off], shift);
}
}
if (pic_width & 1) { // replicate rightmost pixel
dst[pic_width + 0 * w] = dst[pic_width + 0 * w - 1];
dst[pic_width + 1 * w] = dst[pic_width + 1 * w - 1];
dst[pic_width + 2 * w] = dst[pic_width + 2 * w - 1];
}
}
static void InterpolateTwoRows(const fixed_y_t* const best_y,
const fixed_t* prev_uv,
const fixed_t* cur_uv,
const fixed_t* next_uv,
int w,
fixed_y_t* out1,
fixed_y_t* out2,
int rgb_bit_depth) {
const int uv_w = w >> 1;
const int len = (w - 1) >> 1; // length to filter
int k = 3;
const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth);
while (k-- > 0) { // process each R/G/B segments in turn
// special boundary case for i==0
out1[0] = Filter2(cur_uv[0], prev_uv[0], best_y[0], bit_depth);
out2[0] = Filter2(cur_uv[0], next_uv[0], best_y[w], bit_depth);
SharpYuvFilterRow(cur_uv, prev_uv, len, best_y + 0 + 1, out1 + 1,
bit_depth);
SharpYuvFilterRow(cur_uv, next_uv, len, best_y + w + 1, out2 + 1,
bit_depth);
// special boundary case for i == w - 1 when w is even
if (!(w & 1)) {
out1[w - 1] = Filter2(cur_uv[uv_w - 1], prev_uv[uv_w - 1],
best_y[w - 1 + 0], bit_depth);
out2[w - 1] = Filter2(cur_uv[uv_w - 1], next_uv[uv_w - 1],
best_y[w - 1 + w], bit_depth);
}
out1 += w;
out2 += w;
prev_uv += uv_w;
cur_uv += uv_w;
next_uv += uv_w;
}
}
static WEBP_INLINE int RGBToYUVComponent(int r, int g, int b,
const int coeffs[4], int sfix) {
const int srounder = 1 << (YUV_FIX + sfix - 1);
const int luma = coeffs[0] * r + coeffs[1] * g + coeffs[2] * b +
coeffs[3] + srounder;
return (luma >> (YUV_FIX + sfix));
}
static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv,
uint8_t* y_ptr, int y_stride, uint8_t* u_ptr,
int u_stride, uint8_t* v_ptr, int v_stride,
int rgb_bit_depth,
int yuv_bit_depth, int width, int height,
const SharpYuvConversionMatrix* yuv_matrix) {
int i, j;
const fixed_t* const best_uv_base = best_uv;
const int w = (width + 1) & ~1;
const int h = (height + 1) & ~1;
const int uv_w = w >> 1;
const int uv_h = h >> 1;
const int sfix = GetPrecisionShift(rgb_bit_depth);
const int yuv_max = (1 << yuv_bit_depth) - 1;
for (best_uv = best_uv_base, j = 0; j < height; ++j) {
for (i = 0; i < width; ++i) {
const int off = (i >> 1);
const int W = best_y[i];
const int r = best_uv[off + 0 * uv_w] + W;
const int g = best_uv[off + 1 * uv_w] + W;
const int b = best_uv[off + 2 * uv_w] + W;
const int y = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_y, sfix);
if (yuv_bit_depth <= 8) {
y_ptr[i] = clip_8b(y);
} else {
((uint16_t*)y_ptr)[i] = clip(y, yuv_max);
}
}
best_y += w;
best_uv += (j & 1) * 3 * uv_w;
y_ptr += y_stride;
}
for (best_uv = best_uv_base, j = 0; j < uv_h; ++j) {
for (i = 0; i < uv_w; ++i) {
const int off = i;
// Note r, g and b values here are off by W, but a constant offset on all
// 3 components doesn't change the value of u and v with a YCbCr matrix.
const int r = best_uv[off + 0 * uv_w];
const int g = best_uv[off + 1 * uv_w];
const int b = best_uv[off + 2 * uv_w];
const int u = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_u, sfix);
const int v = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_v, sfix);
if (yuv_bit_depth <= 8) {
u_ptr[i] = clip_8b(u);
v_ptr[i] = clip_8b(v);
} else {
((uint16_t*)u_ptr)[i] = clip(u, yuv_max);
((uint16_t*)v_ptr)[i] = clip(v, yuv_max);
}
}
best_uv += 3 * uv_w;
u_ptr += u_stride;
v_ptr += v_stride;
}
return 1;
}
//------------------------------------------------------------------------------
// Main function
static void* SafeMalloc(uint64_t nmemb, size_t size) {
const uint64_t total_size = nmemb * (uint64_t)size;
if (total_size != (size_t)total_size) return NULL;
return malloc((size_t)total_size);
}
#define SAFE_ALLOC(W, H, T) ((T*)SafeMalloc((W) * (H), sizeof(T)))
static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
const uint8_t* b_ptr, int rgb_step, int rgb_stride,
int rgb_bit_depth, uint8_t* y_ptr, int y_stride,
uint8_t* u_ptr, int u_stride, uint8_t* v_ptr,
int v_stride, int yuv_bit_depth, int width,
int height,
const SharpYuvConversionMatrix* yuv_matrix) {
// we expand the right/bottom border if needed
const int w = (width + 1) & ~1;
const int h = (height + 1) & ~1;
const int uv_w = w >> 1;
const int uv_h = h >> 1;
uint64_t prev_diff_y_sum = ~0;
int j, iter;
// TODO(skal): allocate one big memory chunk. But for now, it's easier
// for valgrind debugging to have several chunks.
fixed_y_t* const tmp_buffer = SAFE_ALLOC(w * 3, 2, fixed_y_t); // scratch
fixed_y_t* const best_y_base = SAFE_ALLOC(w, h, fixed_y_t);
fixed_y_t* const target_y_base = SAFE_ALLOC(w, h, fixed_y_t);
fixed_y_t* const best_rgb_y = SAFE_ALLOC(w, 2, fixed_y_t);
fixed_t* const best_uv_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
fixed_t* const target_uv_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
fixed_t* const best_rgb_uv = SAFE_ALLOC(uv_w * 3, 1, fixed_t);
fixed_y_t* best_y = best_y_base;
fixed_y_t* target_y = target_y_base;
fixed_t* best_uv = best_uv_base;
fixed_t* target_uv = target_uv_base;
const uint64_t diff_y_threshold = (uint64_t)(3.0 * w * h);
int ok;
assert(w > 0);
assert(h > 0);
if (best_y_base == NULL || best_uv_base == NULL ||
target_y_base == NULL || target_uv_base == NULL ||
best_rgb_y == NULL || best_rgb_uv == NULL ||
tmp_buffer == NULL) {
ok = 0;
goto End;
}
// Import RGB samples to W/RGB representation.
for (j = 0; j < height; j += 2) {
const int is_last_row = (j == height - 1);
fixed_y_t* const src1 = tmp_buffer + 0 * w;
fixed_y_t* const src2 = tmp_buffer + 3 * w;
// prepare two rows of input
ImportOneRow(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth, width,
src1);
if (!is_last_row) {
ImportOneRow(r_ptr + rgb_stride, g_ptr + rgb_stride, b_ptr + rgb_stride,
rgb_step, rgb_bit_depth, width, src2);
} else {
memcpy(src2, src1, 3 * w * sizeof(*src2));
}
StoreGray(src1, best_y + 0, w);
StoreGray(src2, best_y + w, w);
UpdateW(src1, target_y, w, rgb_bit_depth);
UpdateW(src2, target_y + w, w, rgb_bit_depth);
UpdateChroma(src1, src2, target_uv, uv_w, rgb_bit_depth);
memcpy(best_uv, target_uv, 3 * uv_w * sizeof(*best_uv));
best_y += 2 * w;
best_uv += 3 * uv_w;
target_y += 2 * w;
target_uv += 3 * uv_w;
r_ptr += 2 * rgb_stride;
g_ptr += 2 * rgb_stride;
b_ptr += 2 * rgb_stride;
}
// Iterate and resolve clipping conflicts.
for (iter = 0; iter < kNumIterations; ++iter) {
const fixed_t* cur_uv = best_uv_base;
const fixed_t* prev_uv = best_uv_base;
uint64_t diff_y_sum = 0;
best_y = best_y_base;
best_uv = best_uv_base;
target_y = target_y_base;
target_uv = target_uv_base;
for (j = 0; j < h; j += 2) {
fixed_y_t* const src1 = tmp_buffer + 0 * w;
fixed_y_t* const src2 = tmp_buffer + 3 * w;
{
const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0);
InterpolateTwoRows(best_y, prev_uv, cur_uv, next_uv, w,
src1, src2, rgb_bit_depth);
prev_uv = cur_uv;
cur_uv = next_uv;
}
UpdateW(src1, best_rgb_y + 0 * w, w, rgb_bit_depth);
UpdateW(src2, best_rgb_y + 1 * w, w, rgb_bit_depth);
UpdateChroma(src1, src2, best_rgb_uv, uv_w, rgb_bit_depth);
// update two rows of Y and one row of RGB
diff_y_sum +=
SharpYuvUpdateY(target_y, best_rgb_y, best_y, 2 * w,
rgb_bit_depth + GetPrecisionShift(rgb_bit_depth));
SharpYuvUpdateRGB(target_uv, best_rgb_uv, best_uv, 3 * uv_w);
best_y += 2 * w;
best_uv += 3 * uv_w;
target_y += 2 * w;
target_uv += 3 * uv_w;
}
// test exit condition
if (iter > 0) {
if (diff_y_sum < diff_y_threshold) break;
if (diff_y_sum > prev_diff_y_sum) break;
}
prev_diff_y_sum = diff_y_sum;
}
// final reconstruction
ok = ConvertWRGBToYUV(best_y_base, best_uv_base, y_ptr, y_stride, u_ptr,
u_stride, v_ptr, v_stride, rgb_bit_depth, yuv_bit_depth,
width, height, yuv_matrix);
End:
free(best_y_base);
free(best_uv_base);
free(target_y_base);
free(target_uv_base);
free(best_rgb_y);
free(best_rgb_uv);
free(tmp_buffer);
return ok;
}
#undef SAFE_ALLOC
// Hidden exported init function.
// By default SharpYuvConvert calls it with NULL. If needed, users can declare
// it as extern and call it with a VP8CPUInfo function.
extern void SharpYuvInit(VP8CPUInfo cpu_info_func);
void SharpYuvInit(VP8CPUInfo cpu_info_func) {
static volatile VP8CPUInfo sharpyuv_last_cpuinfo_used =
(VP8CPUInfo)&sharpyuv_last_cpuinfo_used;
const int initialized =
(sharpyuv_last_cpuinfo_used != (VP8CPUInfo)&sharpyuv_last_cpuinfo_used);
if (cpu_info_func == NULL && initialized) return;
if (sharpyuv_last_cpuinfo_used == cpu_info_func) return;
SharpYuvInitDsp(cpu_info_func);
if (!initialized) {
SharpYuvInitGammaTables();
}
sharpyuv_last_cpuinfo_used = cpu_info_func;
}
int SharpYuvConvert(const void* r_ptr, const void* g_ptr,
const void* b_ptr, int rgb_step, int rgb_stride,
int rgb_bit_depth, void* y_ptr, int y_stride,
void* u_ptr, int u_stride, void* v_ptr,
int v_stride, int yuv_bit_depth, int width,
int height, const SharpYuvConversionMatrix* yuv_matrix) {
SharpYuvConversionMatrix scaled_matrix;
const int rgb_max = (1 << rgb_bit_depth) - 1;
const int rgb_round = 1 << (rgb_bit_depth - 1);
const int yuv_max = (1 << yuv_bit_depth) - 1;
const int sfix = GetPrecisionShift(rgb_bit_depth);
if (width < 1 || height < 1 || width == INT_MAX || height == INT_MAX ||
r_ptr == NULL || g_ptr == NULL || b_ptr == NULL || y_ptr == NULL ||
u_ptr == NULL || v_ptr == NULL) {
return 0;
}
if (rgb_bit_depth != 8 && rgb_bit_depth != 10 && rgb_bit_depth != 12 &&
rgb_bit_depth != 16) {
return 0;
}
if (yuv_bit_depth != 8 && yuv_bit_depth != 10 && yuv_bit_depth != 12) {
return 0;
}
if (rgb_bit_depth > 8 && (rgb_step % 2 != 0 || rgb_stride %2 != 0)) {
// Step/stride should be even for uint16_t buffers.
return 0;
}
if (yuv_bit_depth > 8 &&
(y_stride % 2 != 0 || u_stride % 2 != 0 || v_stride % 2 != 0)) {
// Stride should be even for uint16_t buffers.
return 0;
}
SharpYuvInit(NULL);
// Add scaling factor to go from rgb_bit_depth to yuv_bit_depth, to the
// rgb->yuv conversion matrix.
if (rgb_bit_depth == yuv_bit_depth) {
memcpy(&scaled_matrix, yuv_matrix, sizeof(scaled_matrix));
} else {
int i;
for (i = 0; i < 3; ++i) {
scaled_matrix.rgb_to_y[i] =
(yuv_matrix->rgb_to_y[i] * yuv_max + rgb_round) / rgb_max;
scaled_matrix.rgb_to_u[i] =
(yuv_matrix->rgb_to_u[i] * yuv_max + rgb_round) / rgb_max;
scaled_matrix.rgb_to_v[i] =
(yuv_matrix->rgb_to_v[i] * yuv_max + rgb_round) / rgb_max;
}
}
// Also incorporate precision change scaling.
scaled_matrix.rgb_to_y[3] = Shift(yuv_matrix->rgb_to_y[3], sfix);
scaled_matrix.rgb_to_u[3] = Shift(yuv_matrix->rgb_to_u[3], sfix);
scaled_matrix.rgb_to_v[3] = Shift(yuv_matrix->rgb_to_v[3], sfix);
return DoSharpArgbToYuv(r_ptr, g_ptr, b_ptr, rgb_step, rgb_stride,
rgb_bit_depth, y_ptr, y_stride, u_ptr, u_stride,
v_ptr, v_stride, yuv_bit_depth, width, height,
&scaled_matrix);
}
//------------------------------------------------------------------------------

81
sharpyuv/sharpyuv.h Normal file
View File

@ -0,0 +1,81 @@
// Copyright 2022 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Sharp RGB to YUV conversion.
#ifndef WEBP_SHARPYUV_SHARPYUV_H_
#define WEBP_SHARPYUV_SHARPYUV_H_
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
#endif
// SharpYUV API version following the convention from semver.org
#define SHARPYUV_VERSION_MAJOR 0
#define SHARPYUV_VERSION_MINOR 1
#define SHARPYUV_VERSION_PATCH 0
// Version as a uint32_t. The major number is the high 8 bits.
// The minor number is the middle 8 bits. The patch number is the low 16 bits.
#define SHARPYUV_MAKE_VERSION(MAJOR, MINOR, PATCH) \
(((MAJOR) << 24) | ((MINOR) << 16) | (PATCH))
#define SHARPYUV_VERSION \
SHARPYUV_MAKE_VERSION(SHARPYUV_VERSION_MAJOR, SHARPYUV_VERSION_MINOR, \
SHARPYUV_VERSION_PATCH)
// RGB to YUV conversion matrix, in 16 bit fixed point.
// y = rgb_to_y[0] * r + rgb_to_y[1] * g + rgb_to_y[2] * b + rgb_to_y[3]
// u = rgb_to_u[0] * r + rgb_to_u[1] * g + rgb_to_u[2] * b + rgb_to_u[3]
// v = rgb_to_v[0] * r + rgb_to_v[1] * g + rgb_to_v[2] * b + rgb_to_v[3]
// Then y, u and v values are divided by 1<<16 and rounded.
typedef struct {
int rgb_to_y[4];
int rgb_to_u[4];
int rgb_to_v[4];
} SharpYuvConversionMatrix;
// Converts RGB to YUV420 using a downsampling algorithm that minimizes
// artefacts caused by chroma subsampling.
// This is slower than standard downsampling (averaging of 4 UV values).
// Assumes that the image will be upsampled using a bilinear filter. If nearest
// neighbor is used instead, the upsampled image might look worse than with
// standard downsampling.
// r_ptr, g_ptr, b_ptr: pointers to the source r, g and b channels. Should point
// to uint8_t buffers if rgb_bit_depth is 8, or uint16_t buffers otherwise.
// rgb_step: distance in bytes between two horizontally adjacent pixels on the
// r, g and b channels. If rgb_bit_depth is > 8, it should be a
// multiple of 2.
// rgb_stride: distance in bytes between two vertically adjacent pixels on the
// r, g, and b channels. If rgb_bit_depth is > 8, it should be a
// multiple of 2.
// rgb_bit_depth: number of bits for each r/g/b value. One of: 8, 10, 12, 16.
// Note: 16 bit input is truncated to 14 bits before conversion to yuv.
// yuv_bit_depth: number of bits for each y/u/v value. One of: 8, 10, 12.
// y_ptr, u_ptr, v_ptr: pointers to the destination y, u and v channels. Should
// point to uint8_t buffers if yuv_bit_depth is 8, or uint16_t buffers
// otherwise.
// y_stride, u_stride, v_stride: distance in bytes between two vertically
// adjacent pixels on the y, u and v channels. If yuv_bit_depth > 8, they
// should be multiples of 2.
// width, height: width and height of the image in pixels
int SharpYuvConvert(const void* r_ptr, const void* g_ptr, const void* b_ptr,
int rgb_step, int rgb_stride, int rgb_bit_depth,
void* y_ptr, int y_stride, void* u_ptr, int u_stride,
void* v_ptr, int v_stride, int yuv_bit_depth, int width,
int height, const SharpYuvConversionMatrix* yuv_matrix);
// TODO(b/194336375): Add YUV444 to YUV420 conversion. Maybe also add 422
// support (it's rarely used in practice, especially for images).
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_SHARPYUV_SHARPYUV_H_

110
sharpyuv/sharpyuv_csp.c Normal file
View File

@ -0,0 +1,110 @@
// Copyright 2022 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Colorspace utilities.
#include "sharpyuv/sharpyuv_csp.h"
#include <assert.h>
#include <math.h>
#include <string.h>
static int ToFixed16(float f) { return (int)floor(f * (1 << 16) + 0.5f); }
void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space,
SharpYuvConversionMatrix* matrix) {
const float kr = yuv_color_space->kr;
const float kb = yuv_color_space->kb;
const float kg = 1.0f - kr - kb;
const float cr = 0.5f / (1.0f - kb);
const float cb = 0.5f / (1.0f - kr);
const int shift = yuv_color_space->bit_depth - 8;
const float denom = (float)((1 << yuv_color_space->bit_depth) - 1);
float scale_y = 1.0f;
float add_y = 0.0f;
float scale_u = cr;
float scale_v = cb;
float add_uv = (float)(128 << shift);
assert(yuv_color_space->bit_depth >= 8);
if (yuv_color_space->range == kSharpYuvRangeLimited) {
scale_y *= (219 << shift) / denom;
scale_u *= (224 << shift) / denom;
scale_v *= (224 << shift) / denom;
add_y = (float)(16 << shift);
}
matrix->rgb_to_y[0] = ToFixed16(kr * scale_y);
matrix->rgb_to_y[1] = ToFixed16(kg * scale_y);
matrix->rgb_to_y[2] = ToFixed16(kb * scale_y);
matrix->rgb_to_y[3] = ToFixed16(add_y);
matrix->rgb_to_u[0] = ToFixed16(-kr * scale_u);
matrix->rgb_to_u[1] = ToFixed16(-kg * scale_u);
matrix->rgb_to_u[2] = ToFixed16((1 - kb) * scale_u);
matrix->rgb_to_u[3] = ToFixed16(add_uv);
matrix->rgb_to_v[0] = ToFixed16((1 - kr) * scale_v);
matrix->rgb_to_v[1] = ToFixed16(-kg * scale_v);
matrix->rgb_to_v[2] = ToFixed16(-kb * scale_v);
matrix->rgb_to_v[3] = ToFixed16(add_uv);
}
// Matrices are in YUV_FIX fixed point precision.
// WebP's matrix, similar but not identical to kRec601LimitedMatrix.
static const SharpYuvConversionMatrix kWebpMatrix = {
{16839, 33059, 6420, 16 << 16},
{-9719, -19081, 28800, 128 << 16},
{28800, -24116, -4684, 128 << 16},
};
// Kr=0.2990f Kb=0.1140f bits=8 range=kSharpYuvRangeLimited
static const SharpYuvConversionMatrix kRec601LimitedMatrix = {
{16829, 33039, 6416, 16 << 16},
{-9714, -19071, 28784, 128 << 16},
{28784, -24103, -4681, 128 << 16},
};
// Kr=0.2990f Kb=0.1140f bits=8 range=kSharpYuvRangeFull
static const SharpYuvConversionMatrix kRec601FullMatrix = {
{19595, 38470, 7471, 0},
{-11058, -21710, 32768, 128 << 16},
{32768, -27439, -5329, 128 << 16},
};
// Kr=0.2126f Kb=0.0722f bits=8 range=kSharpYuvRangeLimited
static const SharpYuvConversionMatrix kRec709LimitedMatrix = {
{11966, 40254, 4064, 16 << 16},
{-6596, -22189, 28784, 128 << 16},
{28784, -26145, -2639, 128 << 16},
};
// Kr=0.2126f Kb=0.0722f bits=8 range=kSharpYuvRangeFull
static const SharpYuvConversionMatrix kRec709FullMatrix = {
{13933, 46871, 4732, 0},
{-7509, -25259, 32768, 128 << 16},
{32768, -29763, -3005, 128 << 16},
};
const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix(
SharpYuvMatrixType matrix_type) {
switch (matrix_type) {
case kSharpYuvMatrixWebp:
return &kWebpMatrix;
case kSharpYuvMatrixRec601Limited:
return &kRec601LimitedMatrix;
case kSharpYuvMatrixRec601Full:
return &kRec601FullMatrix;
case kSharpYuvMatrixRec709Limited:
return &kRec709LimitedMatrix;
case kSharpYuvMatrixRec709Full:
return &kRec709FullMatrix;
case kSharpYuvMatrixNum:
return NULL;
}
return NULL;
}

59
sharpyuv/sharpyuv_csp.h Normal file
View File

@ -0,0 +1,59 @@
// Copyright 2022 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Colorspace utilities.
#ifndef WEBP_SHARPYUV_SHARPYUV_CSP_H_
#define WEBP_SHARPYUV_SHARPYUV_CSP_H_
#include "sharpyuv/sharpyuv.h"
#ifdef __cplusplus
extern "C" {
#endif
// Range of YUV values.
typedef enum {
kSharpYuvRangeFull, // YUV values between [0;255] (for 8 bit)
kSharpYuvRangeLimited // Y in [16;235], YUV in [16;240] (for 8 bit)
} SharpYuvRange;
// Constants that define a YUV color space.
typedef struct {
// Kr and Kb are defined such that:
// Y = Kr * r + Kg * g + Kb * b where Kg = 1 - Kr - Kb.
float kr;
float kb;
int bit_depth; // 8, 10 or 12
SharpYuvRange range;
} SharpYuvColorSpace;
// Fills in 'matrix' for the given YUVColorSpace.
void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space,
SharpYuvConversionMatrix* matrix);
// Enums for precomputed conversion matrices.
typedef enum {
kSharpYuvMatrixWebp = 0,
kSharpYuvMatrixRec601Limited,
kSharpYuvMatrixRec601Full,
kSharpYuvMatrixRec709Limited,
kSharpYuvMatrixRec709Full,
kSharpYuvMatrixNum
} SharpYuvMatrixType;
// Returns a pointer to a matrix for one of the predefined colorspaces.
const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix(
SharpYuvMatrixType matrix_type);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_SHARPYUV_SHARPYUV_CSP_H_

102
sharpyuv/sharpyuv_dsp.c Normal file
View File

@ -0,0 +1,102 @@
// Copyright 2022 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Speed-critical functions for Sharp YUV.
//
// Author: Skal (pascal.massimino@gmail.com)
#include "sharpyuv/sharpyuv_dsp.h"
#include <assert.h>
#include <stdlib.h>
#include "src/dsp/cpu.h"
//-----------------------------------------------------------------------------
#if !WEBP_NEON_OMIT_C_CODE
static uint16_t clip(int v, int max) {
return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v;
}
static uint64_t SharpYuvUpdateY_C(const uint16_t* ref, const uint16_t* src,
uint16_t* dst, int len, int bit_depth) {
uint64_t diff = 0;
int i;
const int max_y = (1 << bit_depth) - 1;
for (i = 0; i < len; ++i) {
const int diff_y = ref[i] - src[i];
const int new_y = (int)dst[i] + diff_y;
dst[i] = clip(new_y, max_y);
diff += (uint64_t)abs(diff_y);
}
return diff;
}
static void SharpYuvUpdateRGB_C(const int16_t* ref, const int16_t* src,
int16_t* dst, int len) {
int i;
for (i = 0; i < len; ++i) {
const int diff_uv = ref[i] - src[i];
dst[i] += diff_uv;
}
}
static void SharpYuvFilterRow_C(const int16_t* A, const int16_t* B, int len,
const uint16_t* best_y, uint16_t* out,
int bit_depth) {
int i;
const int max_y = (1 << bit_depth) - 1;
for (i = 0; i < len; ++i, ++A, ++B) {
const int v0 = (A[0] * 9 + A[1] * 3 + B[0] * 3 + B[1] + 8) >> 4;
const int v1 = (A[1] * 9 + A[0] * 3 + B[1] * 3 + B[0] + 8) >> 4;
out[2 * i + 0] = clip(best_y[2 * i + 0] + v0, max_y);
out[2 * i + 1] = clip(best_y[2 * i + 1] + v1, max_y);
}
}
#endif // !WEBP_NEON_OMIT_C_CODE
//-----------------------------------------------------------------------------
uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref,
uint16_t* dst, int len, int bit_depth);
void (*SharpYuvUpdateRGB)(const int16_t* src, const int16_t* ref, int16_t* dst,
int len);
void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len,
const uint16_t* best_y, uint16_t* out,
int bit_depth);
extern void InitSharpYuvSSE2(void);
extern void InitSharpYuvNEON(void);
void SharpYuvInitDsp(VP8CPUInfo cpu_info_func) {
(void)cpu_info_func;
#if !WEBP_NEON_OMIT_C_CODE
SharpYuvUpdateY = SharpYuvUpdateY_C;
SharpYuvUpdateRGB = SharpYuvUpdateRGB_C;
SharpYuvFilterRow = SharpYuvFilterRow_C;
#endif
#if defined(WEBP_HAVE_SSE2)
if (cpu_info_func == NULL || cpu_info_func(kSSE2)) {
InitSharpYuvSSE2();
}
#endif // WEBP_HAVE_SSE2
#if defined(WEBP_HAVE_NEON)
if (WEBP_NEON_OMIT_C_CODE || cpu_info_func == NULL || cpu_info_func(kNEON)) {
InitSharpYuvNEON();
}
#endif // WEBP_HAVE_NEON
assert(SharpYuvUpdateY != NULL);
assert(SharpYuvUpdateRGB != NULL);
assert(SharpYuvFilterRow != NULL);
}

29
sharpyuv/sharpyuv_dsp.h Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2022 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Speed-critical functions for Sharp YUV.
#ifndef WEBP_SHARPYUV_SHARPYUV_DSP_H_
#define WEBP_SHARPYUV_SHARPYUV_DSP_H_
#include <stdint.h>
#include "src/dsp/cpu.h"
extern uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref,
uint16_t* dst, int len, int bit_depth);
extern void (*SharpYuvUpdateRGB)(const int16_t* src, const int16_t* ref,
int16_t* dst, int len);
extern void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len,
const uint16_t* best_y, uint16_t* out,
int bit_depth);
void SharpYuvInitDsp(VP8CPUInfo cpu_info_func);
#endif // WEBP_SHARPYUV_SHARPYUV_DSP_H_

114
sharpyuv/sharpyuv_gamma.c Normal file
View File

@ -0,0 +1,114 @@
// Copyright 2022 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Gamma correction utilities.
#include "sharpyuv/sharpyuv_gamma.h"
#include <assert.h>
#include <math.h>
#include <stdint.h>
#include "src/webp/types.h"
// Gamma correction compensates loss of resolution during chroma subsampling.
// Size of pre-computed table for converting from gamma to linear.
#define GAMMA_TO_LINEAR_TAB_BITS 10
#define GAMMA_TO_LINEAR_TAB_SIZE (1 << GAMMA_TO_LINEAR_TAB_BITS)
static uint32_t kGammaToLinearTabS[GAMMA_TO_LINEAR_TAB_SIZE + 2];
#define LINEAR_TO_GAMMA_TAB_BITS 9
#define LINEAR_TO_GAMMA_TAB_SIZE (1 << LINEAR_TO_GAMMA_TAB_BITS)
static uint32_t kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE + 2];
static const double kGammaF = 1. / 0.45;
#define GAMMA_TO_LINEAR_BITS 16
static volatile int kGammaTablesSOk = 0;
void SharpYuvInitGammaTables(void) {
assert(GAMMA_TO_LINEAR_BITS <= 16);
if (!kGammaTablesSOk) {
int v;
const double a = 0.09929682680944;
const double thresh = 0.018053968510807;
const double final_scale = 1 << GAMMA_TO_LINEAR_BITS;
// Precompute gamma to linear table.
{
const double norm = 1. / GAMMA_TO_LINEAR_TAB_SIZE;
const double a_rec = 1. / (1. + a);
for (v = 0; v <= GAMMA_TO_LINEAR_TAB_SIZE; ++v) {
const double g = norm * v;
double value;
if (g <= thresh * 4.5) {
value = g / 4.5;
} else {
value = pow(a_rec * (g + a), kGammaF);
}
kGammaToLinearTabS[v] = (uint32_t)(value * final_scale + .5);
}
// to prevent small rounding errors to cause read-overflow:
kGammaToLinearTabS[GAMMA_TO_LINEAR_TAB_SIZE + 1] =
kGammaToLinearTabS[GAMMA_TO_LINEAR_TAB_SIZE];
}
// Precompute linear to gamma table.
{
const double scale = 1. / LINEAR_TO_GAMMA_TAB_SIZE;
for (v = 0; v <= LINEAR_TO_GAMMA_TAB_SIZE; ++v) {
const double g = scale * v;
double value;
if (g <= thresh) {
value = 4.5 * g;
} else {
value = (1. + a) * pow(g, 1. / kGammaF) - a;
}
kLinearToGammaTabS[v] =
(uint32_t)(final_scale * value + 0.5);
}
// to prevent small rounding errors to cause read-overflow:
kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE + 1] =
kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE];
}
kGammaTablesSOk = 1;
}
}
static WEBP_INLINE int Shift(int v, int shift) {
return (shift >= 0) ? (v << shift) : (v >> -shift);
}
static WEBP_INLINE uint32_t FixedPointInterpolation(int v, uint32_t* tab,
int tab_pos_shift_right,
int tab_value_shift) {
const uint32_t tab_pos = Shift(v, -tab_pos_shift_right);
// fractional part, in 'tab_pos_shift' fixed-point precision
const uint32_t x = v - (tab_pos << tab_pos_shift_right); // fractional part
// v0 / v1 are in kGammaToLinearBits fixed-point precision (range [0..1])
const uint32_t v0 = Shift(tab[tab_pos + 0], tab_value_shift);
const uint32_t v1 = Shift(tab[tab_pos + 1], tab_value_shift);
// Final interpolation.
const uint32_t v2 = (v1 - v0) * x; // note: v1 >= v0.
const int half =
(tab_pos_shift_right > 0) ? 1 << (tab_pos_shift_right - 1) : 0;
const uint32_t result = v0 + ((v2 + half) >> tab_pos_shift_right);
return result;
}
uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth) {
const int shift = GAMMA_TO_LINEAR_TAB_BITS - bit_depth;
if (shift > 0) {
return kGammaToLinearTabS[v << shift];
}
return FixedPointInterpolation(v, kGammaToLinearTabS, -shift, 0);
}
uint16_t SharpYuvLinearToGamma(uint32_t value, int bit_depth) {
return FixedPointInterpolation(
value, kLinearToGammaTabS,
(GAMMA_TO_LINEAR_BITS - LINEAR_TO_GAMMA_TAB_BITS),
bit_depth - GAMMA_TO_LINEAR_BITS);
}

35
sharpyuv/sharpyuv_gamma.h Normal file
View File

@ -0,0 +1,35 @@
// Copyright 2022 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Gamma correction utilities.
#ifndef WEBP_SHARPYUV_SHARPYUV_GAMMA_H_
#define WEBP_SHARPYUV_SHARPYUV_GAMMA_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// Initializes precomputed tables. Must be called once before calling
// SharpYuvGammaToLinear or SharpYuvLinearToGamma.
void SharpYuvInitGammaTables(void);
// Converts a gamma color value on 'bit_depth' bits to a 16 bit linear value.
uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth);
// Converts a 16 bit linear color value to a gamma value on 'bit_depth' bits.
uint16_t SharpYuvLinearToGamma(uint32_t value, int bit_depth);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_SHARPYUV_SHARPYUV_GAMMA_H_

182
sharpyuv/sharpyuv_neon.c Normal file
View File

@ -0,0 +1,182 @@
// Copyright 2022 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Speed-critical functions for Sharp YUV.
//
// Author: Skal (pascal.massimino@gmail.com)
#include "sharpyuv/sharpyuv_dsp.h"
#if defined(WEBP_USE_NEON)
#include <assert.h>
#include <stdlib.h>
#include <arm_neon.h>
#endif
extern void InitSharpYuvNEON(void);
#if defined(WEBP_USE_NEON)
static uint16_t clip_NEON(int v, int max) {
return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v;
}
static uint64_t SharpYuvUpdateY_NEON(const uint16_t* ref, const uint16_t* src,
uint16_t* dst, int len, int bit_depth) {
const int max_y = (1 << bit_depth) - 1;
int i;
const int16x8_t zero = vdupq_n_s16(0);
const int16x8_t max = vdupq_n_s16(max_y);
uint64x2_t sum = vdupq_n_u64(0);
uint64_t diff;
for (i = 0; i + 8 <= len; i += 8) {
const int16x8_t A = vreinterpretq_s16_u16(vld1q_u16(ref + i));
const int16x8_t B = vreinterpretq_s16_u16(vld1q_u16(src + i));
const int16x8_t C = vreinterpretq_s16_u16(vld1q_u16(dst + i));
const int16x8_t D = vsubq_s16(A, B); // diff_y
const int16x8_t F = vaddq_s16(C, D); // new_y
const uint16x8_t H =
vreinterpretq_u16_s16(vmaxq_s16(vminq_s16(F, max), zero));
const int16x8_t I = vabsq_s16(D); // abs(diff_y)
vst1q_u16(dst + i, H);
sum = vpadalq_u32(sum, vpaddlq_u16(vreinterpretq_u16_s16(I)));
}
diff = vgetq_lane_u64(sum, 0) + vgetq_lane_u64(sum, 1);
for (; i < len; ++i) {
const int diff_y = ref[i] - src[i];
const int new_y = (int)(dst[i]) + diff_y;
dst[i] = clip_NEON(new_y, max_y);
diff += (uint64_t)(abs(diff_y));
}
return diff;
}
static void SharpYuvUpdateRGB_NEON(const int16_t* ref, const int16_t* src,
int16_t* dst, int len) {
int i;
for (i = 0; i + 8 <= len; i += 8) {
const int16x8_t A = vld1q_s16(ref + i);
const int16x8_t B = vld1q_s16(src + i);
const int16x8_t C = vld1q_s16(dst + i);
const int16x8_t D = vsubq_s16(A, B); // diff_uv
const int16x8_t E = vaddq_s16(C, D); // new_uv
vst1q_s16(dst + i, E);
}
for (; i < len; ++i) {
const int diff_uv = ref[i] - src[i];
dst[i] += diff_uv;
}
}
static void SharpYuvFilterRow16_NEON(const int16_t* A, const int16_t* B,
int len, const uint16_t* best_y,
uint16_t* out, int bit_depth) {
const int max_y = (1 << bit_depth) - 1;
int i;
const int16x8_t max = vdupq_n_s16(max_y);
const int16x8_t zero = vdupq_n_s16(0);
for (i = 0; i + 8 <= len; i += 8) {
const int16x8_t a0 = vld1q_s16(A + i + 0);
const int16x8_t a1 = vld1q_s16(A + i + 1);
const int16x8_t b0 = vld1q_s16(B + i + 0);
const int16x8_t b1 = vld1q_s16(B + i + 1);
const int16x8_t a0b1 = vaddq_s16(a0, b1);
const int16x8_t a1b0 = vaddq_s16(a1, b0);
const int16x8_t a0a1b0b1 = vaddq_s16(a0b1, a1b0); // A0+A1+B0+B1
const int16x8_t a0b1_2 = vaddq_s16(a0b1, a0b1); // 2*(A0+B1)
const int16x8_t a1b0_2 = vaddq_s16(a1b0, a1b0); // 2*(A1+B0)
const int16x8_t c0 = vshrq_n_s16(vaddq_s16(a0b1_2, a0a1b0b1), 3);
const int16x8_t c1 = vshrq_n_s16(vaddq_s16(a1b0_2, a0a1b0b1), 3);
const int16x8_t e0 = vrhaddq_s16(c1, a0);
const int16x8_t e1 = vrhaddq_s16(c0, a1);
const int16x8x2_t f = vzipq_s16(e0, e1);
const int16x8_t g0 = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i + 0));
const int16x8_t g1 = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i + 8));
const int16x8_t h0 = vaddq_s16(g0, f.val[0]);
const int16x8_t h1 = vaddq_s16(g1, f.val[1]);
const int16x8_t i0 = vmaxq_s16(vminq_s16(h0, max), zero);
const int16x8_t i1 = vmaxq_s16(vminq_s16(h1, max), zero);
vst1q_u16(out + 2 * i + 0, vreinterpretq_u16_s16(i0));
vst1q_u16(out + 2 * i + 8, vreinterpretq_u16_s16(i1));
}
for (; i < len; ++i) {
const int a0b1 = A[i + 0] + B[i + 1];
const int a1b0 = A[i + 1] + B[i + 0];
const int a0a1b0b1 = a0b1 + a1b0 + 8;
const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4;
const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4;
out[2 * i + 0] = clip_NEON(best_y[2 * i + 0] + v0, max_y);
out[2 * i + 1] = clip_NEON(best_y[2 * i + 1] + v1, max_y);
}
}
static void SharpYuvFilterRow32_NEON(const int16_t* A, const int16_t* B,
int len, const uint16_t* best_y,
uint16_t* out, int bit_depth) {
const int max_y = (1 << bit_depth) - 1;
int i;
const uint16x8_t max = vdupq_n_u16(max_y);
for (i = 0; i + 4 <= len; i += 4) {
const int16x4_t a0 = vld1_s16(A + i + 0);
const int16x4_t a1 = vld1_s16(A + i + 1);
const int16x4_t b0 = vld1_s16(B + i + 0);
const int16x4_t b1 = vld1_s16(B + i + 1);
const int32x4_t a0b1 = vaddl_s16(a0, b1);
const int32x4_t a1b0 = vaddl_s16(a1, b0);
const int32x4_t a0a1b0b1 = vaddq_s32(a0b1, a1b0); // A0+A1+B0+B1
const int32x4_t a0b1_2 = vaddq_s32(a0b1, a0b1); // 2*(A0+B1)
const int32x4_t a1b0_2 = vaddq_s32(a1b0, a1b0); // 2*(A1+B0)
const int32x4_t c0 = vshrq_n_s32(vaddq_s32(a0b1_2, a0a1b0b1), 3);
const int32x4_t c1 = vshrq_n_s32(vaddq_s32(a1b0_2, a0a1b0b1), 3);
const int32x4_t e0 = vrhaddq_s32(c1, vmovl_s16(a0));
const int32x4_t e1 = vrhaddq_s32(c0, vmovl_s16(a1));
const int32x4x2_t f = vzipq_s32(e0, e1);
const int16x8_t g = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i));
const int32x4_t h0 = vaddw_s16(f.val[0], vget_low_s16(g));
const int32x4_t h1 = vaddw_s16(f.val[1], vget_high_s16(g));
const uint16x8_t i_16 = vcombine_u16(vqmovun_s32(h0), vqmovun_s32(h1));
const uint16x8_t i_clamped = vminq_u16(i_16, max);
vst1q_u16(out + 2 * i + 0, i_clamped);
}
for (; i < len; ++i) {
const int a0b1 = A[i + 0] + B[i + 1];
const int a1b0 = A[i + 1] + B[i + 0];
const int a0a1b0b1 = a0b1 + a1b0 + 8;
const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4;
const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4;
out[2 * i + 0] = clip_NEON(best_y[2 * i + 0] + v0, max_y);
out[2 * i + 1] = clip_NEON(best_y[2 * i + 1] + v1, max_y);
}
}
static void SharpYuvFilterRow_NEON(const int16_t* A, const int16_t* B, int len,
const uint16_t* best_y, uint16_t* out,
int bit_depth) {
if (bit_depth <= 10) {
SharpYuvFilterRow16_NEON(A, B, len, best_y, out, bit_depth);
} else {
SharpYuvFilterRow32_NEON(A, B, len, best_y, out, bit_depth);
}
}
//------------------------------------------------------------------------------
WEBP_TSAN_IGNORE_FUNCTION void InitSharpYuvNEON(void) {
SharpYuvUpdateY = SharpYuvUpdateY_NEON;
SharpYuvUpdateRGB = SharpYuvUpdateRGB_NEON;
SharpYuvFilterRow = SharpYuvFilterRow_NEON;
}
#else // !WEBP_USE_NEON
void InitSharpYuvNEON(void) {}
#endif // WEBP_USE_NEON

204
sharpyuv/sharpyuv_sse2.c Normal file
View File

@ -0,0 +1,204 @@
// Copyright 2022 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Speed-critical functions for Sharp YUV.
//
// Author: Skal (pascal.massimino@gmail.com)
#include "sharpyuv/sharpyuv_dsp.h"
#if defined(WEBP_USE_SSE2)
#include <stdlib.h>
#include <emmintrin.h>
#endif
extern void InitSharpYuvSSE2(void);
#if defined(WEBP_USE_SSE2)
static uint16_t clip_SSE2(int v, int max) {
return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v;
}
static uint64_t SharpYuvUpdateY_SSE2(const uint16_t* ref, const uint16_t* src,
uint16_t* dst, int len, int bit_depth) {
const int max_y = (1 << bit_depth) - 1;
uint64_t diff = 0;
uint32_t tmp[4];
int i;
const __m128i zero = _mm_setzero_si128();
const __m128i max = _mm_set1_epi16(max_y);
const __m128i one = _mm_set1_epi16(1);
__m128i sum = zero;
for (i = 0; i + 8 <= len; i += 8) {
const __m128i A = _mm_loadu_si128((const __m128i*)(ref + i));
const __m128i B = _mm_loadu_si128((const __m128i*)(src + i));
const __m128i C = _mm_loadu_si128((const __m128i*)(dst + i));
const __m128i D = _mm_sub_epi16(A, B); // diff_y
const __m128i E = _mm_cmpgt_epi16(zero, D); // sign (-1 or 0)
const __m128i F = _mm_add_epi16(C, D); // new_y
const __m128i G = _mm_or_si128(E, one); // -1 or 1
const __m128i H = _mm_max_epi16(_mm_min_epi16(F, max), zero);
const __m128i I = _mm_madd_epi16(D, G); // sum(abs(...))
_mm_storeu_si128((__m128i*)(dst + i), H);
sum = _mm_add_epi32(sum, I);
}
_mm_storeu_si128((__m128i*)tmp, sum);
diff = tmp[3] + tmp[2] + tmp[1] + tmp[0];
for (; i < len; ++i) {
const int diff_y = ref[i] - src[i];
const int new_y = (int)dst[i] + diff_y;
dst[i] = clip_SSE2(new_y, max_y);
diff += (uint64_t)abs(diff_y);
}
return diff;
}
static void SharpYuvUpdateRGB_SSE2(const int16_t* ref, const int16_t* src,
int16_t* dst, int len) {
int i = 0;
for (i = 0; i + 8 <= len; i += 8) {
const __m128i A = _mm_loadu_si128((const __m128i*)(ref + i));
const __m128i B = _mm_loadu_si128((const __m128i*)(src + i));
const __m128i C = _mm_loadu_si128((const __m128i*)(dst + i));
const __m128i D = _mm_sub_epi16(A, B); // diff_uv
const __m128i E = _mm_add_epi16(C, D); // new_uv
_mm_storeu_si128((__m128i*)(dst + i), E);
}
for (; i < len; ++i) {
const int diff_uv = ref[i] - src[i];
dst[i] += diff_uv;
}
}
static void SharpYuvFilterRow16_SSE2(const int16_t* A, const int16_t* B,
int len, const uint16_t* best_y,
uint16_t* out, int bit_depth) {
const int max_y = (1 << bit_depth) - 1;
int i;
const __m128i kCst8 = _mm_set1_epi16(8);
const __m128i max = _mm_set1_epi16(max_y);
const __m128i zero = _mm_setzero_si128();
for (i = 0; i + 8 <= len; i += 8) {
const __m128i a0 = _mm_loadu_si128((const __m128i*)(A + i + 0));
const __m128i a1 = _mm_loadu_si128((const __m128i*)(A + i + 1));
const __m128i b0 = _mm_loadu_si128((const __m128i*)(B + i + 0));
const __m128i b1 = _mm_loadu_si128((const __m128i*)(B + i + 1));
const __m128i a0b1 = _mm_add_epi16(a0, b1);
const __m128i a1b0 = _mm_add_epi16(a1, b0);
const __m128i a0a1b0b1 = _mm_add_epi16(a0b1, a1b0); // A0+A1+B0+B1
const __m128i a0a1b0b1_8 = _mm_add_epi16(a0a1b0b1, kCst8);
const __m128i a0b1_2 = _mm_add_epi16(a0b1, a0b1); // 2*(A0+B1)
const __m128i a1b0_2 = _mm_add_epi16(a1b0, a1b0); // 2*(A1+B0)
const __m128i c0 = _mm_srai_epi16(_mm_add_epi16(a0b1_2, a0a1b0b1_8), 3);
const __m128i c1 = _mm_srai_epi16(_mm_add_epi16(a1b0_2, a0a1b0b1_8), 3);
const __m128i d0 = _mm_add_epi16(c1, a0);
const __m128i d1 = _mm_add_epi16(c0, a1);
const __m128i e0 = _mm_srai_epi16(d0, 1);
const __m128i e1 = _mm_srai_epi16(d1, 1);
const __m128i f0 = _mm_unpacklo_epi16(e0, e1);
const __m128i f1 = _mm_unpackhi_epi16(e0, e1);
const __m128i g0 = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 0));
const __m128i g1 = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 8));
const __m128i h0 = _mm_add_epi16(g0, f0);
const __m128i h1 = _mm_add_epi16(g1, f1);
const __m128i i0 = _mm_max_epi16(_mm_min_epi16(h0, max), zero);
const __m128i i1 = _mm_max_epi16(_mm_min_epi16(h1, max), zero);
_mm_storeu_si128((__m128i*)(out + 2 * i + 0), i0);
_mm_storeu_si128((__m128i*)(out + 2 * i + 8), i1);
}
for (; i < len; ++i) {
// (9 * A0 + 3 * A1 + 3 * B0 + B1 + 8) >> 4 =
// = (8 * A0 + 2 * (A1 + B0) + (A0 + A1 + B0 + B1 + 8)) >> 4
// We reuse the common sub-expressions.
const int a0b1 = A[i + 0] + B[i + 1];
const int a1b0 = A[i + 1] + B[i + 0];
const int a0a1b0b1 = a0b1 + a1b0 + 8;
const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4;
const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4;
out[2 * i + 0] = clip_SSE2(best_y[2 * i + 0] + v0, max_y);
out[2 * i + 1] = clip_SSE2(best_y[2 * i + 1] + v1, max_y);
}
}
static WEBP_INLINE __m128i s16_to_s32(__m128i in) {
return _mm_srai_epi32(_mm_unpacklo_epi16(in, in), 16);
}
static void SharpYuvFilterRow32_SSE2(const int16_t* A, const int16_t* B,
int len, const uint16_t* best_y,
uint16_t* out, int bit_depth) {
const int max_y = (1 << bit_depth) - 1;
int i;
const __m128i kCst8 = _mm_set1_epi32(8);
const __m128i max = _mm_set1_epi16(max_y);
const __m128i zero = _mm_setzero_si128();
for (i = 0; i + 4 <= len; i += 4) {
const __m128i a0 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(A + i + 0)));
const __m128i a1 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(A + i + 1)));
const __m128i b0 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(B + i + 0)));
const __m128i b1 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(B + i + 1)));
const __m128i a0b1 = _mm_add_epi32(a0, b1);
const __m128i a1b0 = _mm_add_epi32(a1, b0);
const __m128i a0a1b0b1 = _mm_add_epi32(a0b1, a1b0); // A0+A1+B0+B1
const __m128i a0a1b0b1_8 = _mm_add_epi32(a0a1b0b1, kCst8);
const __m128i a0b1_2 = _mm_add_epi32(a0b1, a0b1); // 2*(A0+B1)
const __m128i a1b0_2 = _mm_add_epi32(a1b0, a1b0); // 2*(A1+B0)
const __m128i c0 = _mm_srai_epi32(_mm_add_epi32(a0b1_2, a0a1b0b1_8), 3);
const __m128i c1 = _mm_srai_epi32(_mm_add_epi32(a1b0_2, a0a1b0b1_8), 3);
const __m128i d0 = _mm_add_epi32(c1, a0);
const __m128i d1 = _mm_add_epi32(c0, a1);
const __m128i e0 = _mm_srai_epi32(d0, 1);
const __m128i e1 = _mm_srai_epi32(d1, 1);
const __m128i f0 = _mm_unpacklo_epi32(e0, e1);
const __m128i f1 = _mm_unpackhi_epi32(e0, e1);
const __m128i g = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 0));
const __m128i h_16 = _mm_add_epi16(g, _mm_packs_epi32(f0, f1));
const __m128i final = _mm_max_epi16(_mm_min_epi16(h_16, max), zero);
_mm_storeu_si128((__m128i*)(out + 2 * i + 0), final);
}
for (; i < len; ++i) {
// (9 * A0 + 3 * A1 + 3 * B0 + B1 + 8) >> 4 =
// = (8 * A0 + 2 * (A1 + B0) + (A0 + A1 + B0 + B1 + 8)) >> 4
// We reuse the common sub-expressions.
const int a0b1 = A[i + 0] + B[i + 1];
const int a1b0 = A[i + 1] + B[i + 0];
const int a0a1b0b1 = a0b1 + a1b0 + 8;
const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4;
const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4;
out[2 * i + 0] = clip_SSE2(best_y[2 * i + 0] + v0, max_y);
out[2 * i + 1] = clip_SSE2(best_y[2 * i + 1] + v1, max_y);
}
}
static void SharpYuvFilterRow_SSE2(const int16_t* A, const int16_t* B, int len,
const uint16_t* best_y, uint16_t* out,
int bit_depth) {
if (bit_depth <= 10) {
SharpYuvFilterRow16_SSE2(A, B, len, best_y, out, bit_depth);
} else {
SharpYuvFilterRow32_SSE2(A, B, len, best_y, out, bit_depth);
}
}
//------------------------------------------------------------------------------
extern void InitSharpYuvSSE2(void);
WEBP_TSAN_IGNORE_FUNCTION void InitSharpYuvSSE2(void) {
SharpYuvUpdateY = SharpYuvUpdateY_SSE2;
SharpYuvUpdateRGB = SharpYuvUpdateRGB_SSE2;
SharpYuvFilterRow = SharpYuvFilterRow_SSE2;
}
#else // !WEBP_USE_SSE2
void InitSharpYuvSSE2(void) {}
#endif // WEBP_USE_SSE2

View File

@ -36,7 +36,7 @@ libwebp_la_LIBADD += utils/libwebputils.la
# other than the ones listed on the command line, i.e., after linking, it will
# not have unresolved symbols. Some platforms (Windows among them) require all
# symbols in shared libraries to be resolved at library creation.
libwebp_la_LDFLAGS = -no-undefined -version-info 8:2:1
libwebp_la_LDFLAGS = -no-undefined -version-info 8:4:1
libwebpincludedir = $(includedir)/webp
pkgconfig_DATA = libwebp.pc
@ -48,7 +48,7 @@ if BUILD_LIBWEBPDECODER
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 4:2:1
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 4:4:1
pkgconfig_DATA += libwebpdecoder.pc
endif

View File

@ -331,13 +331,13 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
p->scaler_a = has_alpha ? &scalers[3] : NULL;
if (!WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h,
buf->y, out_width, out_height, buf->y_stride, 1,
buf->y, out_width, out_height, buf->y_stride, 1,
work) ||
!WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height,
buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
work + work_size) ||
!WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height,
buf->v, uv_out_width, uv_out_height, buf->v_stride, 1,
buf->v, uv_out_width, uv_out_height, buf->v_stride, 1,
work + work_size + uv_work_size)) {
return 0;
}
@ -345,7 +345,7 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
if (has_alpha) {
if (!WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h,
buf->a, out_width, out_height, buf->a_stride, 1,
buf->a, out_width, out_height, buf->a_stride, 1,
work + work_size + 2 * uv_work_size)) {
return 0;
}
@ -524,13 +524,13 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
p->scaler_a = has_alpha ? &scalers[3] : NULL;
if (!WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h,
tmp + 0 * out_width, out_width, out_height, 0, 1,
tmp + 0 * out_width, out_width, out_height, 0, 1,
work + 0 * work_size) ||
!WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height,
tmp + 1 * out_width, out_width, out_height, 0, 1,
tmp + 1 * out_width, out_width, out_height, 0, 1,
work + 1 * work_size) ||
!WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height,
tmp + 2 * out_width, out_width, out_height, 0, 1,
tmp + 2 * out_width, out_width, out_height, 0, 1,
work + 2 * work_size)) {
return 0;
}
@ -539,7 +539,7 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
if (has_alpha) {
if (!WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h,
tmp + 3 * out_width, out_width, out_height, 0, 1,
tmp + 3 * out_width, out_width, out_height, 0, 1,
work + 3 * work_size)) {
return 0;
}

View File

@ -403,7 +403,7 @@ static const uint8_t kZigzag[16] = {
0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
};
// See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2
// See section 13-2: https://datatracker.ietf.org/doc/html/rfc6386#section-13.2
static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) {
int v;
if (!VP8GetBit(br, p[3], "coeffs")) {

View File

@ -32,7 +32,7 @@ extern "C" {
// version numbers
#define DEC_MAJ_VERSION 1
#define DEC_MIN_VERSION 2
#define DEC_REV_VERSION 1
#define DEC_REV_VERSION 3
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y),

View File

@ -84,7 +84,7 @@ static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {
// to 256 (green component values) + 24 (length prefix values)
// + color_cache_size (between 0 and 2048).
// All values computed for 8-bit first level lookup with Mark Adler's tool:
// http://www.hdfgroup.org/ftp/lib-external/zlib/zlib-1.2.5/examples/enough.c
// https://github.com/madler/zlib/blob/v1.2.5/examples/enough.c
#define FIXED_TABLE_SIZE (630 * 3 + 410)
static const uint16_t kTableSize[12] = {
FIXED_TABLE_SIZE + 654,
@ -178,7 +178,7 @@ static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {
//------------------------------------------------------------------------------
// Decodes the next Huffman code from bit-stream.
// FillBitWindow(br) needs to be called at minimum every second call
// VP8LFillBitWindow(br) needs to be called at minimum every second call
// to ReadSymbol, in order to pre-fetch enough bits.
static WEBP_INLINE int ReadSymbol(const HuffmanCode* table,
VP8LBitReader* const br) {
@ -253,11 +253,11 @@ static int ReadHuffmanCodeLengths(
int symbol;
int max_symbol;
int prev_code_len = DEFAULT_CODE_LENGTH;
HuffmanCode table[1 << LENGTHS_TABLE_BITS];
HuffmanTables tables;
if (!VP8LBuildHuffmanTable(table, LENGTHS_TABLE_BITS,
code_length_code_lengths,
NUM_CODE_LENGTH_CODES)) {
if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) ||
!VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS,
code_length_code_lengths, NUM_CODE_LENGTH_CODES)) {
goto End;
}
@ -277,7 +277,7 @@ static int ReadHuffmanCodeLengths(
int code_len;
if (max_symbol-- == 0) break;
VP8LFillBitWindow(br);
p = &table[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
VP8LSetBitPos(br, br->bit_pos_ + p->bits);
code_len = p->value;
if (code_len < kCodeLengthLiterals) {
@ -300,6 +300,7 @@ static int ReadHuffmanCodeLengths(
ok = 1;
End:
VP8LHuffmanTablesDeallocate(&tables);
if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
return ok;
}
@ -307,7 +308,8 @@ static int ReadHuffmanCodeLengths(
// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
// tree.
static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
int* const code_lengths, HuffmanCode* const table) {
int* const code_lengths,
HuffmanTables* const table) {
int ok = 0;
int size = 0;
VP8LBitReader* const br = &dec->br_;
@ -321,7 +323,7 @@ static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
// The first code is either 1 bit or 8 bit code.
int symbol = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);
code_lengths[symbol] = 1;
// The second code (if present), is always 8 bit long.
// The second code (if present), is always 8 bits long.
if (num_symbols == 2) {
symbol = VP8LReadBits(br, 8);
code_lengths[symbol] = 1;
@ -362,8 +364,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* huffman_image = NULL;
HTreeGroup* htree_groups = NULL;
HuffmanCode* huffman_tables = NULL;
HuffmanCode* huffman_table = NULL;
HuffmanTables* huffman_tables = &hdr->huffman_tables_;
int num_htree_groups = 1;
int num_htree_groups_max = 1;
int max_alphabet_size = 0;
@ -372,6 +373,10 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
int* mapping = NULL;
int ok = 0;
// Check the table has been 0 initialized (through InitMetadata).
assert(huffman_tables->root.start == NULL);
assert(huffman_tables->curr_segment == NULL);
if (allow_recursion && VP8LReadBits(br, 1)) {
// use meta Huffman codes.
const int huffman_precision = VP8LReadBits(br, 3) + 2;
@ -434,16 +439,15 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
sizeof(*code_lengths));
huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size,
sizeof(*huffman_tables));
htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
if (htree_groups == NULL || code_lengths == NULL ||
!VP8LHuffmanTablesAllocate(num_htree_groups * table_size,
huffman_tables)) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
goto Error;
}
huffman_table = huffman_tables;
for (i = 0; i < num_htree_groups_max; ++i) {
// If the index "i" is unused in the Huffman image, just make sure the
// coefficients are valid but do not store them.
@ -468,19 +472,20 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
int max_bits = 0;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
htrees[j] = huffman_table;
if (j == 0 && color_cache_bits > 0) {
alphabet_size += (1 << color_cache_bits);
}
size = ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_table);
size =
ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables);
htrees[j] = huffman_tables->curr_segment->curr_table;
if (size == 0) {
goto Error;
}
if (is_trivial_literal && kLiteralMap[j] == 1) {
is_trivial_literal = (huffman_table->bits == 0);
is_trivial_literal = (htrees[j]->bits == 0);
}
total_size += huffman_table->bits;
huffman_table += size;
total_size += htrees[j]->bits;
huffman_tables->curr_segment->curr_table += size;
if (j <= ALPHA) {
int local_max_bits = code_lengths[0];
int k;
@ -515,14 +520,13 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
hdr->huffman_image_ = huffman_image;
hdr->num_htree_groups_ = num_htree_groups;
hdr->htree_groups_ = htree_groups;
hdr->huffman_tables_ = huffman_tables;
Error:
WebPSafeFree(code_lengths);
WebPSafeFree(mapping);
if (!ok) {
WebPSafeFree(huffman_image);
WebPSafeFree(huffman_tables);
VP8LHuffmanTablesDeallocate(huffman_tables);
VP8LHtreeGroupsFree(htree_groups);
}
return ok;
@ -1281,7 +1285,7 @@ static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
uint8_t* const new_data = (uint8_t*)new_color_map;
new_color_map[0] = transform->data_[0];
for (i = 4; i < 4 * num_colors; ++i) {
// Equivalent to AddPixelEq(), on a byte-basis.
// Equivalent to VP8LAddPixels(), on a byte-basis.
new_data[i] = (data[i] + new_data[i - 4]) & 0xff;
}
for (; i < 4 * final_num_colors; ++i) {
@ -1358,7 +1362,7 @@ static void ClearMetadata(VP8LMetadata* const hdr) {
assert(hdr != NULL);
WebPSafeFree(hdr->huffman_image_);
WebPSafeFree(hdr->huffman_tables_);
VP8LHuffmanTablesDeallocate(&hdr->huffman_tables_);
VP8LHtreeGroupsFree(hdr->htree_groups_);
VP8LColorCacheClear(&hdr->color_cache_);
VP8LColorCacheClear(&hdr->saved_color_cache_);
@ -1673,7 +1677,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
if (dec == NULL) return 0;
assert(dec->hdr_.huffman_tables_ != NULL);
assert(dec->hdr_.huffman_tables_.root.start != NULL);
assert(dec->hdr_.htree_groups_ != NULL);
assert(dec->hdr_.num_htree_groups_ > 0);

View File

@ -51,7 +51,7 @@ typedef struct {
uint32_t* huffman_image_;
int num_htree_groups_;
HTreeGroup* htree_groups_;
HuffmanCode* huffman_tables_;
HuffmanTables huffman_tables_;
} VP8LMetadata;
typedef struct VP8LDecoder VP8LDecoder;

View File

@ -13,6 +13,6 @@ noinst_HEADERS =
noinst_HEADERS += ../webp/format_constants.h
libwebpdemux_la_LIBADD = ../libwebp.la
libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:8:0
libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:10:0
libwebpdemuxincludedir = $(includedir)/webp
pkgconfig_DATA = libwebpdemux.pc

View File

@ -23,6 +23,14 @@
#define NUM_CHANNELS 4
// Channel extraction from a uint32_t representation of a uint8_t RGBA/BGRA
// buffer.
#ifdef WORDS_BIGENDIAN
#define CHANNEL_SHIFT(i) (24 - (i) * 8)
#else
#define CHANNEL_SHIFT(i) ((i) * 8)
#endif
typedef void (*BlendRowFunc)(uint32_t* const, const uint32_t* const, int);
static void BlendPixelRowNonPremult(uint32_t* const src,
const uint32_t* const dst, int num_pixels);
@ -209,35 +217,35 @@ static uint8_t BlendChannelNonPremult(uint32_t src, uint8_t src_a,
const uint8_t dst_channel = (dst >> shift) & 0xff;
const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a;
assert(blend_unscaled < (1ULL << 32) / scale);
return (blend_unscaled * scale) >> 24;
return (blend_unscaled * scale) >> CHANNEL_SHIFT(3);
}
// Blend 'src' over 'dst' assuming they are NOT pre-multiplied by alpha.
static uint32_t BlendPixelNonPremult(uint32_t src, uint32_t dst) {
const uint8_t src_a = (src >> 24) & 0xff;
const uint8_t src_a = (src >> CHANNEL_SHIFT(3)) & 0xff;
if (src_a == 0) {
return dst;
} else {
const uint8_t dst_a = (dst >> 24) & 0xff;
const uint8_t dst_a = (dst >> CHANNEL_SHIFT(3)) & 0xff;
// This is the approximate integer arithmetic for the actual formula:
// dst_factor_a = (dst_a * (255 - src_a)) / 255.
const uint8_t dst_factor_a = (dst_a * (256 - src_a)) >> 8;
const uint8_t blend_a = src_a + dst_factor_a;
const uint32_t scale = (1UL << 24) / blend_a;
const uint8_t blend_r =
BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 0);
const uint8_t blend_g =
BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 8);
const uint8_t blend_b =
BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 16);
const uint8_t blend_r = BlendChannelNonPremult(
src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(0));
const uint8_t blend_g = BlendChannelNonPremult(
src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(1));
const uint8_t blend_b = BlendChannelNonPremult(
src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(2));
assert(src_a + dst_factor_a < 256);
return (blend_r << 0) |
(blend_g << 8) |
(blend_b << 16) |
((uint32_t)blend_a << 24);
return ((uint32_t)blend_r << CHANNEL_SHIFT(0)) |
((uint32_t)blend_g << CHANNEL_SHIFT(1)) |
((uint32_t)blend_b << CHANNEL_SHIFT(2)) |
((uint32_t)blend_a << CHANNEL_SHIFT(3));
}
}
@ -247,7 +255,7 @@ static void BlendPixelRowNonPremult(uint32_t* const src,
const uint32_t* const dst, int num_pixels) {
int i;
for (i = 0; i < num_pixels; ++i) {
const uint8_t src_alpha = (src[i] >> 24) & 0xff;
const uint8_t src_alpha = (src[i] >> CHANNEL_SHIFT(3)) & 0xff;
if (src_alpha != 0xff) {
src[i] = BlendPixelNonPremult(src[i], dst[i]);
}
@ -264,7 +272,7 @@ static WEBP_INLINE uint32_t ChannelwiseMultiply(uint32_t pix, uint32_t scale) {
// Blend 'src' over 'dst' assuming they are pre-multiplied by alpha.
static uint32_t BlendPixelPremult(uint32_t src, uint32_t dst) {
const uint8_t src_a = (src >> 24) & 0xff;
const uint8_t src_a = (src >> CHANNEL_SHIFT(3)) & 0xff;
return src + ChannelwiseMultiply(dst, 256 - src_a);
}
@ -274,7 +282,7 @@ static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst,
int num_pixels) {
int i;
for (i = 0; i < num_pixels; ++i) {
const uint8_t src_alpha = (src[i] >> 24) & 0xff;
const uint8_t src_alpha = (src[i] >> CHANNEL_SHIFT(3)) & 0xff;
if (src_alpha != 0xff) {
src[i] = BlendPixelPremult(src[i], dst[i]);
}

View File

@ -25,7 +25,7 @@
#define DMUX_MAJ_VERSION 1
#define DMUX_MIN_VERSION 2
#define DMUX_REV_VERSION 1
#define DMUX_REV_VERSION 3
typedef struct {
size_t start_; // start location of the data
@ -614,7 +614,6 @@ static int IsValidExtendedFormat(const WebPDemuxer* const dmux) {
while (f != NULL) {
const int cur_frame_set = f->frame_num_;
int frame_count = 0;
// Check frame properties.
for (; f != NULL && f->frame_num_ == cur_frame_set; f = f->next_) {
@ -649,8 +648,6 @@ static int IsValidExtendedFormat(const WebPDemuxer* const dmux) {
dmux->canvas_width_, dmux->canvas_height_)) {
return 0;
}
++frame_count;
}
}
return 1;

View File

@ -6,8 +6,8 @@
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,2,1
PRODUCTVERSION 1,0,2,1
FILEVERSION 1,0,2,3
PRODUCTVERSION 1,0,2,3
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -24,12 +24,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Google, Inc."
VALUE "FileDescription", "libwebpdemux DLL"
VALUE "FileVersion", "1.2.1"
VALUE "FileVersion", "1.2.3"
VALUE "InternalName", "libwebpdemux.dll"
VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "LegalCopyright", "Copyright (C) 2022"
VALUE "OriginalFilename", "libwebpdemux.dll"
VALUE "ProductName", "WebP Image Demuxer"
VALUE "ProductVersion", "1.2.1"
VALUE "ProductVersion", "1.2.3"
END
END
BLOCK "VarFileInfo"

View File

@ -24,6 +24,7 @@ commondir = $(includedir)/webp
COMMON_SOURCES =
COMMON_SOURCES += alpha_processing.c
COMMON_SOURCES += cpu.c
COMMON_SOURCES += cpu.h
COMMON_SOURCES += dec.c
COMMON_SOURCES += dec_clip_tables.c
COMMON_SOURCES += dsp.h

View File

@ -83,7 +83,7 @@ static void ApplyAlphaMultiply_NEON(uint8_t* rgba, int alpha_first,
static int DispatchAlpha_NEON(const uint8_t* WEBP_RESTRICT alpha,
int alpha_stride, int width, int height,
uint8_t* WEBP_RESTRICT dst, int dst_stride) {
uint32_t alpha_mask = 0xffffffffu;
uint32_t alpha_mask = 0xffu;
uint8x8_t mask8 = vdup_n_u8(0xff);
uint32_t tmp[2];
int i, j;
@ -107,6 +107,7 @@ static int DispatchAlpha_NEON(const uint8_t* WEBP_RESTRICT alpha,
dst += dst_stride;
}
vst1_u8((uint8_t*)tmp, mask8);
alpha_mask *= 0x01010101;
alpha_mask &= tmp[0];
alpha_mask &= tmp[1];
return (alpha_mask != 0xffffffffu);
@ -135,7 +136,7 @@ static void DispatchAlphaToGreen_NEON(const uint8_t* WEBP_RESTRICT alpha,
static int ExtractAlpha_NEON(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
int width, int height,
uint8_t* WEBP_RESTRICT alpha, int alpha_stride) {
uint32_t alpha_mask = 0xffffffffu;
uint32_t alpha_mask = 0xffu;
uint8x8_t mask8 = vdup_n_u8(0xff);
uint32_t tmp[2];
int i, j;
@ -157,6 +158,7 @@ static int ExtractAlpha_NEON(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
alpha += alpha_stride;
}
vst1_u8((uint8_t*)tmp, mask8);
alpha_mask *= 0x01010101;
alpha_mask &= tmp[0];
alpha_mask &= tmp[1];
return (alpha_mask == 0xffffffffu);

View File

@ -11,7 +11,7 @@
//
// Author: Christian Duvivier (cduvivier@google.com)
#include "src/dsp/dsp.h"
#include "src/dsp/cpu.h"
#if defined(WEBP_HAVE_NEON_RTCD)
#include <stdio.h>

254
src/dsp/cpu.h Normal file
View File

@ -0,0 +1,254 @@
// Copyright 2022 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// CPU detection functions and macros.
//
// Author: Skal (pascal.massimino@gmail.com)
#ifndef WEBP_DSP_CPU_H_
#define WEBP_DSP_CPU_H_
#ifdef HAVE_CONFIG_H
#include "src/webp/config.h"
#endif
#include "src/webp/types.h"
#if defined(__GNUC__)
#define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__)
#define LOCAL_GCC_PREREQ(maj, min) (LOCAL_GCC_VERSION >= (((maj) << 8) | (min)))
#else
#define LOCAL_GCC_VERSION 0
#define LOCAL_GCC_PREREQ(maj, min) 0
#endif
#if defined(__clang__)
#define LOCAL_CLANG_VERSION ((__clang_major__ << 8) | __clang_minor__)
#define LOCAL_CLANG_PREREQ(maj, min) \
(LOCAL_CLANG_VERSION >= (((maj) << 8) | (min)))
#else
#define LOCAL_CLANG_VERSION 0
#define LOCAL_CLANG_PREREQ(maj, min) 0
#endif
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
#if !defined(HAVE_CONFIG_H)
#if defined(_MSC_VER) && _MSC_VER > 1310 && \
(defined(_M_X64) || defined(_M_IX86))
#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1500 && \
(defined(_M_X64) || defined(_M_IX86))
#define WEBP_MSC_SSE41 // Visual C++ SSE4.1 targets
#endif
#endif
// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp
// files without intrinsics, allowing the corresponding Init() to be called.
// Files containing intrinsics will need to be built targeting the instruction
// set so should succeed on one of the earlier tests.
#if (defined(__SSE2__) || defined(WEBP_MSC_SSE2)) && \
(!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_SSE2))
#define WEBP_USE_SSE2
#endif
#if defined(WEBP_USE_SSE2) && !defined(WEBP_HAVE_SSE2)
#define WEBP_HAVE_SSE2
#endif
#if (defined(__SSE4_1__) || defined(WEBP_MSC_SSE41)) && \
(!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_SSE41))
#define WEBP_USE_SSE41
#endif
#if defined(WEBP_USE_SSE41) && !defined(WEBP_HAVE_SSE41)
#define WEBP_HAVE_SSE41
#endif
#undef WEBP_MSC_SSE41
#undef WEBP_MSC_SSE2
// The intrinsics currently cause compiler errors with arm-nacl-gcc and the
// inline assembly would need to be modified for use with Native Client.
#if ((defined(__ARM_NEON__) || defined(__aarch64__)) && \
(!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_NEON))) && \
!defined(__native_client__)
#define WEBP_USE_NEON
#endif
#if !defined(WEBP_USE_NEON) && defined(__ANDROID__) && \
defined(__ARM_ARCH_7A__) && defined(HAVE_CPU_FEATURES_H)
#define WEBP_ANDROID_NEON // Android targets that may have NEON
#define WEBP_USE_NEON
#endif
// Note: ARM64 is supported in Visual Studio 2017, but requires the direct
// inclusion of arm64_neon.h; Visual Studio 2019 includes this file in
// arm_neon.h. Compile errors were seen with Visual Studio 2019 16.4 with
// vtbl4_u8(); a fix was made in 16.6.
#if defined(_MSC_VER) && ((_MSC_VER >= 1700 && defined(_M_ARM)) || \
(_MSC_VER >= 1926 && defined(_M_ARM64)))
#define WEBP_USE_NEON
#define WEBP_USE_INTRINSICS
#endif
#if defined(WEBP_USE_NEON) && !defined(WEBP_HAVE_NEON)
#define WEBP_HAVE_NEON
#endif
#if defined(__mips__) && !defined(__mips64) && defined(__mips_isa_rev) && \
(__mips_isa_rev >= 1) && (__mips_isa_rev < 6)
#define WEBP_USE_MIPS32
#if (__mips_isa_rev >= 2)
#define WEBP_USE_MIPS32_R2
#if defined(__mips_dspr2) || (defined(__mips_dsp_rev) && __mips_dsp_rev >= 2)
#define WEBP_USE_MIPS_DSP_R2
#endif
#endif
#endif
#if defined(__mips_msa) && defined(__mips_isa_rev) && (__mips_isa_rev >= 5)
#define WEBP_USE_MSA
#endif
#ifndef WEBP_DSP_OMIT_C_CODE
#define WEBP_DSP_OMIT_C_CODE 1
#endif
#if defined(WEBP_USE_NEON) && WEBP_DSP_OMIT_C_CODE
#define WEBP_NEON_OMIT_C_CODE 1
#else
#define WEBP_NEON_OMIT_C_CODE 0
#endif
#if !(LOCAL_CLANG_PREREQ(3, 8) || LOCAL_GCC_PREREQ(4, 8) || \
defined(__aarch64__))
#define WEBP_NEON_WORK_AROUND_GCC 1
#else
#define WEBP_NEON_WORK_AROUND_GCC 0
#endif
// This macro prevents thread_sanitizer from reporting known concurrent writes.
#define WEBP_TSAN_IGNORE_FUNCTION
#if defined(__has_feature)
#if __has_feature(thread_sanitizer)
#undef WEBP_TSAN_IGNORE_FUNCTION
#define WEBP_TSAN_IGNORE_FUNCTION __attribute__((no_sanitize_thread))
#endif
#endif
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
#define WEBP_MSAN
#endif
#endif
#if defined(WEBP_USE_THREAD) && !defined(_WIN32)
#include <pthread.h> // NOLINT
#define WEBP_DSP_INIT(func) \
do { \
static volatile VP8CPUInfo func##_last_cpuinfo_used = \
(VP8CPUInfo)&func##_last_cpuinfo_used; \
static pthread_mutex_t func##_lock = PTHREAD_MUTEX_INITIALIZER; \
if (pthread_mutex_lock(&func##_lock)) break; \
if (func##_last_cpuinfo_used != VP8GetCPUInfo) func(); \
func##_last_cpuinfo_used = VP8GetCPUInfo; \
(void)pthread_mutex_unlock(&func##_lock); \
} while (0)
#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32))
#define WEBP_DSP_INIT(func) \
do { \
static volatile VP8CPUInfo func##_last_cpuinfo_used = \
(VP8CPUInfo)&func##_last_cpuinfo_used; \
if (func##_last_cpuinfo_used == VP8GetCPUInfo) break; \
func(); \
func##_last_cpuinfo_used = VP8GetCPUInfo; \
} while (0)
#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32)
// Defines an Init + helper function that control multiple initialization of
// function pointers / tables.
/* Usage:
WEBP_DSP_INIT_FUNC(InitFunc) {
...function body
}
*/
#define WEBP_DSP_INIT_FUNC(name) \
static WEBP_TSAN_IGNORE_FUNCTION void name##_body(void); \
WEBP_TSAN_IGNORE_FUNCTION void name(void) { WEBP_DSP_INIT(name##_body); } \
static WEBP_TSAN_IGNORE_FUNCTION void name##_body(void)
#define WEBP_UBSAN_IGNORE_UNDEF
#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW
#if defined(__clang__) && defined(__has_attribute)
#if __has_attribute(no_sanitize)
// This macro prevents the undefined behavior sanitizer from reporting
// failures. This is only meant to silence unaligned loads on platforms that
// are known to support them.
#undef WEBP_UBSAN_IGNORE_UNDEF
#define WEBP_UBSAN_IGNORE_UNDEF __attribute__((no_sanitize("undefined")))
// This macro prevents the undefined behavior sanitizer from reporting
// failures related to unsigned integer overflows. This is only meant to
// silence cases where this well defined behavior is expected.
#undef WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW
#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW \
__attribute__((no_sanitize("unsigned-integer-overflow")))
#endif
#endif
// If 'ptr' is NULL, returns NULL. Otherwise returns 'ptr + off'.
// Prevents undefined behavior sanitizer nullptr-with-nonzero-offset warning.
#if !defined(WEBP_OFFSET_PTR)
#define WEBP_OFFSET_PTR(ptr, off) (((ptr) == NULL) ? NULL : ((ptr) + (off)))
#endif
// Regularize the definition of WEBP_SWAP_16BIT_CSP (backward compatibility)
#if !defined(WEBP_SWAP_16BIT_CSP)
#define WEBP_SWAP_16BIT_CSP 0
#endif
// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__)
#if !defined(WORDS_BIGENDIAN) && \
(defined(__BIG_ENDIAN__) || defined(_M_PPC) || \
(defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
#define WORDS_BIGENDIAN
#endif
typedef enum {
kSSE2,
kSSE3,
kSlowSSSE3, // special feature for slow SSSE3 architectures
kSSE4_1,
kAVX,
kAVX2,
kNEON,
kMIPS32,
kMIPSdspR2,
kMSA
} CPUFeature;
#ifdef __cplusplus
extern "C" {
#endif
// returns true if the CPU supports the feature.
typedef int (*VP8CPUInfo)(CPUFeature feature);
WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo;
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_DSP_CPU_H_

View File

@ -18,6 +18,7 @@
#include "src/webp/config.h"
#endif
#include "src/dsp/cpu.h"
#include "src/webp/types.h"
#ifdef __cplusplus
@ -43,220 +44,6 @@ extern "C" {
#define WEBP_RESTRICT
#endif
//------------------------------------------------------------------------------
// CPU detection
#if defined(__GNUC__)
# define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__)
# define LOCAL_GCC_PREREQ(maj, min) \
(LOCAL_GCC_VERSION >= (((maj) << 8) | (min)))
#else
# define LOCAL_GCC_VERSION 0
# define LOCAL_GCC_PREREQ(maj, min) 0
#endif
#if defined(__clang__)
# define LOCAL_CLANG_VERSION ((__clang_major__ << 8) | __clang_minor__)
# define LOCAL_CLANG_PREREQ(maj, min) \
(LOCAL_CLANG_VERSION >= (((maj) << 8) | (min)))
#else
# define LOCAL_CLANG_VERSION 0
# define LOCAL_CLANG_PREREQ(maj, min) 0
#endif
#ifndef __has_builtin
# define __has_builtin(x) 0
#endif
#if !defined(HAVE_CONFIG_H)
#if defined(_MSC_VER) && _MSC_VER > 1310 && \
(defined(_M_X64) || defined(_M_IX86))
#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1500 && \
(defined(_M_X64) || defined(_M_IX86))
#define WEBP_MSC_SSE41 // Visual C++ SSE4.1 targets
#endif
#endif
// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp
// files without intrinsics, allowing the corresponding Init() to be called.
// Files containing intrinsics will need to be built targeting the instruction
// set so should succeed on one of the earlier tests.
#if (defined(__SSE2__) || defined(WEBP_MSC_SSE2)) && \
(!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_SSE2))
#define WEBP_USE_SSE2
#endif
#if defined(WEBP_USE_SSE2) && !defined(WEBP_HAVE_SSE2)
#define WEBP_HAVE_SSE2
#endif
#if (defined(__SSE4_1__) || defined(WEBP_MSC_SSE41)) && \
(!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_SSE41))
#define WEBP_USE_SSE41
#endif
#if defined(WEBP_USE_SSE41) && !defined(WEBP_HAVE_SSE41)
#define WEBP_HAVE_SSE41
#endif
#undef WEBP_MSC_SSE41
#undef WEBP_MSC_SSE2
// The intrinsics currently cause compiler errors with arm-nacl-gcc and the
// inline assembly would need to be modified for use with Native Client.
#if ((defined(__ARM_NEON__) || defined(__aarch64__)) && \
(!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_NEON))) && \
!defined(__native_client__)
#define WEBP_USE_NEON
#endif
#if !defined(WEBP_USE_NEON) && defined(__ANDROID__) && \
defined(__ARM_ARCH_7A__) && defined(HAVE_CPU_FEATURES_H)
#define WEBP_ANDROID_NEON // Android targets that may have NEON
#define WEBP_USE_NEON
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
#define WEBP_USE_NEON
#define WEBP_USE_INTRINSICS
#endif
#if defined(WEBP_USE_NEON) && !defined(WEBP_HAVE_NEON)
#define WEBP_HAVE_NEON
#endif
#if defined(__mips__) && !defined(__mips64) && \
defined(__mips_isa_rev) && (__mips_isa_rev >= 1) && (__mips_isa_rev < 6)
#define WEBP_USE_MIPS32
#if (__mips_isa_rev >= 2)
#define WEBP_USE_MIPS32_R2
#if defined(__mips_dspr2) || (defined(__mips_dsp_rev) && __mips_dsp_rev >= 2)
#define WEBP_USE_MIPS_DSP_R2
#endif
#endif
#endif
#if defined(__mips_msa) && defined(__mips_isa_rev) && (__mips_isa_rev >= 5)
#define WEBP_USE_MSA
#endif
#ifndef WEBP_DSP_OMIT_C_CODE
#define WEBP_DSP_OMIT_C_CODE 1
#endif
#if defined(WEBP_USE_NEON) && WEBP_DSP_OMIT_C_CODE
#define WEBP_NEON_OMIT_C_CODE 1
#else
#define WEBP_NEON_OMIT_C_CODE 0
#endif
#if !(LOCAL_CLANG_PREREQ(3,8) || LOCAL_GCC_PREREQ(4,8) || defined(__aarch64__))
#define WEBP_NEON_WORK_AROUND_GCC 1
#else
#define WEBP_NEON_WORK_AROUND_GCC 0
#endif
// This macro prevents thread_sanitizer from reporting known concurrent writes.
#define WEBP_TSAN_IGNORE_FUNCTION
#if defined(__has_feature)
#if __has_feature(thread_sanitizer)
#undef WEBP_TSAN_IGNORE_FUNCTION
#define WEBP_TSAN_IGNORE_FUNCTION __attribute__((no_sanitize_thread))
#endif
#endif
#if defined(WEBP_USE_THREAD) && !defined(_WIN32)
#include <pthread.h> // NOLINT
#define WEBP_DSP_INIT(func) do { \
static volatile VP8CPUInfo func ## _last_cpuinfo_used = \
(VP8CPUInfo)&func ## _last_cpuinfo_used; \
static pthread_mutex_t func ## _lock = PTHREAD_MUTEX_INITIALIZER; \
if (pthread_mutex_lock(&func ## _lock)) break; \
if (func ## _last_cpuinfo_used != VP8GetCPUInfo) func(); \
func ## _last_cpuinfo_used = VP8GetCPUInfo; \
(void)pthread_mutex_unlock(&func ## _lock); \
} while (0)
#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32))
#define WEBP_DSP_INIT(func) do { \
static volatile VP8CPUInfo func ## _last_cpuinfo_used = \
(VP8CPUInfo)&func ## _last_cpuinfo_used; \
if (func ## _last_cpuinfo_used == VP8GetCPUInfo) break; \
func(); \
func ## _last_cpuinfo_used = VP8GetCPUInfo; \
} while (0)
#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32)
// Defines an Init + helper function that control multiple initialization of
// function pointers / tables.
/* Usage:
WEBP_DSP_INIT_FUNC(InitFunc) {
...function body
}
*/
#define WEBP_DSP_INIT_FUNC(name) \
static WEBP_TSAN_IGNORE_FUNCTION void name ## _body(void); \
WEBP_TSAN_IGNORE_FUNCTION void name(void) { \
WEBP_DSP_INIT(name ## _body); \
} \
static WEBP_TSAN_IGNORE_FUNCTION void name ## _body(void)
#define WEBP_UBSAN_IGNORE_UNDEF
#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW
#if defined(__clang__) && defined(__has_attribute)
#if __has_attribute(no_sanitize)
// This macro prevents the undefined behavior sanitizer from reporting
// failures. This is only meant to silence unaligned loads on platforms that
// are known to support them.
#undef WEBP_UBSAN_IGNORE_UNDEF
#define WEBP_UBSAN_IGNORE_UNDEF \
__attribute__((no_sanitize("undefined")))
// This macro prevents the undefined behavior sanitizer from reporting
// failures related to unsigned integer overflows. This is only meant to
// silence cases where this well defined behavior is expected.
#undef WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW
#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW \
__attribute__((no_sanitize("unsigned-integer-overflow")))
#endif
#endif
// If 'ptr' is NULL, returns NULL. Otherwise returns 'ptr + off'.
// Prevents undefined behavior sanitizer nullptr-with-nonzero-offset warning.
#if !defined(WEBP_OFFSET_PTR)
#define WEBP_OFFSET_PTR(ptr, off) (((ptr) == NULL) ? NULL : ((ptr) + (off)))
#endif
// Regularize the definition of WEBP_SWAP_16BIT_CSP (backward compatibility)
#if !defined(WEBP_SWAP_16BIT_CSP)
#define WEBP_SWAP_16BIT_CSP 0
#endif
// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__)
#if !defined(WORDS_BIGENDIAN) && \
(defined(__BIG_ENDIAN__) || defined(_M_PPC) || \
(defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
#define WORDS_BIGENDIAN
#endif
typedef enum {
kSSE2,
kSSE3,
kSlowSSSE3, // special feature for slow SSSE3 architectures
kSSE4_1,
kAVX,
kAVX2,
kNEON,
kMIPS32,
kMIPSdspR2,
kMSA
} CPUFeature;
// returns true if the CPU supports the feature.
typedef int (*VP8CPUInfo)(CPUFeature feature);
WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo;
//------------------------------------------------------------------------------
// Init stub generator
@ -545,15 +332,6 @@ extern void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v,
extern void WebPConvertRGBA32ToUV_C(const uint16_t* rgb,
uint8_t* u, uint8_t* v, int width);
// utilities for accurate RGB->YUV conversion
extern uint64_t (*WebPSharpYUVUpdateY)(const uint16_t* src, const uint16_t* ref,
uint16_t* dst, int len);
extern void (*WebPSharpYUVUpdateRGB)(const int16_t* src, const int16_t* ref,
int16_t* dst, int len);
extern void (*WebPSharpYUVFilterRow)(const int16_t* A, const int16_t* B,
int len,
const uint16_t* best_y, uint16_t* out);
// Must be called before using the above.
void WebPInitConvertARGBToYUV(void);

View File

@ -9,7 +9,7 @@
//
// ARM NEON version of speed-critical encoding functions.
//
// adapted from libvpx (http://www.webmproject.org/code/)
// adapted from libvpx (https://www.webmproject.org/code/)
#include "src/dsp/dsp.h"

View File

@ -107,63 +107,77 @@ static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
//------------------------------------------------------------------------------
// Predictors
uint32_t VP8LPredictor0_C(uint32_t left, const uint32_t* const top) {
uint32_t VP8LPredictor0_C(const uint32_t* const left,
const uint32_t* const top) {
(void)top;
(void)left;
return ARGB_BLACK;
}
uint32_t VP8LPredictor1_C(uint32_t left, const uint32_t* const top) {
uint32_t VP8LPredictor1_C(const uint32_t* const left,
const uint32_t* const top) {
(void)top;
return left;
return *left;
}
uint32_t VP8LPredictor2_C(uint32_t left, const uint32_t* const top) {
uint32_t VP8LPredictor2_C(const uint32_t* const left,
const uint32_t* const top) {
(void)left;
return top[0];
}
uint32_t VP8LPredictor3_C(uint32_t left, const uint32_t* const top) {
uint32_t VP8LPredictor3_C(const uint32_t* const left,
const uint32_t* const top) {
(void)left;
return top[1];
}
uint32_t VP8LPredictor4_C(uint32_t left, const uint32_t* const top) {
uint32_t VP8LPredictor4_C(const uint32_t* const left,
const uint32_t* const top) {
(void)left;
return top[-1];
}
uint32_t VP8LPredictor5_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average3(left, top[0], top[1]);
uint32_t VP8LPredictor5_C(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average3(*left, top[0], top[1]);
return pred;
}
uint32_t VP8LPredictor6_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(left, top[-1]);
uint32_t VP8LPredictor6_C(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average2(*left, top[-1]);
return pred;
}
uint32_t VP8LPredictor7_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(left, top[0]);
uint32_t VP8LPredictor7_C(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average2(*left, top[0]);
return pred;
}
uint32_t VP8LPredictor8_C(uint32_t left, const uint32_t* const top) {
uint32_t VP8LPredictor8_C(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average2(top[-1], top[0]);
(void)left;
return pred;
}
uint32_t VP8LPredictor9_C(uint32_t left, const uint32_t* const top) {
uint32_t VP8LPredictor9_C(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average2(top[0], top[1]);
(void)left;
return pred;
}
uint32_t VP8LPredictor10_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average4(left, top[-1], top[0], top[1]);
uint32_t VP8LPredictor10_C(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average4(*left, top[-1], top[0], top[1]);
return pred;
}
uint32_t VP8LPredictor11_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Select(top[0], left, top[-1]);
uint32_t VP8LPredictor11_C(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Select(top[0], *left, top[-1]);
return pred;
}
uint32_t VP8LPredictor12_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]);
uint32_t VP8LPredictor12_C(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractFull(*left, top[0], top[-1]);
return pred;
}
uint32_t VP8LPredictor13_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
uint32_t VP8LPredictor13_C(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractHalf(*left, top[0], top[-1]);
return pred;
}

View File

@ -28,23 +28,38 @@ extern "C" {
//------------------------------------------------------------------------------
// Decoding
typedef uint32_t (*VP8LPredictorFunc)(uint32_t left, const uint32_t* const top);
typedef uint32_t (*VP8LPredictorFunc)(const uint32_t* const left,
const uint32_t* const top);
extern VP8LPredictorFunc VP8LPredictors[16];
uint32_t VP8LPredictor0_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor1_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor2_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor3_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor4_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor5_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor6_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor7_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor8_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor9_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor10_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor11_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor12_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor13_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor0_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor1_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor2_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor3_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor4_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor5_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor6_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor7_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor8_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor9_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor10_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor11_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor12_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor13_C(const uint32_t* const left,
const uint32_t* const top);
// These Add/Sub function expects upper[-1] and out[-1] to be readable.
typedef void (*VP8LPredictorAddSubFunc)(const uint32_t* in,
@ -167,9 +182,9 @@ extern VP8LPredictorAddSubFunc VP8LPredictorsSub_C[16];
// -----------------------------------------------------------------------------
// Huffman-cost related functions.
typedef double (*VP8LCostFunc)(const uint32_t* population, int length);
typedef double (*VP8LCostCombinedFunc)(const uint32_t* X, const uint32_t* Y,
int length);
typedef float (*VP8LCostFunc)(const uint32_t* population, int length);
typedef float (*VP8LCostCombinedFunc)(const uint32_t* X, const uint32_t* Y,
int length);
typedef float (*VP8LCombinedShannonEntropyFunc)(const int X[256],
const int Y[256]);
@ -183,7 +198,7 @@ typedef struct { // small struct to hold counters
} VP8LStreaks;
typedef struct { // small struct to hold bit entropy results
double entropy; // entropy
float entropy; // entropy
uint32_t sum; // sum of the population
int nonzeros; // number of non-zero elements in the population
uint32_t max_val; // maximum value in the population

View File

@ -179,7 +179,7 @@ static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
int x; \
assert(upper != NULL); \
for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = (PREDICTOR)(out[x - 1], upper + x); \
const uint32_t pred = (PREDICTOR)(&out[x - 1], upper + x); \
out[x] = VP8LAddPixels(in[x], pred); \
} \
}

View File

@ -402,7 +402,7 @@ static float FastLog2Slow_C(uint32_t v) {
// Compute the combined Shanon's entropy for distribution {X} and {X+Y}
static float CombinedShannonEntropy_C(const int X[256], const int Y[256]) {
int i;
double retval = 0.;
float retval = 0.f;
int sumX = 0, sumXY = 0;
for (i = 0; i < 256; ++i) {
const int x = X[i];
@ -418,7 +418,7 @@ static float CombinedShannonEntropy_C(const int X[256], const int Y[256]) {
}
}
retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY);
return (float)retval;
return retval;
}
void VP8LBitEntropyInit(VP8LBitEntropy* const entropy) {
@ -636,17 +636,17 @@ void VP8LBundleColorMap_C(const uint8_t* const row, int width, int xbits,
//------------------------------------------------------------------------------
static double ExtraCost_C(const uint32_t* population, int length) {
static float ExtraCost_C(const uint32_t* population, int length) {
int i;
double cost = 0.;
float cost = 0.f;
for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2];
return cost;
}
static double ExtraCostCombined_C(const uint32_t* X, const uint32_t* Y,
static float ExtraCostCombined_C(const uint32_t* X, const uint32_t* Y,
int length) {
int i;
double cost = 0.;
float cost = 0.f;
for (i = 2; i < length - 2; ++i) {
const int xy = X[i + 2] + Y[i + 2];
cost += (i >> 1) * xy;
@ -745,7 +745,7 @@ static void PredictorSub##PREDICTOR_I##_C(const uint32_t* in, \
assert(upper != NULL); \
for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = \
VP8LPredictor##PREDICTOR_I##_C(in[x - 1], upper + x); \
VP8LPredictor##PREDICTOR_I##_C(&in[x - 1], upper + x); \
out[x] = VP8LSubPixels(in[x], pred); \
} \
}

View File

@ -103,8 +103,8 @@ static float FastLog2Slow_MIPS32(uint32_t v) {
// cost += i * *(pop + 1);
// pop += 2;
// }
// return (double)cost;
static double ExtraCost_MIPS32(const uint32_t* const population, int length) {
// return (float)cost;
static float ExtraCost_MIPS32(const uint32_t* const population, int length) {
int i, temp0, temp1;
const uint32_t* pop = &population[4];
const uint32_t* const LoopEnd = &population[length];
@ -130,7 +130,7 @@ static double ExtraCost_MIPS32(const uint32_t* const population, int length) {
: "memory", "hi", "lo"
);
return (double)((int64_t)temp0 << 32 | temp1);
return (float)((int64_t)temp0 << 32 | temp1);
}
// C version of this function:
@ -148,9 +148,9 @@ static double ExtraCost_MIPS32(const uint32_t* const population, int length) {
// pX += 2;
// pY += 2;
// }
// return (double)cost;
static double ExtraCostCombined_MIPS32(const uint32_t* const X,
const uint32_t* const Y, int length) {
// return (float)cost;
static float ExtraCostCombined_MIPS32(const uint32_t* const X,
const uint32_t* const Y, int length) {
int i, temp0, temp1, temp2, temp3;
const uint32_t* pX = &X[4];
const uint32_t* pY = &Y[4];
@ -183,7 +183,7 @@ static double ExtraCostCombined_MIPS32(const uint32_t* const X,
: "memory", "hi", "lo"
);
return (double)((int64_t)temp0 << 32 | temp1);
return (float)((int64_t)temp0 << 32 | temp1);
}
#define HUFFMAN_COST_PASS \
@ -347,24 +347,24 @@ static void GetCombinedEntropyUnrefined_MIPS32(const uint32_t X[],
static void AddVector_MIPS32(const uint32_t* pa, const uint32_t* pb,
uint32_t* pout, int size) {
uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
const uint32_t end = ((size) / 4) * 4;
const int end = ((size) / 4) * 4;
const uint32_t* const LoopEnd = pa + end;
int i;
ASM_START
ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout)
ASM_END_0
for (i = end; i < size; ++i) pout[i] = pa[i] + pb[i];
for (i = 0; i < size - end; ++i) pout[i] = pa[i] + pb[i];
}
static void AddVectorEq_MIPS32(const uint32_t* pa, uint32_t* pout, int size) {
uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
const uint32_t end = ((size) / 4) * 4;
const int end = ((size) / 4) * 4;
const uint32_t* const LoopEnd = pa + end;
int i;
ASM_START
ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout)
ASM_END_1
for (i = end; i < size; ++i) pout[i] += pa[i];
for (i = 0; i < size - end; ++i) pout[i] += pa[i];
}
#undef ASM_END_1

View File

@ -239,7 +239,7 @@ static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) {
static float CombinedShannonEntropy_SSE2(const int X[256], const int Y[256]) {
int i;
double retval = 0.;
float retval = 0.f;
int sumX = 0, sumXY = 0;
const __m128i zero = _mm_setzero_si128();
@ -273,7 +273,7 @@ static float CombinedShannonEntropy_SSE2(const int X[256], const int Y[256]) {
}
}
retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY);
return (float)retval;
return retval;
}
#else

View File

@ -188,46 +188,51 @@ static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
return Average2(Average2(a0, a1), Average2(a2, a3));
}
static uint32_t Predictor5_MIPSdspR2(uint32_t left, const uint32_t* const top) {
return Average3(left, top[0], top[1]);
static uint32_t Predictor5_MIPSdspR2(const uint32_t* const left,
const uint32_t* const top) {
return Average3(*left, top[0], top[1]);
}
static uint32_t Predictor6_MIPSdspR2(uint32_t left, const uint32_t* const top) {
return Average2(left, top[-1]);
static uint32_t Predictor6_MIPSdspR2(const uint32_t* const left,
const uint32_t* const top) {
return Average2(*left, top[-1]);
}
static uint32_t Predictor7_MIPSdspR2(uint32_t left, const uint32_t* const top) {
return Average2(left, top[0]);
static uint32_t Predictor7_MIPSdspR2(const uint32_t* const left,
const uint32_t* const top) {
return Average2(*left, top[0]);
}
static uint32_t Predictor8_MIPSdspR2(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor8_MIPSdspR2(const uint32_t* const left,
const uint32_t* const top) {
(void)left;
return Average2(top[-1], top[0]);
}
static uint32_t Predictor9_MIPSdspR2(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor9_MIPSdspR2(const uint32_t* const left,
const uint32_t* const top) {
(void)left;
return Average2(top[0], top[1]);
}
static uint32_t Predictor10_MIPSdspR2(uint32_t left,
static uint32_t Predictor10_MIPSdspR2(const uint32_t* const left,
const uint32_t* const top) {
return Average4(left, top[-1], top[0], top[1]);
return Average4(*left, top[-1], top[0], top[1]);
}
static uint32_t Predictor11_MIPSdspR2(uint32_t left,
static uint32_t Predictor11_MIPSdspR2(const uint32_t* const left,
const uint32_t* const top) {
return Select(top[0], left, top[-1]);
return Select(top[0], *left, top[-1]);
}
static uint32_t Predictor12_MIPSdspR2(uint32_t left,
static uint32_t Predictor12_MIPSdspR2(const uint32_t* const left,
const uint32_t* const top) {
return ClampedAddSubtractFull(left, top[0], top[-1]);
return ClampedAddSubtractFull(*left, top[0], top[-1]);
}
static uint32_t Predictor13_MIPSdspR2(uint32_t left,
static uint32_t Predictor13_MIPSdspR2(const uint32_t* const left,
const uint32_t* const top) {
return ClampedAddSubtractHalf(left, top[0], top[-1]);
return ClampedAddSubtractHalf(*left, top[0], top[-1]);
}
// Add green to blue and red channels (i.e. perform the inverse transform of

View File

@ -188,17 +188,21 @@ static WEBP_INLINE uint32_t Average3_NEON(uint32_t a0, uint32_t a1,
return avg;
}
static uint32_t Predictor5_NEON(uint32_t left, const uint32_t* const top) {
return Average3_NEON(left, top[0], top[1]);
static uint32_t Predictor5_NEON(const uint32_t* const left,
const uint32_t* const top) {
return Average3_NEON(*left, top[0], top[1]);
}
static uint32_t Predictor6_NEON(uint32_t left, const uint32_t* const top) {
return Average2_NEON(left, top[-1]);
static uint32_t Predictor6_NEON(const uint32_t* const left,
const uint32_t* const top) {
return Average2_NEON(*left, top[-1]);
}
static uint32_t Predictor7_NEON(uint32_t left, const uint32_t* const top) {
return Average2_NEON(left, top[0]);
static uint32_t Predictor7_NEON(const uint32_t* const left,
const uint32_t* const top) {
return Average2_NEON(*left, top[0]);
}
static uint32_t Predictor13_NEON(uint32_t left, const uint32_t* const top) {
return ClampedAddSubtractHalf_NEON(left, top[0], top[-1]);
static uint32_t Predictor13_NEON(const uint32_t* const left,
const uint32_t* const top) {
return ClampedAddSubtractHalf_NEON(*left, top[0], top[-1]);
}
// Batch versions of those functions.

View File

@ -138,42 +138,51 @@ static WEBP_INLINE uint32_t Average4_SSE2(uint32_t a0, uint32_t a1,
return output;
}
static uint32_t Predictor5_SSE2(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average3_SSE2(left, top[0], top[1]);
static uint32_t Predictor5_SSE2(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average3_SSE2(*left, top[0], top[1]);
return pred;
}
static uint32_t Predictor6_SSE2(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2_SSE2(left, top[-1]);
static uint32_t Predictor6_SSE2(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average2_SSE2(*left, top[-1]);
return pred;
}
static uint32_t Predictor7_SSE2(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2_SSE2(left, top[0]);
static uint32_t Predictor7_SSE2(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average2_SSE2(*left, top[0]);
return pred;
}
static uint32_t Predictor8_SSE2(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor8_SSE2(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average2_SSE2(top[-1], top[0]);
(void)left;
return pred;
}
static uint32_t Predictor9_SSE2(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor9_SSE2(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average2_SSE2(top[0], top[1]);
(void)left;
return pred;
}
static uint32_t Predictor10_SSE2(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average4_SSE2(left, top[-1], top[0], top[1]);
static uint32_t Predictor10_SSE2(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average4_SSE2(*left, top[-1], top[0], top[1]);
return pred;
}
static uint32_t Predictor11_SSE2(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Select_SSE2(top[0], left, top[-1]);
static uint32_t Predictor11_SSE2(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Select_SSE2(top[0], *left, top[-1]);
return pred;
}
static uint32_t Predictor12_SSE2(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractFull_SSE2(left, top[0], top[-1]);
static uint32_t Predictor12_SSE2(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractFull_SSE2(*left, top[0], top[-1]);
return pred;
}
static uint32_t Predictor13_SSE2(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractHalf_SSE2(left, top[0], top[-1]);
static uint32_t Predictor13_SSE2(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractHalf_SSE2(*left, top[0], top[-1]);
return pred;
}

View File

@ -14,6 +14,10 @@
#ifndef WEBP_DSP_MSA_MACRO_H_
#define WEBP_DSP_MSA_MACRO_H_
#include "src/dsp/dsp.h"
#if defined(WEBP_USE_MSA)
#include <stdint.h>
#include <msa.h>
@ -1389,4 +1393,5 @@ static WEBP_INLINE uint32_t func_hadd_uh_u32(v8u16 in) {
} while (0)
#define AVER_UB2_UB(...) AVER_UB2(v16u8, __VA_ARGS__)
#endif // WEBP_USE_MSA
#endif // WEBP_DSP_MSA_MACRO_H_

View File

@ -12,10 +12,12 @@
#ifndef WEBP_DSP_NEON_H_
#define WEBP_DSP_NEON_H_
#include <arm_neon.h>
#include "src/dsp/dsp.h"
#if defined(WEBP_USE_NEON)
#include <arm_neon.h>
// Right now, some intrinsics functions seem slower, so we disable them
// everywhere except newer clang/gcc or aarch64 where the inline assembly is
// incompatible.
@ -98,4 +100,5 @@ static WEBP_INLINE int32x4x4_t Transpose4x4_NEON(const int32x4x4_t rows) {
} while (0)
#endif
#endif // WEBP_USE_NEON
#endif // WEBP_DSP_NEON_H_

View File

@ -194,50 +194,6 @@ void WebPConvertRGBA32ToUV_C(const uint16_t* rgb,
//-----------------------------------------------------------------------------
#if !WEBP_NEON_OMIT_C_CODE
#define MAX_Y ((1 << 10) - 1) // 10b precision over 16b-arithmetic
static uint16_t clip_y(int v) {
return (v < 0) ? 0 : (v > MAX_Y) ? MAX_Y : (uint16_t)v;
}
static uint64_t SharpYUVUpdateY_C(const uint16_t* ref, const uint16_t* src,
uint16_t* dst, int len) {
uint64_t diff = 0;
int i;
for (i = 0; i < len; ++i) {
const int diff_y = ref[i] - src[i];
const int new_y = (int)dst[i] + diff_y;
dst[i] = clip_y(new_y);
diff += (uint64_t)abs(diff_y);
}
return diff;
}
static void SharpYUVUpdateRGB_C(const int16_t* ref, const int16_t* src,
int16_t* dst, int len) {
int i;
for (i = 0; i < len; ++i) {
const int diff_uv = ref[i] - src[i];
dst[i] += diff_uv;
}
}
static void SharpYUVFilterRow_C(const int16_t* A, const int16_t* B, int len,
const uint16_t* best_y, uint16_t* out) {
int i;
for (i = 0; i < len; ++i, ++A, ++B) {
const int v0 = (A[0] * 9 + A[1] * 3 + B[0] * 3 + B[1] + 8) >> 4;
const int v1 = (A[1] * 9 + A[0] * 3 + B[1] * 3 + B[0] + 8) >> 4;
out[2 * i + 0] = clip_y(best_y[2 * i + 0] + v0);
out[2 * i + 1] = clip_y(best_y[2 * i + 1] + v1);
}
}
#endif // !WEBP_NEON_OMIT_C_CODE
#undef MAX_Y
//-----------------------------------------------------------------------------
void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width);
void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width);
void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb,
@ -247,18 +203,9 @@ void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width);
void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v,
int src_width, int do_store);
uint64_t (*WebPSharpYUVUpdateY)(const uint16_t* ref, const uint16_t* src,
uint16_t* dst, int len);
void (*WebPSharpYUVUpdateRGB)(const int16_t* ref, const int16_t* src,
int16_t* dst, int len);
void (*WebPSharpYUVFilterRow)(const int16_t* A, const int16_t* B, int len,
const uint16_t* best_y, uint16_t* out);
extern void WebPInitConvertARGBToYUVSSE2(void);
extern void WebPInitConvertARGBToYUVSSE41(void);
extern void WebPInitConvertARGBToYUVNEON(void);
extern void WebPInitSharpYUVSSE2(void);
extern void WebPInitSharpYUVNEON(void);
WEBP_DSP_INIT_FUNC(WebPInitConvertARGBToYUV) {
WebPConvertARGBToY = ConvertARGBToY_C;
@ -269,17 +216,10 @@ WEBP_DSP_INIT_FUNC(WebPInitConvertARGBToYUV) {
WebPConvertRGBA32ToUV = WebPConvertRGBA32ToUV_C;
#if !WEBP_NEON_OMIT_C_CODE
WebPSharpYUVUpdateY = SharpYUVUpdateY_C;
WebPSharpYUVUpdateRGB = SharpYUVUpdateRGB_C;
WebPSharpYUVFilterRow = SharpYUVFilterRow_C;
#endif
if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_HAVE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
WebPInitConvertARGBToYUVSSE2();
WebPInitSharpYUVSSE2();
}
#endif // WEBP_HAVE_SSE2
#if defined(WEBP_HAVE_SSE41)
@ -293,7 +233,6 @@ WEBP_DSP_INIT_FUNC(WebPInitConvertARGBToYUV) {
if (WEBP_NEON_OMIT_C_CODE ||
(VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {
WebPInitConvertARGBToYUVNEON();
WebPInitSharpYUVNEON();
}
#endif // WEBP_HAVE_NEON
@ -302,7 +241,4 @@ WEBP_DSP_INIT_FUNC(WebPInitConvertARGBToYUV) {
assert(WebPConvertRGB24ToY != NULL);
assert(WebPConvertBGR24ToY != NULL);
assert(WebPConvertRGBA32ToUV != NULL);
assert(WebPSharpYUVUpdateY != NULL);
assert(WebPSharpYUVUpdateRGB != NULL);
assert(WebPSharpYUVFilterRow != NULL);
}

View File

@ -10,7 +10,7 @@
// inline YUV<->RGB conversion function
//
// The exact naming is Y'CbCr, following the ITU-R BT.601 standard.
// More information at: http://en.wikipedia.org/wiki/YCbCr
// More information at: https://en.wikipedia.org/wiki/YCbCr
// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16
// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128
// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128

Some files were not shown because too many files have changed in this diff Show More