Compare commits

..

8 Commits

Author SHA1 Message Date
50f60add5c Fix OOB write in BuildHuffmanTable.
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)
(cherry picked from commit 2af26267cd)
2023-09-07 15:40:16 -07:00
5df85e9c0b EncodeAlphaInternal: clear result->bw on error
This avoids a double free should the function fail prior to
VP8BitWriterInit() and a previous trial result's buffer carried over.
Previously in ApplyFiltersAndEncode() trial.bw (with a previous
iteration's buffer) would be freed, followed by best.bw pointing to the
same buffer.

Since:
187d379d add a fallback to ALPHA_NO_COMPRESSION

In addition, check the return value of VP8BitWriterInit() in this
function.

Bug: webp:603
Change-Id: Ic258381ee26c8c16bc211d157c8153831c8c6910
(cherry picked from commit a486d800b6)
2023-02-28 00:26:34 +00:00
89e226a3c7 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
(cherry picked from commit e3cfafaf71)
(cherry picked from commit 20ef03ee35)
2022-04-06 21:55:27 -07:00
4d0964cd0c 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
(cherry picked from commit a828a59b49)
(cherry picked from commit dd80bb4343)
2022-04-06 21:50:21 -07:00
5d805f7205 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
(cherry picked from commit fe153fae98)
(cherry picked from commit ddd65f0d19)
2022-04-06 21:50:21 -07:00
b14eba6497 alpha_processing_neon.c: fix 0x01... typo
one instance was overlong leading to a int64->uint32 conversion warning

Change-Id: I56d5ab75d89960c79293f62cd489d7ab519bbc34
(cherry picked from commit 03d1219055)
2022-03-08 19:37:04 +00:00
9183ff2ef9 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
(cherry picked from commit 924e7ca654)
2022-03-03 18:06:24 +00:00
68d52453cd Fix lossless encoding for MIPS.
Bug: webp:558
Change-Id: I3d3ddb64ed26a8d8ff5664664c5f20f6eadfeb4f
(cherry picked from commit e4cbcdd2b5)
2022-03-02 02:56:13 +00:00
312 changed files with 13509 additions and 37751 deletions

View File

@ -1,240 +0,0 @@
# ----------------------------------
# Options affecting listfile parsing
# ----------------------------------
with section("parse"):
# Specify structure for custom cmake functions
additional_commands = { 'foo': { 'flags': ['BAR', 'BAZ'],
'kwargs': {'DEPENDS': '*', 'HEADERS': '*', 'SOURCES': '*'}}}
# Override configurations per-command where available
override_spec = {}
# Specify variable tags.
vartags = []
# Specify property tags.
proptags = []
# -----------------------------
# Options affecting formatting.
# -----------------------------
with section("format"):
# Disable formatting entirely, making cmake-format a no-op
disable = False
# How wide to allow formatted cmake files
line_width = 80
# How many spaces to tab for indent
tab_size = 2
# If true, lines are indented using tab characters (utf-8 0x09) instead of
# <tab_size> space characters (utf-8 0x20). In cases where the layout would
# require a fractional tab character, the behavior of the fractional
# indentation is governed by <fractional_tab_policy>
use_tabchars = False
# If <use_tabchars> is True, then the value of this variable indicates how
# fractional indentions are handled during whitespace replacement. If set to
# 'use-space', fractional indentation is left as spaces (utf-8 0x20). If set
# to `round-up` fractional indentation is replaced with a single tab character
# (utf-8 0x09) effectively shifting the column to the next tabstop
fractional_tab_policy = 'use-space'
# If an argument group contains more than this many sub-groups (parg or kwarg
# groups) then force it to a vertical layout.
max_subgroups_hwrap = 3
# If a positional argument group contains more than this many arguments, then
# force it to a vertical layout.
max_pargs_hwrap = 6
# If a cmdline positional group consumes more than this many lines without
# nesting, then invalidate the layout (and nest)
max_rows_cmdline = 2
# If true, separate flow control names from their parentheses with a space
separate_ctrl_name_with_space = False
# If true, separate function names from parentheses with a space
separate_fn_name_with_space = False
# If a statement is wrapped to more than one line, than dangle the closing
# parenthesis on its own line.
dangle_parens = False
# If the trailing parenthesis must be 'dangled' on its on line, then align it
# to this reference: `prefix`: the start of the statement, `prefix-indent`:
# the start of the statement, plus one indentation level, `child`: align to
# the column of the arguments
dangle_align = 'prefix'
# If the statement spelling length (including space and parenthesis) is
# smaller than this amount, then force reject nested layouts.
min_prefix_chars = 4
# If the statement spelling length (including space and parenthesis) is larger
# than the tab width by more than this amount, then force reject un-nested
# layouts.
max_prefix_chars = 10
# If a candidate layout is wrapped horizontally but it exceeds this many
# lines, then reject the layout.
max_lines_hwrap = 2
# What style line endings to use in the output.
line_ending = 'unix'
# Format command names consistently as 'lower' or 'upper' case
command_case = 'canonical'
# Format keywords consistently as 'lower' or 'upper' case
keyword_case = 'unchanged'
# A list of command names which should always be wrapped
always_wrap = []
# If true, the argument lists which are known to be sortable will be sorted
# lexicographicall
enable_sort = True
# If true, the parsers may infer whether or not an argument list is sortable
# (without annotation).
autosort = False
# By default, if cmake-format cannot successfully fit everything into the
# desired linewidth it will apply the last, most agressive attempt that it
# made. If this flag is True, however, cmake-format will print error, exit
# with non-zero status code, and write-out nothing
require_valid_layout = False
# A dictionary mapping layout nodes to a list of wrap decisions. See the
# documentation for more information.
layout_passes = {}
# ------------------------------------------------
# Options affecting comment reflow and formatting.
# ------------------------------------------------
with section("markup"):
# What character to use for bulleted lists
bullet_char = '*'
# What character to use as punctuation after numerals in an enumerated list
enum_char = '.'
# If comment markup is enabled, don't reflow the first comment block in each
# listfile. Use this to preserve formatting of your copyright/license
# statements.
first_comment_is_literal = True
# If comment markup is enabled, don't reflow any comment block which matches
# this (regex) pattern. Default is `None` (disabled).
literal_comment_pattern = None
# Regular expression to match preformat fences in comments default=
# ``r'^\s*([`~]{3}[`~]*)(.*)$'``
fence_pattern = '^\\s*([`~]{3}[`~]*)(.*)$'
# Regular expression to match rulers in comments default=
# ``r'^\s*[^\w\s]{3}.*[^\w\s]{3}$'``
ruler_pattern = '^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$'
# If a comment line matches starts with this pattern then it is explicitly a
# trailing comment for the preceeding argument. Default is '#<'
explicit_trailing_pattern = '#<'
# If a comment line starts with at least this many consecutive hash
# characters, then don't lstrip() them off. This allows for lazy hash rulers
# where the first hash char is not separated by space
hashruler_min_length = 10
# If true, then insert a space between the first hash char and remaining hash
# chars in a hash ruler, and normalize its length to fill the column
canonicalize_hashrulers = True
# enable comment markup parsing and reflow
enable_markup = True
# ----------------------------
# Options affecting the linter
# ----------------------------
with section("lint"):
# a list of lint codes to disable
disabled_codes = []
# regular expression pattern describing valid function names
function_pattern = '[0-9a-z_]+'
# regular expression pattern describing valid macro names
macro_pattern = '[0-9A-Z_]+'
# regular expression pattern describing valid names for variables with global
# (cache) scope
global_var_pattern = '[A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for variables with global
# scope (but internal semantic)
internal_var_pattern = '_[A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for variables with local
# scope
local_var_pattern = '[a-z][a-z0-9_]+'
# regular expression pattern describing valid names for privatedirectory
# variables
private_var_pattern = '_[0-9a-z_]+'
# regular expression pattern describing valid names for public directory
# variables
public_var_pattern = '[A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for function/macro
# arguments and loop variables.
argument_var_pattern = '[a-z][a-z0-9_]+'
# regular expression pattern describing valid names for keywords used in
# functions or macros
keyword_pattern = '[A-Z][0-9A-Z_]+'
# In the heuristic for C0201, how many conditionals to match within a loop in
# before considering the loop a parser.
max_conditionals_custom_parser = 2
# Require at least this many newlines between statements
min_statement_spacing = 1
# Require no more than this many newlines between statements
max_statement_spacing = 2
max_returns = 6
max_branches = 12
max_arguments = 5
max_localvars = 15
max_statements = 50
# -------------------------------
# Options affecting file encoding
# -------------------------------
with section("encode"):
# If true, emit the unicode byte-order mark (BOM) at the start of the file
emit_byteorder_mark = False
# Specify the encoding of the input file. Defaults to utf-8
input_encoding = 'utf-8'
# Specify the encoding of the output file. Defaults to utf-8. Note that cmake
# only claims to support utf-8 so be careful when using anything else
output_encoding = 'utf-8'
# -------------------------------------
# Miscellaneous configurations options.
# -------------------------------------
with section("misc"):
# A dictionary containing any per-command configuration overrides. Currently
# only `command_case` is supported.
per_command = {}

1
.gitattributes vendored
View File

@ -1,6 +1,5 @@
.gitattributes export-ignore .gitattributes export-ignore
.gitignore export-ignore .gitignore export-ignore
.mailmap export-ignore .mailmap export-ignore
*.bat text eol=crlf
*.pdf -text -diff *.pdf -text -diff
*.ppm -text -diff *.ppm -text -diff

15
.gitignore vendored
View File

@ -1,11 +1,8 @@
*.l[ao] *.l[ao]
*.[ao] *.[ao]
*.pc *.pc
.DS_Store
.deps .deps
.idea
.libs .libs
.vscode
/aclocal.m4 /aclocal.m4
/ar-lib /ar-lib
/autom4te.cache /autom4te.cache
@ -36,8 +33,7 @@ src/webp/stamp-h1
*.idb *.idb
*.pdb *.pdb
/iosbuild /iosbuild
/xcframeworkbuild /WebP.framework
/WebP*.*framework
CMakeCache.txt CMakeCache.txt
CMakeFiles/ CMakeFiles/
cmake_install.cmake cmake_install.cmake
@ -46,12 +42,3 @@ cmake_install.cmake
extras/get_disto extras/get_disto
extras/vwebp_sdl extras/vwebp_sdl
extras/webp_quality extras/webp_quality
tests/fuzzer/advanced_api_fuzzer
tests/fuzzer/animation_api_fuzzer
tests/fuzzer/animdecoder_fuzzer
tests/fuzzer/animencoder_fuzzer
tests/fuzzer/demux_api_fuzzer
tests/fuzzer/enc_dec_fuzzer
tests/fuzzer/huffman_fuzzer
tests/fuzzer/mux_demux_api_fuzzer
tests/fuzzer/simple_api_fuzzer

View File

@ -8,13 +8,6 @@ Vikas Arora <vikasa@google.com>
<vikasa@google.com> <vikaas.arora@gmail.com> <vikasa@google.com> <vikaas.arora@gmail.com>
<slobodan.prijic@imgtec.com> <Slobodan.Prijic@imgtec.com> <slobodan.prijic@imgtec.com> <Slobodan.Prijic@imgtec.com>
<vrabaud@google.com> <vincent.rabaud@gmail.com> <vrabaud@google.com> <vincent.rabaud@gmail.com>
Vincent Rabaud <vrabaud@google.com>
Tamar Levy <tamar.levy@intel.com> Tamar Levy <tamar.levy@intel.com>
<qrczak@google.com> <qrczak> <qrczak@google.com> <qrczak>
Hui Su <huisu@google.com> Hui Su <huisu@google.com>
James Zern <jzern@google.com>
Roberto Alanis <alanisbaez@google.com>
Brian Ledger <brianpl@google.com>
Maryla Ustarroz-Calonge <maryla@google.com>
Yannis Guyon <yguyon@google.com>
Henner Zeller <hzeller@google.com> <h.zeller@acm.org>

441
.pylintrc
View File

@ -1,441 +0,0 @@
# 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

View File

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

27
AUTHORS
View File

@ -1,32 +1,15 @@
Contributors: Contributors:
- Aidan O'Loan (aidanol at gmail dot com) - Aidan O'Loan (aidanol at gmail dot com)
- Alan Browning (browning at google dot com) - Alan Browning (browning at google dot com)
- Alexandru Ardelean (ardeleanalex at gmail dot com)
- Anuraag Agrawal (anuraaga at gmail dot com)
- Arthur Eubanks (aeubanks at google dot com)
- Brian Ledger (brianpl at google dot com)
- Charles Munger (clm at google dot com) - Charles Munger (clm at google dot com)
- Cheng Yi (cyi at google dot com) - Cheng Yi (cyi at google dot com)
- Christian Duvivier (cduvivier at google dot com) - Christian Duvivier (cduvivier at google dot com)
- Christopher Degawa (ccom at randomderp dot com)
- Clement Courbet (courbet at google dot com)
- devtools-clrobot at google dot com (devtools-clrobot@google dot com)
- Djordje Pesut (djordje dot pesut at imgtec dot com) - Djordje Pesut (djordje dot pesut at imgtec dot com)
- Frank (1433351828 at qq dot com)
- Frank Barchard (fbarchard at google dot com)
- Henner Zeller (hzeller at google dot com)
- Hui Su (huisu at google dot com) - Hui Su (huisu at google dot com)
- H. Vetinari (h dot vetinari at gmx dot com)
- Ilya Kurdyukov (jpegqs at gmail dot com)
- Ingvar Stepanyan (rreverser at google dot com)
- Istvan Stefan (Istvan dot Stefan at arm dot com)
- James Zern (jzern at google dot com) - James Zern (jzern at google dot com)
- Jan Engelhardt (jengelh at medozas dot de) - Jan Engelhardt (jengelh at medozas dot de)
- Jehan (jehan at girinstud dot io) - Jehan (jehan at girinstud dot io)
- Jeremy Maitin-Shepard (jbms at google dot com)
- Johann Koenig (johann dot koenig at duck dot com) - Johann Koenig (johann dot koenig at duck dot com)
- Jonathan Grant (jgrantinfotech at gmail dot com)
- Jonliu1993 (13720414433 at 163 dot com)
- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com) - Jovan Zelincevic (jovan dot zelincevic at imgtec dot com)
- Jyrki Alakuijala (jyrki at google dot com) - Jyrki Alakuijala (jyrki at google dot com)
- Konstantin Ivlev (tomskside at gmail dot com) - Konstantin Ivlev (tomskside at gmail dot com)
@ -35,22 +18,16 @@ Contributors:
- Mans Rullgard (mans at mansr dot com) - Mans Rullgard (mans at mansr dot com)
- Marcin Kowalczyk (qrczak at google dot com) - Marcin Kowalczyk (qrczak at google dot com)
- Martin Olsson (mnemo at minimum dot se) - Martin Olsson (mnemo at minimum dot se)
- Maryla Ustarroz-Calonge (maryla at google dot com)
- Masahiro Hanada (hanada at atmark-techno dot com)
- Mikołaj Zalewski (mikolajz at google dot com) - Mikołaj Zalewski (mikolajz at google dot com)
- Mislav Bradac (mislavm at google dot com) - Mislav Bradac (mislavm at google dot com)
- natewood (natewood at fb dot com)
- Nico Weber (thakis at chromium dot org) - Nico Weber (thakis at chromium dot org)
- Noel Chromium (noel at chromium dot org) - Noel Chromium (noel at chromium dot org)
- Nozomi Isozaki (nontan at pixiv dot co dot jp)
- Oliver Wolff (oliver dot wolff at qt dot io) - Oliver Wolff (oliver dot wolff at qt dot io)
- Owen Rodley (orodley at google dot com) - Owen Rodley (orodley at google dot com)
- Ozkan Sezer (sezeroz at gmail dot com)
- Parag Salasakar (img dot mips1 at gmail dot com) - Parag Salasakar (img dot mips1 at gmail dot com)
- Pascal Massimino (pascal dot massimino at gmail dot com) - Pascal Massimino (pascal dot massimino at gmail dot com)
- Paweł Hajdan, Jr (phajdan dot jr at chromium dot org) - Paweł Hajdan, Jr (phajdan dot jr at chromium dot org)
- Pierre Joye (pierre dot php at gmail dot com) - Pierre Joye (pierre dot php at gmail dot com)
- Roberto Alanis (alanisbaez at google dot com)
- Sam Clegg (sbc at chromium dot org) - Sam Clegg (sbc at chromium dot org)
- Scott Hancher (seh at google dot com) - Scott Hancher (seh at google dot com)
- Scott LaVarnway (slavarnway at google dot com) - Scott LaVarnway (slavarnway at google dot com)
@ -59,14 +36,10 @@ Contributors:
- Somnath Banerjee (somnath dot banerjee at gmail dot com) - Somnath Banerjee (somnath dot banerjee at gmail dot com)
- Sriraman Tallam (tmsriram at google dot com) - Sriraman Tallam (tmsriram at google dot com)
- Tamar Levy (tamar dot levy at intel dot com) - Tamar Levy (tamar dot levy at intel dot com)
- Thiago Perrotta (tperrotta at google dot com)
- Timothy Gu (timothygu99 at gmail dot com) - Timothy Gu (timothygu99 at gmail dot com)
- Urvang Joshi (urvang at google dot com) - Urvang Joshi (urvang at google dot com)
- Vikas Arora (vikasa at google dot com) - Vikas Arora (vikasa at google dot com)
- Vincent Rabaud (vrabaud at google dot com) - Vincent Rabaud (vrabaud at google dot com)
- Vlad Tsyrklevich (vtsyrklevich at chromium dot org) - Vlad Tsyrklevich (vtsyrklevich at chromium dot org)
- Wan-Teh Chang (wtc at google dot com)
- wrv (wrv at utexas dot edu)
- Yang Zhang (yang dot zhang at arm dot com) - Yang Zhang (yang dot zhang at arm dot com)
- Yannis Guyon (yguyon at google dot com) - Yannis Guyon (yguyon at google dot com)
- Zhi An Ng (zhin at chromium dot org)

View File

@ -1,5 +1,3 @@
# Ignore this file during non-NDK builds.
ifdef NDK_ROOT
LOCAL_PATH := $(call my-dir) LOCAL_PATH := $(call my-dir)
WEBP_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD -DWEBP_USE_THREAD WEBP_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD -DWEBP_USE_THREAD
@ -35,15 +33,6 @@ else
NEON := c NEON := c
endif endif
sharpyuv_srcs := \
sharpyuv/sharpyuv.c \
sharpyuv/sharpyuv_cpu.c \
sharpyuv/sharpyuv_csp.c \
sharpyuv/sharpyuv_dsp.c \
sharpyuv/sharpyuv_gamma.c \
sharpyuv/sharpyuv_neon.$(NEON) \
sharpyuv/sharpyuv_sse2.c \
dec_srcs := \ dec_srcs := \
src/dec/alpha_dec.c \ src/dec/alpha_dec.c \
src/dec/buffer_dec.c \ src/dec/buffer_dec.c \
@ -85,7 +74,6 @@ dsp_dec_srcs := \
src/dsp/lossless_msa.c \ src/dsp/lossless_msa.c \
src/dsp/lossless_neon.$(NEON) \ src/dsp/lossless_neon.$(NEON) \
src/dsp/lossless_sse2.c \ src/dsp/lossless_sse2.c \
src/dsp/lossless_sse41.c \
src/dsp/rescaler.c \ src/dsp/rescaler.c \
src/dsp/rescaler_mips32.c \ src/dsp/rescaler_mips32.c \
src/dsp/rescaler_mips_dsp_r2.c \ src/dsp/rescaler_mips_dsp_r2.c \
@ -164,7 +152,6 @@ utils_dec_srcs := \
src/utils/color_cache_utils.c \ src/utils/color_cache_utils.c \
src/utils/filters_utils.c \ src/utils/filters_utils.c \
src/utils/huffman_utils.c \ src/utils/huffman_utils.c \
src/utils/palette.c \
src/utils/quant_levels_dec_utils.c \ src/utils/quant_levels_dec_utils.c \
src/utils/random_utils.c \ src/utils/random_utils.c \
src/utils/rescaler_utils.c \ src/utils/rescaler_utils.c \
@ -216,13 +203,12 @@ endif # ENABLE_SHARED=1
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
$(sharpyuv_srcs) \
$(dsp_enc_srcs) \ $(dsp_enc_srcs) \
$(enc_srcs) \ $(enc_srcs) \
$(utils_enc_srcs) \ $(utils_enc_srcs) \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src $(LOCAL_PATH) LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src
# prefer arm over thumb mode for performance gains # prefer arm over thumb mode for performance gains
LOCAL_ARM_MODE := arm LOCAL_ARM_MODE := arm
@ -292,4 +278,3 @@ include $(WEBP_SRC_PATH)/examples/Android.mk
ifeq ($(USE_CPUFEATURES),yes) ifeq ($(USE_CPUFEATURES),yes)
$(call import-module,android/cpufeatures) $(call import-module,android/cpufeatures)
endif endif
endif # NDK_ROOT

View File

@ -1,35 +1,9 @@
# Copyright (c) 2020 Google LLC. cmake_minimum_required(VERSION 3.5)
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
if(APPLE)
cmake_minimum_required(VERSION 3.17)
else()
cmake_minimum_required(VERSION 3.16)
endif()
project(WebP C) project(WebP C)
# Options for coder / decoder executables. # Options for coder / decoder executables.
if(BUILD_SHARED_LIBS) option(WEBP_ENABLE_SIMD "Enable any SIMD optimization." ON)
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.
set(WEBP_ENABLE_SIMD_DEFAULT ON)
endif()
option(WEBP_ENABLE_SIMD "Enable any SIMD optimization."
${WEBP_ENABLE_SIMD_DEFAULT})
option(WEBP_BUILD_ANIM_UTILS "Build animation utilities." ON) option(WEBP_BUILD_ANIM_UTILS "Build animation utilities." ON)
option(WEBP_BUILD_CWEBP "Build the cwebp command line tool." ON) option(WEBP_BUILD_CWEBP "Build the cwebp command line tool." ON)
option(WEBP_BUILD_DWEBP "Build the dwebp command line tool." ON) option(WEBP_BUILD_DWEBP "Build the dwebp command line tool." ON)
@ -37,31 +11,14 @@ option(WEBP_BUILD_GIF2WEBP "Build the gif2webp conversion tool." ON)
option(WEBP_BUILD_IMG2WEBP "Build the img2webp animation tool." ON) option(WEBP_BUILD_IMG2WEBP "Build the img2webp animation tool." ON)
option(WEBP_BUILD_VWEBP "Build the vwebp viewer tool." ON) option(WEBP_BUILD_VWEBP "Build the vwebp viewer tool." ON)
option(WEBP_BUILD_WEBPINFO "Build the webpinfo command line tool." ON) option(WEBP_BUILD_WEBPINFO "Build the webpinfo command line tool." ON)
option(WEBP_BUILD_LIBWEBPMUX "Build the libwebpmux library." ON)
option(WEBP_BUILD_WEBPMUX "Build the webpmux command line tool." ON) option(WEBP_BUILD_WEBPMUX "Build the webpmux command line tool." ON)
option(WEBP_BUILD_EXTRAS "Build extras." ON) option(WEBP_BUILD_EXTRAS "Build extras." ON)
option(WEBP_BUILD_WEBP_JS "Emscripten build of webp.js." OFF) option(WEBP_BUILD_WEBP_JS "Emscripten build of webp.js." OFF)
option(WEBP_BUILD_FUZZTEST "Build the fuzztest tests." OFF)
option(WEBP_USE_THREAD "Enable threading support" ON)
option(WEBP_NEAR_LOSSLESS "Enable near-lossless encoding" ON) option(WEBP_NEAR_LOSSLESS "Enable near-lossless encoding" ON)
option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces." option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces."
OFF) OFF)
set(WEBP_BITTRACE "0" CACHE STRING "Bit trace mode (0=none, 1=bit, 2=bytes)") 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) set_property(CACHE WEBP_BITTRACE PROPERTY STRINGS 0 1 2)
option(WEBP_ENABLE_WUNUSED_RESULT "Add [[nodiscard]] to some functions. \
CMake must be at least 3.21 to force C23" OFF)
if(WEBP_LINK_STATIC)
if(WIN32)
set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
else()
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
endif()
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# vwebp does not compile on Ubuntu with static libraries so disabling it for
# now.
set(WEBP_BUILD_VWEBP OFF)
endif()
# Option needed for handling Unicode file names on Windows. # Option needed for handling Unicode file names on Windows.
if(WIN32) if(WIN32)
@ -69,6 +26,7 @@ if(WIN32)
endif() endif()
if(WEBP_BUILD_WEBP_JS) if(WEBP_BUILD_WEBP_JS)
set(WEBP_ENABLE_SIMD OFF)
set(WEBP_BUILD_ANIM_UTILS OFF) set(WEBP_BUILD_ANIM_UTILS OFF)
set(WEBP_BUILD_CWEBP OFF) set(WEBP_BUILD_CWEBP OFF)
set(WEBP_BUILD_DWEBP OFF) set(WEBP_BUILD_DWEBP OFF)
@ -78,45 +36,21 @@ if(WEBP_BUILD_WEBP_JS)
set(WEBP_BUILD_WEBPINFO OFF) set(WEBP_BUILD_WEBPINFO OFF)
set(WEBP_BUILD_WEBPMUX OFF) set(WEBP_BUILD_WEBPMUX OFF)
set(WEBP_BUILD_EXTRAS OFF) set(WEBP_BUILD_EXTRAS OFF)
set(WEBP_USE_THREAD OFF)
if(WEBP_ENABLE_SIMD)
message(NOTICE
"wasm2js does not support SIMD, disabling webp.js generation.")
endif()
endif() endif()
set(SHARPYUV_DEP_LIBRARIES)
set(SHARPYUV_DEP_INCLUDE_DIRS)
set(WEBP_DEP_LIBRARIES) set(WEBP_DEP_LIBRARIES)
set(WEBP_DEP_INCLUDE_DIRS) set(WEBP_DEP_INCLUDE_DIRS)
if(NOT CMAKE_BUILD_TYPE) if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" set(CMAKE_BUILD_TYPE "Release"
CACHE STRING "Build type: Release, Debug, MinSizeRel or RelWithDebInfo" CACHE "Build type: Release, Debug, MinSizeRel or RelWithDebInfo" STRING
FORCE) FORCE)
endif() endif()
# Include dependencies. # Include dependencies.
if(WEBP_BUILD_ANIM_UTILS
OR WEBP_BUILD_CWEBP
OR WEBP_BUILD_DWEBP
OR WEBP_BUILD_EXTRAS
OR WEBP_BUILD_GIF2WEBP
OR WEBP_BUILD_IMG2WEBP)
set(WEBP_FIND_IMG_LIBS TRUE)
else()
set(WEBP_FIND_IMG_LIBS FALSE)
endif()
include(cmake/deps.cmake) include(cmake/deps.cmake)
include(GNUInstallDirs) include(GNUInstallDirs)
if(BUILD_SHARED_LIBS AND NOT DEFINED CMAKE_INSTALL_RPATH)
# Set the rpath to match autoconf/libtool behavior. Note this must be set
# before target creation.
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
endif()
# ############################################################################## # ##############################################################################
# Options. # Options.
if(WEBP_ENABLE_SWAP_16BIT_CSP) if(WEBP_ENABLE_SWAP_16BIT_CSP)
@ -132,63 +66,24 @@ if(WEBP_UNICODE)
add_definitions(-DUNICODE -D_UNICODE) add_definitions(-DUNICODE -D_UNICODE)
endif() endif()
if(WIN32 AND BUILD_SHARED_LIBS)
add_definitions(-DWEBP_DLL)
endif()
# pkg-config variables used by *.pc.in.
set(prefix ${CMAKE_INSTALL_PREFIX}) set(prefix ${CMAKE_INSTALL_PREFIX})
set(exec_prefix "\${prefix}") set(exec_prefix "\$\{prefix\}")
if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") set(libdir "\$\{prefix\}/lib")
set(libdir "${CMAKE_INSTALL_LIBDIR}") set(includedir "\$\{prefix\}/include")
else()
set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
endif()
if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
set(includedir "${CMAKE_INSTALL_INCLUDEDIR}")
else()
set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
endif()
set(PTHREAD_LIBS ${CMAKE_THREAD_LIBS_INIT}) set(PTHREAD_LIBS ${CMAKE_THREAD_LIBS_INIT})
set(INSTALLED_LIBRARIES) set(INSTALLED_LIBRARIES)
if(MSVC)
# match the naming convention used by nmake
set(webp_libname_prefix "lib")
set(CMAKE_SHARED_LIBRARY_PREFIX "${webp_libname_prefix}")
set(CMAKE_IMPORT_LIBRARY_PREFIX "${webp_libname_prefix}")
set(CMAKE_STATIC_LIBRARY_PREFIX "${webp_libname_prefix}")
endif()
if(NOT WIN32)
set(CMAKE_C_VISIBILITY_PRESET hidden)
endif()
if(WEBP_ENABLE_WUNUSED_RESULT)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21.0)
set(CMAKE_C_STANDARD 23)
else()
unset(CMAKE_C_STANDARD)
add_compile_options($<$<COMPILE_LANGUAGE:C>:-std=gnu2x>)
endif()
add_compile_options(-Wunused-result)
add_definitions(-DWEBP_ENABLE_NODISCARD=1)
endif()
# ############################################################################## # ##############################################################################
# Android only. # Android only.
if(ANDROID) if(ANDROID)
include_directories(${ANDROID_NDK}/sources/android/cpufeatures) include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
add_library(cpufeatures-webp STATIC add_library(cpufeatures STATIC
${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c) ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
list(APPEND INSTALLED_LIBRARIES cpufeatures-webp) list(APPEND INSTALLED_LIBRARIES cpufeatures)
target_link_libraries(cpufeatures-webp dl) target_link_libraries(cpufeatures dl)
set(SHARPYUV_DEP_LIBRARIES ${SHARPYUV_DEP_LIBRARIES} cpufeatures-webp) set(WEBP_DEP_LIBRARIES ${WEBP_DEP_LIBRARIES} cpufeatures)
set(WEBP_DEP_LIBRARIES ${WEBP_DEP_LIBRARIES} cpufeatures-webp) set(WEBP_DEP_INCLUDE_DIRS ${WEBP_DEP_INCLUDE_DIRS}
set(cpufeatures_include_dir ${ANDROID_NDK}/sources/android/cpufeatures) ${ANDROID_NDK}/sources/android/cpufeatures)
set(SHARPYUV_DEP_INCLUDE_DIRS ${SHARPYUV_DEP_INCLUDE_DIRS}
${cpufeatures_include_dir})
set(WEBP_DEP_INCLUDE_DIRS ${WEBP_DEP_INCLUDE_DIRS} ${cpufeatures_include_dir})
add_definitions(-DHAVE_CPU_FEATURES_H=1) add_definitions(-DHAVE_CPU_FEATURES_H=1)
set(HAVE_CPU_FEATURES_H 1) set(HAVE_CPU_FEATURES_H 1)
else() else()
@ -197,7 +92,7 @@ endif()
function(configure_pkg_config FILE) function(configure_pkg_config FILE)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.in" configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.in"
"${CMAKE_CURRENT_BINARY_DIR}/${FILE}" @ONLY) "${CMAKE_CURRENT_BINARY_DIR}/${FILE}")
if(HAVE_MATH_LIBRARY) if(HAVE_MATH_LIBRARY)
# MSVC doesn't have libm # MSVC doesn't have libm
@ -206,8 +101,10 @@ function(configure_pkg_config FILE)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${FILE} ${data}) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${FILE} ${data})
endif() endif()
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${FILE}" install(
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) FILES "${CMAKE_CURRENT_BINARY_DIR}/${FILE}"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
endfunction() endfunction()
# ############################################################################## # ##############################################################################
@ -217,15 +114,23 @@ endfunction()
# E.g.: libimagedec_la_SOURCES = image_dec.c image_dec.h # E.g.: libimagedec_la_SOURCES = image_dec.c image_dec.h
function(parse_Makefile_am FOLDER VAR SRC_REGEX) function(parse_Makefile_am FOLDER VAR SRC_REGEX)
file(READ ${FOLDER}/Makefile.am MAKEFILE_AM) file(READ ${FOLDER}/Makefile.am MAKEFILE_AM)
string(REGEX MATCHALL "${SRC_REGEX}_SOURCES[ ]*\\+?=[ ]+[0-9a-z\\._ ]*" string(REGEX MATCHALL
FILES_PER_LINE ${MAKEFILE_AM}) "${SRC_REGEX}_SOURCES[ ]*\\+?=[ ]+[0-9a-z\\._ ]*"
FILES_PER_LINE
${MAKEFILE_AM})
set(SRCS ${${VAR}}) set(SRCS ${${VAR}})
foreach(FILES ${FILES_PER_LINE}) foreach(FILES ${FILES_PER_LINE})
string(FIND ${FILES} "=" OFFSET) string(FIND ${FILES} "=" OFFSET)
math(EXPR OFFSET "${OFFSET} + 2") math(EXPR OFFSET "${OFFSET} + 2")
string(SUBSTRING ${FILES} ${OFFSET} -1 FILES) string(SUBSTRING ${FILES}
${OFFSET}
-1
FILES)
if(FILES) if(FILES)
string(REGEX MATCHALL "[0-9a-z\\._]+" FILES ${FILES}) string(REGEX MATCHALL
"[0-9a-z\\._]+"
FILES
${FILES})
foreach(FILE ${FILES}) foreach(FILE ${FILES})
list(APPEND SRCS ${FOLDER}/${FILE}) list(APPEND SRCS ${FOLDER}/${FILE})
endforeach() endforeach()
@ -254,129 +159,43 @@ endforeach()
# Generate the config.h file. # Generate the config.h file.
configure_file(${CMAKE_CURRENT_LIST_DIR}/cmake/config.h.in configure_file(${CMAKE_CURRENT_LIST_DIR}/cmake/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/src/webp/config.h @ONLY) ${CMAKE_CURRENT_BINARY_DIR}/src/webp/config.h)
add_definitions(-DHAVE_CONFIG_H) add_definitions(-DHAVE_CONFIG_H)
# Set the version numbers.
macro(set_version FILE TARGET_NAME NAME_IN_MAKEFILE)
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} SOURCE_FILE)
string(REGEX MATCH
"${NAME_IN_MAKEFILE}_la_LDFLAGS[^\n]* -version-info [0-9:]+" TMP
${SOURCE_FILE})
string(REGEX MATCH "[0-9:]+" TMP ${TMP})
string(REGEX REPLACE ":" " " LT_VERSION ${TMP})
# See the libtool docs for more information:
# https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
#
# c=<current>, a=<age>, r=<revision>
#
# libtool generates a .so file as .so.[c-a].a.r, while -version-info c:r:a is
# passed to libtool.
#
# We set FULL = [c-a].a.r and MAJOR = [c-a].
separate_arguments(LT_VERSION)
list(GET LT_VERSION 0 LT_CURRENT)
list(GET LT_VERSION 1 LT_REVISION)
list(GET LT_VERSION 2 LT_AGE)
math(EXPR LT_CURRENT_MINUS_AGE "${LT_CURRENT} - ${LT_AGE}")
set_target_properties(
${TARGET_NAME}
PROPERTIES VERSION ${LT_CURRENT_MINUS_AGE}.${LT_AGE}.${LT_REVISION}
SOVERSION ${LT_CURRENT_MINUS_AGE})
if(APPLE)
# For compatibility, set MACHO_COMPATIBILITY_VERSION and
# MACHO_CURRENT_VERSION to match libtool. These properties were introduced
# in 3.17:
# https://cmake.org/cmake/help/latest/prop_tgt/MACHO_COMPATIBILITY_VERSION.html
math(EXPR LIBWEBP_MACHO_COMPATIBILITY_VERSION "${LT_CURRENT} + 1")
set_target_properties(
${TARGET_NAME}
PROPERTIES MACHO_COMPATIBILITY_VERSION
${LIBWEBP_MACHO_COMPATIBILITY_VERSION}
MACHO_CURRENT_VERSION
${LIBWEBP_MACHO_COMPATIBILITY_VERSION}.${LT_REVISION})
endif()
endmacro()
# ############################################################################## # ##############################################################################
# Build the webpdecoder library. # Build the webpdecoder library.
# Creates a source file with an unused stub function in $CMAKE_BINARY_DIR and
# adds it to the specified target. Currently used only with Xcode.
#
# See also:
# https://cmake.org/cmake/help/v3.18/command/add_library.html#object-libraries
# "Some native build systems (such as Xcode) may not like targets that have only
# object files, so consider adding at least one real source file to any target
# that references $<TARGET_OBJECTS:objlib>."
function(libwebp_add_stub_file TARGET)
set(stub_source_dir "${CMAKE_BINARY_DIR}")
set(stub_source_file "${stub_source_dir}/libwebp_${TARGET}_stub.c")
set(stub_source_code
"// Generated file. DO NOT EDIT!\n"
"// C source file created for target ${TARGET}.\n"
"void libwebp_${TARGET}_stub_function(void)\;\n"
"void libwebp_${TARGET}_stub_function(void) {}\n")
file(WRITE "${stub_source_file}" ${stub_source_code})
target_sources(${TARGET} PRIVATE ${stub_source_file})
endfunction()
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv "WEBP_SHARPYUV_SRCS" "")
add_library(sharpyuv ${WEBP_SHARPYUV_SRCS})
target_link_libraries(sharpyuv ${SHARPYUV_DEP_LIBRARIES})
set_version(sharpyuv/Makefile.am sharpyuv sharpyuv)
target_include_directories(
sharpyuv PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src)
set_target_properties(
sharpyuv
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/sharpyuv.h;\
${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/sharpyuv_csp.h")
configure_pkg_config("sharpyuv/libsharpyuv.pc")
install(
TARGETS sharpyuv
EXPORT ${PROJECT_NAME}Targets
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webp/sharpyuv
INCLUDES
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
${CMAKE_INSTALL_INCLUDEDIR}/webp
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
if(MSVC) if(MSVC)
# avoid security warnings for e.g., fopen() used in the examples. # avoid security warnings for e.g., fopen() used in the examples.
add_definitions(-D_CRT_SECURE_NO_WARNINGS) add_definitions(-D_CRT_SECURE_NO_WARNINGS)
else() else()
add_compile_options(-Wall) add_definitions(-Wall)
endif() endif()
include_directories(${WEBP_DEP_INCLUDE_DIRS}) include_directories(${WEBP_DEP_INCLUDE_DIRS})
add_library(webpdecode OBJECT ${WEBP_DEC_SRCS}) add_library(webpdecode OBJECT ${WEBP_DEC_SRCS})
target_include_directories(webpdecode PRIVATE ${CMAKE_CURRENT_BINARY_DIR} target_include_directories(webpdecode
${CMAKE_CURRENT_SOURCE_DIR}) PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
add_library(webpdspdecode OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS}) add_library(webpdspdecode OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS})
target_include_directories(webpdspdecode PRIVATE ${CMAKE_CURRENT_BINARY_DIR} target_include_directories(webpdspdecode
${CMAKE_CURRENT_SOURCE_DIR}) PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
add_library(webputilsdecode OBJECT ${WEBP_UTILS_COMMON_SRCS} ${CMAKE_CURRENT_SOURCE_DIR})
${WEBP_UTILS_DEC_SRCS}) add_library(webputilsdecode
target_include_directories(webputilsdecode PRIVATE ${CMAKE_CURRENT_BINARY_DIR} OBJECT
${CMAKE_CURRENT_SOURCE_DIR}) ${WEBP_UTILS_COMMON_SRCS}
add_library( ${WEBP_UTILS_DEC_SRCS})
webpdecoder $<TARGET_OBJECTS:webpdecode> $<TARGET_OBJECTS:webpdspdecode> target_include_directories(webputilsdecode
$<TARGET_OBJECTS:webputilsdecode>) PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
if(XCODE) ${CMAKE_CURRENT_SOURCE_DIR})
libwebp_add_stub_file(webpdecoder) add_library(webpdecoder
endif() $<TARGET_OBJECTS:webpdecode>
$<TARGET_OBJECTS:webpdspdecode>
$<TARGET_OBJECTS:webputilsdecode>)
target_link_libraries(webpdecoder ${WEBP_DEP_LIBRARIES}) target_link_libraries(webpdecoder ${WEBP_DEP_LIBRARIES})
target_include_directories( target_include_directories(
webpdecoder webpdecoder
PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
INTERFACE INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_BINARY_DIR}>" $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
set_target_properties( set_target_properties(
webpdecoder webpdecoder
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\ PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
@ -386,28 +205,35 @@ configure_pkg_config("src/libwebpdecoder.pc")
# Build the webp library. # Build the webp library.
add_library(webpencode OBJECT ${WEBP_ENC_SRCS}) add_library(webpencode OBJECT ${WEBP_ENC_SRCS})
target_include_directories( target_include_directories(webpencode
webpencode PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src) ${CMAKE_CURRENT_SOURCE_DIR})
add_library(webpdsp OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS} add_library(webpdsp
${WEBP_DSP_ENC_SRCS}) OBJECT
target_include_directories(webpdsp PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${WEBP_DSP_COMMON_SRCS}
${CMAKE_CURRENT_SOURCE_DIR}) ${WEBP_DSP_DEC_SRCS}
add_library(webputils OBJECT ${WEBP_UTILS_COMMON_SRCS} ${WEBP_UTILS_DEC_SRCS} ${WEBP_DSP_ENC_SRCS})
${WEBP_UTILS_ENC_SRCS}) target_include_directories(webpdsp
target_include_directories(webputils PRIVATE ${CMAKE_CURRENT_BINARY_DIR} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}) ${CMAKE_CURRENT_SOURCE_DIR})
add_library(webp $<TARGET_OBJECTS:webpdecode> $<TARGET_OBJECTS:webpdsp> add_library(webputils
$<TARGET_OBJECTS:webpencode> $<TARGET_OBJECTS:webputils>) OBJECT
target_link_libraries(webp sharpyuv) ${WEBP_UTILS_COMMON_SRCS}
if(XCODE) ${WEBP_UTILS_DEC_SRCS}
libwebp_add_stub_file(webp) ${WEBP_UTILS_ENC_SRCS})
endif() target_include_directories(webputils
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
add_library(webp
$<TARGET_OBJECTS:webpdecode>
$<TARGET_OBJECTS:webpdsp>
$<TARGET_OBJECTS:webpencode>
$<TARGET_OBJECTS:webputils>)
target_link_libraries(webp ${WEBP_DEP_LIBRARIES}) target_link_libraries(webp ${WEBP_DEP_LIBRARIES})
target_include_directories( target_include_directories(webp
webp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src> ${CMAKE_CURRENT_BINARY_DIR}
$<INSTALL_INTERFACE:include>) PUBLIC $<INSTALL_INTERFACE:include>)
set_target_properties( set_target_properties(
webp webp
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\ PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
@ -416,33 +242,76 @@ ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
# Make sure the OBJECT libraries are built with position independent code (it is # Make sure the OBJECT libraries are built with position independent code (it is
# not ON by default). # not ON by default).
set_target_properties(webpdecode webpdspdecode webputilsdecode webpencode set_target_properties(webpdecode
webpdsp webputils PROPERTIES POSITION_INDEPENDENT_CODE ON) webpdspdecode
webputilsdecode
webpencode
webpdsp
webputils
PROPERTIES POSITION_INDEPENDENT_CODE ON)
configure_pkg_config("src/libwebp.pc") configure_pkg_config("src/libwebp.pc")
# Build the webp demux library. # Build the webp demux library.
add_library(webpdemux ${WEBP_DEMUX_SRCS}) add_library(webpdemux ${WEBP_DEMUX_SRCS})
target_link_libraries(webpdemux webp) target_link_libraries(webpdemux webp)
target_include_directories( target_include_directories(webpdemux
webpdemux PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PUBLIC $<INSTALL_INTERFACE:include>) ${CMAKE_CURRENT_BINARY_DIR}
PUBLIC $<INSTALL_INTERFACE:include>)
set_target_properties( set_target_properties(
webpdemux webpdemux
PROPERTIES PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
PUBLIC_HEADER
"${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/demux.h;\ ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/demux.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\ ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h") ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
configure_pkg_config("src/demux/libwebpdemux.pc") configure_pkg_config("src/demux/libwebpdemux.pc")
set_version(src/Makefile.am webp webp) # Set the version numbers.
set_version(src/Makefile.am webpdecoder webpdecoder) function(parse_version FILE NAME VAR)
set_version(src/demux/Makefile.am webpdemux webpdemux) file(READ ${CMAKE_CURRENT_SOURCE_DIR}/src/${FILE} SOURCE_FILE)
string(REGEX MATCH
"${NAME}_la_LDFLAGS[^\n]* -version-info [0-9:]+"
TMP
${SOURCE_FILE})
string(REGEX MATCH
"[0-9:]+"
TMP
${TMP})
string(REGEX
REPLACE ":"
"."
VERSION
${TMP})
set(${VAR} "${VERSION}" PARENT_SCOPE)
endfunction()
parse_version(Makefile.am webp WEBP_WEBP_SOVERSION)
set_target_properties(webp
PROPERTIES VERSION
${PACKAGE_VERSION}
SOVERSION
${WEBP_WEBP_SOVERSION})
parse_version(Makefile.am webpdecoder WEBP_DECODER_SOVERSION)
set_target_properties(webpdecoder
PROPERTIES VERSION
${PACKAGE_VERSION}
SOVERSION
${WEBP_DECODER_SOVERSION})
parse_version(demux/Makefile.am webpdemux WEBP_DEMUX_SOVERSION)
set_target_properties(webpdemux
PROPERTIES VERSION
${PACKAGE_VERSION}
SOVERSION
${WEBP_DEMUX_SOVERSION})
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_FILE) file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_FILE)
string(REGEX MATCH "AC_INIT\\([^\n]*\\[[0-9\\.]+\\]" TMP ${CONFIGURE_FILE}) string(REGEX MATCH
string(REGEX MATCH "[0-9\\.]+" PROJECT_VERSION ${TMP}) "AC_INIT\\([^\n]*\\[[0-9\\.]+\\]"
TMP
${CONFIGURE_FILE})
string(REGEX MATCH
"[0-9\\.]+"
PROJECT_VERSION
${TMP})
# Define the libraries to install. # Define the libraries to install.
list(APPEND INSTALLED_LIBRARIES webpdecoder webp webpdemux) list(APPEND INSTALLED_LIBRARIES webpdecoder webp webpdemux)
@ -455,16 +324,12 @@ math(EXPR WEBP_SIMD_FILES_TO_INCLUDE_RANGE
foreach(I_FILE RANGE ${WEBP_SIMD_FILES_TO_INCLUDE_RANGE}) foreach(I_FILE RANGE ${WEBP_SIMD_FILES_TO_INCLUDE_RANGE})
list(GET WEBP_SIMD_FILES_TO_INCLUDE ${I_FILE} FILE) list(GET WEBP_SIMD_FILES_TO_INCLUDE ${I_FILE} FILE)
list(GET WEBP_SIMD_FLAGS_TO_INCLUDE ${I_FILE} SIMD_COMPILE_FLAG) list(GET WEBP_SIMD_FLAGS_TO_INCLUDE ${I_FILE} SIMD_COMPILE_FLAG)
set_source_files_properties(${FILE} PROPERTIES COMPILE_FLAGS set_source_files_properties(${FILE}
${SIMD_COMPILE_FLAG}) PROPERTIES
COMPILE_FLAGS
${SIMD_COMPILE_FLAG})
endforeach() endforeach()
if(NOT WEBP_BUILD_LIBWEBPMUX)
set(WEBP_BUILD_GIF2WEBP OFF)
set(WEBP_BUILD_IMG2WEBP OFF)
set(WEBP_BUILD_WEBPMUX OFF)
endif()
if(WEBP_BUILD_GIF2WEBP AND NOT GIF_FOUND) if(WEBP_BUILD_GIF2WEBP AND NOT GIF_FOUND)
set(WEBP_BUILD_GIF2WEBP OFF) set(WEBP_BUILD_GIF2WEBP OFF)
endif() endif()
@ -477,32 +342,32 @@ endif()
if(WEBP_BUILD_ANIM_UTILS if(WEBP_BUILD_ANIM_UTILS
OR WEBP_BUILD_CWEBP OR WEBP_BUILD_CWEBP
OR WEBP_BUILD_DWEBP OR WEBP_BUILD_DWEBP
OR WEBP_BUILD_EXTRAS
OR WEBP_BUILD_FUZZTEST
OR WEBP_BUILD_GIF2WEBP OR WEBP_BUILD_GIF2WEBP
OR WEBP_BUILD_IMG2WEBP OR WEBP_BUILD_IMG2WEBP
OR WEBP_BUILD_VWEBP OR WEBP_BUILD_VWEBP)
OR WEBP_BUILD_WEBPMUX
OR WEBP_BUILD_WEBPINFO)
# Example utility library. # Example utility library.
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "EXAMPLEUTIL_SRCS" parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "EXAMPLEUTIL_SRCS"
"example_util_[^ ]*") "example_util_[^ ]*")
list(APPEND EXAMPLEUTIL_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/examples/stopwatch.h) list(APPEND EXAMPLEUTIL_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/examples/stopwatch.h)
add_library(exampleutil STATIC ${EXAMPLEUTIL_SRCS}) add_library(exampleutil STATIC ${EXAMPLEUTIL_SRCS})
target_link_libraries(exampleutil imageioutil)
target_include_directories( target_include_directories(
exampleutil PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>) exampleutil
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEIOUTILS_SRCS" parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEIOUTILS_SRCS"
"imageio_util_[^ ]*") "imageio_util_[^ ]*")
add_library(imageioutil STATIC ${IMAGEIOUTILS_SRCS}) add_library(imageioutil STATIC ${IMAGEIOUTILS_SRCS})
target_link_libraries(imageioutil webp) target_link_libraries(imageioutil webp)
target_link_libraries(exampleutil imageioutil)
# Image-decoding utility library. # Image-decoding utility library.
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEDEC_SRCS" parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEDEC_SRCS"
"imagedec_[^ ]*") "imagedec_[^ ]*")
add_library(imagedec STATIC ${IMAGEDEC_SRCS}) add_library(imagedec STATIC ${IMAGEDEC_SRCS})
target_link_libraries(imagedec imageioutil webpdemux webp target_link_libraries(imagedec
imageioutil
webpdemux
webp
${WEBP_DEP_IMG_LIBRARIES}) ${WEBP_DEP_IMG_LIBRARIES})
# Image-encoding utility library. # Image-encoding utility library.
@ -511,12 +376,12 @@ if(WEBP_BUILD_ANIM_UTILS
add_library(imageenc STATIC ${IMAGEENC_SRCS}) add_library(imageenc STATIC ${IMAGEENC_SRCS})
target_link_libraries(imageenc imageioutil webp) target_link_libraries(imageenc imageioutil webp)
set_property( set_property(TARGET exampleutil
TARGET exampleutil imageioutil imagedec imageenc imageioutil
PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src imagedec
${CMAKE_CURRENT_BINARY_DIR}/src) imageenc
target_include_directories(imagedec PRIVATE ${WEBP_DEP_IMG_INCLUDE_DIRS}) PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src
target_include_directories(imageenc PRIVATE ${WEBP_DEP_IMG_INCLUDE_DIRS}) ${CMAKE_CURRENT_BINARY_DIR}/src)
endif() endif()
if(WEBP_BUILD_DWEBP) if(WEBP_BUILD_DWEBP)
@ -533,21 +398,26 @@ if(WEBP_BUILD_CWEBP)
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "CWEBP_SRCS" "cwebp") parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "CWEBP_SRCS" "cwebp")
add_executable(cwebp ${CWEBP_SRCS}) add_executable(cwebp ${CWEBP_SRCS})
target_link_libraries(cwebp exampleutil imagedec webp) target_link_libraries(cwebp exampleutil imagedec webp)
target_include_directories(cwebp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src target_include_directories(cwebp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
${CMAKE_CURRENT_SOURCE_DIR})
install(TARGETS cwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install(TARGETS cwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif() endif()
if(WEBP_BUILD_LIBWEBPMUX) if(WEBP_BUILD_GIF2WEBP OR WEBP_BUILD_IMG2WEBP)
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/mux "WEBP_MUX_SRCS" "") parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/mux "WEBP_MUX_SRCS" "")
add_library(libwebpmux ${WEBP_MUX_SRCS}) add_library(libwebpmux ${WEBP_MUX_SRCS})
target_link_libraries(libwebpmux webp) target_link_libraries(libwebpmux webp)
target_include_directories(libwebpmux PRIVATE ${CMAKE_CURRENT_BINARY_DIR} target_include_directories(libwebpmux
${CMAKE_CURRENT_SOURCE_DIR}) PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
set_version(src/mux/Makefile.am libwebpmux webpmux) ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties( parse_version(mux/Makefile.am webpmux WEBP_MUX_SOVERSION)
libwebpmux set_target_properties(libwebpmux
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux.h;\ PROPERTIES VERSION
${PACKAGE_VERSION}
SOVERSION
${WEBP_MUX_SOVERSION})
set_target_properties(libwebpmux
PROPERTIES PUBLIC_HEADER
"${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\ ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h;") ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h;")
set_target_properties(libwebpmux PROPERTIES OUTPUT_NAME webpmux) set_target_properties(libwebpmux PROPERTIES OUTPUT_NAME webpmux)
@ -561,10 +431,13 @@ if(WEBP_BUILD_GIF2WEBP)
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "GIF2WEBP_SRCS" parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "GIF2WEBP_SRCS"
"gif2webp") "gif2webp")
add_executable(gif2webp ${GIF2WEBP_SRCS}) add_executable(gif2webp ${GIF2WEBP_SRCS})
target_link_libraries(gif2webp exampleutil imageioutil webp libwebpmux target_link_libraries(gif2webp
exampleutil
imageioutil
webp
libwebpmux
${WEBP_DEP_GIF_LIBRARIES}) ${WEBP_DEP_GIF_LIBRARIES})
target_include_directories(gif2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src target_include_directories(gif2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
${CMAKE_CURRENT_SOURCE_DIR})
install(TARGETS gif2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install(TARGETS gif2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif() endif()
@ -574,10 +447,13 @@ if(WEBP_BUILD_IMG2WEBP)
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "IMG2WEBP_SRCS" parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "IMG2WEBP_SRCS"
"img2webp") "img2webp")
add_executable(img2webp ${IMG2WEBP_SRCS}) add_executable(img2webp ${IMG2WEBP_SRCS})
target_link_libraries(img2webp exampleutil imagedec imageioutil webp target_link_libraries(img2webp
exampleutil
imagedec
imageioutil
webp
libwebpmux) libwebpmux)
target_include_directories(img2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src target_include_directories(img2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
${CMAKE_CURRENT_SOURCE_DIR})
install(TARGETS img2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install(TARGETS img2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif() endif()
@ -588,17 +464,17 @@ if(WEBP_BUILD_VWEBP)
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS}) include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "VWEBP_SRCS" "vwebp") parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "VWEBP_SRCS" "vwebp")
add_executable(vwebp ${VWEBP_SRCS}) add_executable(vwebp ${VWEBP_SRCS})
target_link_libraries( target_link_libraries(vwebp
vwebp ${OPENGL_LIBRARIES}
${OPENGL_LIBRARIES} exampleutil
exampleutil ${GLUT_glut_LIBRARY}
GLUT::GLUT imageioutil
imageioutil webp
webp webpdemux)
webpdemux) target_include_directories(vwebp
target_include_directories( PRIVATE ${GLUT_INCLUDE_DIR}
vwebp PRIVATE ${GLUT_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/src
${OPENGL_INCLUDE_DIR}) ${OPENGL_INCLUDE_DIR})
install(TARGETS vwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install(TARGETS vwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
check_c_compiler_flag("-Wno-deprecated-declarations" HAS_NO_DEPRECATED) check_c_compiler_flag("-Wno-deprecated-declarations" HAS_NO_DEPRECATED)
@ -616,8 +492,7 @@ if(WEBP_BUILD_WEBPINFO)
"webpinfo") "webpinfo")
add_executable(webpinfo ${WEBPINFO_SRCS}) add_executable(webpinfo ${WEBPINFO_SRCS})
target_link_libraries(webpinfo exampleutil imageioutil) 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}) install(TARGETS webpinfo RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif() endif()
@ -638,101 +513,63 @@ if(WEBP_BUILD_EXTRAS)
parse_makefile_am(${EXTRAS_MAKEFILE} "WEBP_QUALITY_SRCS" "webp_quality") parse_makefile_am(${EXTRAS_MAKEFILE} "WEBP_QUALITY_SRCS" "webp_quality")
parse_makefile_am(${EXTRAS_MAKEFILE} "VWEBP_SDL_SRCS" "vwebp_sdl") 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 # get_disto
add_executable(get_disto ${GET_DISTO_SRCS}) add_executable(get_disto ${GET_DISTO_SRCS})
target_link_libraries(get_disto imagedec) target_link_libraries(get_disto imagedec)
target_include_directories(get_disto PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} target_include_directories(get_disto
${CMAKE_CURRENT_BINARY_DIR}/src) PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}/src)
install(TARGETS get_disto RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# webp_quality # webp_quality
add_executable(webp_quality ${WEBP_QUALITY_SRCS}) add_executable(webp_quality ${WEBP_QUALITY_SRCS} ${WEBP_EXTRAS_SRCS})
target_link_libraries(webp_quality exampleutil imagedec extras) target_link_libraries(webp_quality exampleutil imagedec)
target_include_directories(webp_quality PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} target_include_directories(webp_quality
${CMAKE_CURRENT_BINARY_DIR}) PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR})
install(TARGETS webp_quality RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# vwebp_sdl # vwebp_sdl
find_package(SDL2 QUIET) find_package(SDL)
if(WEBP_BUILD_VWEBP AND SDL2_FOUND) if(SDL_FOUND)
add_executable(vwebp_sdl ${VWEBP_SDL_SRCS}) add_executable(vwebp_sdl ${VWEBP_SDL_SRCS})
target_link_libraries(vwebp_sdl ${SDL2_LIBRARIES} imageioutil webp) target_link_libraries(vwebp_sdl ${SDL_LIBRARY} imageioutil webp)
target_include_directories( target_include_directories(vwebp_sdl
vwebp_sdl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}/src ${SDL2_INCLUDE_DIRS}) ${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/src
${SDL_INCLUDE_DIR})
set(WEBP_HAVE_SDL 1) set(WEBP_HAVE_SDL 1)
target_compile_definitions(vwebp_sdl PUBLIC WEBP_HAVE_SDL) target_compile_definitions(vwebp_sdl PUBLIC WEBP_HAVE_SDL)
install(TARGETS vwebp_sdl RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
set(CMAKE_REQUIRED_INCLUDES "${SDL2_INCLUDE_DIRS}")
check_c_source_compiles(
"
#define SDL_MAIN_HANDLED
#include \"SDL.h\"
int main(void) {
return 0;
}
"
HAVE_JUST_SDL_H)
set(CMAKE_REQUIRED_INCLUDES)
if(HAVE_JUST_SDL_H)
target_compile_definitions(vwebp_sdl PRIVATE WEBP_HAVE_JUST_SDL_H)
endif()
endif() endif()
endif() endif()
if(WEBP_BUILD_WEBP_JS) if(WEBP_BUILD_WEBP_JS)
# The default stack size changed from 5MB to 64KB in 3.1.27. See # JavaScript version
# https://crbug.com/webp/614. add_executable(webp_js ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.27") target_link_libraries(webp_js webpdecoder SDL)
# TOTAL_STACK size was renamed to STACK_SIZE in 3.1.27. The old name was target_include_directories(webp_js PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
# kept for compatibility, but prefer the new one in case it is removed in set(WEBP_HAVE_SDL 1)
# the future. set_target_properties(
set(emscripten_stack_size "-sSTACK_SIZE=5MB") webp_js
else() PROPERTIES LINK_FLAGS
set(emscripten_stack_size "-sTOTAL_STACK=5MB") "-s EXPORTED_FUNCTIONS='[\"_WebpToSDL\"]' -s INVOKE_RUN=0 \
endif() -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
find_package(SDL2 REQUIRED) set_target_properties(webp_js PROPERTIES OUTPUT_NAME webp)
# wasm2js does not support SIMD. target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
if(NOT WEBP_ENABLE_SIMD)
# JavaScript version
add_executable(webp_js ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
target_link_libraries(webp_js webpdecoder SDL2)
target_include_directories(webp_js PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
set(WEBP_HAVE_SDL 1)
set_target_properties(
webp_js
PROPERTIES
# Emscripten puts -sUSE_SDL2=1 in this variable, though it's needed at
# compile time to ensure the headers are downloaded.
COMPILE_OPTIONS "${SDL2_LIBRARIES}"
LINK_FLAGS
"-sWASM=0 ${emscripten_stack_size} \
-sEXPORTED_FUNCTIONS=_WebPToSDL -sINVOKE_RUN=0 \
-sEXPORTED_RUNTIME_METHODS=cwrap ${SDL2_LIBRARIES} \
-sALLOW_MEMORY_GROWTH")
set_target_properties(webp_js PROPERTIES OUTPUT_NAME webp)
target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
endif()
# WASM version # WASM version
add_executable(webp_wasm ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c) add_executable(webp_wasm ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
target_link_libraries(webp_wasm webpdecoder SDL2) target_link_libraries(webp_wasm webpdecoder SDL)
target_include_directories(webp_wasm PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(webp_wasm PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
set_target_properties( set_target_properties(
webp_wasm webp_wasm
PROPERTIES PROPERTIES LINK_FLAGS "-s WASM=1 \
# Emscripten puts -sUSE_SDL2=1 in this variable, though it's needed at -s EXPORTED_FUNCTIONS='[\"_WebpToSDL\"]' -s INVOKE_RUN=0 \
# compile time to ensure the headers are downloaded. -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
COMPILE_OPTIONS "${SDL2_LIBRARIES}"
LINK_FLAGS
"-sWASM=1 ${emscripten_stack_size} \
-sEXPORTED_FUNCTIONS=_WebPToSDL -sINVOKE_RUN=0 \
-sEXPORTED_RUNTIME_METHODS=cwrap ${SDL2_LIBRARIES} \
-sALLOW_MEMORY_GROWTH")
target_compile_definitions(webp_wasm PUBLIC EMSCRIPTEN WEBP_HAVE_SDL) target_compile_definitions(webp_wasm PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
target_compile_definitions(webpdspdecode PUBLIC EMSCRIPTEN) target_compile_definitions(webpdspdecode PUBLIC EMSCRIPTEN)
@ -744,15 +581,15 @@ if(WEBP_BUILD_ANIM_UTILS)
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "ANIM_DIFF_SRCS" parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "ANIM_DIFF_SRCS"
"anim_diff") "anim_diff")
add_executable(anim_diff ${ANIM_DIFF_SRCS}) add_executable(anim_diff ${ANIM_DIFF_SRCS})
target_link_libraries( target_link_libraries(anim_diff
anim_diff exampleutil
exampleutil imagedec
imagedec imageenc
imageenc imageioutil
imageioutil webp
webp libwebpmux
webpdemux webpdemux
${WEBP_DEP_GIF_LIBRARIES}) ${WEBP_DEP_GIF_LIBRARIES})
target_include_directories(anim_diff PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src) target_include_directories(anim_diff PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
# anim_dump # anim_dump
@ -760,63 +597,47 @@ if(WEBP_BUILD_ANIM_UTILS)
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "ANIM_DUMP_SRCS" parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "ANIM_DUMP_SRCS"
"anim_dump") "anim_dump")
add_executable(anim_dump ${ANIM_DUMP_SRCS}) add_executable(anim_dump ${ANIM_DUMP_SRCS})
target_link_libraries( target_link_libraries(anim_dump
anim_dump exampleutil
exampleutil imagedec
imagedec imageenc
imageenc imageioutil
imageioutil webp
webp libwebpmux
webpdemux webpdemux
${WEBP_DEP_GIF_LIBRARIES}) ${WEBP_DEP_GIF_LIBRARIES})
target_include_directories(anim_dump PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src) target_include_directories(anim_dump PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
endif() endif()
if(WEBP_BUILD_FUZZTEST)
add_subdirectory(tests/fuzzer)
endif()
# Install the different headers and libraries. # Install the different headers and libraries.
install( include(GNUInstallDirs)
TARGETS ${INSTALLED_LIBRARIES} install(TARGETS ${INSTALLED_LIBRARIES}
EXPORT ${PROJECT_NAME}Targets EXPORT ${PROJECT_NAME}Targets
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webp PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webp
INCLUDES INCLUDES
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
set(ConfigPackageLocation ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake/) set(ConfigPackageLocation ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake/)
install(EXPORT ${PROJECT_NAME}Targets NAMESPACE ${PROJECT_NAME}:: install(EXPORT ${PROJECT_NAME}Targets
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${ConfigPackageLocation}) DESTINATION ${ConfigPackageLocation})
# Create the CMake version file. # Create the CMake version file.
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
write_basic_package_version_file( write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake" "${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake"
VERSION ${PACKAGE_VERSION} COMPATIBILITY AnyNewerVersion) VERSION ${PACKAGE_VERSION}
COMPATIBILITY AnyNewerVersion)
# Create the Config file. # Create the Config file.
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
# Fix libwebpmux reference. The target name libwebpmux is used for compatibility
# purposes, but the library mentioned in WebPConfig.cmake should be the
# unprefixed version. Note string(...) can be replaced with list(TRANSFORM ...)
# if cmake_minimum_required is >= 3.12.
string(REGEX REPLACE "libwebpmux" "webpmux" INSTALLED_LIBRARIES
"${INSTALLED_LIBRARIES}")
if(MSVC)
# For compatibility with nmake, MSVC builds use a custom prefix (lib) that
# needs to be included in the library name.
string(REGEX REPLACE "[A-Za-z0-9_]+" "${CMAKE_STATIC_LIBRARY_PREFIX}\\0"
INSTALLED_LIBRARIES "${INSTALLED_LIBRARIES}")
endif()
configure_package_config_file( configure_package_config_file(
${CMAKE_CURRENT_SOURCE_DIR}/cmake/WebPConfig.cmake.in ${CMAKE_CURRENT_SOURCE_DIR}/cmake/WebPConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake
INSTALL_DESTINATION ${ConfigPackageLocation} INSTALL_DESTINATION
PATH_VARS CMAKE_INSTALL_INCLUDEDIR) ${ConfigPackageLocation})
# Install the generated CMake files. # Install the generated CMake files.
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake" install(FILES "${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake"
@ -848,6 +669,7 @@ foreach(I_MAN RANGE ${MAN_PAGES_RANGE})
if(WEBP_BUILD_${EXEC_BUILD}) if(WEBP_BUILD_${EXEC_BUILD})
list(GET MAN_PAGES ${I_MAN} MAN_PAGE) list(GET MAN_PAGES ${I_MAN} MAN_PAGE)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man/${MAN_PAGE} install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man/${MAN_PAGE}
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 COMPONENT doc) DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
COMPONENT doc)
endif() endif()
endforeach() endforeach()

View File

@ -1,78 +0,0 @@
# How to Contribute
We'd love to accept your patches and contributions to this project. There are
just a few small guidelines you need to follow.
## Contributor License Agreement
Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution;
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to <https://cla.developers.google.com/> to see
your current agreements on file or to sign a new one.
You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.
## Code reviews
All submissions, including submissions by project members, require review. We
use a [Gerrit](https://www.gerritcodereview.com) instance hosted at
https://chromium-review.googlesource.com for this purpose.
## Sending patches
The basic git workflow for modifying libwebp code and sending for review is:
1. Get the latest version of the repository locally:
```sh
git clone https://chromium.googlesource.com/webm/libwebp && cd libwebp
```
2. Copy the commit-msg script into ./git/hooks (this will add an ID to all of
your commits):
```sh
curl -Lo .git/hooks/commit-msg https://chromium-review.googlesource.com/tools/hooks/commit-msg && chmod u+x .git/hooks/commit-msg
```
3. Modify the local copy of libwebp. Make sure the code
[builds successfully](https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/building.md#cmake).
4. Choose a short and representative commit message:
```sh
git commit -a -m "Set commit message here"
```
5. Send the patch for review:
```sh
git push https://chromium-review.googlesource.com/webm/libwebp HEAD:refs/for/main
```
Go to https://chromium-review.googlesource.com to view your patch and
request a review from the maintainers.
See the
[WebM Project page](https://www.webmproject.org/code/contribute/submitting-patches/)
for additional details.
## Code Style
The C code style is based on the
[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) and
`clang-format --style=Google`, though this project doesn't use the tool to
enforce the formatting.
CMake files are formatted with
[cmake-format](https://cmake-format.readthedocs.io/en/latest/). `cmake-format
-i` can be used to format individual files, it will use the settings from
`.cmake-format.py`.
## Community Guidelines
This project follows
[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).

923
ChangeLog
View File

@ -1,923 +1,4 @@
bf0bf1e7 api.md: add WebPValidateDecoderConfig to pseudocode
e8ae210d update NEWS
ce53efd7 bump version to 1.6.0
1c333170 update AUTHORS
85e098e5 webpmux: fix heap overflow w/-get/-set
418340d8 Merge "Make histogram allocation and access more readable and type-safe." into main
23ce76fa Merge "VP8BitReaderSetBuffer: move NULL check to call site" into main
bbf3cbb1 VP8BitReaderSetBuffer: move NULL check to call site
f6b87e03 Fix const style guide
8852f89a Have lossless return the same results with/without -mt
e015dcc0 Make histogram allocation and access more readable and type-safe.
753ed11e enc_neon.c: fix aarch64 compilation w/gcc < 8.5.0
0cd0b7a7 enc_fuzzer.cc: remove duplicate <cstdlib> include
2209ffba swig,cosmetics: normalize includes
15e2e1ee analysis_enc.c: remove unused include
98c27801 IWYU: Include all headers for symbols used in files.
eb3ff781 Only use valid histograms in VP8LHistogramSet
57e324e2 Refactor VP8LHistogram histogram_enc.cc
7191a602 Merge "Generalize trivial histograms" into main
19696e0a Merge "alpha_processing_sse2: quiet signed conv warning" into main
89b01ecc Merge "cwebp: add `-resize_mode`" into main
52a430a7 Generalize trivial histograms
e53e2130 Cache all costs in the histograms
f8b360c4 alpha_processing_sse2: quiet signed conv warning
eb4f8137 cwebp: add `-resize_mode`
ad52d5fc dec/dsp/enc/utils,cosmetics: rm struct member '_' suffix
ed7cd6a7 utils.c,cosmetics: rm struct member '_' suffix
3a23b0f0 random_utils.[hc],cosmetics: rm struct member '_' suffix
a99d0e6f quant_levels_dec_utils.c,cosmetics: rm struct member '_' suffix
1ed4654d huffman_encode_utils.[hc],cosmetics: rm struct member '_' suffix
f0689e48 config_enc.c,cosmetics: rm struct member '_' suffix
24262266 mux,cosmetics: rm struct member '_' suffix
3f54b1aa demux,cosmetics: rm struct member '_' suffix
295804e4 examples,cosmetics: rm struct member '_' suffix
5225592f Refactor VP8LHistogram to hide initializations from the user.
00338240 Remove some computations in histogram clustering
44f91b0d Speed DispatchAlpha_SSE2 up
ee8e8c62 Fix member naming for VP8LHistogram
a1ad3f1e Merge "Remove now unused ExtraCostCombined" into main
321561b4 Remove now unused ExtraCostCombined
e0ae21d2 WebPMemoryWriterClear: use WebPMemoryWriterInit
a4183d94 Remove the computation of ExtraCost when comparing histograms
f2b3f527 Get AVX2 into WebP lossless
7c70ff7a Clean dsp/lossless includes
9dd5ae81 Use the full register in PredictorSub13_SSE2
613be8fc Makefile.vc: add /MP to CFLAGS
1d86819f Merge changes I1437390a,I10a20de5,I1ac777d1 into main
743a5f09 enc_neon: enable vld1q_u8_x4 for clang & msvc
565da148 pngdec.c: add support for 'eXIf' tag
319860e9 pngdec.c: support ImageMagick app1 exif text data
815fc1e1 pngdec.c: add missing #ifdef for png_get_iCCP
980b708e enc_neon: fix build w/aarch64 gcc < 9.4.0
73b728cb cmake: bump minimum version to 3.16
6a22b670 Add a function to validate a WebPDecoderConfig
7ed2b10e Use consistently signed stride types.
654bfb04 Avoid nullptr arithmetic in VP8BitReaderSetBuffer
f8f24107 Fix potential "divide by zero" in examples found by coverity
2af6c034 Merge tag 'v1.5.0'
a4d7a715 update ChangeLog (tag: v1.5.0, origin/1.5.0)
c3d85ce4 update NEWS
ad14e811 tests/fuzzer/*: add missing <string_view> include
74cd026e fuzz_utils.cc: fix build error w/WEBP_REDUCE_SIZE
a027aa93 mux_demux_api_fuzzer.cc: fix -Wshadow warning
25e17c68 update ChangeLog (tag: v1.5.0-rc1)
aa2684fc update NEWS
36923846 bump version to 1.5.0
ceea8ff6 update AUTHORS
e4f7a9f0 img2webp: add a warning for unused options
1b4c967f Merge "Properly check the data size against the end of the RIFF chunk" into main
9e5ecfaf Properly check the data size against the end of the RIFF chunk
da0d9c7d examples: exit w/failure w/no args
fcff86c7 {gif,img}2webp: sync -m help w/cwebp
b76c4a84 man/img2webp.1: sync -m text w/cwebp.1 & gif2webp.1
30633519 muxread: fix reading of buffers > riff size
4c85d860 yuv.h: update RGB<->YUV coefficients in comment
0ab789e0 Merge changes I6dfedfd5,I2376e2dc into main
03236450 {ios,xcframework}build.sh: fix compilation w/Xcode 16
61e2cfda rework AddVectorEq_SSE2
7bda3deb rework AddVector_SSE2
2ddaaf0a Fix variable names in SharpYuvComputeConversionMatrix
a3ba6f19 Makefile.vc: fix gif2webp link error
f999d94f gif2webp: add -sharp_yuv/-near_lossless
dfdcb7f9 Merge "lossless.h: fix function declaration mismatches" into main (tag: webp-rfc9649)
78ed6839 fix overread in Intra4Preds_NEON
d516a68e lossless.h: fix function declaration mismatches
87406904 Merge "Improve documentation of SharpYuvConversionMatrix." into main
fdb229ea Merge changes I07a7e36a,Ib29980f7,I2316122d,I2356e314,I32b53dd3, ... into main
0c3cd9cc Improve documentation of SharpYuvConversionMatrix.
169dfbf9 disable Intra4Preds_NEON
2dd5eb98 dsp/yuv*: use WEBP_RESTRICT qualifier
23bbafbe dsp/upsampling*: use WEBP_RESTRICT qualifier
35915b38 dsp/rescaler*: use WEBP_RESTRICT qualifier
a32b436b dsp/lossless*: use WEBP_RESTRICT qualifier
04d4b4f3 dsp/filters*: use WEBP_RESTRICT qualifier
b1cb37e6 dsp/enc*: use WEBP_RESTRICT qualifier
201894ef dsp/dec*: use WEBP_RESTRICT qualifier
02eac8a7 dsp/cost*: use WEBP_RESTRICT qualifier
84b118c9 Merge "webp-container-spec: normalize notes & unknown chunk link" into main
052cf42f webp-container-spec: normalize notes & unknown chunk link
220ee529 Search for best predictor transform bits
78619478 Try to reduce the sampling for the entropy image
14f09ab7 webp-container-spec: reorder chunk size - N text
a78c5356 Remove a useless malloc for entropy image
bc491763 Merge "Refactor predictor finding" into main
34f92238 man/{cwebp,img2webp}.1: rm 'if needed' from -sharp_yuv
367ca938 Refactor predictor finding
a582b53b webp-lossless-bitstream-spec: clarify some text
0fd25d84 Merge "anim_encode.c: fix function ref in comment" into main
f8882913 anim_encode.c: fix function ref in comment
40e4ca60 specs_generation.md: update kramdown command line
57883c78 img2webp: add -exact/-noexact per-frame options
1c8eba97 img2webp,cosmetics: add missing '.' spacers to help
2e81017c Convert predictor_enc.c to fixed point
94de6c7f Merge "Fix fuzztest link errors w/-DBUILD_SHARED_LIBS=1" into main
51d9832a Fix fuzztest link errors w/-DBUILD_SHARED_LIBS=1
7bcb36b8 Merge "Fix static overflow warning." into main
8e0cc14c Fix static overflow warning.
cea68462 README.md: add security report note
615e5874 Merge "make VP8LPredictor[01]_C() static" into main
233e86b9 Merge changes Ie43dc5ef,I94cd8bab into main
1a29fd2f make VP8LPredictor[01]_C() static
dd9d3770 Do*Filter_*: remove row & num_rows parameters
ab451a49 Do*Filter_C: remove dead 'inverse' code paths
f9a480f7 {TrueMotion,TM16}_NEON: remove zero extension
04834aca Merge changes I25c30a9e,I0a192fc6,I4cf89575 into main
39a602af webp-lossless-bitstream-spec: normalize predictor transform ref
f28c837d Merge "webp-container-spec: align anim pseudocode w/prose" into main
74be8e22 Fix implicit conversion issues
0c01db7c Merge "Increase the transform bits if possible." into main
f2d6dc1e Increase the transform bits if possible.
caa19e5b update link to issue tracker
c9dd9bd4 webp-container-spec: align anim pseudocode w/prose
8a7c8dc6 WASM: Enable VP8L_USE_FAST_LOAD
f0c53cd9 WASM: don't use USE_GENERIC_TREE
eef903d0 WASM: Enable 64-bit BITS caching
6296cc8d iterator_enc: make VP8IteratorReset() static
fbd93896 histogram_enc: make VP8LGetHistogramSize static
cc7ff545 cost_enc: make VP8CalculateLevelCosts[] static
4e2828ba vp8l_dec: make VP8LClear() static
d742b24a Intra16Preds_NEON: fix truemotion saturation
c7bb4cb5 Intra4Preds_NEON: fix truemotion saturation
952a989b Merge "Remove TODO now that log is using fixed point." into main
dde11574 Remove TODO now that log is using fixed point.
a1ca153d Fix hidden myerr in my_error_exit
3bd94202 Merge changes Iff6e47ed,I24c67cd5,Id781e761 into main
d27d246e Merge "Convert VP8LFastSLog2 to fixed point" into main
4838611f Disable msg_code use in fuzzing mode
314a142a Use QuantizeBlock_NEON for VP8EncQuantizeBlockWHT on Arm
3bfb05e3 Add AArch64 Neon implementation of Intra16Preds
baa93808 Add AArch64 Neon implementation of Intra4Preds
41a5e582 Fix errors when compiling code as C++
fb444b69 Convert VP8LFastSLog2 to fixed point
c1c89f51 Fix WEBP_NODISCARD comment and C++ version
66408c2c Switch the histogram_enc.h API to fixed point
ac1e410d Remove leftover tiff dep
b78d3957 Disable TIFF on fuzztest.
cff21a7d Do not build statically on oss-fuzz.
6853a8e5 Merge "Move more internal fuzzers to public." into main
9bc09db4 Merge "Convert VP8LFastLog2 to fixed point" into main
0a9f1c19 Convert VP8LFastLog2 to fixed point
db0cb9c2 Move more internal fuzzers to public.
ff2b5b15 Merge "advanced_api_fuzzer.cc: use crop dims in OOM check" into main
c4af79d0 Put 0 at the end of a palette and do not store it.
0ec80aef Delete last references to delta palettization
96d79f84 advanced_api_fuzzer.cc: use crop dims in OOM check
c35c7e02 Fix huffman fuzzer to not leak.
f2fe8dec Bump fuzztest dependency.
9ce982fd Fix fuzz tests to work on oss-fuzz
3ba8af1a Do not escape quotes anymore in build.sh
ea0e121b Allow centipede to be used as a fuzzing engine.
27731afd make VP8I4ModeOffsets & VP8MakeIntra4Preds static
ddd6245e oss-fuzz/build.sh: use heredoc for script creation
50074930 oss-fuzz/build.sh,cosmetics: fix indent
20e92f7d Limit the possible fuzz engines.
4f200de5 Switch public fuzz tests to fuzztest.
64186bb3 Add huffman_fuzzer to .gitignore
0905f61c Move build script from oss-fuzz repo to here.
e8678758 Fix link to Javascript documentation
5e5b8f0c Fix SSE2 Transform_AC3 function name
45129ee0 Revert "Check all the rows."
ee26766a Check all the rows.
7ec51c59 Increase the transform bits if possible.
3cd16fd3 Revert "Increase the transform bits if possible."
971a03d8 Increase the transform bits if possible.
1bf198a2 Allow transform_bits to be different during encoding.
1e462ca8 Define MAX_TRANSFORM_BITS according to the specification.
64d1ec23 Use (MIN/NUM)_(TRANSFORM/HUFFMAN)_BITS where appropriate
a90160e1 Refactor histograms in predictors.
a7aa7525 Fix some function declarations
68ff4e1e Merge "jpegdec: add a hint for EOF/READ errors" into main
79e7968a jpegdec: add a hint for EOF/READ errors
d33455cd man/*: s/BUGS/REPORTING BUGS/
a67ff735 normalize example exit status
edc28909 upsampling_{neon,sse41}: fix int sanitizer warning
3cada4ce ImgIoUtilReadFile: check ftell() return
dc950585 Merge tag 'v1.4.0'
845d5476 update ChangeLog (tag: v1.4.0, origin/1.4.0)
8a6a55bb update NEWS
cf7c5a5d provide a way to opt-out/override WEBP_NODISCARD
cc34288a update ChangeLog (tag: v1.4.0-rc1)
f13c0886 NEWS: fix date
74555950 Merge "vwebp: fix window title when options are given" into 1.4.0
d781646c vwebp: fix window title when options are given
c2e394de update NEWS
f6d15cb7 bump version to 1.4.0
57c388b8 update AUTHORS
b3d1b2cb Merge changes I26f4aa22,I83386b6c,I320ed1a2 into main
07216886 webp-container-spec: fix VP8 chunk ref ('VP8'->'VP8 ')
f88666eb webp_js/*.html: fix canvas mapping
e2c8f233 cmake,wasm: simplify SDL2 related flags
d537cd37 cmake: fix vwebp_sdl compile w/libsdl-org release
6c484cbf CMakeLists.txt: add missing WEBP_BUILD_EXTRAS check
7b0bc235 man/cwebp.1: add more detail to -partition_limit
3c0011bb WebPMuxGetChunk: add an assert
955a3d14 Merge "muxread,MuxGet: add an assert" into main
00abc000 muxread,MuxGet: add an assert
40e85a0b Have the window title reflect the filename.
1bf46358 man/cwebp.1: clarify -pass > 1 behavior w/o -size/-psnr
eba03acb webp-container-spec: replace 'above' with 'earlier'
a16d30cb webp-container-spec: clarify chunk order requirements
8a7e9112 Merge "CMakeLists.txt: apply cmake-format" into main
7fac6c1b Merge "Copy C code to not have multiplication overflow" into main
e2922e43 Merge "Check for the presence of the ANDROID_ABI variable" into main
501d9274 Copy C code to not have multiplication overflow
fba7d62e CMakeLists.txt: apply cmake-format
661c1b66 Merge "windows exports: use dllexport attribute, instead of visibility." into main
8487860a windows exports: use dllexport attribute, instead of visibility.
8ea678b9 webp/mux.h: data lifetime note w/copy_data=0
79e05c7f Check for the presence of the ANDROID_ABI variable
45f995a3 Expose functions for managing non-image chunks on WebPAnimEncoder
1fb9f3dc gifdec: fix ErrorGIFNotAvailable() declaration
4723db65 cosmetics: s/SANITY_CHECK/DCHECK/
f4b9bc9e clear -Wextra-semi-stmt warnings
713982b8 Limit animdecoder_fuzzer to 320MB
cbe825e4 cmake: fix sharpyuv simd files' build
f99305e9 Makefile.vc: add ARM64 support
5efd6300 mv SharpYuvEstimate420Risk to extras/
e78e924f Makefile.vc: add sharpyuv_risk_table.obj
d7a0506d Add YUV420 riskiness metric.
89c5b917 Merge "BuildHuffmanTable check sorted[] array bounds before writing" into main
34c80749 Remove alpha encoding pessimization.
13d9c30b Add a WEBP_NODISCARD
24d7f9cb Switch code to SDL2.
0b56dedc BuildHuffmanTable check sorted[] array bounds before writing
a429c0de sharpyuv: convert some for() to do/while
f0cd7861 DoSharpArgbToYuv: remove constant from loop
339231cc SharpYuvConvertWithOptions,cosmetics: fix formatting
307071f1 Remove medium/large code model-specific inline asm
deadc339 Fix transfer functions where toGamma and toLinear are swapped.
e7b78d43 Merge "Fix bug in FromLinearLog100." into main
15a1309e Merge "webp-lossless-bitstream-spec: delete extra blank line" into main
54ca9752 Fix bug in FromLinearLog100.
d2cb2d8c Dereference after NULL check.
e9d50107 webp-lossless-bitstream-spec: delete extra blank line
78657971 Merge changes Ief442c90,Ie6e9c9a5 into main
e30a5884 webp-lossless-bitstream-spec: update variable names
09ca1368 Merge "webp-container-spec: change assert to MUST be TRUE" into main
38cb4fc0 iosbuild,xcframeworkbuild: add SharpYuv framework
40afa926 webp-lossless-bitstream-spec: simplify abstract
9db21143 webp-container-spec: change assert to MUST be TRUE
cdbf88ae Fix typo in API docs for incremental decoding
05c46984 Reformat vcpkg build instructions.
8534f539 Merge "Never send VP8_STATUS_SUSPENDED back in non-incremental." into main
35e197bd Never send VP8_STATUS_SUSPENDED back in non-incremental.
61441425 Add vcpkg installation instructions
dce8397f Fix next is invalid pointer when WebPSafeMalloc fails
57c58105 Cmake: wrong public macro WEBP_INCLUDE_DIRS
c1ffd9ac Merge "vp8l_enc: fix non-C90 code" into main
a3965948 Merge changes If628bb93,Ic79f6309,I45f0db23 into main
f80e9b7e vp8l_enc: fix non-C90 code
accd141d Update lossless spec for two simple codes.
ac17ffff Fix non-C90 code.
433c7dca Fix static analyzer warnings.
5fac76cf Merge tag 'v1.3.2'
ca332209 update ChangeLog (tag: v1.3.2)
1ace578c update NEWS
63234c42 bump version to 1.3.2
a35ea50d Add a fuzzer for ReadHuffmanCodes
95ea5226 Fix invalid incremental decoding check.
2af26267 Fix OOB write in BuildHuffmanTable.
902bc919 Fix OOB write in BuildHuffmanTable.
7ba44f80 Homogenize "__asm__ volatile" vs "asm volatile"
68e27135 webp-container-spec: reorder example chunk layout
943b932a Merge changes I6a4d0a04,Ibc37b91e into main
1cc94f95 decode.h: wrap idec example in /* */
63acdd1e decode.h: fix decode example
aac5c5d0 ReadHuffmanCode: rm redundant num code lengths check
a2de25f6 webp-lossless-bitstream-spec: normalize list item case
68820f0e webp-lossless-bitstream-spec: normalize pixel ref
cdb31aa8 webp-lossless-bitstream-spec: add missing periods
0535a8cf webp-lossless-bitstream-spec: fix grammar
b6c4ce26 normalize numbered list item format
dd7364c3 Merge "palette.c: fix msvc warnings" into main
c63c5df6 palette.c: fix msvc warnings
0a2cad51 webp-container-spec: move terms from intro section
dd88d2ff webp-lossless-bitstream-spec: color_cache -> color cache
6e750547 Merge changes I644d7d39,Icf05491e,Ic02e6652,I63b11258 into main
67a7cc2b webp-lossless-bitstream-spec: fix code blocks
1432ebba Refactor palette sorting computation.
cd436142 webp-lossless-bitstream-spec: block -> chunk
3cb66f64 webp-lossless-bitstream-spec: add some missing commas
56471a53 webp-lossless-bitstream-spec: normalize item text in 5.1
af7fbfd2 vp8l_dec,ReadTransform: improve error status reporting
7d8e0896 vp8l_dec: add VP8LSetError()
a71ce1cf animencoder_fuzzer: fix error check w/Nallocfuzz
e94b36d6 webp-lossless-bitstream-spec: relocate details from 5.1
84628e56 webp-lossless-bitstream-spec: clarify image width changes
ee722997 alpha_dec: add missing VP8SetError()
0081693d enc_dec_fuzzer: use WebPDecode()
0fcb311c enc_dec_fuzzer: fix WebPEncode/pic.error_code check
982c177c webp-lossless-bitstream-spec: fix struct member refs
56cf5625 webp-lossless-bitstream-spec: use RFC 7405 for ABNF
6c6b3fd3 webp-lossless-bitstream-spec,cosmetics: delete blank lines
29b9eb15 Merge changes Id56ca4fd,I662bd1d7 into main
47c0af8d ReadHuffmanCodes: rm max_alphabet_size calc
b92deba3 animencoder_fuzzer: no WebPAnimEncoderAssemble check w/nallocfuzz
6be9bf8b animencoder_fuzzer: fix leak on alloc failure
5c965e55 vp8l_dec,cosmetics: add some /*param=*/ comments
e4fc2f78 webp-lossless-bitstream-spec: add validity note for max_symbol
71916726 webp-lossless-bitstream-spec: fix max_symbol definition
eac3bd5c Have the palette code be in its own file.
e2c85878 Add an initializer for the SharpYuvOptions struct.
4222b006 Merge tag 'v1.3.1'
25d94f47 Implement more transfer functions in libsharpyuv
2153a679 Merge changes Id0300937,I5dba5ccf,I57bb68e0,I2dba7b4e,I172aca36, ... into main
4298e976 webp-lossless-bitstream-spec: add PredictorTransformOutput
cd7e02be webp-lossless-bitstream-spec: fix RIFF-header ABNF
6c3845f9 webp-lossless-bitstream-spec: split LZ77 Backward Ref section
7f1b6799 webp-lossless-bitstream-spec: split Meta Prefix Codes section
7b634d8f webp-lossless-bitstream-spec: note transform order
6d6d4915 webp-lossless-bitstream-spec: update transformations text
fd7bb21c update ChangeLog (tag: v1.3.1-rc2, tag: v1.3.1)
e1adea50 update NEWS
6b1c722a lossless_common.h,cosmetics: fix a typo
08d60d60 webp-lossless-bitstream-spec: split code length section
7a12afcc webp-lossless-bitstream-spec: rm unused anchor
43393320 enc/*: normalize WebPEncodingSetError() calls
287fdefe enc/*: add missing WebPEncodingSetError() calls
c3bd7cff EncodeAlphaInternal: add missing error check
14a9dbfb webp-lossless-bitstream-spec: refine single node text
64819c7c Implement ExtractGreen_SSE2
d49cfbb3 vp8l_enc,WriteImage: add missing error check
2e5a9ec3 muxread,MuxImageParse: add missing error checks
ebb6f949 cmake,emscripten: explicitly set stack size
59a2b1f9 WebPDecodeYUV: check u/v/stride/uv_stride ptrs
8e965ccb Call png_get_channels() to see if image has alpha
fe80fbbd webp-container-spec: add some missing commas
e8ed3176 Merge "treat FILTER_NONE as a regular Unfilter[] call" into main
03a7a048 webp-lossless-bitstream-spec: rm redundant statement
c437c7aa webp-lossless-bitstream-spec: mv up prefix code group def
e4f17a31 webp-lossless-bitstream-spec: fix section reference
e2ecd5e9 webp-lossless-bitstream-spec: clarify ABNF syntax
8b55425a webp-lossless-bitstream-spec: refine pixel copy text
29c9f2d4 webp-lossless-bitstream-spec: minor wording updates
6b02f660 treat FILTER_NONE as a regular Unfilter[] call
7f75c91c webp-container-spec: fix location of informative msg
f6499943 webp-container-spec: consistently quote FourCCs
49918af3 webp-container-spec: minor wording updates
7f0a3419 update ChangeLog (tag: v1.3.1-rc1)
bab7efbe update NEWS
7138bf8f bump version to 1.3.1
435b4ded update AUTHORS
47351229 update .mailmap
46bc4fc9 Merge "Switch ExtraCost to ints and implement it in SSE." into main
828b4ce0 Switch ExtraCost to ints and implement it in SSE.
ff6c7f4e CONTRIBUTING.md: add C style / cmake-format notes
dd530437 add .cmake-format.py
adbe2cb1 cmake,cosmetics: apply cmake-format
15b36508 doc/webp-container-spec: rm future codec comment
c369c4bf doc/webp-lossless-bitstream-spec: improve link text
1de35f47 doc/webp-container-spec: don't use 'currently'
bb06a16e doc/webp-container-spec: prefer present tense
9f38b71e doc/webp-lossless-bitstream-spec: prefer present tense
7acb6b82 doc/webp-container-spec: avoid i.e. & e.g.
4967e7cd doc/webp-lossless-bitstream-spec: avoid i.e. & e.g.
e3366659 Merge "Do not find_package image libraries if not needed." into main
428588ef clarify single leaf node trees and use of canonical prefix coding
709ec152 Do not find_package image libraries if not needed.
8dd80ef8 fuzz_utils.h: lower kFuzzPxLimit w/ASan
8f187b9f Clean message calls in CMake
cba30078 WebPConfig.cmake.in: use calculated include path
6cf9a76a Merge "webp-lossless-bitstream-spec: remove use of 'dynamics'" into main
740943b2 Merge "Specialize and optimize ITransform_SSE2 using do_two" into main
2d547e24 Compare kFuzzPxLimit to max_num_operations
ac42dde1 Specialize and optimize ITransform_SSE2 using do_two
17e0ef1d webp-lossless-bitstream-spec: remove use of 'dynamics'
ed274371 neon.h,cosmetics: clear a couple lint warnings
3fb82947 cpu.h,cosmetics: segment defines
0c496a4f cpu.h: add WEBP_AARCH64
8151f388 move VP8GetCPUInfo declaration to cpu.c
916548c2 Make kFuzzPxLimit sanitizer dependent
4070b271 advanced_api_fuzzer: reduce scaling limit
761f49c3 Merge "webp-lossless-bitstream-spec: add missing bits to ABNF" into main
84d04c48 webp-lossless-bitstream-spec: add missing bits to ABNF
0696e1a7 advanced_api_fuzzer: reduce scaling limit
93d88aa2 Merge "deps.cmake: remove unneeded header checks" into main
118e0035 deps.cmake: remove unneeded header checks
4c3d7018 webp-lossless-bitstream-spec: condense normal-prefix-code
a6a09b32 webp-lossless-bitstream-spec: fix 2 code typos
50ac4f7c Merge "cpu.h: enable NEON w/_M_ARM64EC" into main
4b7d7b4f Add contribution instructions
0afbd97b cpu.h: enable NEON w/_M_ARM64EC
349f4353 Merge changes Ibd89e56b,Ic57e7f84,I89096614 into main
8f7513b7 upsampling_neon.c: fix WEBP_SWAP_16BIT_CSP check
cbf624b5 advanced_api_fuzzer: reduce scaling limit
89edfdd1 Skip slow scaling in libwebp advanced_api_fuzzer
859f19f7 Reduce libwebp advanced_api_fuzzer threshold
a4f04835 Merge changes Ic389aaa2,I329ccd79 into main
1275fac8 Makefile.vc: fix img2webp link w/dynamic cfg
2fe27bb9 img2webp: normalize help output
24bed3d9 cwebp: reflow -near_lossless help text
0825faa4 img2webp: add -sharp_yuv/-near_lossless
d64e6d7d Merge "PaletteSortModifiedZeng: fix leak on error" into main
0e12a22d Merge "EncodeAlphaInternal: clear result->bw on error" into main
0edbb6ea PaletteSortModifiedZeng: fix leak on error
41ffe04e Merge "Update yapf style from "chromium" to "yapf"" into main
2d9d9265 Update yapf style from "chromium" to "yapf"
a486d800 EncodeAlphaInternal: clear result->bw on error
1347a32d Skip big scaled advanced_api_fuzzer
52b6f067 Fix scaling limit in advanced_api_fuzzer.c
73618428 Limit scaling in libwebp advanced_api_fuzzer.c
b54d21a0 Merge "CMakeLists.txt: allow CMAKE_INSTALL_RPATH to be set empty" into main
31c28db5 libwebp{,demux,mux}.pc.in: Requires -> Requires.private
d9a505ff CMakeLists.txt: allow CMAKE_INSTALL_RPATH to be set empty
bdf33d03 Merge tag 'v1.3.0'
b5577769 update ChangeLog (tag: v1.3.0-rc1, tag: v1.3.0)
0ba77244 update NEWS
e763eb1e bump version to 1.3.0
2a8686fc update AUTHORS
106a57c1 Merge "*/Android.mk: add a check for NDK_ROOT" into main
c5e841c4 Merge "extras: WebpToSDL -> WebPToSDL" into main
dbc30715 Merge "xcframeworkbuild.sh: bump MACOSX_CATALYST_MIN_VERSION" into main
6fc1a9f9 */Android.mk: add a check for NDK_ROOT
d3e151fc doc/api.md,webp_js/README.md: Webp -> WebP
ed92a626 extras: WebpToSDL -> WebPToSDL
6eb0189b xcframeworkbuild.sh: bump MACOSX_CATALYST_MIN_VERSION
1d58575b CMake: align .pc variables with autoconf
e5fe2cfc webp-lossless-bitstream-spec,cosmetics: reflow paragraphs
0ceeeab9 webp-lossless-bitstream-spec: add amendment note
607611cd Merge "webp-container-spec: normalize section title case" into main
f853685e lossless: SUBTRACT_GREEN -> SUBTRACT_GREEN_TRANSFORM
786497e4 webp-lossless-bitstream-spec: fix inv color txfm description
c6ac672d webp-lossless-bitstream-spec: fix num_code_lengths check
b5700efb webp-lossless-bitstream-spec,cosmetics: grammar/capitalization
d8ed8c11 webp-container-spec: normalize section title case
52ec0b8f Merge changes Ie975dbb5,Ifc8c93af,I6ca7c5d6,I2e8d66f5,I152477b8 into main
5097ef62 webp-container-spec,cosmetics: grammar/capitalization
e3ba2b1f webp-lossless-bitstream-spec,cosmetics: reflow abstract
1e8e3ded webp-lossless-bitstream-spec: reword abstract re alpha
017cb6fa webp-container-spec,cosmetics: normalize range syntax
f6a4684b webp-lossless-bitstream-spec,cosmetics: normalize range syntax
54ebd5a3 webp-lossless-bitstream-spec: limit dist map lut to 69 cols
44741f9c webp-lossless-bitstream-spec: fix dist mapping example
fad0ece7 pnmdec.c: use snprintf instead of sprintf
3f73e8f7 sharpyuv: add SharpYuvGetVersion()
ce2f2d66 SharpYuvConvert: fix a race on SharpYuvGetCPUInfo
a458e308 sharpyuv_dsp.h: restore sharpyuv_cpu.h include
9ba800a7 Merge changes Id72fbf3b,Ic59d23a2 into main
979c0ebb sharpyuv: add SharpYuvGetCPUInfo
8bab09a4 Merge "*.pc.in: rename lib_prefix to webp_libname_prefix" into main
769387c5 cpu.c,cosmetics: fix a typo
a02978c2 sharpyuv/Makefile.am+cmake: add missing -lm
28aedcb9 *.pc.in: rename lib_prefix to webp_libname_prefix
c42e6d5a configure.ac: export an empty lib_prefix variable
dfc843aa Merge "*.pc.in: add lib prefix to lib names w/MSVC" into main
2498209b *.pc.in: add lib prefix to lib names w/MSVC
ac252b61 Merge "analysis_enc.c: fix a dead store warning" into main
56944762 analysis_enc.c: fix a dead store warning
d34f9b99 Merge "webp-lossless-bitstream-spec: convert BNF to ABNF" into main
dc05b4db Merge changes I96bc063c,I45880467,If9e18e5a,I6ee938e4,I0a410b28, ... into main
83270c7f webp-container-spec: add prose for rendering process
73b19b64 webp-container-spec: note reserved fields MUST be ignored
57101d3f webp-lossless-bitstream-spec: improve 'small' color table stmt
dfd32e45 webp-container-spec: remove redundant sentence
8a6185dd doc/webp-*: fix some punctuation, grammar
72776530 webp-lossless-bitstream-spec: convert BNF to ABNF
d992bb08 cmake: rename cpufeatures target to cpufeatures-webp
3ed2b275 webp-container-spec: clarify background color note
951c292d webp-container-spec: come too late -> out of order
902dd787 webp-container-spec: prefer hex literals
a8f6b5ee webp-container-spec: change SHOULD to MUST w/ANIM chunk
1dc59435 webp-container-spec: add unknown fields MUST be ignored
280a810f webp-container-spec: make padding byte=0 a MUST
41f0bf68 webp-container-spec: update note on trailing data
6bdd36db webp-container-spec: clarify Chunk Size is in bytes
87e36c48 Merge "webp_js/README.md,cosmetics: reflow some lines" into main
5b01f321 Merge "Update Windows makefile to build libsharpyuv library." into main
19b1a71c webp_js/README.md,cosmetics: reflow some lines
780db756 Update Windows makefile to build libsharpyuv library.
e407d4b3 CMakeLists.txt: replace GLUT_glut_LIBRARY w/GLUT::GLUT
abf73d62 Merge "WebPConfig.cmake.in: add find_dependency(Threads)" into main
25807fb4 Merge "cmake: restore compatibility with cmake < 3.12" into main
5dbc4bfa WebPConfig.cmake.in: add find_dependency(Threads)
b2a175dd Merge "Update wasm instructions." into main
cb90f76b Update wasm instructions.
02d15258 cmake: restore compatibility with cmake < 3.12
5ba046e2 CMake: add_definitions -> add_compile_options
e68765af dsp,neon: use vaddv in a few more places
e8f83de2 Set libsharpyuv include dir to 'webp' subdirectory.
15a91ab1 cmake,cosmetics: apply cmake-format
0dd49d1a CMakeLists.txt: set @ONLY in configure_file() calls
62b1bfe8 Merge changes I2877e7bb,I777cad70,I15af7d1a,I686e6740,If10538a9, ... into main
95c8fe5f Merge changes Iecea3603,I9dc228ab into main
e7c805cf picture_csp_enc.c: remove SafeInitSharpYuv
6af8845a sharpyuv: prefer webp/types.h
639619ce cmake: fix dll exports
782ed48c sharpyuv,SharpYuvInit: add mutex protection when available
cad0d5ad sharyuv_{neon,sse2}.c: merge WEBP_USE_* sections
ef70ee06 add a few missing <stddef.h> includes for NULL
f0f9eda4 sharpyuv.h: remove <inttypes.h>
9b902cba Merge "picture_csp_enc.c,CheckNonOpaque: rm unneeded local" into main
9c1d457c cmake/cpu.cmake: remove unused variable
9ac25bcb CMakeLists.txt,win32: match naming convention used by nmake
76c353ba picture_csp_enc.c,CheckNonOpaque: rm unneeded local
5000de54 Merge "cwebp: fix WebPPictureHasTransparency call" into main
e1729309 Merge "WebPPictureHasTransparency: add missing pointer check" into main
00ff988a vp8l_enc,AddSingleSubGreen: clear int sanitizer warnings
e2fecc22 dsp/lossless_enc.c: clear int sanitizer warnings
129cf9e9 dsp/lossless.c: clear int sanitizer warnings
ad7d1753 dsp/lossless_enc.c: clear int sanitizer warnings
5037220e VP8LSubtractGreenFromBlueAndRed_C: clear int sanitizer warnings
2ee786c7 upsampling_sse2.c: clear int sanitizer warnings
4cc157d4 ParseOptionalChunks: clear int sanitizer warning
892cf033 BuildHuffmanTable: clear int sanitizer warning
3a9a4d45 VP8GetSigned: clear int sanitizer warnings
704a3d0a dsp/lossless.c: quiet int sanitizer warnings
1a6c109c WebPPictureHasTransparency: add missing pointer check
c626e7d5 cwebp: fix WebPPictureHasTransparency call
866e349c Merge tag 'v1.2.4'
c170df38 Merge "Create libsharpyuv.a in makefile.unix." into main
9d7ff74a Create libsharpyuv.a in makefile.unix.
0d1f1254 update ChangeLog (tag: v1.2.4)
fcbc2d78 Merge "doc/*.txt: restrict code to 69 columns" into main
4ad0e189 Merge "webp-container-spec.txt: normalize fourcc spelling" into main
980d2488 update NEWS
9fde8127 bump version to 1.2.4
7a0a9935 doc/*.txt: restrict code to 69 columns
c040a615 webp-container-spec.txt: normalize fourcc spelling
aff1c546 dsp,x86: normalize types w/_mm_cvtsi128_si32 calls
ab540ae0 dsp,x86: normalize types w/_mm_cvtsi32_si128 calls
8980362e dsp,x86: normalize types w/_mm_set* calls (2)
e626925c lossless: fix crunch mode w/WEBP_REDUCE_SIZE
83539239 dsp,x86: normalize types w/_mm_set* calls
8a4576ce webp-container-spec.txt: replace &amp; with &
db870881 Merge "webp-container-spec.txt: make reserved 0 values a MUST" into main
01d7d378 webp-lossless-bitstream-spec: number all sections
337cf69f webp-lossless-bitstream-spec: mv Nomenclature after Intro
79be856e Merge changes I7111d1f7,I872cd62c into main
5b87983a webp-container-spec.txt: make reserved 0 values a MUST
bd939123 Merge changes I7a25b1a6,I51b2c2a0,I87d0cbcf,I6ec60af6,I0a3fe9dc into main
04764b56 libwebp.pc: add libsharpyuv to requires
7deee810 libsharpyuv: add pkg-config file
1a64a7e6 webp-container-spec.txt: clarify some SHOULDs
bec2c88a webp-container-spec.txt: move ChunkHeader to terminology
c9359332 webp-container-spec.txt: clarify 'VP8 '/'XMP ' fourccs
70fe3063 webp-container-spec.txt: rightsize table entries
ddbf3f3f webp-container-spec.txt: update 'key words' text
c151e95b utils.h,WEBP_ALIGN: make bitmask unsigned
748e92bb add WebPInt32ToMem
3fe15b67 Merge "Build libsharpyuv as a full installable library." into main
4f402f34 add WebPMemToInt32
a3b68c19 Build libsharpyuv as a full installable library.
b4994eaa CMake: set rpath for shared objects
94cd7117 Merge "CMake: fix dylib versioning" into main
e91451b6 Fix the lossless specs a bit more.
231bdfb7 CMake: fix dylib versioning
bfad7ab5 CMakeLists.txt: correct libwebpmux name in WebPConfig.cmake
c2e3fd30 Revert "cmake: fix webpmux lib name for cmake linking"
7366f7f3 Merge "lossless: fix crunch mode w/WEBP_REDUCE_SIZE" into main
84163d9d lossless: fix crunch mode w/WEBP_REDUCE_SIZE
d01c1eb3 webp-lossless-bitstream-spec,cosmetics: normalize capitalization
8813ca8e Merge tag 'v1.2.3'
3c4a0fbf update ChangeLog (tag: v1.2.3)
56a480e8 dsp/cpu.h: add missing extern "C"
62b45bdd update ChangeLog (tag: v1.2.3-rc1)
8764ec7a Merge changes Idb037953,Id582e395 into 1.2.3
bcb872c3 vwebp: fix file name display in windows unicode build
67c44ac5 webpmux: fix -frame option in windows unicode build
8278825a makefile.unix: add sharpyuv objects to clean target
14a49e01 update NEWS
34b1dc33 bump version to 1.2.3
0b397fda update AUTHORS
c16488ac update .mailmap
5a2d929c Merge "unicode.h: set console mode before using wprintf" into main
169f867f unicode.h: set console mode before using wprintf
a94b855c Merge "libsharpyuv: add version defines" into main
f83bdb52 libsharpyuv: add version defines
bef0d797 unicode_gif.h: fix -Wdeclaration-after-statement
404c1622 Rename Huffman coding to prefix coding in the bitstream spec
8895f8a3 Merge "run_static_analysis.sh: fix scan-build archive path" into main
92a673d2 Merge "Add -fvisibility=hidden flag in CMakeLists." into main
67c1d722 Merge "add WEBP_MSAN" into main
1124ff66 Add -fvisibility=hidden flag in CMakeLists.
e15b3560 add WEBP_MSAN
ec9e782a sharpyuv: remove minimum image size from sharpyuv library
7bd07f3b run_static_analysis.sh: fix scan-build archive path
5ecee06f Merge "sharpyuv: increase precision of gamma<->linear conversion" into main
f81dd7d6 Merge changes I3d17d529,I53026880,I1bd61639,I6bd4b25d,Icfec8fba into main
2d607ee6 sharpyuv: increase precision of gamma<->linear conversion
266cbbc5 sharpyuv: add 32bit version of SharpYuvFilterRow.
9fc12274 CMake: add src to webpinfo includes
7d18f40a CMake: add WEBP_BUILD_WEBPINFO to list of checks for exampleutil
11309aa5 CMake: add WEBP_BUILD_WEBPMUX to list of checks for exampleutil
4bc762f7 CMake: link imageioutil to exampleutil after defined
0d1b9bc4 WEBP_DEP_LIBRARIES: use Threads::Threads
20ef48f0 Merge "sharpyuv: add support for 10/12/16 bit rgb and 10/12 bit yuv." into main
93c54371 sharpyuv: add support for 10/12/16 bit rgb and 10/12 bit yuv.
53cf2b49 normalize WebPValidatePicture declaration w/definition
d3006f4b sharpyuv: slightly improve precision
ea967098 Merge changes Ia01bd397,Ibf3771af into main
11bc8410 Merge changes I2d317c4b,I9e77f6db into main
30453ea4 Add an internal WebPValidatePicture.
6c43219a Some renamings for consistency.
4f59fa73 update .mailmap
e74f8a62 webp-lossless-bitstream-spec,cosmetics: normalize range syntax
5a709ec0 webp-lossless-bitstream-spec,cosmetics: fix code typo
a2093acc webp-lossless-bitstream-spec: add amendment note
86c66930 webp-lossless-bitstream-spec: fix BNF
232f22da webp-lossless-bitstream-spec: fix 'simple code' snippet
44dd765d webp-lossless-bitstream-spec: fix ColorTransform impl
7a7e33e9 webp-lossless-bitstream-spec: fix TR-pixel right border note
86f94ee0 Update lossless spec with Huffman codes.
a3927cc8 sharpyuv.c,cosmetics: fix indent
6c45cef7 Make sure the stride has a minimum value in the importer.
0c8b0e67 sharpyuv: cleanup/cosmetic changes
dc3841e0 {histogram,predictor}_enc: quiet int -> float warnings
a19a25bb Replace doubles by floats in lossless misc cost estimations.
42888f6c Add an option to enable static builds.
7efcf3cc Merge "Fix typo in color constants: Marix -> Matrix" into main
8f4b5c62 Fix typo in color constants: Marix -> Matrix
90084d84 Merge "demux,IsValidExtendedFormat: remove unused variable" into main
ed643f61 Merge changes I452d2485,Ic6d75475 into main
8fa053d1 Rename SharpYUV to SharpYuv for consistency.
99a87562 SharpYuvComputeConversionMatrix: quiet int->float warnings
deb426be Makefile.vc: add sharpyuv_csp.obj to SHARPYUV_OBJS
779597d4 demux,IsValidExtendedFormat: remove unused variable
40e8aa57 Merge "libsharpyuv: add colorspace utilities" into main
01a05de1 libsharpyuv: add colorspace utilities
2de4b05a Merge changes Id9890a60,I376d81e6,I1c958838 into main
b8bca81f Merge "configure.ac: use LT_INIT if available" into main
e8e77b9c Merge changes I479bc487,I39864691,I5d486c2c,I186d13be into main
7e7d5d50 Merge ".gitignore: add Android Studio & VS code dirs" into main
10c50848 normalize label indent
89f774e6 mux{edit,internal}: fix leaks on error
2d3293ad ExUtilInitCommandLineArguments: fix leak on error
ec34fd70 anim_util: fix leaks on error
e4717287 gif2webp: fix segfault on OOM
e3cfafaf GetBackwardReferences: fail on alloc error
a828a59b BackwardReferencesHashChainDistanceOnly: fix segfault on OOM
fe153fae VP8LEncodeStream: fix segfault on OOM
919acc0e .gitignore: add Android Studio & VS code dirs
efa0731b configure.ac: use LT_INIT if available
0957fd69 tiffdec: add grayscale support
e685feef Merge "Make libsharpyuv self-contained by removing dependency on cpu.c" into main
841960b6 Make libsharpyuv self-contained by removing dependency on cpu.c
617cf036 image_dec: add WebPGetEnabledInputFileFormats()
7a68afaa Let SharpArgbToYuv caller pass in an RGB>YUV conversion matrix.
34bb332c man/cwebp.1: add note about crop/resize order
f0e9351c webp-lossless-bitstream-spec,cosmetics: fix some typos
5ccbd6ed vp8l_dec.c,cosmetics: fix a few typos
c3d0c2d7 fix ios build scripts after sharpyuv dep added
d0d2292e Merge "Make libwebp depend on libsharpyuv." into main
03d12190 alpha_processing_neon.c: fix 0x01... typo
d55d447c Make libwebp depend on libsharpyuv.
e4cbcdd2 Fix lossless encoding for MIPS.
924e7ca6 alpha_processing_neon.c: fix Dispatch/ExtractAlpha_NEON
0fa0ea54 Makefile.vc: use /MANIFEST:EMBED
29cc95ce Basic version of libsharpyuv in libwebp, in C.
a30f2190 examples/webpmux.c: fix a couple of typos
66b3ce23 Fix bad overflow check in ReadTIFF()
54e61a38 Markdownify libwebp docs and reorganize them.
b4533deb CMakeLists.txt,cosmetics: break long line
b9d2f9cd quant_enc.c: use WEBP_RESTRICT qualifier
ec178f2c Add progress hook granularity in lossless
26139c73 Rename MAX_COST to MAX_BIT_COST in histogram_enc.c
13b82816 cmake: fix webpmux lib name for cmake linking
88b6a396 webp-container-spec.txt,cosmetics: normalize formatting
6f496540 Merge tag 'v1.2.2'
4074acf8 dsp.h: bump msvc arm64 version requirement to 16.6
b0a86089 update ChangeLog (tag: v1.2.2)
6db8248c libwebp: Fix VP8EncTokenLoop() progress
827a307f BMP enc: fix the transparency case
db25f1b4 libwebp: Fix VP8EncTokenLoop() progress
286e7fce libwebp: do not destroy jpeg codec twice on error
6e8a4126 libwebp: do not destroy jpeg codec twice on error
faf21968 Merge "BMP enc: fix the transparency case" into main
480cd51d BMP enc: fix the transparency case
9195ea05 update ChangeLog (tag: v1.2.2-rc2)
4acae017 update NEWS
883f0633 man/img2webp.1: update date
567e1f44 Reword img2webp synopsis command line
1b0c15db man/img2webp.1: update date
17bade38 Merge "Reword img2webp synopsis command line" into main
a80954a1 Reword img2webp synopsis command line
f084244d anim_decode: fix alpha blending with big-endian
b217b4ff webpinfo: fix fourcc comparison w/big-endian
ec497b75 Merge "anim_decode: fix alpha blending with big-endian" into main
e4886716 anim_decode: fix alpha blending with big-endian
e3cb052c webpinfo: fix fourcc comparison w/big-endian
a510fedb patch-check: detect duplicated files
f035d2e4 update ChangeLog (tag: v1.2.2-rc1)
7031946a update NEWS
973390b6 bump version to 1.2.2
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
e0241154 Merge "libwebp/CMake: Add <BUILD_INTERFACE> to webp incl" into main
edea6444 libwebp/CMake: Add <BUILD_INTERFACE> to webp incl
ece18e55 dsp.h: respect --disable-sse2/sse4.1/neon
a89a3230 wicdec: support alpha from WebP WIC decoder
26f4aa01 Merge "alpha_processing: fix visual studio warnings" into main
8f594663 alpha_processing: fix visual studio warnings
46d844e6 Merge "cpu.cmake: fix compiler flag detection w/3.17.0+" into main
298d26ea Merge changes I593adf92,If20675e7,Ifac68eac into main
a1e5dae0 alpha_processing*: use WEBP_RESTRICT qualifier
327ef24f cpu.cmake: fix compiler flag detection w/3.17.0+
f70819de configure: enable libwebpmux by default
dc7e2b42 configure: add informational notices when disabling binaries
9df23ddd configure: move lib flag checks before binaries
a2e18f10 Merge "WebPConfig.config.in: correct WEBP_INCLUDE_DIRS" into main
e1a8d4f3 Merge "bit_reader_inl_utils: uniformly apply WEBP_RESTRICT" into main
4de35f43 rescaler.c: fix alignment
0f13eec7 bit_reader_inl_utils: uniformly apply WEBP_RESTRICT
277d3074 Fix size_t overflow in WebPRescalerInit
97adbba5 WebPConfig.config.in: correct WEBP_INCLUDE_DIRS
b60d4603 advanced_api_fuzzer: add extreme config value coverage
72fe52f6 anim_encode.c,cosmetics: normalize indent
116d235c anim_encode: Fix encoded_frames_[] overflow
6f445b3e CMake: set CMP0072 to NEW
b1cf887f define WEBP_RESTRICT for MSVC
3e265136 Add WEBP_RESTRICT & use it in VP8BitReader
f6d29247 vp8l_dec::ProcessRows: fix int overflow in multiply
de3b4ba8 CMake: add WEBP_BUILD_LIBWEBPMUX
7f09d3d1 CMakeLists.txt: rm libwebpmux dep from anim_{diff,dump}
4edea4a6 Init{RGB,YUV}Rescaler: fix a few more int overflows
c9e26bdb rescaler_utils: set max valid scaled w/h to INT_MAX/2
28d488e6 utils.h: add SizeOverflow()
695bdaa2 Export/EmitRescaledRowsRGBA: fix pointer offset int overflow
685d073e Init{RGB,YUV}Rescaler: fix int overflows in multiplication
d38bd0dd WebPFlipBuffer: fix integer overflow
109ff0f1 utils: allow MALLOC_LIMIT to indicate a max
a2fce867 WebPRescalerImportRowExpand_C: promote some vals before multiply
776983d4 AllocateBuffer: fix int multiplication overflow check
315abbd6 Merge "Revert "Do not use a palette for one color images.""
eae815d0 Merge changes Ica3bbf75,I82f82954
afbca5a1 Require Emscripten 2.0.18
3320416b CMakeLists,emscripten: use EXPORTED_RUNTIME_METHODS
29145ed6 Update README instructions for using Emscripten
1f579139 cosmetics: remove use of 'sanity' / 'master'
29b6129c WebPAnimEncoderNewInternal: remove some unnecessary inits
b60869a1 Revert "Do not use a palette for one color images."
6fb4cddc demux: move padded size calc post unpadded validation
05b72d42 vp8l_enc.c: normalize index types
b6513fba Do not use a palette for one color images.
98bbe35b Fix multi-threading with palettes.
b1674240 Add modified Zeng's method to palette sorting.
88c90c45 add CONTRIBUTING.md
6a9916d7 WebPRescalerInit: add missing int64_t promotion
b6cf52d5 WebPIoInitFromOptions: treat use_scaling as a bool
3b12b7f4 WebPIoInitFromOptions: treat use_cropping as a bool
595fa13f add WebPCheckCropDimensions()
8fdaecb0 Disable cross-color when palette is used.
8933bac2 WebPIoInitFromOptions: respect incoming bypass_filtering val
7d416ff0 webpdec,cosmetics: match error text to function call
ec6cfeb5 Fix typo on WebPPictureAlloc() in README
7e58a1a2 *.cmake: add license header
5651a6b2 cmake: fix .so versioning
25ae67b3 xcframeworkbuild.sh: add arm64 simulator target
5d4ee4c3 cosmetics: remove use of the term 'dummy'
01b38ee1 faster CollectColorXXXTransforms_SSE41
652aa344 Merge "Use BitCtz for FastSLog2Slow_C"
0320e1e3 add the missing default BitsCtz() code
8886f620 Use BitCtz for FastSLog2Slow_C
fae41617 faster CombinedShannonEntropy_SSE2
5bd2704e Introduce the BitCtz() function.
fee64287 Merge "wicdec,icc: treat unsupported op as non-fatal"
33ddb894 lossless_sse{2,41}: remove some unneeded includes
b27ea852 wicdec,icc: treat unsupported op as non-fatal
b78494a9 Merge "Fix undefined signed shift."
e79974cd Fix undefined signed shift.
a8853394 SSE4.1 versions of BGRA to RGB/BGR color-space conversions
a09a6472 SSE4.1 version of TransformColorInverse
401da22b Merge "pngdec: check version before using png_get_chunk_malloc_max"
26907822 pngdec: check version before using png_get_chunk_malloc_max
06c1e72e Code cleanup
8f0d41aa Merge changes Id135bbf4,I99e59797
373eb170 gif2webp: don't store loop-count if there's only 1 frame
759b9d5a cmake: add WEBP_USE_THREAD option
926ce921 cmake: don't install binaries from extras/
9c367bc6 WebPAnimDecoderNewInternal: validate bitstream before alloc
47f64f6e filters_sse2: import Chromium change
cc3577e9 fuzzer/*: use src/ based include paths
004d77ff Merge tag 'v1.2.0'
fedac6cc update ChangeLog (tag: v1.2.0-rc3, tag: v1.2.0)
170a8712 Fix check_c_source_compiles with pthread.
ceddb5fc Fix check_c_source_compiles with pthread.
85995719 disable CombinedShannonEntropy_SSE2 on x86
289757fe TiffDec: enforce stricter mem/dimension limit on tiles
8af7436f Merge "{ios,xcframework}build.sh: make min version(s) more visible" into 1.2.0
e56c3c5b pngdec: raise memory limit if needed
8696147d pngdec: raise memory limit if needed
13b8e9fe {ios,xcframework}build.sh: make min version(s) more visible
a9225410 animdecoder_fuzzer: fix memory leak
d6c2285d update gradle to 6.1.1
8df77fb1 animdecoder_fuzzer: fix memory leak
52ce6333 update NEWS
28c49820 bump version to 1.2.0
7363dff2 webp/encode.h: restore WEBP_ENCODER_ABI_VERSION to v1.1.0
826aafa5 update AUTHORS
63258823 animdecoder_fuzzer: validate canvas size
9eb26381 CMake: remove duplicate "include(GNUInstallDirs)"
2e7bed79 WebPPicture: clarify the ownership of user-owned data.
cccf5e33 webpmux: add an '-set loop <value>' option
c9a3f6a1 Merge changes Ie29f9867,I289c54c4
319f56f1 iosbuild.sh: sync some aspects of xcframeworkbuild.sh
e8e8db98 add xcframeworkbuild.sh
ae545534 dsp.h: allow config.h to override MSVC SIMD autodetection
fef789f3 Merge "cmake: fix per-file assembly flags"
fc14fc03 Have C encoding predictors use decoding predictors.
7656f0b3 README,cosmetics: fix a couple typos
d2e245ea cmake: disable webp.js if WEBP_ENABLE_SIMD=1
96099a79 cmake: fix per-file assembly flags
5abb5582 Merge "cmake: fix compilation w/Xcode generator"
8484a120 cmake: fix compilation w/Xcode generator
d7bf01c9 Merge changes Ifcae0f38,Iee2d7401
36c81ff6 WASM-SIMD: port 2 patches from rreverser@'s tree
988b02ab Merge "Couple of fixes to allow SIMD on Emscripten"
26faf770 wicdec: fail with animated images
ab2d08a8 [cd]webp: document lack of animated webp support
52273943 Couple of fixes to allow SIMD on Emscripten
8870ba7f Fix skia bug #10952
4b3c6953 Detect if StoreFrame read more than anmf_payload_size bytes
17fd4ba8 webp/decode.h,cosmetics: normalize 'flip' comment
411d3677 remove some unreachable break statements
3700ffd7 WebPPictureHasTransparency: remove unreachable return
83604bf3 {animencoder,enc_dec}_fuzzer: convert some abort()s to returns
eb44119c Merge changes I8ae09473,I678c8b1e
9f6055fc fuzz_utils.h: rename max() to Max()
695788e7 fuzz_utils.h: make functions WEBP_INLINE
906c1fcd make ImgIoUtilReadFile use WebPMalloc instead of malloc
8cb7e536 rename demux_api_fuzzer.c -> mux_demux_api_fuzzer.c
443db47d add animdecoder_fuzzer.cc
36a6eea3 Merge "import fuzzers from oss-fuzz/chromium"
ec5f12c1 Makefile.vc: remove deprecated /Gm option
64425a08 picture_tools_enc: fix windows build warning
bd94090a import fuzzers from oss-fuzz/chromium
cf847cba use WEBP_DSP_INIT_FUNC for Init{GammaTables*,GetCoeffs}
55a080e5 Add WebPReplaceTransparentPixels() in dsp
84739717 GetBackgroundColorGIF: promote to uint32_t before << 24
def64e92 cwebp: Fix -print_psnr for near_lossless
cf2f88b3 Add palette and spatial for q >= 75 and -m 5
f0110bae Add no-color cache configuration to the cruncher
749a8b99 Better estimate of the cache cost.
4f9f00cc Use spatial predictors on top of palette no matter what.
7658c686 Add spatial prediction on top of palette in cruncher.
133ff0e3 webp_js: force WASM=0 option explicitly
e3c259a2 Fix integer overflow in EmitFancyRGB.
b3ff0bde man/{gif2,img2}webp,webpmux: normalize some wording
f9b30586 fix ABI breakage introduced by 6a0ff358
1d58dcfc README.webp_js: update note about emscripten version
44070266 README.webp_js: s/fastcomp/upstream/
2565fa8f README.webp_js: update cmake command
47309ef5 webp: WEBP_OFFSET_PTR()
687ab00e DC{4,8,16}_NEON: replace vmovl w/vaddl
1b92fe75 DC16_NEON,aarch64: use vaddlv
53f3d8cf dec_neon,DC8_NEON: use vaddlv instead of movl+vaddv
27d08240 Fix integer overflow in WebPAnimDecoderGetNext()
69776e38 Merge "remove call to MBAnalyzeBestIntra4Mode for method >= 5"
a99078c1 remove call to MBAnalyzeBestIntra4Mode for method >= 5
22e404cc CMakeLists.txt: fix set(CACHE) argument order
71690b52 fix MSVC warning
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)
7f006436 Makefile.vc: fix webp_quality.exe link 7f006436 Makefile.vc: fix webp_quality.exe link
cf047e83 Makefile.vc: fix webp_quality.exe link
c074c653 update NEWS c074c653 update NEWS
30f09551 bump version to 1.1.0 30f09551 bump version to 1.1.0
a76694a1 update AUTHORS a76694a1 update AUTHORS
@ -1560,7 +641,7 @@ b016cb91 NEON: faster fancy upsampling
f04eb376 Merge tag 'v0.5.2' f04eb376 Merge tag 'v0.5.2'
341d711c NEON: 5% faster conversion to RGB565 and RGBA4444 341d711c NEON: 5% faster conversion to RGB565 and RGBA4444
abb54827 remove Clang warnings with unused arch arguments. abb54827 remove Clang warnings with unused arch arguments.
ece9684f update ChangeLog (tag: v0.5.2-rc2, tag: v0.5.2) ece9684f update ChangeLog (tag: v0.5.2-rc2, tag: v0.5.2, origin/0.5.2)
aa7744ca anim_util: quiet implicit conv warnings in 32-bit aa7744ca anim_util: quiet implicit conv warnings in 32-bit
d9120271 jpegdec: correct ContextFill signature d9120271 jpegdec: correct ContextFill signature
24eb3940 Remove some errors when compiling the code as C++. 24eb3940 Remove some errors when compiling the code as C++.
@ -1847,7 +928,7 @@ bbb6ecd9 Merge "Add MSA optimized distortion functions"
c0991a14 io,EmitRescaledAlphaYUV: factor out a common expr c0991a14 io,EmitRescaledAlphaYUV: factor out a common expr
48bf5ed1 build.gradle: remove tab 48bf5ed1 build.gradle: remove tab
bfef6c9f Merge tag 'v0.5.1' bfef6c9f Merge tag 'v0.5.1'
3d97bb75 update ChangeLog (tag: v0.5.1) 3d97bb75 update ChangeLog (tag: v0.5.1, origin/0.5.1)
deb54d91 Clarify the expected 'config' lifespan in WebPIDecode() deb54d91 Clarify the expected 'config' lifespan in WebPIDecode()
435308e0 Add MSA optimized encoder transform functions 435308e0 Add MSA optimized encoder transform functions
dce64bfa Add MSA optimized alpha filter functions dce64bfa Add MSA optimized alpha filter functions

View File

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

View File

@ -5,15 +5,12 @@ LIBWEBPDECODER_BASENAME = libwebpdecoder
LIBWEBP_BASENAME = libwebp LIBWEBP_BASENAME = libwebp
LIBWEBPMUX_BASENAME = libwebpmux LIBWEBPMUX_BASENAME = libwebpmux
LIBWEBPDEMUX_BASENAME = libwebpdemux LIBWEBPDEMUX_BASENAME = libwebpdemux
LIBSHARPYUV_BASENAME = libsharpyuv
!IFNDEF ARCH !IFNDEF ARCH
!IF ! [ cl 2>&1 | find "x86" > NUL ] !IF ! [ cl 2>&1 | find "x86" > NUL ]
ARCH = x86 ARCH = x86
!ELSE IF ! [ cl 2>&1 | find "x64" > NUL ] !ELSE IF ! [ cl 2>&1 | find "x64" > NUL ]
ARCH = x64 ARCH = x64
!ELSE IF ! [ cl 2>&1 | find "ARM64" > NUL ]
ARCH = ARM64
!ELSE IF ! [ cl 2>&1 | find "ARM" > NUL ] !ELSE IF ! [ cl 2>&1 | find "ARM" > NUL ]
ARCH = ARM ARCH = ARM
!ELSE !ELSE
@ -31,14 +28,15 @@ PLATFORM_LDFLAGS = /SAFESEH
NOLOGO = /nologo NOLOGO = /nologo
CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG
CCDEBUG = cl.exe $(NOLOGO) /Od /Zi /D_DEBUG /RTC1 CCDEBUG = cl.exe $(NOLOGO) /Od /Gm /Zi /D_DEBUG /RTC1
CFLAGS = /I. /Isrc $(NOLOGO) /MP /W3 /EHsc /c CFLAGS = /I. /Isrc $(NOLOGO) /W3 /EHsc /c
CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST:EMBED /NXCOMPAT /DYNAMICBASE LDFLAGS = /LARGEADDRESSAWARE /MANIFEST /NXCOMPAT /DYNAMICBASE
LDFLAGS = $(LDFLAGS) $(PLATFORM_LDFLAGS) LDFLAGS = $(LDFLAGS) $(PLATFORM_LDFLAGS)
LNKDLL = link.exe /DLL $(NOLOGO) LNKDLL = link.exe /DLL $(NOLOGO)
LNKEXE = link.exe $(NOLOGO) LNKEXE = link.exe $(NOLOGO)
LNKLIB = lib.exe $(NOLOGO) LNKLIB = lib.exe $(NOLOGO)
MT = mt.exe $(NOLOGO)
RCNODBG = rc.exe $(NOLOGO) /l"0x0409" # 0x409 = U.S. English RCNODBG = rc.exe $(NOLOGO) /l"0x0409" # 0x409 = U.S. English
RCDEBUG = $(RCNODBG) /D_DEBUG RCDEBUG = $(RCNODBG) /D_DEBUG
@ -84,7 +82,6 @@ OUTPUT_DIRS = $(DIRBIN) $(DIRINC) $(DIRLIB) \
$(DIROBJ)\extras \ $(DIROBJ)\extras \
$(DIROBJ)\imageio \ $(DIROBJ)\imageio \
$(DIROBJ)\mux \ $(DIROBJ)\mux \
$(DIROBJ)\sharpyuv \
$(DIROBJ)\utils \ $(DIROBJ)\utils \
# Target configuration # Target configuration
@ -99,7 +96,6 @@ LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug
LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug
LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
LIBSHARPYUV_BASENAME = $(LIBSHARPYUV_BASENAME)_debug
!ELSE IF "$(CFG)" == "release-dynamic" !ELSE IF "$(CFG)" == "release-dynamic"
CC = $(CCNODBG) CC = $(CCNODBG)
RC = $(RCNODBG) RC = $(RCNODBG)
@ -113,7 +109,6 @@ LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug
LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug
LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
LIBSHARPYUV_BASENAME = $(LIBSHARPYUV_BASENAME)_debug
!ENDIF !ENDIF
!IF "$(STATICLIBBUILD)" == "TRUE" !IF "$(STATICLIBBUILD)" == "TRUE"
@ -123,14 +118,13 @@ LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME).lib
LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME).lib LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME).lib
LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME).lib LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME).lib
LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME).lib LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME).lib
LIBSHARPYUV = $(DIRLIB)\$(LIBSHARPYUV_BASENAME).lib
!ELSE IF "$(DLLBUILD)" == "TRUE" !ELSE IF "$(DLLBUILD)" == "TRUE"
CC = $(CC) /I$(DIROBJ) $(RTLIB) /DWEBP_DLL DLLINC = webp_dll.h
CC = $(CC) /I$(DIROBJ) /FI$(DLLINC) $(RTLIB) /DWEBP_DLL
LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME)_dll.lib LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME)_dll.lib
LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME)_dll.lib LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME)_dll.lib
LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME)_dll.lib LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME)_dll.lib
LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME)_dll.lib LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME)_dll.lib
LIBSHARPYUV = $(DIRLIB)\$(LIBSHARPYUV_BASENAME)_dll.lib
LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME)_dll.pdb LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME)_dll.pdb
CFGSET = TRUE CFGSET = TRUE
!ENDIF !ENDIF
@ -180,15 +174,6 @@ CFLAGS = $(CFLAGS) /D_UNICODE /DUNICODE
# A config was provided, so the library can be built. # A config was provided, so the library can be built.
# #
SHARPYUV_OBJS = \
$(DIROBJ)\sharpyuv\sharpyuv.obj \
$(DIROBJ)\sharpyuv\sharpyuv_cpu.obj \
$(DIROBJ)\sharpyuv\sharpyuv_csp.obj \
$(DIROBJ)\sharpyuv\sharpyuv_dsp.obj \
$(DIROBJ)\sharpyuv\sharpyuv_gamma.obj \
$(DIROBJ)\sharpyuv\sharpyuv_neon.obj \
$(DIROBJ)\sharpyuv\sharpyuv_sse2.obj \
DEC_OBJS = \ DEC_OBJS = \
$(DIROBJ)\dec\alpha_dec.obj \ $(DIROBJ)\dec\alpha_dec.obj \
$(DIROBJ)\dec\buffer_dec.obj \ $(DIROBJ)\dec\buffer_dec.obj \
@ -230,8 +215,6 @@ DSP_DEC_OBJS = \
$(DIROBJ)\dsp\lossless_msa.obj \ $(DIROBJ)\dsp\lossless_msa.obj \
$(DIROBJ)\dsp\lossless_neon.obj \ $(DIROBJ)\dsp\lossless_neon.obj \
$(DIROBJ)\dsp\lossless_sse2.obj \ $(DIROBJ)\dsp\lossless_sse2.obj \
$(DIROBJ)\dsp\lossless_sse41.obj \
$(DIROBJ)\dsp\lossless_avx2.obj \
$(DIROBJ)\dsp\rescaler.obj \ $(DIROBJ)\dsp\rescaler.obj \
$(DIROBJ)\dsp\rescaler_mips32.obj \ $(DIROBJ)\dsp\rescaler_mips32.obj \
$(DIROBJ)\dsp\rescaler_mips_dsp_r2.obj \ $(DIROBJ)\dsp\rescaler_mips_dsp_r2.obj \
@ -271,7 +254,6 @@ DSP_ENC_OBJS = \
$(DIROBJ)\dsp\lossless_enc_neon.obj \ $(DIROBJ)\dsp\lossless_enc_neon.obj \
$(DIROBJ)\dsp\lossless_enc_sse2.obj \ $(DIROBJ)\dsp\lossless_enc_sse2.obj \
$(DIROBJ)\dsp\lossless_enc_sse41.obj \ $(DIROBJ)\dsp\lossless_enc_sse41.obj \
$(DIROBJ)\dsp\lossless_enc_avx2.obj \
$(DIROBJ)\dsp\ssim.obj \ $(DIROBJ)\dsp\ssim.obj \
$(DIROBJ)\dsp\ssim_sse2.obj \ $(DIROBJ)\dsp\ssim_sse2.obj \
@ -325,7 +307,6 @@ ENC_OBJS = \
EXTRAS_OBJS = \ EXTRAS_OBJS = \
$(DIROBJ)\extras\extras.obj \ $(DIROBJ)\extras\extras.obj \
$(DIROBJ)\extras\quality_estimate.obj \ $(DIROBJ)\extras\quality_estimate.obj \
$(DIROBJ)\extras\sharpyuv_risk_table.obj \
IMAGEIO_UTIL_OBJS = \ IMAGEIO_UTIL_OBJS = \
$(DIROBJ)\imageio\imageio_util.obj \ $(DIROBJ)\imageio\imageio_util.obj \
@ -341,7 +322,6 @@ UTILS_DEC_OBJS = \
$(DIROBJ)\utils\color_cache_utils.obj \ $(DIROBJ)\utils\color_cache_utils.obj \
$(DIROBJ)\utils\filters_utils.obj \ $(DIROBJ)\utils\filters_utils.obj \
$(DIROBJ)\utils\huffman_utils.obj \ $(DIROBJ)\utils\huffman_utils.obj \
$(DIROBJ)\utils\palette.obj \
$(DIROBJ)\utils\quant_levels_dec_utils.obj \ $(DIROBJ)\utils\quant_levels_dec_utils.obj \
$(DIROBJ)\utils\rescaler_utils.obj \ $(DIROBJ)\utils\rescaler_utils.obj \
$(DIROBJ)\utils\random_utils.obj \ $(DIROBJ)\utils\random_utils.obj \
@ -354,13 +334,12 @@ UTILS_ENC_OBJS = \
$(DIROBJ)\utils\quant_levels_utils.obj \ $(DIROBJ)\utils\quant_levels_utils.obj \
LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS) LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) \ LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
$(DSP_ENC_OBJS) $(UTILS_ENC_OBJS) $(DLL_OBJS) $(UTILS_ENC_OBJS) $(DLL_OBJS)
LIBWEBPMUX_OBJS = $(MUX_OBJS) $(LIBWEBPMUX_OBJS) LIBWEBPMUX_OBJS = $(MUX_OBJS) $(LIBWEBPMUX_OBJS)
LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS) $(LIBWEBPDEMUX_OBJS) LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS) $(LIBWEBPDEMUX_OBJS)
LIBSHARPYUV_OBJS = $(SHARPYUV_OBJS)
OUT_LIBS = $(LIBWEBPDECODER) $(LIBWEBP) $(LIBSHARPYUV) OUT_LIBS = $(LIBWEBPDECODER) $(LIBWEBP)
!IF "$(ARCH)" == "ARM" !IF "$(ARCH)" == "ARM"
ex: $(OUT_LIBS) ex: $(OUT_LIBS)
all: ex all: ex
@ -388,14 +367,14 @@ $(DIRBIN)\anim_dump.exe: $(EX_GIF_DEC_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\anim_dump.exe: $(IMAGEIO_ENC_OBJS) $(DIRBIN)\anim_dump.exe: $(IMAGEIO_ENC_OBJS)
$(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj $(IMAGEIO_DEC_OBJS) $(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj $(IMAGEIO_DEC_OBJS)
$(DIRBIN)\cwebp.exe: $(IMAGEIO_UTIL_OBJS) $(DIRBIN)\cwebp.exe: $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\cwebp.exe: $(LIBWEBPDEMUX) $(LIBSHARPYUV) $(DIRBIN)\cwebp.exe: $(LIBWEBPDEMUX)
$(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj $(IMAGEIO_DEC_OBJS) $(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj $(IMAGEIO_DEC_OBJS)
$(DIRBIN)\dwebp.exe: $(IMAGEIO_ENC_OBJS) $(DIRBIN)\dwebp.exe: $(IMAGEIO_ENC_OBJS)
$(DIRBIN)\dwebp.exe: $(IMAGEIO_UTIL_OBJS) $(DIRBIN)\dwebp.exe: $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\dwebp.exe: $(LIBWEBPDEMUX) $(DIRBIN)\dwebp.exe: $(LIBWEBPDEMUX)
$(DIRBIN)\gif2webp.exe: $(DIROBJ)\examples\gif2webp.obj $(EX_GIF_DEC_OBJS) $(DIRBIN)\gif2webp.exe: $(DIROBJ)\examples\gif2webp.obj $(EX_GIF_DEC_OBJS)
$(DIRBIN)\gif2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBPMUX) $(DIRBIN)\gif2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBPMUX)
$(DIRBIN)\gif2webp.exe: $(LIBWEBP) $(LIBSHARPYUV) $(DIRBIN)\gif2webp.exe: $(LIBWEBP)
$(DIRBIN)\vwebp.exe: $(DIROBJ)\examples\vwebp.obj $(EX_UTIL_OBJS) $(DIRBIN)\vwebp.exe: $(DIROBJ)\examples\vwebp.obj $(EX_UTIL_OBJS)
$(DIRBIN)\vwebp.exe: $(IMAGEIO_UTIL_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP) $(DIRBIN)\vwebp.exe: $(IMAGEIO_UTIL_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\vwebp_sdl.exe: $(DIROBJ)\extras\vwebp_sdl.obj $(DIRBIN)\vwebp_sdl.exe: $(DIROBJ)\extras\vwebp_sdl.obj
@ -406,7 +385,7 @@ $(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP)
$(DIRBIN)\img2webp.exe: $(DIROBJ)\examples\img2webp.obj $(LIBWEBPMUX) $(DIRBIN)\img2webp.exe: $(DIROBJ)\examples\img2webp.obj $(LIBWEBPMUX)
$(DIRBIN)\img2webp.exe: $(IMAGEIO_DEC_OBJS) $(DIRBIN)\img2webp.exe: $(IMAGEIO_DEC_OBJS)
$(DIRBIN)\img2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(DIRBIN)\img2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\img2webp.exe: $(LIBWEBPDEMUX) $(LIBWEBP) $(LIBSHARPYUV) $(DIRBIN)\img2webp.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\get_disto.exe: $(DIROBJ)\extras\get_disto.obj $(DIRBIN)\get_disto.exe: $(DIROBJ)\extras\get_disto.obj
$(DIRBIN)\get_disto.exe: $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS) $(DIRBIN)\get_disto.exe: $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\get_disto.exe: $(LIBWEBPDEMUX) $(LIBWEBP) $(DIRBIN)\get_disto.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
@ -429,16 +408,17 @@ $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS): $(OUTPUT_DIRS)
$(IMAGEIO_DEC_OBJS) $(IMAGEIO_ENC_OBJS) $(EXTRAS_OBJS): $(OUTPUT_DIRS) $(IMAGEIO_DEC_OBJS) $(IMAGEIO_ENC_OBJS) $(EXTRAS_OBJS): $(OUTPUT_DIRS)
!ENDIF # ARCH == ARM !ENDIF # ARCH == ARM
$(LIBSHARPYUV): $(LIBSHARPYUV_OBJS)
$(LIBWEBPDECODER): $(LIBWEBPDECODER_OBJS) $(LIBWEBPDECODER): $(LIBWEBPDECODER_OBJS)
$(LIBWEBP): $(LIBWEBP_OBJS) $(LIBSHARPYUV) $(LIBWEBP): $(LIBWEBP_OBJS)
$(LIBWEBPMUX): $(LIBWEBPMUX_OBJS) $(LIBWEBPMUX): $(LIBWEBPMUX_OBJS)
$(LIBWEBPDEMUX): $(LIBWEBPDEMUX_OBJS) $(LIBWEBPDEMUX): $(LIBWEBPDEMUX_OBJS)
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS) $(LIBSHARPYUV_OBJS): \ $(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): $(OUTPUT_DIRS)
$(OUTPUT_DIRS)
!IF "$(DLLBUILD)" == "TRUE" !IF "$(DLLBUILD)" == "TRUE"
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): \
$(DIROBJ)\$(DLLINC)
{$(DIROBJ)}.c{$(DIROBJ)}.obj: {$(DIROBJ)}.c{$(DIROBJ)}.obj:
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$@ $< $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$@ $<
@ -448,20 +428,20 @@ $(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS) $(LIBSHARPYUV_OBJS): \
$(RC) /fo$@ $< $(RC) /fo$@ $<
{src\mux}.rc{$(DIROBJ)\mux}.res: {src\mux}.rc{$(DIROBJ)\mux}.res:
$(RC) /fo$@ $< $(RC) /fo$@ $<
{sharpyuv}.rc{$(DIROBJ)\sharpyuv}.res:
$(RC) /fo$@ $<
$(LIBSHARPYUV): $(DIROBJ)\sharpyuv\$(LIBSHARPYUV_BASENAME:_debug=).res $(LIBWEBP): $(DIROBJ)\$(LIBWEBP_BASENAME:_debug=).res
$(LIBWEBP): $(LIBSHARPYUV) $(DIROBJ)\$(LIBWEBP_BASENAME:_debug=).res
$(LIBWEBPDECODER): $(DIROBJ)\$(LIBWEBPDECODER_BASENAME:_debug=).res $(LIBWEBPDECODER): $(DIROBJ)\$(LIBWEBPDECODER_BASENAME:_debug=).res
$(LIBWEBPMUX): $(LIBWEBP) $(DIROBJ)\mux\$(LIBWEBPMUX_BASENAME:_debug=).res $(LIBWEBPMUX): $(LIBWEBP) $(DIROBJ)\mux\$(LIBWEBPMUX_BASENAME:_debug=).res
$(LIBWEBPDEMUX): $(LIBWEBP) $(DIROBJ)\demux\$(LIBWEBPDEMUX_BASENAME:_debug=).res $(LIBWEBPDEMUX): $(LIBWEBP) $(DIROBJ)\demux\$(LIBWEBPDEMUX_BASENAME:_debug=).res
$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX) $(LIBSHARPYUV): $(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
$(LNKDLL) /out:$(DIRBIN)\$(@B:_dll=.dll) /implib:$@ $(LFLAGS) $** $(LNKDLL) /out:$(DIRBIN)\$(@B:_dll=.dll) /implib:$@ $(LFLAGS) $**
-xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y -xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y
clean::
@-erase /s $(DIROBJ)\$(DLLINC) 2> NUL
!ELSE !ELSE
$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX) $(LIBSHARPYUV): $(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
$(LNKLIB) /out:$@ $** $(LNKLIB) /out:$@ $**
-xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y -xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y
!ENDIF !ENDIF
@ -469,6 +449,13 @@ $(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX) $(LIBSHARPYUV):
$(OUTPUT_DIRS): $(OUTPUT_DIRS):
@if not exist "$(@)" mkdir "$(@)" @if not exist "$(@)" mkdir "$(@)"
# generate a helper include to define WEBP_EXTERN suitable for the DLL build
$(DIROBJ)\$(DLLINC):
@echo #ifndef WEBP_DLL_H_ > $@
@echo #define WEBP_DLL_H_ >> $@
@echo #define WEBP_EXTERN __declspec(dllexport) >> $@
@echo #endif /* WEBP_DLL_H_ */ >> $@
.SUFFIXES: .c .obj .res .exe .SUFFIXES: .c .obj .res .exe
# File-specific flag builds. Note batch rules take precedence over wildcards, # File-specific flag builds. Note batch rules take precedence over wildcards,
# so for now name each file individually. # so for now name each file individually.
@ -494,8 +481,6 @@ $(DIROBJ)\examples\gifdec.obj: examples\gifdec.c
$(CC) $(CFLAGS) /Fd$(DIROBJ)\extras\ /Fo$(DIROBJ)\extras\ $< $(CC) $(CFLAGS) /Fd$(DIROBJ)\extras\ /Fo$(DIROBJ)\extras\ $<
{imageio}.c{$(DIROBJ)\imageio}.obj:: {imageio}.c{$(DIROBJ)\imageio}.obj::
$(CC) $(CFLAGS) /Fd$(DIROBJ)\imageio\ /Fo$(DIROBJ)\imageio\ $< $(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:: {src\dec}.c{$(DIROBJ)\dec}.obj::
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dec\ $< $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dec\ $<
{src\demux}.c{$(DIROBJ)\demux}.obj:: {src\demux}.c{$(DIROBJ)\demux}.obj::
@ -516,9 +501,13 @@ LNKLIBS = $(LNKLIBS) Shell32.lib
{$(DIROBJ)\examples}.obj{$(DIRBIN)}.exe: {$(DIROBJ)\examples}.obj{$(DIRBIN)}.exe:
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS) $(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS)
$(MT) -manifest $@.manifest -outputresource:$@;1
del $@.manifest
{$(DIROBJ)\extras}.obj{$(DIRBIN)}.exe: {$(DIROBJ)\extras}.obj{$(DIRBIN)}.exe:
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS) $(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS)
$(MT) -manifest $@.manifest -outputresource:$@;1
del $@.manifest
clean:: clean::
@-erase /s $(DIROBJ)\*.dll 2> NUL @-erase /s $(DIROBJ)\*.dll 2> NUL

123
NEWS
View File

@ -1,126 +1,3 @@
- 6/30/2025 version 1.6.0
This is a binary compatible release.
API changes:
- libwebp: WebPValidateDecoderConfig
* additional x86 (AVX2, SSE2), general optimizations and compression
improvements for lossless
* `-mt` returns same results as single-threaded lossless (regressed in
1.5.0, #426506716)
* miscellaneous warning, bug & build fixes (#393104377, #397130631,
#398288323, #398066379, #427503509)
Tool updates:
* cwebp can restrict the use of `-resize` with `-resize_mode` (#405437935)
- 12/19/2024 version 1.5.0
This is a binary compatible release.
API changes:
- `cross_color_transform_bits` added to WebPAuxStats
* minor lossless encoder speed and compression improvements
* lossless encoding does not use floats anymore
* additional Arm optimizations for lossy & lossless + general code generation
improvements
* improvements to WASM performance (#643)
* improvements and corrections in webp-container-spec.txt and
webp-lossless-bitstream-spec.txt (#646, #355607636)
* further security related hardening and increased fuzzing coverage w/fuzztest
(oss-fuzz: #382816119, #70112, #70102, #69873, #69825, #69508, #69208)
* miscellaneous warning, bug & build fixes (#499, #562, #381372617,
#381109771, #42340561, #375011696, #372109644, chromium: #334120888)
Tool updates:
* gif2webp: add -sharp_yuv & -near_lossless
* img2webp: add -exact & -noexact
* exit codes normalized; running an example program with no
arguments will output its help and exit with an error (#42340557,
#381372617)
- 4/12/2024: version 1.4.0
This is a binary compatible release.
* API changes:
- libwebpmux: WebPAnimEncoderSetChunk, WebPAnimEncoderGetChunk,
WebPAnimEncoderDeleteChunk
- libsharpyuv: SharpYuvOptionsInit, SharpYuvConvertWithOptions
- extras: SharpYuvEstimate420Risk
* further security related hardening in libwebp & examples
* some minor optimizations in the lossless encoder
* added WEBP_NODISCARD to report unused result warnings; enable with
-DWEBP_ENABLE_NODISCARD=1
* improvements and corrections in webp-container-spec.txt and
webp-lossless-bitstream-spec.txt (#611)
* miscellaneous warning, bug & build fixes (#615, #619, #632, #635)
- 9/13/2023: version 1.3.2
This is a binary compatible release.
* security fix for lossless decoder (chromium: #1479274, CVE-2023-4863)
- 6/23/2023: version 1.3.1
This is a binary compatible release.
* security fixes for lossless encoder (#603, chromium: #1420107, #1455619,
CVE-2023-1999)
* improve error reporting through WebPPicture error codes
* fix upsampling for RGB565 and RGBA4444 in NEON builds
* img2webp: add -sharp_yuv & -near_lossless
* Windows builds:
- fix compatibility with clang-cl (#607)
- improve Arm64 performance with cl.exe
- add Arm64EC support
* fix webp_js with emcc >= 3.1.27 (stack size change, #614)
* CMake fixes (#592, #610, #612)
* further updates to the container and lossless bitstream docs (#581, #611)
- 12/16/2022: version 1.3.0
This is a binary compatible release.
* add libsharpyuv, which exposes -sharp_yuv/config.use_sharp_yuv
functionality to other libraries; libwebp now depends on this library
* major updates to the container and lossless bitstream docs (#448, #546,
#551)
* miscellaneous warning, bug & build fixes (#576, #583, #584)
- 8/4/2022: version 1.2.4
This is a binary compatible release.
* restore CMake libwebpmux target name for compatibility with 1.2.2 (#575)
* fix lossless crunch mode encoding with WEBP_REDUCE_SIZE
(chromium: #1345547, #1345595, #1345772, #1345804)
- 6/30/2022: version 1.2.3
This is a binary compatible release.
* security fix for lossless encoder (#565, chromium:1313709)
* improved progress granularity in WebPReportProgress() when using lossless
* improved precision in Sharp YUV (-sharp_yuv) conversion
* many corrections to webp-lossless-bitstream-spec.txt (#551)
* crash/leak fixes on error/OOM and other bug fixes (#558, #563, #569, #573)
- 1/11/2022: version 1.2.2
This is a binary compatible release.
* webpmux: add "-set bgcolor A,R,G,B"
* 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
* add ARM64 simulator support to xcframeworkbuild.sh (#510)
* further security related hardening in libwebp & examples
(issues: #497, #508, #518)
(chromium: #1196480, #1196773, #1196775, #1196777, #1196778, #1196850)
(oss-fuzz: #28658, #28978)
* toolchain updates and bug fixes (#498, #501, #502, #504, #505, #506, #509,
#533)
* use more inclusive language within the source (#507)
- 12/23/2020: version 1.2.0
* API changes:
- libwebp:
encode.h: add a qmin / qmax range for quality factor (cwebp adds -qrange)
* lossless encoder improvements
* SIMD support for Wasm builds
* add xcframeworkbuild.sh, supports Mac Catalyst builds
* import fuzzers from oss-fuzz & chromium (#409)
* webpmux: add an '-set loop <value>' option (#494)
* toolchain updates and bug fixes (#449, #463, #470, #475, #477, #478, #479,
#488, #491)
- 12/18/2019: version 1.1.0 - 12/18/2019: version 1.1.0
* API changes: * API changes:
- libwebp: - libwebp:

View File

@ -1,245 +0,0 @@
# 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

789
README Normal file
View File

@ -0,0 +1,789 @@
__ __ ____ ____ ____
/ \\/ \/ _ \/ _ )/ _ \
\ / __/ _ \ __/
\__\__/\____/\_____/__/ ____ ___
/ _/ / \ \ / _ \/ _/
/ \_/ / / \ \ __/ \__
\____/____/\_____/_____/____/v1.1.0
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, gif2web, 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.
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)
-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]
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 (!WebPPictureAllocate(&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

View File

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

256
README.mux Normal file
View File

@ -0,0 +1,256 @@
 __ __ ____ ____ ____ __ __ _ __ __
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
\ / __/ _ \ __/ / / (_/ /__
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v1.1.0
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:
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

80
README.webp_js Normal file
View File

@ -0,0 +1,80 @@
__ __ ____ ____ ____ __ ____
/ \\/ \ _ \ _ \ _ \ (__)/ __\
\ / __/ _ \ __/ _) \_ \
\__\__/_____/____/_/ /____/____/
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://kripken.github.io/emscripten-site/docs/getting_started/downloads.html
After installation, you should have some global variable positioned to the
location of the SDK. In particular, $EMSCRIPTEN should point to the
top-level directory containing Emscripten tools.
- make sure the file $EMSCRIPTEN/cmake/Modules/Platform/Emscripten.cmake is
accessible. This is the toolchain file used by CMake to invoke Emscripten.
If $EMSCRIPTEN is unset search for Emscripten.cmake under $EMSDK and set
$EMSCRIPTEN accordingly, for example:
unix-like environments: export EMSCRIPTEN=$EMSDK/fastcomp/emscripten
windows: set EMSCRIPTEN=%EMSDK%\fastcomp\emscripten
- configure the project 'WEBP_JS' with CMake using:
cd webp_js && \
cmake -DWEBP_BUILD_WEBP_JS=ON \
-DEMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES=1 \
-DCMAKE_TOOLCHAIN_FILE=$EMSCRIPTEN/cmake/Modules/Platform/Emscripten.cmake \
../
- compile webp.js using 'make'.
- that's it! Upon completion, you should have the webp.js and
webp.js.mem 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 1.37.8) and of
your WASM-enabled browser to run this version. Consider it very experimental!
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.

View File

@ -105,14 +105,6 @@ model {
sources { sources {
c { c {
source { source {
srcDir "sharpyuv"
include "sharpyuv.c"
include "sharpyuv_cpu.c"
include "sharpyuv_csp.c"
include "sharpyuv_dsp.c"
include "sharpyuv_gamma.c"
include "sharpyuv_neon.c"
include "sharpyuv_sse2.c"
srcDir "src/dec" srcDir "src/dec"
include "alpha_dec.c" include "alpha_dec.c"
include "buffer_dec.c" include "buffer_dec.c"
@ -149,7 +141,6 @@ model {
include "lossless_msa.c" include "lossless_msa.c"
include "lossless_neon.$NEON" include "lossless_neon.$NEON"
include "lossless_sse2.c" include "lossless_sse2.c"
include "lossless_sse41.c"
include "rescaler.c" include "rescaler.c"
include "rescaler_mips32.c" include "rescaler_mips32.c"
include "rescaler_mips_dsp_r2.c" include "rescaler_mips_dsp_r2.c"
@ -173,7 +164,6 @@ model {
include "color_cache_utils.c" include "color_cache_utils.c"
include "filters_utils.c" include "filters_utils.c"
include "huffman_utils.c" include "huffman_utils.c"
include "palette.c"
include "quant_levels_dec_utils.c" include "quant_levels_dec_utils.c"
include "random_utils.c" include "random_utils.c"
include "rescaler_utils.c" include "rescaler_utils.c"
@ -442,3 +432,8 @@ model {
} }
} }
} }
// Task to generate the wrapper.
task wrapper(type: Wrapper) {
gradleVersion = '2.13'
}

View File

@ -3,17 +3,9 @@ set(WEBP_VERSION ${WebP_VERSION})
@PACKAGE_INIT@ @PACKAGE_INIT@
if(@WEBP_USE_THREAD@) include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
include(CMakeFindDependencyMacro)
find_dependency(Threads REQUIRED)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") set(WebP_INCLUDE_DIRS "webp")
set(WEBP_INCLUDE_DIRS ${WebP_INCLUDE_DIRS})
set_and_check(WebP_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
set(WebP_INCLUDE_DIRS ${WebP_INCLUDE_DIR})
set(WEBP_INCLUDE_DIRS ${WebP_INCLUDE_DIR})
set(WebP_LIBRARIES "@INSTALLED_LIBRARIES@") set(WebP_LIBRARIES "@INSTALLED_LIBRARIES@")
set(WEBP_LIBRARIES "${WebP_LIBRARIES}") set(WEBP_LIBRARIES "${WebP_LIBRARIES}")
check_required_components(WebP)

View File

@ -16,18 +16,48 @@
/* Define to 1 if you have the <cpu-features.h> header file. */ /* Define to 1 if you have the <cpu-features.h> header file. */
#cmakedefine HAVE_CPU_FEATURES_H 1 #cmakedefine HAVE_CPU_FEATURES_H 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H 1
/* Define to 1 if you have the <GLUT/glut.h> header file. */ /* Define to 1 if you have the <GLUT/glut.h> header file. */
#cmakedefine HAVE_GLUT_GLUT_H 1 #cmakedefine HAVE_GLUT_GLUT_H 1
/* Define to 1 if you have the <GL/glut.h> header file. */ /* Define to 1 if you have the <GL/glut.h> header file. */
#cmakedefine HAVE_GL_GLUT_H 1 #cmakedefine HAVE_GL_GLUT_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H 1
/* Define to 1 if you have the <OpenGL/glut.h> header file. */ /* Define to 1 if you have the <OpenGL/glut.h> header file. */
#cmakedefine HAVE_OPENGL_GLUT_H 1 #cmakedefine HAVE_OPENGL_GLUT_H 1
/* Have PTHREAD_PRIO_INHERIT. */
#cmakedefine HAVE_PTHREAD_PRIO_INHERIT @HAVE_PTHREAD_PRIO_INHERIT@
/* Define to 1 if you have the <shlwapi.h> header file. */ /* Define to 1 if you have the <shlwapi.h> header file. */
#cmakedefine HAVE_SHLWAPI_H 1 #cmakedefine HAVE_SHLWAPI_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1 #cmakedefine HAVE_UNISTD_H 1
@ -63,6 +93,13 @@
/* Define to the version of this package. */ /* Define to the version of this package. */
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@" #cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
#cmakedefine PTHREAD_CREATE_JOINABLE 1
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS 1
/* Version number of package */ /* Version number of package */
#cmakedefine VERSION "@VERSION@" #cmakedefine VERSION "@VERSION@"
@ -94,9 +131,6 @@
/* Set to 1 if SSE4.1 is supported */ /* Set to 1 if SSE4.1 is supported */
#cmakedefine WEBP_HAVE_SSE41 1 #cmakedefine WEBP_HAVE_SSE41 1
/* Set to 1 if AVX2 is supported */
#cmakedefine WEBP_HAVE_AVX2 1
/* Set to 1 if TIFF library is installed */ /* Set to 1 if TIFF library is installed */
#cmakedefine WEBP_HAVE_TIFF 1 #cmakedefine WEBP_HAVE_TIFF 1

View File

@ -1,11 +1,3 @@
# Copyright (c) 2021 Google LLC.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
# Check for SIMD extensions. # Check for SIMD extensions.
include(CMakePushCheckState) include(CMakePushCheckState)
@ -18,8 +10,7 @@ function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
unset(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG} CACHE) unset(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG} CACHE)
cmake_push_check_state() cmake_push_check_state()
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}) set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
check_c_source_compiles( check_c_source_compiles("
"
#include \"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/dsp.h\" #include \"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/dsp.h\"
int main(void) { int main(void) {
#if !defined(WEBP_USE_${WEBP_SIMD_FLAG}) #if !defined(WEBP_USE_${WEBP_SIMD_FLAG})
@ -27,8 +18,7 @@ function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
#endif #endif
return 0; return 0;
} }
" " WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG})
WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG})
cmake_pop_check_state() cmake_pop_check_state()
if(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG}) if(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG})
set(WEBP_HAVE_${WEBP_SIMD_FLAG} 1 PARENT_SCOPE) set(WEBP_HAVE_${WEBP_SIMD_FLAG} 1 PARENT_SCOPE)
@ -38,30 +28,25 @@ function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
endfunction() endfunction()
# those are included in the names of WEBP_USE_* in c++ code. # those are included in the names of WEBP_USE_* in c++ code.
set(WEBP_SIMD_FLAGS "AVX2;SSE41;SSE2;MIPS32;MIPS_DSP_R2;NEON;MSA") set(WEBP_SIMD_FLAGS "SSE41;SSE2;MIPS32;MIPS_DSP_R2;NEON;MSA")
set(WEBP_SIMD_FILE_EXTENSIONS set(WEBP_SIMD_FILE_EXTENSIONS
"_avx2.c;_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c") "_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c")
if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC") if(MSVC)
# With at least Visual Studio 12 (2013)+ /arch is not necessary to build SSE2 # MSVC does not have a SSE4 flag but AVX support implies SSE4 support.
# or SSE4 code unless a lesser /arch is forced. MSVC does not have a SSE4 set(SIMD_ENABLE_FLAGS "/arch:AVX;/arch:SSE2;;;;")
# flag, but an AVX one. Using that with SSE4 code risks generating illegal
# instructions when used on machines with SSE4 only. The flags are left for
# older (untested) versions to avoid any potential compatibility issues.
if(MSVC_VERSION GREATER_EQUAL 1800 AND NOT CMAKE_C_FLAGS MATCHES "/arch:")
set(SIMD_ENABLE_FLAGS)
else()
set(SIMD_ENABLE_FLAGS "/arch:AVX2;/arch:AVX;/arch:SSE2;;;;")
endif()
set(SIMD_DISABLE_FLAGS) set(SIMD_DISABLE_FLAGS)
else() else()
set(SIMD_ENABLE_FLAGS "-mavx2;-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa") set(SIMD_ENABLE_FLAGS
set(SIMD_DISABLE_FLAGS "-mno-avx2;-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa") "-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa")
set(SIMD_DISABLE_FLAGS
"-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa")
endif() endif()
set(WEBP_SIMD_FILES_TO_NOT_INCLUDE)
set(WEBP_SIMD_FILES_TO_INCLUDE) set(WEBP_SIMD_FILES_TO_INCLUDE)
set(WEBP_SIMD_FLAGS_TO_INCLUDE) set(WEBP_SIMD_FLAGS_TO_INCLUDE)
if(ANDROID AND ANDROID_ABI) if(${ANDROID})
if(${ANDROID_ABI} STREQUAL "armeabi-v7a") if(${ANDROID_ABI} STREQUAL "armeabi-v7a")
# This is because Android studio uses the configuration "-march=armv7-a # This is because Android studio uses the configuration "-march=armv7-a
# -mfloat-abi=softfp -mfpu=vfpv3-d16" that does not trigger neon # -mfloat-abi=softfp -mfpu=vfpv3-d16" that does not trigger neon
@ -72,14 +57,9 @@ endif()
list(LENGTH WEBP_SIMD_FLAGS WEBP_SIMD_FLAGS_LENGTH) list(LENGTH WEBP_SIMD_FLAGS WEBP_SIMD_FLAGS_LENGTH)
math(EXPR WEBP_SIMD_FLAGS_RANGE "${WEBP_SIMD_FLAGS_LENGTH} - 1") math(EXPR WEBP_SIMD_FLAGS_RANGE "${WEBP_SIMD_FLAGS_LENGTH} - 1")
unset(HIGHEST_SSE_FLAG)
foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE}) foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
# With Emscripten 2.0.9 -msimd128 -mfpu=neon will enable NEON, but the source
# will fail to compile.
if(EMSCRIPTEN AND ${I_SIMD} GREATER_EQUAL 2)
break()
endif()
list(GET WEBP_SIMD_FLAGS ${I_SIMD} WEBP_SIMD_FLAG) list(GET WEBP_SIMD_FLAGS ${I_SIMD} WEBP_SIMD_FLAG)
# First try with no extra flag added as the compiler might have default flags # First try with no extra flag added as the compiler might have default flags
@ -90,15 +70,10 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD}) webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD})
if(NOT WEBP_HAVE_${WEBP_SIMD_FLAG}) if(NOT WEBP_HAVE_${WEBP_SIMD_FLAG})
list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
if(EMSCRIPTEN)
set(SIMD_COMPILE_FLAG "-msimd128 ${SIMD_COMPILE_FLAG}")
endif()
set(CMAKE_REQUIRED_FLAGS ${SIMD_COMPILE_FLAG}) set(CMAKE_REQUIRED_FLAGS ${SIMD_COMPILE_FLAG})
webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD}) webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD})
else() else()
if(MSVC AND SIMD_ENABLE_FLAGS) if(MSVC)
# The detection for SSE2/SSE4 support under MSVC is based on the compiler
# version so e.g., clang-cl will require flags to enable the assembly.
list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
else() else()
set(SIMD_COMPILE_FLAG " ") set(SIMD_COMPILE_FLAG " ")
@ -106,14 +81,20 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
endif() endif()
# Check which files we should include or not. # Check which files we should include or not.
list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION) list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION)
file(GLOB SIMD_FILES file(GLOB SIMD_FILES "${CMAKE_CURRENT_LIST_DIR}/../"
"${CMAKE_CURRENT_LIST_DIR}/../sharpyuv/*${WEBP_SIMD_FILE_EXTENSION}" "src/dsp/*${WEBP_SIMD_FILE_EXTENSION}")
"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/*${WEBP_SIMD_FILE_EXTENSION}")
if(WEBP_HAVE_${WEBP_SIMD_FLAG}) if(WEBP_HAVE_${WEBP_SIMD_FLAG})
if(${I_SIMD} LESS 2 AND NOT HIGHEST_SSE_FLAG)
set(HIGHEST_SSE_FLAG ${SIMD_COMPILE_FLAG})
endif()
# Memorize the file and flags. # Memorize the file and flags.
foreach(FILE ${SIMD_FILES}) foreach(FILE ${SIMD_FILES})
list(APPEND WEBP_SIMD_FILES_TO_INCLUDE ${FILE}) list(APPEND WEBP_SIMD_FILES_TO_INCLUDE ${FILE})
list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${SIMD_COMPILE_FLAG}) if(${I_SIMD} LESS 2)
list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${HIGHEST_SSE_FLAG})
else()
list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${SIMD_COMPILE_FLAG})
endif()
endforeach() endforeach()
else() else()
# Remove the file from the list. # Remove the file from the list.
@ -125,12 +106,6 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
list(GET SIMD_DISABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) list(GET SIMD_DISABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
include(CheckCCompilerFlag) include(CheckCCompilerFlag)
if(SIMD_COMPILE_FLAG) if(SIMD_COMPILE_FLAG)
# Between 3.17.0 and 3.18.2 check_cxx_compiler_flag() sets a normal
# variable at parent scope while check_cxx_source_compiles() continues
# to set an internal cache variable, so we unset both to avoid the
# failure / success state persisting between checks. See
# https://gitlab.kitware.com/cmake/cmake/-/issues/21207.
unset(HAS_COMPILE_FLAG)
unset(HAS_COMPILE_FLAG CACHE) unset(HAS_COMPILE_FLAG CACHE)
check_c_compiler_flag(${SIMD_COMPILE_FLAG} HAS_COMPILE_FLAG) check_c_compiler_flag(${SIMD_COMPILE_FLAG} HAS_COMPILE_FLAG)
if(HAS_COMPILE_FLAG) if(HAS_COMPILE_FLAG)
@ -142,11 +117,12 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
set(COMMON_PATTERNS) set(COMMON_PATTERNS)
endif() endif()
set(CMAKE_REQUIRED_DEFINITIONS ${SIMD_COMPILE_FLAG}) set(CMAKE_REQUIRED_DEFINITIONS ${SIMD_COMPILE_FLAG})
check_c_source_compiles( check_c_source_compiles("int main(void) {return 0;}"
"int main(void) {return 0;}" FLAG_${SIMD_COMPILE_FLAG} FAIL_REGEX FLAG_${SIMD_COMPILE_FLAG}
"warning: argument unused during compilation:" ${COMMON_PATTERNS}) FAIL_REGEX
"warning: argument unused during compilation:"
${COMMON_PATTERNS})
if(NOT FLAG_${SIMD_COMPILE_FLAG}) if(NOT FLAG_${SIMD_COMPILE_FLAG})
unset(HAS_COMPILE_FLAG)
unset(HAS_COMPILE_FLAG CACHE) unset(HAS_COMPILE_FLAG CACHE)
endif() endif()
endif() endif()

View File

@ -1,52 +1,44 @@
# Copyright (c) 2021 Google LLC.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
# Generate the config.h to compile with specific intrinsics / libs. # Generate the config.h to compile with specific intrinsics / libs.
# Check for compiler options. # Check for compiler options.
include(CheckCSourceCompiles) include(CheckCSourceCompiles)
check_c_source_compiles( check_c_source_compiles("
"
int main(void) { int main(void) {
(void)__builtin_bswap16(0); (void)__builtin_bswap16(0);
return 0; return 0;
} }
" " HAVE_BUILTIN_BSWAP16)
HAVE_BUILTIN_BSWAP16) check_c_source_compiles("
check_c_source_compiles(
"
int main(void) { int main(void) {
(void)__builtin_bswap32(0); (void)__builtin_bswap32(0);
return 0; return 0;
} }
" " HAVE_BUILTIN_BSWAP32)
HAVE_BUILTIN_BSWAP32) check_c_source_compiles("
check_c_source_compiles(
"
int main(void) { int main(void) {
(void)__builtin_bswap64(0); (void)__builtin_bswap64(0);
return 0; return 0;
} }
" " HAVE_BUILTIN_BSWAP64)
HAVE_BUILTIN_BSWAP64)
# Check for libraries. # Check for libraries.
if(WEBP_USE_THREAD) find_package(Threads)
find_package(Threads) if(Threads_FOUND)
if(Threads_FOUND) if(CMAKE_USE_PTHREADS_INIT)
# work around cmake bug on QNX (https://cmake.org/Bug/view.php?id=11333) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
if(CMAKE_USE_PTHREADS_INIT AND NOT CMAKE_SYSTEM_NAME STREQUAL "QNX")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
endif()
list(APPEND WEBP_DEP_LIBRARIES Threads::Threads)
endif() endif()
set(WEBP_USE_THREAD ${Threads_FOUND}) foreach(PTHREAD_TEST HAVE_PTHREAD_PRIO_INHERIT PTHREAD_CREATE_UNDETACHED)
check_c_source_compiles("
#include <pthread.h>
int main (void) {
int attr = ${PTHREAD_TEST};
return attr;
}
" ${PTHREAD_TEST})
endforeach()
list(APPEND WEBP_DEP_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
endif() endif()
set(WEBP_USE_THREAD ${Threads_FOUND})
# TODO: this seems unused, check with autotools. # TODO: this seems unused, check with autotools.
set(LT_OBJDIR ".libs/") set(LT_OBJDIR ".libs/")
@ -57,88 +49,89 @@ set(WEBP_HAVE_GL ${OPENGL_FOUND})
# Check if we need to link to the C math library. We do not look for it as it is # Check if we need to link to the C math library. We do not look for it as it is
# not found when cross-compiling, while it is here. # not found when cross-compiling, while it is here.
check_c_source_compiles( check_c_source_compiles("
"
#include <math.h> #include <math.h>
int main(int argc, char** argv) { int main(int argc, char** argv) {
return (int)pow(argc, 2.5); return (int)pow(argc, 2.5);
} }
" " HAVE_MATH_LIBRARY)
HAVE_MATH_LIBRARY)
if(NOT HAVE_MATH_LIBRARY) if(NOT HAVE_MATH_LIBRARY)
message(STATUS "Adding -lm flag.") message(STATUS "Adding -lm flag.")
list(APPEND SHARPYUV_DEP_LIBRARIES m)
list(APPEND WEBP_DEP_LIBRARIES m) list(APPEND WEBP_DEP_LIBRARIES m)
endif() endif()
# Find the standard image libraries. # Find the standard image libraries.
set(WEBP_DEP_IMG_LIBRARIES) set(WEBP_DEP_IMG_LIBRARIES)
set(WEBP_DEP_IMG_INCLUDE_DIRS) set(WEBP_DEP_IMG_INCLUDE_DIRS)
if(WEBP_FIND_IMG_LIBS) foreach(I_LIB PNG JPEG TIFF)
foreach(I_LIB PNG JPEG TIFF) find_package(${I_LIB})
# Disable tiff when compiling in static mode as it is failing on Ubuntu. set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND})
if(WEBP_LINK_STATIC AND ${I_LIB} STREQUAL "TIFF") if(${I_LIB}_FOUND)
message(STATUS "TIFF is disabled when statically linking.") list(APPEND WEBP_DEP_IMG_LIBRARIES ${${I_LIB}_LIBRARIES})
continue() list(APPEND WEBP_DEP_IMG_INCLUDE_DIRS ${${I_LIB}_INCLUDE_DIR}
endif() ${${I_LIB}_INCLUDE_DIRS})
find_package(${I_LIB})
set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND})
if(${I_LIB}_FOUND)
list(APPEND WEBP_DEP_IMG_LIBRARIES ${${I_LIB}_LIBRARIES})
list(APPEND WEBP_DEP_IMG_INCLUDE_DIRS ${${I_LIB}_INCLUDE_DIR}
${${I_LIB}_INCLUDE_DIRS})
endif()
endforeach()
if(WEBP_DEP_IMG_INCLUDE_DIRS)
list(REMOVE_DUPLICATES WEBP_DEP_IMG_INCLUDE_DIRS)
endif() endif()
endforeach()
if(WEBP_DEP_IMG_INCLUDE_DIRS)
list(REMOVE_DUPLICATES WEBP_DEP_IMG_INCLUDE_DIRS)
endif()
# GIF detection, gifdec isn't part of the imageio lib. # GIF detection, gifdec isn't part of the imageio lib.
include(CMakePushCheckState) include(CMakePushCheckState)
set(WEBP_DEP_GIF_LIBRARIES) set(WEBP_DEP_GIF_LIBRARIES)
set(WEBP_DEP_GIF_INCLUDE_DIRS) set(WEBP_DEP_GIF_INCLUDE_DIRS)
find_package(GIF) find_package(GIF)
set(WEBP_HAVE_GIF ${GIF_FOUND}) set(WEBP_HAVE_GIF ${GIF_FOUND})
if(GIF_FOUND) if(GIF_FOUND)
# GIF find_package only locates the header and library, it doesn't fail # GIF find_package only locates the header and library, it doesn't fail
# compile tests when detecting the version, but falls back to 3 (as of at # compile tests when detecting the version, but falls back to 3 (as of at
# least cmake 3.7.2). Make sure the library links to avoid incorrect # least cmake 3.7.2). Make sure the library links to avoid incorrect detection
# detection when cross compiling. # when cross compiling.
cmake_push_check_state() cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES ${GIF_LIBRARIES}) set(CMAKE_REQUIRED_LIBRARIES ${GIF_LIBRARIES})
set(CMAKE_REQUIRED_INCLUDES ${GIF_INCLUDE_DIR}) set(CMAKE_REQUIRED_INCLUDES ${GIF_INCLUDE_DIR})
check_c_source_compiles( check_c_source_compiles("
"
#include <gif_lib.h> #include <gif_lib.h>
int main(void) { int main(void) {
(void)DGifOpenFileHandle; (void)DGifOpenFileHandle;
return 0; return 0;
} }
" " GIF_COMPILES)
GIF_COMPILES) cmake_pop_check_state()
cmake_pop_check_state() if(GIF_COMPILES)
if(GIF_COMPILES) list(APPEND WEBP_DEP_GIF_LIBRARIES ${GIF_LIBRARIES})
list(APPEND WEBP_DEP_GIF_LIBRARIES ${GIF_LIBRARIES}) list(APPEND WEBP_DEP_GIF_INCLUDE_DIRS ${GIF_INCLUDE_DIR})
list(APPEND WEBP_DEP_GIF_INCLUDE_DIRS ${GIF_INCLUDE_DIR}) else()
else() unset(GIF_FOUND)
unset(GIF_FOUND)
endif()
endif() endif()
endif() endif()
# Check for specific headers. # Check for specific headers.
include(CheckIncludeFiles) include(CheckIncludeFiles)
check_include_files("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS)
check_include_files(dlfcn.h HAVE_DLFCN_H)
check_include_files(GLUT/glut.h HAVE_GLUT_GLUT_H) check_include_files(GLUT/glut.h HAVE_GLUT_GLUT_H)
check_include_files(GL/glut.h HAVE_GL_GLUT_H) check_include_files(GL/glut.h HAVE_GL_GLUT_H)
check_include_files(inttypes.h HAVE_INTTYPES_H)
check_include_files(memory.h HAVE_MEMORY_H)
check_include_files(OpenGL/glut.h HAVE_OPENGL_GLUT_H) check_include_files(OpenGL/glut.h HAVE_OPENGL_GLUT_H)
check_include_files(shlwapi.h HAVE_SHLWAPI_H) check_include_files(shlwapi.h HAVE_SHLWAPI_H)
check_include_files(stdint.h HAVE_STDINT_H)
check_include_files(stdlib.h HAVE_STDLIB_H)
check_include_files(strings.h HAVE_STRINGS_H)
check_include_files(string.h HAVE_STRING_H)
check_include_files(sys/stat.h HAVE_SYS_STAT_H)
check_include_files(sys/types.h HAVE_SYS_TYPES_H)
check_include_files(unistd.h HAVE_UNISTD_H) check_include_files(unistd.h HAVE_UNISTD_H)
check_include_files(wincodec.h HAVE_WINCODEC_H) check_include_files(wincodec.h HAVE_WINCODEC_H)
check_include_files(windows.h HAVE_WINDOWS_H) check_include_files(windows.h HAVE_WINDOWS_H)
# Windows specifics # Windows specifics
if(HAVE_WINCODEC_H) if(HAVE_WINCODEC_H)
list(APPEND WEBP_DEP_LIBRARIES shlwapi ole32 windowscodecs) list(APPEND WEBP_DEP_LIBRARIES
shlwapi
ole32
windowscodecs)
endif() endif()
# Check for SIMD extensions. # Check for SIMD extensions.
@ -150,12 +143,17 @@ set(PACKAGE_NAME ${PROJECT_NAME})
# Read from configure.ac. # Read from configure.ac.
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_AC) file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_AC)
string(REGEX MATCHALL "\\[([0-9a-z\\.:/]*)\\]" CONFIGURE_AC_PACKAGE_INFO string(REGEX MATCHALL
"\\[([0-9a-z\\.:/]*)\\]"
CONFIGURE_AC_PACKAGE_INFO
${CONFIGURE_AC}) ${CONFIGURE_AC})
function(strip_bracket VAR) function(strip_bracket VAR)
string(LENGTH ${${VAR}} TMP_LEN) string(LENGTH ${${VAR}} TMP_LEN)
math(EXPR TMP_LEN ${TMP_LEN}-2) math(EXPR TMP_LEN ${TMP_LEN}-2)
string(SUBSTRING ${${VAR}} 1 ${TMP_LEN} TMP_SUB) string(SUBSTRING ${${VAR}}
1
${TMP_LEN}
TMP_SUB)
set(${VAR} ${TMP_SUB} PARENT_SCOPE) set(${VAR} ${TMP_SUB} PARENT_SCOPE)
endfunction() endfunction()

View File

@ -1,6 +1,6 @@
AC_INIT([libwebp], [1.6.0], AC_INIT([libwebp], [1.1.0],
[https://issues.webmproject.org],, [https://bugs.chromium.org/p/webp],,
[https://developers.google.com/speed/webp]) [http://developers.google.com/speed/webp])
AC_CANONICAL_HOST AC_CANONICAL_HOST
AC_PREREQ([2.60]) AC_PREREQ([2.60])
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
@ -9,8 +9,7 @@ dnl === automake >= 1.12 requires this for 'unusual archivers' support.
dnl === it must occur before LT_INIT (AC_PROG_LIBTOOL). dnl === it must occur before LT_INIT (AC_PROG_LIBTOOL).
m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
dnl === AC_PROG_LIBTOOL is deprecated. AC_PROG_LIBTOOL
m4_ifdef([LT_INIT], [LT_INIT], [AC_PROG_LIBTOOL])
AC_PROG_SED AC_PROG_SED
AM_PROG_CC_C_O AM_PROG_CC_C_O
@ -28,46 +27,11 @@ AC_ARG_ENABLE([everything],
AS_HELP_STRING([--enable-everything], AS_HELP_STRING([--enable-everything],
[Enable all optional targets. These can still be [Enable all optional targets. These can still be
disabled with --disable-target]), disabled with --disable-target]),
[SET_IF_UNSET([enable_libsharpyuv], [$enableval]) [SET_IF_UNSET([enable_libwebpdecoder], [$enableval])
SET_IF_UNSET([enable_libwebpdecoder], [$enableval])
SET_IF_UNSET([enable_libwebpdemux], [$enableval]) SET_IF_UNSET([enable_libwebpdemux], [$enableval])
SET_IF_UNSET([enable_libwebpextras], [$enableval]) SET_IF_UNSET([enable_libwebpextras], [$enableval])
SET_IF_UNSET([enable_libwebpmux], [$enableval])]) SET_IF_UNSET([enable_libwebpmux], [$enableval])])
dnl === Check whether libwebpmux should be built
AC_MSG_CHECKING(whether libwebpmux is to be built)
AC_ARG_ENABLE([libwebpmux],
AS_HELP_STRING([--disable-libwebpmux],
[Disable libwebpmux @<:@default=no@:>@]),
[], [enable_libwebpmux=yes])
AC_MSG_RESULT(${enable_libwebpmux-no})
AM_CONDITIONAL([BUILD_MUX], [test "$enable_libwebpmux" = "yes"])
dnl === Check whether libwebpdemux should be built
AC_MSG_CHECKING(whether libwebpdemux is to be built)
AC_ARG_ENABLE([libwebpdemux],
AS_HELP_STRING([--disable-libwebpdemux],
[Disable libwebpdemux @<:@default=no@:>@]),
[], [enable_libwebpdemux=yes])
AC_MSG_RESULT(${enable_libwebpdemux-no})
AM_CONDITIONAL([BUILD_DEMUX], [test "$enable_libwebpdemux" = "yes"])
dnl === Check whether decoder library should be built.
AC_MSG_CHECKING(whether decoder library is to be built)
AC_ARG_ENABLE([libwebpdecoder],
AS_HELP_STRING([--enable-libwebpdecoder],
[Build libwebpdecoder @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpdecoder-no})
AM_CONDITIONAL([BUILD_LIBWEBPDECODER], [test "$enable_libwebpdecoder" = "yes"])
dnl === Check whether libwebpextras should be built
AC_MSG_CHECKING(whether libwebpextras is to be built)
AC_ARG_ENABLE([libwebpextras],
AS_HELP_STRING([--enable-libwebpextras],
[Build libwebpextras @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpextras-no})
AM_CONDITIONAL([BUILD_EXTRAS], [test "$enable_libwebpextras" = "yes"])
dnl === If --enable-asserts is not defined, define NDEBUG dnl === If --enable-asserts is not defined, define NDEBUG
AC_MSG_CHECKING(whether asserts are enabled) AC_MSG_CHECKING(whether asserts are enabled)
@ -106,7 +70,6 @@ TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wall])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wconstant-conversion]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wconstant-conversion])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wdeclaration-after-statement]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wdeclaration-after-statement])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra-semi-stmt])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wfloat-conversion]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wfloat-conversion])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-nonliteral]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-nonliteral])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-security]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-security])
@ -116,9 +79,7 @@ TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wold-style-definition])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wparentheses-equality]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wparentheses-equality])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshadow]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshadow])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshorten-64-to-32]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshorten-64-to-32])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wstrict-prototypes])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wundef]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wundef])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code-aggressive])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused-but-set-variable]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused-but-set-variable])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused])
@ -161,25 +122,6 @@ AS_IF([test "$GCC" = "yes" ], [
AC_SUBST([AM_CFLAGS]) AC_SUBST([AM_CFLAGS])
dnl === Check for machine specific flags dnl === Check for machine specific flags
AC_ARG_ENABLE([avx2],
AS_HELP_STRING([--disable-avx2],
[Disable detection of AVX2 support
@<:@default=auto@:>@]))
AS_IF([test "x$enable_avx2" != "xno" -a "x$enable_sse4_1" != "xno"
-a "x$enable_sse2" != "xno"], [
AVX2_FLAGS="$INTRINSICS_CFLAGS $AVX2_FLAGS"
TEST_AND_ADD_CFLAGS([AVX2_FLAGS], [-mavx2])
AS_IF([test -n "$AVX2_FLAGS"], [
SAVED_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS $AVX2_FLAGS"
AC_CHECK_HEADER([immintrin.h],
[AC_DEFINE(WEBP_HAVE_AVX2, [1],
[Set to 1 if AVX2 is supported])],
[AVX2_FLAGS=""])
CFLAGS=$SAVED_CFLAGS])
AC_SUBST([AVX2_FLAGS])])
AC_ARG_ENABLE([sse4.1], AC_ARG_ENABLE([sse4.1],
AS_HELP_STRING([--disable-sse4.1], AS_HELP_STRING([--disable-sse4.1],
[Disable detection of SSE4.1 support [Disable detection of SSE4.1 support
@ -282,9 +224,6 @@ AS_IF([test "x$enable_neon" != "xno"], [
*android*) AC_CHECK_HEADERS([cpu-features.h]) ;; *android*) AC_CHECK_HEADERS([cpu-features.h]) ;;
esac esac
;; ;;
aarch64*|arm64*)
AC_DEFINE(WEBP_HAVE_NEON, [1], [Set to 1 if NEON is supported])
;;
esac esac
AC_SUBST([NEON_FLAGS])]) AC_SUBST([NEON_FLAGS])])
@ -469,10 +408,6 @@ AS_IF([test "x$enable_gl" != "xno"], [
if test "$glut_support" = "yes" -a "$enable_libwebpdemux" = "yes"; then if test "$glut_support" = "yes" -a "$enable_libwebpdemux" = "yes"; then
build_vwebp=yes build_vwebp=yes
else
AC_MSG_NOTICE(
m4_normalize([Not building vwebp.
OpenGL libraries and --enable-libwebpdemux are required.]))
fi fi
]) ])
AM_CONDITIONAL([BUILD_VWEBP], [test "$build_vwebp" = "yes"]) AM_CONDITIONAL([BUILD_VWEBP], [test "$build_vwebp" = "yes"])
@ -485,7 +420,7 @@ AC_ARG_ENABLE([sdl],
@<:@default=auto@:>@])) @<:@default=auto@:>@]))
AS_IF([test "x$enable_sdl" != "xno"], [ AS_IF([test "x$enable_sdl" != "xno"], [
CLEAR_LIBVARS([SDL]) CLEAR_LIBVARS([SDL])
AC_PATH_PROGS([LIBSDL_CONFIG], [sdl2-config]) AC_PATH_PROGS([LIBSDL_CONFIG], [sdl-config])
if test -n "$LIBSDL_CONFIG"; then if test -n "$LIBSDL_CONFIG"; then
SDL_INCLUDES=`$LIBSDL_CONFIG --cflags` SDL_INCLUDES=`$LIBSDL_CONFIG --cflags`
SDL_LIBS="`$LIBSDL_CONFIG --libs`" SDL_LIBS="`$LIBSDL_CONFIG --libs`"
@ -495,12 +430,13 @@ AS_IF([test "x$enable_sdl" != "xno"], [
sdl_header="no" sdl_header="no"
LIBCHECK_PROLOGUE([SDL]) LIBCHECK_PROLOGUE([SDL])
AC_CHECK_HEADER([SDL2/SDL.h], [sdl_header="SDL2/SDL.h"], AC_CHECK_HEADER([SDL/SDL.h], [sdl_header="SDL/SDL.h"],
[AC_MSG_WARN(SDL2 library not available - no SDL.h)]) [AC_CHECK_HEADER([SDL.h], [sdl_header="SDL.h"],
[AC_MSG_WARN(SDL library not available - no sdl.h)])])
if test x"$sdl_header" != "xno"; then if test x"$sdl_header" != "xno"; then
AC_LANG_PUSH(C) AC_LANG_PUSH(C)
SDL_SAVED_LIBS="$LIBS" SDL_SAVED_LIBS="$LIBS"
for lib in "" "-lSDL2" "-lSDL2main -lSDL2"; do for lib in "" "-lSDL" "-lSDLmain -lSDL"; do
LIBS="$SDL_SAVED_LIBS $lib" LIBS="$SDL_SAVED_LIBS $lib"
# Perform a full link to ensure SDL_main is resolved if needed. # Perform a full link to ensure SDL_main is resolved if needed.
AC_LINK_IFELSE( AC_LINK_IFELSE(
@ -531,7 +467,7 @@ AS_IF([test "x$enable_sdl" != "xno"], [
if test x"$sdl_support" = "xyes"; then if test x"$sdl_support" = "xyes"; then
build_vwebp_sdl=yes build_vwebp_sdl=yes
else else
AC_MSG_NOTICE([Not building vwebp-sdl. SDL library is required.]) AC_MSG_WARN(Optional SDL library not found)
fi fi
]) ])
@ -655,17 +591,11 @@ AS_IF([test "x$enable_gif" != "xno"], [
if test "$gif_support" = "yes" -a \ if test "$gif_support" = "yes" -a \
"$enable_libwebpdemux" = "yes"; then "$enable_libwebpdemux" = "yes"; then
build_anim_diff=yes build_anim_diff=yes
else
AC_MSG_NOTICE(
[Not building anim_diff. libgif and --enable-libwebpdemux are required.])
fi fi
if test "$gif_support" = "yes" -a \ if test "$gif_support" = "yes" -a \
"$enable_libwebpmux" = "yes"; then "$enable_libwebpmux" = "yes"; then
build_gif2webp=yes build_gif2webp=yes
else
AC_MSG_NOTICE(
[Not building gif2webp. libgif and --enable-libwebpmux are required.])
fi fi
]) ])
AM_CONDITIONAL([BUILD_ANIMDIFF], [test "${build_anim_diff}" = "yes"]) AM_CONDITIONAL([BUILD_ANIMDIFF], [test "${build_anim_diff}" = "yes"])
@ -673,17 +603,11 @@ AM_CONDITIONAL([BUILD_GIF2WEBP], [test "${build_gif2webp}" = "yes"])
if test "$enable_libwebpdemux" = "yes" -a "$enable_libwebpmux" = "yes"; then if test "$enable_libwebpdemux" = "yes" -a "$enable_libwebpmux" = "yes"; then
build_img2webp=yes build_img2webp=yes
else
AC_MSG_NOTICE(
m4_normalize([Not building img2webp.
--enable-libwebpdemux & --enable-libwebpmux are required.]))
fi fi
AM_CONDITIONAL([BUILD_IMG2WEBP], [test "${build_img2webp}" = "yes"]) AM_CONDITIONAL([BUILD_IMG2WEBP], [test "${build_img2webp}" = "yes"])
if test "$enable_libwebpmux" = "yes"; then if test "$enable_libwebpmux" = "yes"; then
build_webpinfo=yes build_webpinfo=yes
else
AC_MSG_NOTICE([Not building webpinfo. --enable-libwebpdemux is required.])
fi fi
AM_CONDITIONAL([BUILD_WEBPINFO], [test "${build_webpinfo}" = "yes"]) AM_CONDITIONAL([BUILD_WEBPINFO], [test "${build_webpinfo}" = "yes"])
@ -767,23 +691,52 @@ else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
fi fi
dnl === Check whether libwebpmux should be built
AC_MSG_CHECKING(whether libwebpmux is to be built)
AC_ARG_ENABLE([libwebpmux],
AS_HELP_STRING([--enable-libwebpmux],
[Build libwebpmux @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpmux-no})
AM_CONDITIONAL([BUILD_MUX], [test "$enable_libwebpmux" = "yes"])
dnl === Check whether libwebpdemux should be built
AC_MSG_CHECKING(whether libwebpdemux is to be built)
AC_ARG_ENABLE([libwebpdemux],
AS_HELP_STRING([--disable-libwebpdemux],
[Disable libwebpdemux @<:@default=no@:>@]),
[], [enable_libwebpdemux=yes])
AC_MSG_RESULT(${enable_libwebpdemux-no})
AM_CONDITIONAL([BUILD_DEMUX], [test "$enable_libwebpdemux" = "yes"])
dnl === Check whether decoder library should be built.
AC_MSG_CHECKING(whether decoder library is to be built)
AC_ARG_ENABLE([libwebpdecoder],
AS_HELP_STRING([--enable-libwebpdecoder],
[Build libwebpdecoder @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpdecoder-no})
AM_CONDITIONAL([BUILD_LIBWEBPDECODER], [test "$enable_libwebpdecoder" = "yes"])
dnl === Check whether libwebpextras should be built
AC_MSG_CHECKING(whether libwebpextras is to be built)
AC_ARG_ENABLE([libwebpextras],
AS_HELP_STRING([--enable-libwebpextras],
[Build libwebpextras @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpextras-no})
AM_CONDITIONAL([BUILD_EXTRAS], [test "$enable_libwebpextras" = "yes"])
dnl ========================= dnl =========================
dnl Add an empty webp_libname_prefix variable for use in *.pc.in.
AC_SUBST([webp_libname_prefix])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([src/webp/config.h]) AC_CONFIG_HEADERS([src/webp/config.h])
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile \ AC_CONFIG_FILES([Makefile src/Makefile man/Makefile \
examples/Makefile extras/Makefile imageio/Makefile \ examples/Makefile extras/Makefile imageio/Makefile \
sharpyuv/Makefile sharpyuv/libsharpyuv.pc \
src/dec/Makefile src/enc/Makefile src/dsp/Makefile \ src/dec/Makefile src/enc/Makefile src/dsp/Makefile \
src/demux/Makefile src/mux/Makefile \ src/demux/Makefile src/mux/Makefile \
src/utils/Makefile \ src/utils/Makefile \
src/libwebp.pc src/libwebpdecoder.pc \ src/libwebp.pc src/libwebpdecoder.pc \
src/demux/libwebpdemux.pc src/mux/libwebpmux.pc]) src/demux/libwebpdemux.pc src/mux/libwebpmux.pc])
dnl fix exports from MinGW builds
AC_CONFIG_COMMANDS_POST([$SED -i 's/-DDLL_EXPORT/-DWEBP_DLL/' config.status])
AC_OUTPUT AC_OUTPUT
AC_MSG_NOTICE([ AC_MSG_NOTICE([

29
doc/README Normal file
View File

@ -0,0 +1,29 @@
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/

View File

@ -1,386 +0,0 @@
# WebP APIs
## Encoding API
The main encoding functions are available in the header src/webp/encode.h
The ready-to-use ones are:
```c
size_t WebPEncodeRGB(const uint8_t* rgb, int width, int height, int stride,
float quality_factor, uint8_t** output);
size_t WebPEncodeBGR(const uint8_t* bgr, int width, int height, int stride,
float quality_factor, uint8_t** output);
size_t WebPEncodeRGBA(const uint8_t* rgba, int width, int height, int stride,
float quality_factor, uint8_t** output);
size_t WebPEncodeBGRA(const uint8_t* bgra, int width, int height, int stride,
float quality_factor, uint8_t** output);
```
They will convert raw RGB samples to a WebP data. The only control supplied is
the quality factor.
There are some variants for using the lossless format:
```c
size_t WebPEncodeLosslessRGB(const uint8_t* rgb, int width, int height,
int stride, uint8_t** output);
size_t WebPEncodeLosslessBGR(const uint8_t* bgr, int width, int height,
int stride, uint8_t** output);
size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, int width, int height,
int stride, uint8_t** output);
size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, int width, int height,
int stride, uint8_t** output);
```
Of course in this case, no quality factor is needed since the compression occurs
without loss of the input values, at the expense of larger output sizes.
### Advanced encoding API
A more advanced API is based on the WebPConfig and WebPPicture structures.
WebPConfig contains the encoding settings and is not tied to a particular
picture. WebPPicture contains input data, on which some WebPConfig will be used
for compression. The encoding flow looks like:
```c
#include <webp/encode.h>
// Setup a config, starting form a preset and tuning some additional
// parameters
WebPConfig config;
if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) {
return 0; // version error
}
// ... additional tuning
config.sns_strength = 90;
config.filter_sharpness = 6;
config_error = WebPValidateConfig(&config); // not mandatory, but useful
// Setup the input data
WebPPicture pic;
if (!WebPPictureInit(&pic)) {
return 0; // version error
}
pic.width = width;
pic.height = height;
// allocated picture of dimension width x height
if (!WebPPictureAlloc(&pic)) {
return 0; // memory error
}
// at this point, 'pic' has been initialized as a container,
// and can receive the Y/U/V samples.
// Alternatively, one could use ready-made import functions like
// WebPPictureImportRGB(), which will take care of memory allocation.
// In any case, past this point, one will have to call
// WebPPictureFree(&pic) to reclaim memory.
// Set up a byte-output write method. WebPMemoryWriter, for instance.
WebPMemoryWriter wrt;
WebPMemoryWriterInit(&wrt); // initialize 'wrt'
pic.writer = MyFileWriter;
pic.custom_ptr = my_opaque_structure_to_make_MyFileWriter_work;
// Compress!
int ok = WebPEncode(&config, &pic); // ok = 0 => error occurred!
WebPPictureFree(&pic); // must be called independently of the 'ok' result.
// output data should have been handled by the writer at that point.
// -> compressed data is the memory buffer described by wrt.mem / wrt.size
// deallocate the memory used by compressed data
WebPMemoryWriterClear(&wrt);
```
## Decoding API
This is mainly just one function to call:
```c
#include "webp/decode.h"
uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size,
int* width, int* height);
```
Please have a look at the file src/webp/decode.h for the details. There are
variants for decoding in BGR/RGBA/ARGB/BGRA order, along with decoding to raw
Y'CbCr samples. One can also decode the image directly into a pre-allocated
buffer.
To detect a WebP file and gather the picture's dimensions, the function:
```c
int WebPGetInfo(const uint8_t* data, size_t data_size,
int* width, int* height);
```
is supplied. No decoding is involved when using it.
### Incremental decoding API
In the case when data is being progressively transmitted, pictures can still be
incrementally decoded using a slightly more complicated API. Decoder state is
stored into an instance of the WebPIDecoder object. This object can be created
with the purpose of decoding either RGB or Y'CbCr samples. For instance:
```c
WebPDecBuffer buffer;
WebPInitDecBuffer(&buffer);
buffer.colorspace = MODE_BGR;
...
WebPIDecoder* idec = WebPINewDecoder(&buffer);
```
As data is made progressively available, this incremental-decoder object can be
used to decode the picture further. There are two (mutually exclusive) ways to
pass freshly arrived data:
either by appending the fresh bytes:
```c
WebPIAppend(idec, fresh_data, size_of_fresh_data);
```
or by just mentioning the new size of the transmitted data:
```c
WebPIUpdate(idec, buffer, size_of_transmitted_buffer);
```
Note that 'buffer' can be modified between each call to WebPIUpdate, in
particular when the buffer is resized to accommodate larger data.
These functions will return the decoding status: either VP8_STATUS_SUSPENDED if
decoding is not finished yet or VP8_STATUS_OK when decoding is done. Any other
status is an error condition.
The 'idec' object must always be released (even upon an error condition) by
calling: WebPIDelete(idec).
To retrieve partially decoded picture samples, one must use the corresponding
method: WebPIDecGetRGB or WebPIDecGetYUVA. It will return the last displayable
pixel row.
Lastly, note that decoding can also be performed into a pre-allocated pixel
buffer. This buffer must be passed when creating a WebPIDecoder, calling
WebPINewRGB() or WebPINewYUVA().
Please have a look at the src/webp/decode.h header for further details.
### Advanced Decoding API
WebP decoding supports an advanced API which provides on-the-fly cropping and
rescaling, something of great usefulness on memory-constrained environments like
mobile phones. Basically, the memory usage will scale with the output's size,
not the input's, when one only needs a quick preview or a zoomed in portion of
an otherwise too-large picture. Some CPU can be saved too, incidentally.
```c
// A) Init a configuration object
WebPDecoderConfig config;
CHECK(WebPInitDecoderConfig(&config));
// B) optional: retrieve the bitstream's features.
CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
// C) Adjust 'config' options, if needed
config.options.no_fancy_upsampling = 1;
config.options.use_scaling = 1;
config.options.scaled_width = scaledWidth();
config.options.scaled_height = scaledHeight();
// etc.
// D) Specify 'config' output options for specifying output colorspace.
// Optionally the external image decode buffer can also be specified.
config.output.colorspace = MODE_BGRA;
// Optionally, the config.output can be pointed to an external buffer as
// well for decoding the image. This externally supplied memory buffer
// should be big enough to store the decoded picture.
config.output.u.RGBA.rgba = (uint8_t*) memory_buffer;
config.output.u.RGBA.stride = scanline_stride;
config.output.u.RGBA.size = total_size_of_the_memory_buffer;
config.output.is_external_memory = 1;
config_error = WebPValidateDecoderConfig(&config); // not mandatory, but useful
// 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).

View File

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

View File

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

View File

@ -1,524 +0,0 @@
# 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)
-resize_mode <string> .. one of: up_only, down_only, always (default)
-mt .................... use multi-threading if available
-low_memory ............ reduce memory usage (slower encoding)
-map <int> ............. print map of extra info
-print_psnr ............ prints averaged PSNR distortion
-print_ssim ............ prints averaged SSIM distortion
-print_lsim ............ prints local-similarity distortion
-d <file.pgm> .......... dump the compressed output (PGM file)
-alpha_method <int> .... transparency-compression method (0..1), default=1
-alpha_filter <string> . predictive filtering for alpha plane,
one of: none, fast (default) or best
-exact ................. preserve RGB values in transparent area, default=off
-blend_alpha <hex> ..... blend colors against background color
expressed as RGB values written in
hexadecimal, e.g. 0xc0e0d0 for red=0xc0
green=0xe0 and blue=0xd0
-noalpha ............... discard any transparency information
-lossless .............. encode image losslessly, default=off
-near_lossless <int> ... use near-lossless image preprocessing
(0..100=off), default=100
-hint <string> ......... specify image characteristics hint,
one of: photo, picture or graph
-metadata <string> ..... comma separated list of metadata to
copy from the input to the output if present.
Valid values: all, none (default), exif, icc, xmp
-short ................. condense printed message
-quiet ................. don't print anything
-version ............... print version number and exit
-noasm ................. disable all assembly optimizations
-v ..................... verbose, e.g. print encoding/decoding times
-progress .............. report encoding progress
```
Experimental Options:
```
-jpeg_like ............. roughly match expected JPEG size
-af .................... auto-adjust filter strength
-pre <int> ............. pre-processing filter
```
The main options you might want to try in order to further tune the visual
quality are:
-preset -sns -f -m
Namely:
* `preset` will set up a default encoding configuration targeting a particular
type of input. It should appear first in the list of options, so that
subsequent options can take effect on top of this preset. Default value is
'default'.
* `sns` will progressively turn on (when going from 0 to 100) some additional
visual optimizations (like: segmentation map re-enforcement). This option
will balance the bit allocation differently. It tries to take bits from the
"easy" parts of the picture and use them in the "difficult" ones instead.
Usually, raising the sns value (at fixed -q value) leads to larger files,
but with better quality. Typical value is around '75'.
* `f` option directly links to the filtering strength used by the codec's
in-loop processing. The higher the value, the smoother the highly-compressed
area will look. This is particularly useful when aiming at very small files.
Typical values are around 20-30. Note that using the option
-strong/-nostrong will change the type of filtering. Use "-f 0" to turn
filtering off.
* `m` controls the trade-off between encoding speed and quality. Default is 4.
You can try -m 5 or -m 6 to explore more (time-consuming) encoding
possibilities. A lower value will result in faster encoding at the expense
of quality.
## Decoding tool
There is a decoding sample in examples/dwebp.c which will take a .webp file and
decode it to a PNG image file (amongst other formats). This is simply to
demonstrate the use of the API. You can verify the file test.webp decodes to
exactly the same as test_ref.ppm by using:
```shell
cd examples
./dwebp test.webp -ppm -o test.ppm
diff test.ppm test_ref.ppm
```
The full list of options is available using -h:
```shell
> dwebp -h
Usage: dwebp in_file [options] [-o out_file]
```
Decodes the WebP image file to PNG format [Default]. Note: Animated WebP files
are not supported.
Use following options to convert into alternate image formats:
```
-pam ......... save the raw RGBA samples as a color PAM
-ppm ......... save the raw RGB samples as a color PPM
-bmp ......... save as uncompressed BMP format
-tiff ........ save as uncompressed TIFF format
-pgm ......... save the raw YUV samples as a grayscale PGM
file with IMC4 layout
-yuv ......... save the raw YUV samples in flat layout
```
Other options are:
```
-version ..... print version number and exit
-nofancy ..... don't use the fancy YUV420 upscaler
-nofilter .... disable in-loop filtering
-nodither .... disable dithering
-dither <d> .. dithering strength (in 0..100)
-alpha_dither use alpha-plane dithering if needed
-mt .......... use multi-threading
-crop <x> <y> <w> <h> ... crop output with the given rectangle
-resize <w> <h> ......... resize output (*after* any cropping)
-flip ........ flip the output vertically
-alpha ....... only save the alpha plane
-incremental . use incremental decoding (useful for tests)
-h ........... this help message
-v ........... verbose (e.g. print encoding/decoding times)
-quiet ....... quiet mode, don't print anything
-noasm ....... disable all assembly optimizations
```
## WebP file analysis tool
`webpinfo` can be used to print out the chunk level structure and bitstream
header information of WebP files. It can also check if the files are of valid
WebP format.
Usage:
```shell
webpinfo [options] in_files
```
Note: there could be multiple input files; options must come before input files.
Options:
```
-version ........... Print version number and exit.
-quiet ............. Do not show chunk parsing information.
-diag .............. Show parsing error diagnosis.
-summary ........... Show chunk stats summary.
-bitstream_info .... Parse bitstream header.
```
## Visualization tool
There's a little self-serve visualization tool called 'vwebp' under the
examples/ directory. It uses OpenGL to open a simple drawing window and show a
decoded WebP file. It's not yet integrated in the automake build system, but you
can try to manually compile it using the recommendations below.
Usage:
```shell
vwebp in_file [options]
```
Decodes the WebP image file and visualize it using OpenGL
Options are:
```
-version ..... print version number and exit
-noicc ....... don't use the icc profile if present
-nofancy ..... don't use the fancy YUV420 upscaler
-nofilter .... disable in-loop filtering
-dither <int> dithering strength (0..100), default=50
-noalphadither disable alpha plane dithering
-usebgcolor .. display background color
-mt .......... use multi-threading
-info ........ print info
-h ........... this help message
```
Keyboard shortcuts:
```
'c' ................ toggle use of color profile
'b' ................ toggle background color display
'i' ................ overlay file information
'd' ................ disable blending & disposal (debug)
'q' / 'Q' / ESC .... quit
```
### Building
Prerequisites:
1. OpenGL & OpenGL Utility Toolkit (GLUT)
Linux: `sudo apt-get install freeglut3-dev mesa-common-dev`
Mac + Xcode: These libraries should be available in the OpenGL / GLUT
frameworks.
Windows: http://freeglut.sourceforge.net/index.php#download
2. (Optional) qcms (Quick Color Management System)
1. Download qcms from Mozilla / Chromium:
https://hg.mozilla.org/mozilla-central/file/0e7639e3bdfb/gfx/qcms
https://source.chromium.org/chromium/chromium/src/+/main:third_party/qcms/;drc=d4a2f8e1ed461d8fc05ed88d1ae2dc94c9773825
2. Build and archive the source files as libqcms.a / qcms.lib
3. Update makefile.unix / Makefile.vc
1. Define WEBP_HAVE_QCMS
2. Update include / library paths to reference the qcms directory.
Build using makefile.unix / Makefile.vc:
```shell
$ make -f makefile.unix examples/vwebp
> nmake /f Makefile.vc CFG=release-static \
../obj/x64/release-static/bin/vwebp.exe
```
## Animation creation tool
The utility `img2webp` can turn a sequence of input images (PNG, JPEG, ...) into
an animated WebP file. It offers fine control over duration, encoding modes,
etc.
Usage:
```shell
img2webp [file_options] [[frame_options] frame_file]... [-o webp_file]
```
File-level options (only used at the start of compression):
```
-min_size ............ minimize size
-kmax <int> .......... maximum number of frame between key-frames
(0=only keyframes)
-kmin <int> .......... minimum number of frame between key-frames
(0=disable key-frames altogether)
-mixed ............... use mixed lossy/lossless automatic mode
-near_lossless <int> . use near-lossless image preprocessing
(0..100=off), default=100
-sharp_yuv ........... use sharper (and slower) RGB->YUV conversion
(lossy only)
-loop <int> .......... loop count (default: 0, = infinite loop)
-v ................... verbose mode
-h ................... this help
-version ............. print version number and exit
```
Per-frame options (only used for subsequent images input):
```
-d <int> ............. frame duration in ms (default: 100)
-lossless ............ use lossless mode (default)
-lossy ............... use lossy mode
-q <float> ........... quality
-m <int> ............. compression method (0=fast, 6=slowest), default=4
-exact, -noexact ..... preserve or alter RGB values in transparent area
(default: -noexact, may cause artifacts
with lossy animations)
```
example: `img2webp -loop 2 in0.png -lossy in1.jpg -d 80 in2.tiff -o out.webp`
Note: if a single file name is passed as the argument, the arguments will be
tokenized from this file. The file name must not start with the character '-'.
## Animated GIF conversion
Animated GIF files can be converted to WebP files with animation using the
gif2webp utility available under examples/. The files can then be viewed using
vwebp.
Usage:
```shell
gif2webp [options] gif_file -o webp_file
```
Options:
```
-h / -help ............. this help
-lossy ................. encode image using lossy compression
-mixed ................. for each frame in the image, pick lossy
or lossless compression heuristically
-near_lossless <int> ... use near-lossless image preprocessing
(0..100=off), default=100
-sharp_yuv ............. use sharper (and slower) RGB->YUV conversion
(lossy only)
-q <float> ............. quality factor (0:small..100:big)
-m <int> ............... compression method (0=fast, 6=slowest), default=4
-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 Although you may be viewing an alternate representation, this document
is sourced in Markdown, a light-duty markup scheme, and is optimized for is sourced in Markdown, a light-duty markup scheme, and is optimized for
the [kramdown](https://kramdown.gettalong.org/) transformer. the [kramdown](http://kramdown.rubyforge.org/) transformer.
See the accompanying specs_generation.md. External link targets are referenced See the accompanying README. External link targets are referenced at the
at the end of this file. end of this file.
--> -->
@ -20,48 +20,50 @@ WebP Container Specification
Introduction Introduction
------------ ------------
WebP is an image format that uses either (i) the VP8 key frame encoding to WebP is an image format that uses either (i) the VP8 key frame encoding
compress image data in a lossy way or (ii) the WebP lossless encoding. These to compress image data in a lossy way, or (ii) the WebP lossless encoding
encoding schemes should make it more efficient than older formats, such as JPEG, (and possibly other encodings in the future). These encoding schemes should
GIF, and PNG. It is optimized for fast image transfer over the network (for make it more efficient than currently used formats. It is optimized for fast
example, for websites). The WebP format has feature parity (color profile, image transfer over the network (e.g., for websites). The WebP format has
metadata, animation, etc.) with other formats as well. This document describes feature parity (color profile, metadata, animation etc) with other formats as
the structure of a WebP file. well. This document describes the structure of a WebP file.
The WebP container (that is, the RIFF container for WebP) allows feature support The WebP container (i.e., RIFF container for WebP) allows feature support over
over and above the basic use case of WebP (that is, a file containing a single and above the basic use case of WebP (i.e., a file containing a single image
image encoded as a VP8 key frame). The WebP container provides additional encoded as a VP8 key frame). The WebP container provides additional support
support for the following: for:
* Lossless Compression: An image can be losslessly compressed, using the * **Lossless compression.** An image can be losslessly compressed, using the
WebP Lossless Format. WebP Lossless Format.
* Metadata: An image may have metadata stored in Exchangeable Image File * **Metadata.** An image may have metadata stored in EXIF or XMP formats.
Format (Exif) or Extensible Metadata Platform (XMP) format.
* Transparency: An image may have transparency, that is, an alpha channel. * **Transparency.** An image may have transparency, i.e., an alpha channel.
* Color Profile: An image may have an embedded ICC profile as described * **Color Profile.** An image may have an embedded ICC profile as described
by the [International Color Consortium][iccspec]. by the [International Color Consortium][iccspec].
* Animation: An image may have multiple frames with pauses between them, * **Animation.** An image may have multiple frames with pauses between them,
making it an animation. making it an animation.
Terminology & Basics The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
-------------------- "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in [RFC 2119][].
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in BCP 14 [RFC 2119][] [RFC 8174][]
when, and only when, they appear in all capitals, as shown here.
A WebP file contains either a still image (that is, an encoded matrix of pixels)
or an [animation](#animation). Optionally, it can also contain transparency
information, a color profile and metadata. We refer to the matrix of pixels as
the _canvas_ of the image.
Bit numbering in chunk diagrams starts at `0` for the most significant bit Bit numbering in chunk diagrams starts at `0` for the most significant bit
('MSB 0'), as described in [RFC 1166][]. ('MSB 0') as described in [RFC 1166][].
**Note:** Out of the features mentioned above, lossy compression, lossless
compression, transparency, metadata, color profile and animation are finalized
and are to be considered stable.
Terminology &amp; Basics
------------------------
A WebP file contains either a still image (i.e., an encoded matrix of pixels)
or an [animation](#animation). Optionally, it can also contain transparency
information, color profile and metadata. In case we need to refer only to the
matrix of pixels, we will call it the _canvas_ of the image.
Below are additional terms used throughout this document: Below are additional terms used throughout this document:
@ -84,25 +86,19 @@ _uint32_
_FourCC_ _FourCC_
: A four-character code (FourCC) is a _uint32_ created by concatenating four : A _FourCC_ (four-character code) is a _uint32_ created by concatenating four
ASCII characters in little-endian order. This means 'aaaa' (0x61616161) and ASCII characters in little-endian order.
'AAAA' (0x41414141) are treated as different _FourCCs_.
_1-based_ _1-based_
: An unsigned integer field storing values offset by `-1`, for example, such a : An unsigned integer field storing values offset by `-1`. e.g., Such a field
field would store value _25_ as _24_. would store value _25_ as _24_.
_ChunkHeader('ABCD')_
: Used to describe the _FourCC_ and _Chunk Size_ header of individual chunks,
where 'ABCD' is the FourCC for the chunk. This element's size is 8 bytes.
RIFF File Format 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. document format.
The basic element of a RIFF file is a _chunk_. It consists of: The basic element of a RIFF file is a _chunk_. It consists of:
@ -114,7 +110,7 @@ The basic element of a RIFF file is a _chunk_. It consists of:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Chunk Size | | Chunk Size |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Chunk Payload : | Chunk Payload |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chunk FourCC: 32 bits Chunk FourCC: 32 bits
@ -123,15 +119,21 @@ Chunk FourCC: 32 bits
Chunk Size: 32 bits (_uint32_) Chunk Size: 32 bits (_uint32_)
: The size of the chunk in bytes, not including this field, the chunk : The size of the chunk not including this field, the chunk identifier or
identifier, or padding. padding.
Chunk Payload: _Chunk Size_ bytes Chunk Payload: _Chunk Size_ bytes
: The data payload. If _Chunk Size_ is odd, a single padding byte -- which MUST : The data payload. If _Chunk Size_ is odd, a single padding byte -- that
be `0` to conform with RIFF -- is added. SHOULD be `0` -- is added.
**Note**: RIFF has a convention that all-uppercase chunk FourCCs are standard _ChunkHeader('ABCD')_
: This is used to describe the _FourCC_ and _Chunk Size_ header of individual
chunks, where 'ABCD' is the FourCC for the chunk. This element's
size is 8 bytes.
**Note:** RIFF has a convention that all-uppercase chunk FourCCs are standard
chunks that apply to any RIFF file format, while FourCCs specific to a file chunks that apply to any RIFF file format, while FourCCs specific to a file
format are all lowercase. WebP does not follow this convention. format are all lowercase. WebP does not follow this convention.
@ -151,25 +153,23 @@ WebP File Header
'RIFF': 32 bits 'RIFF': 32 bits
: The ASCII characters 'R', 'I', 'F', 'F'. : The ASCII characters 'R' 'I' 'F' 'F'.
File Size: 32 bits (_uint32_) File Size: 32 bits (_uint32_)
: The size of the file in bytes, starting at offset 8. The maximum value of : The size of the file in bytes starting at offset 8. The maximum value of
this field is 2^32 minus 10 bytes and thus the size of the whole file is at this field is 2^32 minus 10 bytes and thus the size of the whole file is at
most 4 GiB minus 2 bytes. most 4GiB minus 2 bytes.
'WEBP': 32 bits 'WEBP': 32 bits
: The ASCII characters 'W', 'E', 'B', 'P'. : The ASCII characters 'W' 'E' 'B' 'P'.
A WebP file MUST begin with a RIFF header with the FourCC 'WEBP'. The file size A WebP file MUST begin with a RIFF header with the FourCC 'WEBP'. The file size
in the header is the total size of the chunks that follow plus `4` bytes for in the header is the total size of the chunks that follow plus `4` bytes for
the 'WEBP' FourCC. The file SHOULD NOT contain any data after the data the 'WEBP' FourCC. The file SHOULD NOT contain anything after it. As the size
specified by _File Size_. Readers MAY parse such files, ignoring the trailing of any chunk is even, the size given by the RIFF header is also even. The
data. As the size of any chunk is even, the size given by the RIFF header is contents of individual chunks will be described in the following sections.
also even. The contents of individual chunks are described in the following
sections.
Simple File Format (Lossy) Simple File Format (Lossy)
@ -184,43 +184,37 @@ Simple WebP (lossy) file format:
0 1 2 3 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| WebP file header (12 bytes) | | WebP file header (12 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: 'VP8 ' Chunk : | VP8 chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
'VP8 ' Chunk: VP8 chunk:
0 1 2 3 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('VP8 ') | | ChunkHeader('VP8 ') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: VP8 data : | VP8 data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
VP8 data: _Chunk Size_ bytes VP8 data: _Chunk Size_ bytes
: VP8 bitstream data. : VP8 bitstream data.
Note that the fourth character in the 'VP8 ' FourCC is an ASCII space (0x20). The VP8 bitstream format specification can be found at [VP8 Data Format and
Decoding Guide][vp8spec]. Note that the VP8 frame header contains the VP8 frame
The VP8 bitstream format specification is described in [VP8 Data Format and
Decoding Guide][rfc 6386]. Note that the VP8 frame header contains the VP8 frame
width and height. That is assumed to be the width and height of the canvas. width and height. That is assumed to be the width and height of the canvas.
The VP8 specification describes how to decode the image into Y'CbCr format. To The VP8 specification describes how to decode the image into Y'CbCr
convert to RGB, [Recommendation BT.601][rec601] SHOULD be used. Applications MAY format. To convert to RGB, Rec. 601 SHOULD be used.
use another conversion method, but visual results may differ among decoders.
Simple File Format (Lossless) Simple File Format (Lossless)
----------------------------- -----------------------------
**Note**: Older readers may not support files using the lossless format. **Note:** Older readers may not support files using the lossless format.
This layout SHOULD be used if the image requires _lossless_ encoding (with an This layout SHOULD be used if the image requires _lossless_ encoding (with an
optional transparency channel) and does not require advanced features provided optional transparency channel) and does not require advanced features provided
@ -231,22 +225,19 @@ Simple WebP (lossless) file format:
0 1 2 3 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| WebP file header (12 bytes) | | WebP file header (12 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: 'VP8L' Chunk : | VP8L chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
'VP8L' Chunk: VP8L chunk:
0 1 2 3 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('VP8L') | | ChunkHeader('VP8L') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: VP8L data : | VP8L data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
VP8L data: _Chunk Size_ bytes VP8L data: _Chunk Size_ bytes
@ -262,23 +253,23 @@ and height of the canvas.
Extended File Format Extended File Format
-------------------- --------------------
**Note**: Older readers may not support files using the extended format. **Note:** Older readers may not support files using the extended format.
An extended format file consists of: An extended format file consists of:
* A 'VP8X' Chunk with information about features used in the file. * A 'VP8X' chunk with information about features used in the file.
* An optional 'ICCP' Chunk with a color profile. * An optional 'ICCP' chunk with color profile.
* An optional 'ANIM' Chunk with animation control data. * An optional 'ANIM' chunk with animation control data.
* Image data. * Image data.
* An optional 'EXIF' Chunk with Exif metadata. * An optional 'EXIF' chunk with EXIF metadata.
* An optional 'XMP ' Chunk with XMP metadata. * An optional 'XMP ' chunk with XMP metadata.
* An optional list of [unknown chunks](#unknown-chunks). * An optional list of [unknown chunks](#unknown-chunks). _\[status: experimental\]_
For a _still image_, the _image data_ consists of a single frame, which is made For a _still image_, the _image data_ consists of a single frame, which is made
up of: up of:
@ -290,18 +281,15 @@ up of:
For an _animated image_, the _image data_ consists of multiple frames. More For an _animated image_, the _image data_ consists of multiple frames. More
details about frames can be found in the [Animation](#animation) section. details about frames can be found in the [Animation](#animation) section.
All chunks necessary for reconstruction and color correction, that is, 'VP8X', All chunks SHOULD be placed in the same order as listed above. If a chunk
'ICCP', 'ANIM', 'ANMF', 'ALPH', 'VP8 ', and 'VP8L', MUST appear in the order appears in the wrong place, the file is invalid, but readers MAY parse the
described earlier. Readers SHOULD fail when chunks necessary for reconstruction file, ignoring the chunks that come too late.
and color correction are out of order.
[Metadata](#metadata) and [unknown chunks](#unknown-chunks) MAY appear out of **Rationale:** Setting the order of chunks should allow quicker file
order. parsing. For example, if an 'ALPH' chunk does not appear in its required
position, a decoder can choose to stop searching for it. The rule of
**Rationale:** The chunks necessary for reconstruction should appear first in ignoring late chunks should make programs that need to do a full search
the file to allow a reader to begin decoding an image before receiving all of give the same results as the ones stopping early.
the data. An application may benefit from varying the order of metadata and
custom chunks to suit the implementation.
Extended WebP file header: Extended WebP file header:
{:#extended_header} {:#extended_header}
@ -309,12 +297,9 @@ Extended WebP file header:
0 1 2 3 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| WebP file header (12 bytes) | | WebP file header (12 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('VP8X') | | ChunkHeader('VP8X') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Rsv|I|L|E|X|A|R| Reserved | |Rsv|I|L|E|X|A|R| Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@ -325,20 +310,20 @@ Extended WebP file header:
Reserved (Rsv): 2 bits Reserved (Rsv): 2 bits
: MUST be `0`. Readers MUST ignore this field. : SHOULD be `0`.
ICC profile (I): 1 bit ICC profile (I): 1 bit
: Set if the file contains an 'ICCP' Chunk. : Set if the file contains an ICC profile.
Alpha (L): 1 bit Alpha (L): 1 bit
: Set if any of the frames of the image contain transparency information : Set if any of the frames of the image contain transparency information
("alpha"). ("alpha").
Exif metadata (E): 1 bit EXIF metadata (E): 1 bit
: Set if the file contains Exif metadata. : Set if the file contains EXIF metadata.
XMP metadata (X): 1 bit XMP metadata (X): 1 bit
@ -346,38 +331,38 @@ XMP metadata (X): 1 bit
Animation (A): 1 bit Animation (A): 1 bit
: Set if this is an animated image. Data in 'ANIM' and 'ANMF' Chunks should be : Set if this is an animated image. Data in 'ANIM' and 'ANMF' chunks should be
used to control the animation. used to control the animation.
Reserved (R): 1 bit Reserved (R): 1 bit
: MUST be `0`. Readers MUST ignore this field. : SHOULD be `0`.
Reserved: 24 bits Reserved: 24 bits
: MUST be `0`. Readers MUST ignore this field. : SHOULD be `0`.
Canvas Width Minus One: 24 bits Canvas Width Minus One: 24 bits
: _1-based_ width of the canvas in pixels. : _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 Canvas Height Minus One: 24 bits
: _1-based_ height of the canvas in pixels. : _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`. The product of _Canvas Width_ and _Canvas Height_ MUST be at most `2^32 - 1`.
Future specifications may add more fields. Unknown fields MUST be ignored. Future specifications MAY add more fields.
### Chunks ### Chunks
#### Animation #### Animation
An animation is controlled by 'ANIM' and 'ANMF' Chunks. An animation is controlled by ANIM and ANMF chunks.
'ANIM' Chunk: ANIM Chunk:
{:#anim_chunk} {:#anim_chunk}
For an animated image, this chunk contains the _global parameters_ of the For an animated image, this chunk contains the _global parameters_ of the
@ -387,7 +372,6 @@ animation.
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ANIM') | | ChunkHeader('ANIM') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Background Color | | Background Color |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@ -399,14 +383,14 @@ Background Color: 32 bits (_uint32_)
: The default background color of the canvas in \[Blue, Green, Red, Alpha\] : The default background color of the canvas in \[Blue, Green, Red, Alpha\]
byte order. This color MAY be used to fill the unused space on the canvas byte order. This color MAY be used to fill the unused space on the canvas
around the frames, as well as the transparent pixels of the first frame. around the frames, as well as the transparent pixels of the first frame.
The background color is also used when the Disposal method is `1`. Background color is also used when disposal method is `1`.
**Notes**: **Note**:
* The background color MAY contain a non-opaque alpha value, even if the * Background color MAY contain a transparency value (alpha), even if the
_Alpha_ flag in the ['VP8X' Chunk](#extended_header) is unset. _Alpha_ flag in [VP8X chunk](#extended_header) is unset.
* Viewer applications SHOULD treat the background color value as a hint and * Viewer applications SHOULD treat the background color value as a hint, and
are not required to use it. are not required to use it.
* The canvas is cleared at the start of each loop. The background color MAY be * The canvas is cleared at the start of each loop. The background color MAY be
@ -414,14 +398,13 @@ Background Color: 32 bits (_uint32_)
Loop Count: 16 bits (_uint16_) Loop Count: 16 bits (_uint16_)
: The number of times to loop the animation. If it is `0`, this means : The number of times to loop the animation. `0` means infinitely.
infinitely.
This chunk MUST appear if the _Animation_ flag in the 'VP8X' Chunk is set. This chunk MUST appear if the _Animation_ flag in the VP8X chunk is set.
If the _Animation_ flag is not set and this chunk is present, it MUST be If the _Animation_ flag is not set and this chunk is present, it
ignored. SHOULD be ignored.
'ANMF' Chunk: ANMF chunk:
For animated images, this chunk contains information about a _single_ frame. For animated images, this chunk contains information about a _single_ frame.
If the _Animation flag_ is not set, then this chunk SHOULD NOT be present. If the _Animation flag_ is not set, then this chunk SHOULD NOT be present.
@ -430,7 +413,6 @@ If the _Animation flag_ is not set, then this chunk SHOULD NOT be present.
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ANMF') | | ChunkHeader('ANMF') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Frame X | ... | Frame X | ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@ -440,47 +422,47 @@ If the _Animation flag_ is not set, then this chunk SHOULD NOT be present.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Frame Duration | Reserved |B|D| | Frame Duration | Reserved |B|D|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Frame Data : | Frame Data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Frame X: 24 bits (_uint24_) 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_) 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_) Frame Width Minus One: 24 bits (_uint24_)
: The _1-based_ width of the frame. : 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_) Frame Height Minus One: 24 bits (_uint24_)
: The _1-based_ height of the frame. : 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_) Frame Duration: 24 bits (_uint24_)
: The time to wait before displaying the next frame, in 1-millisecond units. : The time to wait before displaying the next frame, in 1 millisecond units.
Note that the interpretation of the Frame Duration of 0 (and often <= 10) is Note the interpretation of frame duration of 0 (and often <= 10) is
defined by the implementation. Many tools and browsers assign a minimum implementation defined. Many tools and browsers assign a minimum duration
duration similar to GIF. similar to GIF.
Reserved: 6 bits Reserved: 6 bits
: MUST be `0`. Readers MUST ignore this field. : SHOULD be 0.
Blending method (B): 1 bit Blending method (B): 1 bit
: Indicates how transparent pixels of _the current frame_ are to be blended : Indicates how transparent pixels of _the current frame_ are to be blended
with corresponding pixels of the previous canvas: with corresponding pixels of the previous canvas:
* `0`: Use alpha-blending. After disposing of the previous frame, render the * `0`: Use alpha blending. After disposing of the previous frame, render the
current frame on the canvas using [alpha-blending](#alpha-blending). If current frame on the canvas using [alpha-blending](#alpha-blending). If
the current frame does not have an alpha channel, assume the alpha value the current frame does not have an alpha channel, assume alpha value of
is 255, effectively replacing the rectangle. 255, effectively replacing the rectangle.
* `1`: Do not blend. After disposing of the previous frame, render the * `1`: Do not blend. After disposing of the previous frame, render the
current frame on the canvas by overwriting the rectangle covered by the current frame on the canvas by overwriting the rectangle covered by the
@ -493,20 +475,20 @@ Disposal method (D): 1 bit
* `0`: Do not dispose. Leave the canvas as is. * `0`: Do not dispose. Leave the canvas as is.
* `1`: Dispose to the background color. Fill the _rectangle_ on the canvas * `1`: Dispose to background color. Fill the _rectangle_ on the canvas
covered by the _current frame_ with the background color specified in the covered by the _current frame_ with background color specified in the
['ANIM' Chunk](#anim_chunk). [ANIM chunk](#anim_chunk).
**Notes**: **Notes**:
* The frame disposal only applies to the _frame rectangle_, that is, the * The frame disposal only applies to the _frame rectangle_, that is, the
rectangle defined by _Frame X_, _Frame Y_, _frame width_, and _frame rectangle defined by _Frame X_, _Frame Y_, _frame width_ and _frame height_.
height_. It may or may not cover the whole canvas. It may or may not cover the whole canvas.
{:#alpha-blending} {:#alpha-blending}
* Alpha-blending: * **Alpha-blending**:
Given that each of the R, G, B, and A channels is 8 bits, and the RGB Given that each of the R, G, B and A channels is 8-bit, and the RGB
channels are _not premultiplied_ by alpha, the formula for blending channels are _not premultiplied_ by alpha, the formula for blending
'dst' onto 'src' is: 'dst' onto 'src' is:
@ -515,17 +497,16 @@ Disposal method (D): 1 bit
if blend.A = 0 then if blend.A = 0 then
blend.RGB = 0 blend.RGB = 0
else else
blend.RGB = blend.RGB = (src.RGB * src.A +
(src.RGB * src.A + dst.RGB * dst.A * (1 - src.A / 255)) / blend.A
dst.RGB * dst.A * (1 - src.A / 255)) / blend.A
~~~~~ ~~~~~
* Alpha-blending SHOULD be done in linear color space, by taking into account * Alpha-blending SHOULD be done in linear color space, by taking into account
the [color profile](#color-profile) of the image. If the color profile is the [color profile](#color-profile) of the image. If the color profile is
not present, standard RGB (sRGB) is to be assumed. (Note that sRGB also not present, sRGB is to be assumed. (Note that sRGB also needs to be
needs to be linearized due to a gamma of ~2.2.) linearized due to a gamma of ~2.2).
Frame Data: _Chunk Size_ bytes - `16` Frame Data: _Chunk Size_ - `16` bytes
: Consists of: : Consists of:
@ -535,8 +516,8 @@ Frame Data: _Chunk Size_ bytes - `16`
* An optional list of [unknown chunks](#unknown-chunks). * An optional list of [unknown chunks](#unknown-chunks).
**Note**: The 'ANMF' payload, _Frame Data_, consists of individual **Note**: The 'ANMF' payload, _Frame Data_ above, consists of individual
_padded_ chunks, as described by the [RIFF file format](#riff-file-format). _padded_ chunks as described by the [RIFF file format](#riff-file-format).
#### Alpha #### Alpha
@ -544,29 +525,26 @@ _padded_ chunks, as described by the [RIFF file format](#riff-file-format).
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ALPH') | | ChunkHeader('ALPH') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Rsv| P | F | C | Alpha Bitstream... | |Rsv| P | F | C | Alpha Bitstream... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Reserved (Rsv): 2 bits Reserved (Rsv): 2 bits
: MUST be `0`. Readers MUST ignore this field. : SHOULD be `0`.
Preprocessing (P): 2 bits Pre-processing (P): 2 bits
: These _informative_ bits are used to signal the preprocessing that has : These INFORMATIVE bits are used to signal the pre-processing that has
been performed during compression. The decoder can use this information to been performed during compression. The decoder can use this information to
for example, dither the values or smooth the gradients prior to display. e.g. dither the values or smooth the gradients prior to display.
* `0`: No preprocessing. * `0`: no pre-processing
* `1`: Level reduction. * `1`: level reduction
Decoders are not required to use this information in any specified way.
Filtering method (F): 2 bits Filtering method (F): 2 bits
: The filtering methods used are described as follows: : The filtering method used:
* `0`: None. * `0`: None.
* `1`: Horizontal filter. * `1`: Horizontal filter.
@ -590,25 +568,27 @@ made depending on the filtering method:
where `clip(v)` is equal to: where `clip(v)` is equal to:
* 0 if v < 0, * 0 if v < 0
* 255 if v > 255, or * 255 if v > 255
* v otherwise * v otherwise
The final value is derived by adding the decompressed value `X` to the The final value is derived by adding the decompressed value `X` to the
predictor and using modulo-256 arithmetic to wrap the \[256..511\] range predictor and using modulo-256 arithmetic to wrap the \[256-511\] range
into the \[0..255\] one: into the \[0-255\] one:
`alpha = (predictor + X) % 256` `alpha = (predictor + X) % 256`
There are special cases for the left-most and top-most pixel positions. For There are special cases for left-most and top-most pixel positions:
example, the top-left value at location (0, 0) uses 0 as the predictor value.
Otherwise:
* Top-left value at location (0,0) uses 0 as predictor value. Otherwise,
* For horizontal or gradient filtering methods, the left-most pixels at * For horizontal or gradient filtering methods, the left-most pixels at
location (0, y) are predicted using the location (0, y-1) just above. location (0, y) are predicted using the location (0, y-1) just above.
* For vertical or gradient filtering methods, the top-most pixels at * For vertical or gradient filtering methods, the top-most pixels at
location (x, 0) are predicted using the location (x-1, 0) on the left. location (x, 0) are predicted using the location (x-1, 0) on the left.
Decoders are not required to use this information in any specified way.
Compression method (C): 2 bits Compression method (C): 2 bits
: The compression method used: : The compression method used:
@ -616,37 +596,37 @@ Compression method (C): 2 bits
* `0`: No compression. * `0`: No compression.
* `1`: Compressed using the WebP lossless format. * `1`: Compressed using the WebP lossless format.
Alpha bitstream: _Chunk Size_ bytes - `1` Alpha bitstream: _Chunk Size_ - `1` bytes
: Encoded alpha bitstream. : Encoded alpha bitstream.
This optional chunk contains encoded alpha data for this frame. A frame This optional chunk contains encoded alpha data for this frame. A frame
containing a 'VP8L' Chunk SHOULD NOT contain this chunk. containing a 'VP8L' chunk SHOULD NOT contain this chunk.
**Rationale**: The transparency information is already part of the 'VP8L' **Rationale**: The transparency information is already part of the 'VP8L'
Chunk. chunk.
The alpha channel data is stored as uncompressed raw data (when the The alpha channel data is stored as uncompressed raw data (when
compression method is '0') or compressed using the lossless format compression method is '0') or compressed using the lossless format
(when the compression method is '1'). (when the compression method is '1').
* Raw data: This consists of a byte sequence of length = width * height, * Raw data: consists of a byte sequence of length width * height,
containing all the 8-bit transparency values in scan order. containing all the 8-bit transparency values in scan order.
* Lossless format compression: The byte sequence is a compressed * Lossless format compression: the byte sequence is a compressed
image-stream (as described in ["WebP Lossless Bitstream Format"] image-stream (as described in the [WebP Lossless Bitstream Format]
[webpllspec]) of implicit dimensions width x height. That is, this [webpllspec]) of implicit dimension width x height. That is, this
image-stream does NOT contain any headers describing the image dimensions. image-stream does NOT contain any headers describing the image dimension.
**Rationale**: The dimensions are already known from other sources, **Rationale**: the dimension is already known from other sources,
so storing them again would be redundant and prone to error. so storing it again would be redundant and error-prone.
Once the image-stream is decoded into Alpha, Red, Green, Blue (ARGB) color Once the image-stream is decoded into ARGB color values, following
values, following the process described in the lossless format the process described in the lossless format specification, the
specification, the transparency information must be extracted from the transparency information must be extracted from the *green* channel
*green* channel of the ARGB quadruplet. of the ARGB quadruplet.
**Rationale**: The green channel is allowed extra transformation **Rationale**: the green channel is allowed extra transformation
steps in the specification -- unlike the other channels -- that can steps in the specification -- unlike the other channels -- that can
improve compression. improve compression.
@ -654,23 +634,22 @@ compression method is '0') or compressed using the lossless format
This chunk contains compressed bitstream data for a single frame. This chunk contains compressed bitstream data for a single frame.
A bitstream chunk may be either (i) a 'VP8 ' Chunk, using 'VP8 ' (note the A bitstream chunk may be either (i) a VP8 chunk, using "VP8 " (note the
significant fourth-character space) as its FourCC, _or_ (ii) a 'VP8L' Chunk, significant fourth-character space) as its tag _or_ (ii) a VP8L chunk, using
using 'VP8L' as its FourCC. "VP8L" as its tag.
The formats of 'VP8 ' and 'VP8L' Chunks are as described in sections The formats of VP8 and VP8L chunks are as described in sections
[Simple File Format (Lossy)](#simple-file-format-lossy) [Simple File Format (Lossy)](#simple-file-format-lossy)
and [Simple File Format (Lossless)](#simple-file-format-lossless), respectively. and [Simple File Format (Lossless)](#simple-file-format-lossless) respectively.
#### Color Profile #### Color profile
0 1 2 3 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ICCP') | | ChunkHeader('ICCP') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Color Profile : | Color Profile |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Color Profile: _Chunk Size_ bytes Color Profile: _Chunk Size_ bytes
@ -687,145 +666,114 @@ If this chunk is not present, sRGB SHOULD be assumed.
#### Metadata #### Metadata
Metadata can be stored in 'EXIF' or 'XMP ' Chunks. Metadata can be stored in 'EXIF' or 'XMP ' chunks.
There SHOULD be at most one chunk of each type ('EXIF' and 'XMP '). If there There SHOULD be at most one chunk of each type ('EXIF' and 'XMP '). If there
are more such chunks, readers MAY ignore all except the first one. are more such chunks, readers MAY ignore all except the first one. Also, a file
may possibly contain both 'EXIF' and 'XMP ' chunks.
The chunks are defined as follows: The chunks are defined as follows:
'EXIF' Chunk: EXIF chunk:
0 1 2 3 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('EXIF') | | ChunkHeader('EXIF') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Exif Metadata : | EXIF Metadata |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Exif Metadata: _Chunk Size_ bytes EXIF Metadata: _Chunk Size_ bytes
: Image metadata in Exif format. : image metadata in EXIF format.
'XMP ' Chunk: XMP chunk:
0 1 2 3 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('XMP ') | | ChunkHeader('XMP ') |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: XMP Metadata : | XMP Metadata |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
XMP Metadata: _Chunk Size_ bytes XMP Metadata: _Chunk Size_ bytes
: Image metadata in XMP format. : image metadata in XMP format.
Note that the fourth character in the 'XMP ' FourCC is an ASCII space (0x20).
Additional guidance about handling metadata can be found in the Additional guidance about handling metadata can be found in the
Metadata Working Group's ["Guidelines for Handling Metadata"][metadata]. Metadata Working Group's [Guidelines for Handling Metadata][metadata].
#### Unknown Chunks #### Unknown Chunks _\[status: experimental\]_
A RIFF chunk (described in the [RIFF File Format](#riff-file-format) section) A RIFF chunk (described in [this](#terminology-amp-basics) section) whose _chunk
whose FourCC is different from any of the chunks described in this document, is tag_ is different from any of the chunks described in this document, is
considered an _unknown chunk_. considered an _unknown chunk_.
**Rationale**: Allowing unknown chunks gives a provision for future extension **Rationale**: Allowing unknown chunks gives a provision for future extension
of the format and also allows storage of any application-specific data. of the format, and also allows storage of any application-specific data.
A file MAY contain unknown chunks: A file MAY contain unknown chunks:
* at the end of the file, as described in [Extended WebP file * At the end of the file as described in [Extended WebP file
header](#extended_header) section, or header](#extended_header) section.
* at the end of 'ANMF' Chunks, as described in the * At the end of ANMF chunks as described in the
[Animation](#animation) section. [Animation](#animation) section.
Readers SHOULD ignore these chunks. Writers SHOULD preserve them in their Readers SHOULD ignore these chunks. Writers SHOULD preserve them in their
original order (unless they specifically intend to modify these chunks). original order (unless they specifically intend to modify these chunks).
### Canvas Assembly from Frames ### Assembling the Canvas from frames
Here we provide an overview of how a reader MUST assemble a canvas in the case Here we provide an overview of how a reader should assemble a canvas in the
of an animated image. case of an animated image. The notation _VP8X.field_ means the field in the
'VP8X' chunk with the same description.
The process begins with creating a canvas using the dimensions given in the Displaying an _animated image_ canvas MUST be equivalent to the following
'VP8X' Chunk, `Canvas Width Minus One + 1` pixels wide by `Canvas Height Minus pseudocode:
One + 1` pixels high. The `Loop Count` field from the 'ANIM' Chunk controls how
many times the animation process is repeated. This is `Loop Count - 1` for
nonzero `Loop Count` values or infinite if the `Loop Count` is zero.
At the beginning of each loop iteration, the canvas is filled using the
background color from the 'ANIM' Chunk or an application-defined color.
'ANMF' Chunks contain individual frames given in display order. Before rendering
each frame, the previous frame's `Disposal method` is applied.
The rendering of the decoded frame begins at the Cartesian coordinates (`2 *
Frame X`, `2 * Frame Y`), using the top-left corner of the canvas as the origin.
`Frame Width Minus One + 1` pixels wide by `Frame Height Minus One + 1` pixels
high are rendered onto the canvas using the `Blending method`.
The canvas is displayed for `Frame Duration` milliseconds. This continues until
all frames given by 'ANMF' Chunks have been displayed. A new loop iteration is
then begun, or the canvas is left in its final state if all iterations have been
completed.
The following pseudocode illustrates the rendering process. The notation
_VP8X.field_ means the field in the 'VP8X' Chunk with the same description.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
VP8X.flags.hasAnimation MUST be TRUE assert VP8X.flags.hasAnimation
canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with
background color ANIM.background_color or background color ANIM.background_color.
application-defined color.
loop_count ← ANIM.loopCount loop_count ← ANIM.loopCount
dispose_method ← Dispose to background color dispose_method ← ANIM.disposeMethod
if loop_count == 0: if loop_count == 0:
loop_count = ∞ loop_count = ∞
frame_params ← nil frame_params ← nil
next chunk in image_data is ANMF MUST be TRUE assert next chunk in image_data is ANMF
for loop = 0..loop_count - 1 for loop = 0..loop_count - 1
clear canvas to ANIM.background_color or application-defined color clear canvas to ANIM.background_color or application defined color
until eof or non-ANMF chunk until eof or non-ANMF chunk
frame_params.frameX = Frame X frame_params.frameX = Frame X
frame_params.frameY = Frame Y frame_params.frameY = Frame Y
frame_params.frameWidth = Frame Width Minus One + 1 frame_params.frameWidth = Frame Width Minus One + 1
frame_params.frameHeight = Frame Height Minus One + 1 frame_params.frameHeight = Frame Height Minus One + 1
frame_params.frameDuration = Frame Duration frame_params.frameDuration = Frame Duration
frame_right = frame_params.frameX + frame_params.frameWidth frame_right = frame_params.frameX + frame_params.frameWidth
frame_bottom = frame_params.frameY + frame_params.frameHeight frame_bottom = frame_params.frameY + frame_params.frameHeight
VP8X.canvasWidth >= frame_right MUST be TRUE assert VP8X.canvasWidth >= frame_right
VP8X.canvasHeight >= frame_bottom MUST be TRUE assert VP8X.canvasHeight >= frame_bottom
for subchunk in 'Frame Data': for subchunk in 'Frame Data':
if subchunk.tag == "ALPH": if subchunk.tag == "ALPH":
alpha subchunks not found in 'Frame Data' earlier MUST be assert alpha subchunks not found in 'Frame Data' earlier
TRUE frame_params.alpha = alpha_data
frame_params.alpha = alpha_data else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L": assert bitstream subchunks not found in 'Frame Data' earlier
bitstream subchunks not found in 'Frame Data' earlier MUST frame_params.bitstream = bitstream_data
be TRUE render frame with frame_params.alpha and frame_params.bitstream on
frame_params.bitstream = bitstream_data canvas with top-left corner at (frame_params.frameX,
apply dispose_method. frame_params.frameY), using dispose method dispose_method.
render frame with frame_params.alpha and frame_params.bitstream canvas contains the decoded image.
on canvas with top-left corner at (frame_params.frameX, Show the contents of the canvas for frame_params.frameDuration * 1ms.
frame_params.frameY), using Blending method
frame_params.blendingMethod.
canvas contains the decoded image.
Show the contents of the canvas for
frame_params.frameDuration * 1 ms.
dispose_method = frame_params.disposeMethod
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Example File Layouts Example File Layouts
-------------------- --------------------
A lossy-encoded image with alpha may look as follows: A lossy encoded image with alpha may look as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RIFF/WEBP RIFF/WEBP
@ -834,16 +782,16 @@ RIFF/WEBP
+- VP8 (bitstream) +- VP8 (bitstream)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A lossless-encoded image may look as follows: A losslessly encoded image may look as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RIFF/WEBP RIFF/WEBP
+- VP8X (descriptions of features used) +- VP8X (descriptions of features used)
+- VP8L (lossless bitstream)
+- XYZW (unknown chunk) +- XYZW (unknown chunk)
+- VP8L (lossless bitstream)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A lossless image with an ICC profile and XMP metadata may A lossless image with ICC profile and XMP metadata may
look as follows: look as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -854,7 +802,7 @@ RIFF/WEBP
+- XMP (metadata) +- XMP (metadata)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An animated image with Exif metadata may look as follows: An animated image with EXIF metadata may look as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RIFF/WEBP RIFF/WEBP
@ -867,11 +815,9 @@ RIFF/WEBP
+- EXIF (metadata) +- EXIF (metadata)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/webp-lossless-bitstream-spec.txt [vp8spec]: http://tools.ietf.org/html/rfc6386
[iccspec]: https://www.color.org/icc_specs2.xalter [webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt
[metadata]: https://web.archive.org/web/20180919181934/http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf [iccspec]: http://www.color.org/icc_specs2.xalter
[rec601]: https://www.itu.int/rec/R-REC-BT.601 [metadata]: http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
[rfc 1166]: https://datatracker.ietf.org/doc/html/rfc1166 [rfc 1166]: http://tools.ietf.org/html/rfc1166
[rfc 2119]: https://datatracker.ietf.org/doc/html/rfc2119 [rfc 2119]: http://tools.ietf.org/html/rfc2119
[rfc 6386]: https://datatracker.ietf.org/doc/html/rfc6386
[rfc 8174]: https://datatracker.ietf.org/doc/html/rfc8174

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,3 @@
# Ignore this file during non-NDK builds.
ifdef NDK_ROOT
LOCAL_PATH := $(call my-dir) LOCAL_PATH := $(call my-dir)
################################################################################ ################################################################################
@ -93,4 +91,3 @@ LOCAL_STATIC_LIBRARIES := example_util imageio_util webp
LOCAL_MODULE := webpinfo_example LOCAL_MODULE := webpinfo_example
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
endif # NDK_ROOT

View File

@ -47,7 +47,7 @@ anim_dump_LDADD += ../imageio/libimageenc.la
anim_dump_LDADD += $(PNG_LIBS) $(GIF_LIBS) $(TIFF_LIBS) -lm anim_dump_LDADD += $(PNG_LIBS) $(GIF_LIBS) $(TIFF_LIBS) -lm
cwebp_SOURCES = cwebp.c stopwatch.h cwebp_SOURCES = cwebp.c stopwatch.h
cwebp_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir) cwebp_CPPFLAGS = $(AM_CPPFLAGS)
cwebp_LDADD = cwebp_LDADD =
cwebp_LDADD += libexample_util.la cwebp_LDADD += libexample_util.la
cwebp_LDADD += ../imageio/libimageio_util.la cwebp_LDADD += ../imageio/libimageio_util.la
@ -67,7 +67,7 @@ dwebp_LDADD += ../src/libwebp.la
dwebp_LDADD +=$(PNG_LIBS) $(JPEG_LIBS) dwebp_LDADD +=$(PNG_LIBS) $(JPEG_LIBS)
gif2webp_SOURCES = gif2webp.c gifdec.c gifdec.h gif2webp_SOURCES = gif2webp.c gifdec.c gifdec.h
gif2webp_CPPFLAGS = $(AM_CPPFLAGS) $(GIF_INCLUDES) -I$(top_srcdir) gif2webp_CPPFLAGS = $(AM_CPPFLAGS) $(GIF_INCLUDES)
gif2webp_LDADD = gif2webp_LDADD =
gif2webp_LDADD += libexample_util.la gif2webp_LDADD += libexample_util.la
gif2webp_LDADD += ../imageio/libimageio_util.la gif2webp_LDADD += ../imageio/libimageio_util.la
@ -92,7 +92,7 @@ webpmux_LDADD += ../src/mux/libwebpmux.la
webpmux_LDADD += ../src/libwebp.la webpmux_LDADD += ../src/libwebp.la
img2webp_SOURCES = img2webp.c img2webp_SOURCES = img2webp.c
img2webp_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir) img2webp_CPPFLAGS = $(AM_CPPFLAGS)
img2webp_LDADD = img2webp_LDADD =
img2webp_LDADD += libexample_util.la img2webp_LDADD += libexample_util.la
img2webp_LDADD += ../imageio/libimageio_util.la img2webp_LDADD += ../imageio/libimageio_util.la

View File

@ -16,13 +16,12 @@
#include <assert.h> #include <assert.h>
#include <limits.h> #include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h> // for 'strtod'.
#include <string.h> // for 'strcmp'. #include <string.h> // for 'strcmp'.
#include "./anim_util.h" #include "./anim_util.h"
#include "./example_util.h" #include "./example_util.h"
#include "./unicode.h" #include "./unicode.h"
#include "webp/types.h"
#if defined(_MSC_VER) && _MSC_VER < 1900 #if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf #define snprintf _snprintf
@ -207,9 +206,8 @@ static void Help(void) {
printf(" -version ............ print version number and exit\n"); printf(" -version ............ print version number and exit\n");
} }
// Returns 0 on success, 1 if animation files differ, and 2 for any error.
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
int return_code = 2; int return_code = -1;
int dump_frames = 0; int dump_frames = 0;
const char* dump_folder = NULL; const char* dump_folder = NULL;
double min_psnr = 0.; double min_psnr = 0.;
@ -271,18 +269,18 @@ int main(int argc, const char* argv[]) {
} }
if (parse_error) { if (parse_error) {
Help(); Help();
FREE_WARGV_AND_RETURN(return_code); FREE_WARGV_AND_RETURN(-1);
} }
} }
if (argc < 3) { if (argc < 3) {
Help(); Help();
FREE_WARGV_AND_RETURN(return_code); FREE_WARGV_AND_RETURN(-1);
} }
if (!got_input2) { if (!got_input2) {
Help(); Help();
FREE_WARGV_AND_RETURN(return_code); FREE_WARGV_AND_RETURN(-1);
} }
if (dump_frames) { if (dump_frames) {
@ -295,7 +293,7 @@ int main(int argc, const char* argv[]) {
if (!ReadAnimatedImage(files[i], &images[i], dump_frames, dump_folder)) { if (!ReadAnimatedImage(files[i], &images[i], dump_frames, dump_folder)) {
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n", WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n",
(const W_CHAR*)files[i]); (const W_CHAR*)files[i]);
return_code = 2; return_code = -2;
goto End; goto End;
} else { } else {
MinimizeAnimationFrames(&images[i], max_diff); MinimizeAnimationFrames(&images[i], max_diff);
@ -306,7 +304,7 @@ int main(int argc, const char* argv[]) {
premultiply, min_psnr)) { premultiply, min_psnr)) {
WFPRINTF(stderr, "\nFiles %s and %s differ.\n", (const W_CHAR*)files[0], WFPRINTF(stderr, "\nFiles %s and %s differ.\n", (const W_CHAR*)files[0],
(const W_CHAR*)files[1]); (const W_CHAR*)files[1]);
return_code = 1; return_code = -3;
} else { } else {
WPRINTF("\nFiles %s and %s are identical.\n", (const W_CHAR*)files[0], WPRINTF("\nFiles %s and %s are identical.\n", (const W_CHAR*)files[0],
(const W_CHAR*)files[1]); (const W_CHAR*)files[1]);

View File

@ -12,14 +12,12 @@
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> // for 'strcmp'. #include <string.h> // for 'strcmp'.
#include "../imageio/image_enc.h"
#include "./anim_util.h" #include "./anim_util.h"
#include "./unicode.h"
#include "webp/decode.h" #include "webp/decode.h"
#include "webp/types.h" #include "../imageio/image_enc.h"
#include "./unicode.h"
#if defined(_MSC_VER) && _MSC_VER < 1900 #if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf #define snprintf _snprintf
@ -37,7 +35,6 @@ static void Help(void) {
printf(" -version ............ print version number and exit\n"); printf(" -version ............ print version number and exit\n");
} }
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
int error = 0; int error = 0;
const W_CHAR* dump_folder = TO_W_CHAR("."); const W_CHAR* dump_folder = TO_W_CHAR(".");
@ -50,7 +47,7 @@ int main(int argc, const char* argv[]) {
if (argc < 2) { if (argc < 2) {
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
for (c = 1; !error && c < argc; ++c) { for (c = 1; !error && c < argc; ++c) {
@ -76,7 +73,7 @@ int main(int argc, const char* argv[]) {
suffix = TO_W_CHAR("pam"); suffix = TO_W_CHAR("pam");
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-version")) { } else if (!strcmp(argv[c], "-version")) {
int dec_version, demux_version; int dec_version, demux_version;
GetAnimatedImageVersions(&dec_version, &demux_version); GetAnimatedImageVersions(&dec_version, &demux_version);
@ -85,7 +82,7 @@ int main(int argc, const char* argv[]) {
(dec_version >> 0) & 0xff, (dec_version >> 0) & 0xff,
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff, (demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
(demux_version >> 0) & 0xff); (demux_version >> 0) & 0xff);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); FREE_WARGV_AND_RETURN(0);
} else { } else {
uint32_t i; uint32_t i;
AnimatedImage image; AnimatedImage image;
@ -101,11 +98,7 @@ int main(int argc, const char* argv[]) {
for (i = 0; !error && i < image.num_frames; ++i) { for (i = 0; !error && i < image.num_frames; ++i) {
W_CHAR out_file[1024]; W_CHAR out_file[1024];
WebPDecBuffer buffer; WebPDecBuffer buffer;
if (!WebPInitDecBuffer(&buffer)) { WebPInitDecBuffer(&buffer);
fprintf(stderr, "Cannot init dec buffer\n");
error = 1;
continue;
}
buffer.colorspace = MODE_RGBA; buffer.colorspace = MODE_RGBA;
buffer.is_external_memory = 1; buffer.is_external_memory = 1;
buffer.width = image.canvas_width; buffer.width = image.canvas_width;
@ -124,5 +117,5 @@ int main(int argc, const char* argv[]) {
ClearAnimatedImage(&image); ClearAnimatedImage(&image);
} }
} }
FREE_WARGV_AND_RETURN(error ? EXIT_FAILURE : EXIT_SUCCESS); FREE_WARGV_AND_RETURN(error ? 1 : 0);
} }

View File

@ -19,16 +19,13 @@
#if defined(WEBP_HAVE_GIF) #if defined(WEBP_HAVE_GIF)
#include <gif_lib.h> #include <gif_lib.h>
#endif #endif
#include "webp/format_constants.h"
#include "webp/decode.h"
#include "webp/demux.h"
#include "../imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "./gifdec.h" #include "./gifdec.h"
#include "./unicode.h" #include "./unicode.h"
#include "./unicode_gif.h" #include "./unicode_gif.h"
#include "webp/decode.h"
#include "webp/demux.h"
#include "webp/format_constants.h"
#include "webp/mux_types.h"
#include "webp/types.h"
#if defined(_MSC_VER) && _MSC_VER < 1900 #if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf #define snprintf _snprintf
@ -244,7 +241,7 @@ static int ReadAnimatedWebP(const char filename[],
image->bgcolor = anim_info.bgcolor; image->bgcolor = anim_info.bgcolor;
// Allocate frames. // Allocate frames.
if (!AllocateFrames(image, anim_info.frame_count)) goto End; if (!AllocateFrames(image, anim_info.frame_count)) return 0;
// Decode frames. // Decode frames.
while (WebPAnimDecoderHasMoreFrames(dec)) { while (WebPAnimDecoderHasMoreFrames(dec)) {
@ -408,7 +405,7 @@ static uint32_t GetBackgroundColorGIF(GifFileType* gif) {
return 0xffffffff; // Invalid: assume white. return 0xffffffff; // Invalid: assume white.
} else { } else {
const GifColorType color = color_map->Colors[gif->SBackGroundColor]; const GifColorType color = color_map->Colors[gif->SBackGroundColor];
return (0xffu << 24) | return (0xff << 24) |
(color.Red << 16) | (color.Red << 16) |
(color.Green << 8) | (color.Green << 8) |
(color.Blue << 0); (color.Blue << 0);
@ -561,10 +558,7 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
} }
} }
// Allocate frames. // Allocate frames.
if (!AllocateFrames(image, frame_count)) { AllocateFrames(image, frame_count);
DGifCloseFile(gif, NULL);
return 0;
}
canvas_width = image->canvas_width; canvas_width = image->canvas_width;
canvas_height = image->canvas_height; canvas_height = image->canvas_height;
@ -774,7 +768,6 @@ void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
*psnr = 99.; // PSNR when images are identical. *psnr = 99.; // PSNR when images are identical.
} else { } else {
sse /= stride * height; sse /= stride * height;
assert(sse != 0.0);
*psnr = 4.3429448 * log(255. * 255. / sse); *psnr = 4.3429448 * log(255. * 255. / sse);
} }
} }

View File

@ -12,7 +12,6 @@
// //
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -24,13 +23,9 @@
#include "../examples/example_util.h" #include "../examples/example_util.h"
#include "../imageio/image_dec.h" #include "../imageio/image_dec.h"
#include "../imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "../imageio/webpdec.h"
#include "./stopwatch.h" #include "./stopwatch.h"
#include "./unicode.h" #include "./unicode.h"
#include "imageio/metadata.h"
#include "sharpyuv/sharpyuv.h"
#include "webp/encode.h" #include "webp/encode.h"
#include "webp/types.h"
#ifndef WEBP_DLL #ifndef WEBP_DLL
#ifdef __cplusplus #ifdef __cplusplus
@ -97,7 +92,7 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic,
WFPRINTF(stderr, "Error! Could not process file %s\n", WFPRINTF(stderr, "Error! Could not process file %s\n",
(const W_CHAR*)filename); (const W_CHAR*)filename);
} }
WebPFree((void*)data); free((void*)data);
return ok; return ok;
} }
@ -124,7 +119,7 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic,
WFPRINTF(stderr, "Error! Could not process file %s\n", WFPRINTF(stderr, "Error! Could not process file %s\n",
(const W_CHAR*)filename); (const W_CHAR*)filename);
} }
WebPFree((void*)data); free((void*)data);
return ok; return ok;
} }
@ -153,7 +148,7 @@ static void PrintPercents(const int counts[4]) {
int s; int s;
const int total = counts[0] + counts[1] + counts[2] + counts[3]; const int total = counts[0] + counts[1] + counts[2] + counts[3];
for (s = 0; s < 4; ++s) { for (s = 0; s < 4; ++s) {
fprintf(stderr, "| %3d%%", (int)(100. * counts[s] / total + .5)); fprintf(stderr, "| %2d%%", (int)(100. * counts[s] / total + .5));
} }
fprintf(stderr, "| %7d\n", total); fprintf(stderr, "| %7d\n", total);
} }
@ -180,14 +175,8 @@ static void PrintFullLosslessInfo(const WebPAuxStats* const stats,
if (stats->lossless_features & 8) fprintf(stderr, " PALETTE"); if (stats->lossless_features & 8) fprintf(stderr, " PALETTE");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
fprintf(stderr, " * Precision Bits: histogram=%d", stats->histogram_bits); fprintf(stderr, " * Precision Bits: histogram=%d transform=%d cache=%d\n",
if (stats->lossless_features & 1) { stats->histogram_bits, stats->transform_bits, stats->cache_bits);
fprintf(stderr, " prediction=%d", stats->transform_bits);
}
if (stats->lossless_features & 2) {
fprintf(stderr, " cross-color=%d", stats->cross_color_transform_bits);
}
fprintf(stderr, " cache=%d\n", stats->cache_bits);
if (stats->palette_size > 0) { if (stats->palette_size > 0) {
fprintf(stderr, " * Palette size: %d\n", stats->palette_size); fprintf(stderr, " * Palette size: %d\n", stats->palette_size);
} }
@ -314,7 +303,6 @@ static int MyWriter(const uint8_t* data, size_t data_size,
// Dumps a picture as a PGM file using the IMC4 layout. // Dumps a picture as a PGM file using the IMC4 layout.
static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) { static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
int y; int y;
int ok = 0;
const int uv_width = (picture->width + 1) / 2; const int uv_width = (picture->width + 1) / 2;
const int uv_height = (picture->height + 1) / 2; const int uv_height = (picture->height + 1) / 2;
const int stride = (picture->width + 1) & ~1; const int stride = (picture->width + 1) & ~1;
@ -329,26 +317,23 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
if (f == NULL) return 0; if (f == NULL) return 0;
fprintf(f, "P5\n%d %d\n255\n", stride, height); fprintf(f, "P5\n%d %d\n255\n", stride, height);
for (y = 0; y < picture->height; ++y) { for (y = 0; y < picture->height; ++y) {
if (fwrite(src_y, picture->width, 1, f) != 1) goto Error; if (fwrite(src_y, picture->width, 1, f) != 1) return 0;
if (picture->width & 1) fputc(0, f); // pad if (picture->width & 1) fputc(0, f); // pad
src_y += picture->y_stride; src_y += picture->y_stride;
} }
for (y = 0; y < uv_height; ++y) { for (y = 0; y < uv_height; ++y) {
if (fwrite(src_u, uv_width, 1, f) != 1) goto Error; if (fwrite(src_u, uv_width, 1, f) != 1) return 0;
if (fwrite(src_v, uv_width, 1, f) != 1) goto Error; if (fwrite(src_v, uv_width, 1, f) != 1) return 0;
src_u += picture->uv_stride; src_u += picture->uv_stride;
src_v += picture->uv_stride; src_v += picture->uv_stride;
} }
for (y = 0; y < alpha_height; ++y) { for (y = 0; y < alpha_height; ++y) {
if (fwrite(src_a, picture->width, 1, f) != 1) goto Error; if (fwrite(src_a, picture->width, 1, f) != 1) return 0;
if (picture->width & 1) fputc(0, f); // pad if (picture->width & 1) fputc(0, f); // pad
src_a += picture->a_stride; src_a += picture->a_stride;
} }
ok = 1;
Error:
fclose(f); fclose(f);
return ok; return 1;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -517,37 +502,6 @@ static int WriteWebPWithMetadata(FILE* const out,
return (fwrite(webp, webp_size, 1, out) == 1); return (fwrite(webp, webp_size, 1, out) == 1);
} }
//------------------------------------------------------------------------------
// Resize
enum {
RESIZE_MODE_DOWN_ONLY,
RESIZE_MODE_UP_ONLY,
RESIZE_MODE_ALWAYS,
RESIZE_MODE_DEFAULT = RESIZE_MODE_ALWAYS
};
static void ApplyResizeMode(const int resize_mode,
const WebPPicture* const pic,
int* const resize_w, int* const resize_h) {
const int src_w = pic->width;
const int src_h = pic->height;
const int dst_w = *resize_w;
const int dst_h = *resize_h;
if (resize_mode == RESIZE_MODE_DOWN_ONLY) {
if ((dst_w == 0 && src_h <= dst_h) ||
(dst_h == 0 && src_w <= dst_w) ||
(src_w <= dst_w && src_h <= dst_h)) {
*resize_w = *resize_h = 0;
}
} else if (resize_mode == RESIZE_MODE_UP_ONLY) {
if (src_w >= dst_w && src_h >= dst_h) {
*resize_w = *resize_h = 0;
}
}
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static int ProgressReport(int percent, const WebPPicture* const picture) { static int ProgressReport(int percent, const WebPPicture* const picture) {
@ -571,7 +525,6 @@ static void HelpLong(void) {
printf(" cwebp [-preset <...>] [options] in_file [-o out_file]\n\n"); printf(" cwebp [-preset <...>] [options] in_file [-o out_file]\n\n");
printf("If input size (-s) for an image is not specified, it is\n" printf("If input size (-s) for an image is not specified, it is\n"
"assumed to be a PNG, JPEG, TIFF or WebP file.\n"); "assumed to be a PNG, JPEG, TIFF or WebP file.\n");
printf("Note: Animated PNG and WebP files are not supported.\n");
#ifdef HAVE_WINCODEC_H #ifdef HAVE_WINCODEC_H
printf("Windows builds can take as input any of the files handled by WIC.\n"); printf("Windows builds can take as input any of the files handled by WIC.\n");
#endif #endif
@ -612,12 +565,8 @@ static void HelpLong(void) {
printf(" " printf(" "
"the first partition (0=no degradation ... 100=full)\n"); "the first partition (0=no degradation ... 100=full)\n");
printf(" -pass <int> ............ analysis pass number (1..10)\n"); printf(" -pass <int> ............ analysis pass number (1..10)\n");
printf(" -qrange <min> <max> .... specifies the permissible quality range\n"
" (default: 0 100)\n");
printf(" -crop <x> <y> <w> <h> .. crop picture with the given rectangle\n"); printf(" -crop <x> <y> <w> <h> .. crop picture with the given rectangle\n");
printf(" -resize <w> <h> ........ resize picture (*after* any cropping)\n"); printf(" -resize <w> <h> ........ resize picture (after any cropping)\n");
printf(" -resize_mode <string> .. one of: up_only, down_only,"
" always (default)\n");
printf(" -mt .................... use multi-threading if available\n"); printf(" -mt .................... use multi-threading if available\n");
printf(" -low_memory ............ reduce memory usage (slower encoding)\n"); printf(" -low_memory ............ reduce memory usage (slower encoding)\n");
printf(" -map <int> ............. print map of extra info\n"); printf(" -map <int> ............. print map of extra info\n");
@ -637,8 +586,9 @@ static void HelpLong(void) {
" green=0xe0 and blue=0xd0\n"); " green=0xe0 and blue=0xd0\n");
printf(" -noalpha ............... discard any transparency information\n"); printf(" -noalpha ............... discard any transparency information\n");
printf(" -lossless .............. encode image losslessly, default=off\n"); printf(" -lossless .............. encode image losslessly, default=off\n");
printf(" -near_lossless <int> ... use near-lossless image preprocessing\n" printf(" -near_lossless <int> ... use near-lossless image\n"
" (0..100=off), default=100\n"); " preprocessing (0..100=off), "
"default=100\n");
printf(" -hint <string> ......... specify image characteristics hint,\n"); printf(" -hint <string> ......... specify image characteristics hint,\n");
printf(" one of: photo, picture or graph\n"); printf(" one of: photo, picture or graph\n");
@ -665,7 +615,6 @@ static void HelpLong(void) {
printf(" -af .................... auto-adjust filter strength\n"); printf(" -af .................... auto-adjust filter strength\n");
printf(" -pre <int> ............. pre-processing filter\n"); printf(" -pre <int> ............. pre-processing filter\n");
printf("\n"); printf("\n");
printf("Supported input formats:\n %s\n", WebPGetEnabledInputFileFormats());
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -692,9 +641,8 @@ static const char* const kErrorMessages[VP8_ENC_ERROR_LAST] = {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
int return_value = EXIT_FAILURE; int return_value = -1;
const char* in_file = NULL, *out_file = NULL, *dump_file = NULL; const char* in_file = NULL, *out_file = NULL, *dump_file = NULL;
FILE* out = NULL; FILE* out = NULL;
int c; int c;
@ -705,7 +653,6 @@ int main(int argc, const char* argv[]) {
uint32_t background_color = 0xffffffu; uint32_t background_color = 0xffffffu;
int crop = 0, crop_x = 0, crop_y = 0, crop_w = 0, crop_h = 0; int crop = 0, crop_x = 0, crop_y = 0, crop_w = 0, crop_h = 0;
int resize_w = 0, resize_h = 0; int resize_w = 0, resize_h = 0;
int resize_mode = RESIZE_MODE_DEFAULT;
int lossless_preset = 6; int lossless_preset = 6;
int use_lossless_preset = -1; // -1=unset, 0=don't use, 1=use it int use_lossless_preset = -1; // -1=unset, 0=don't use, 1=use it
int show_progress = 0; int show_progress = 0;
@ -717,7 +664,6 @@ int main(int argc, const char* argv[]) {
WebPConfig config; WebPConfig config;
WebPAuxStats stats; WebPAuxStats stats;
WebPMemoryWriter memory_writer; WebPMemoryWriter memory_writer;
int use_memory_writer;
Metadata metadata; Metadata metadata;
Stopwatch stop_watch; Stopwatch stop_watch;
@ -729,25 +675,25 @@ int main(int argc, const char* argv[]) {
!WebPPictureInit(&original_picture) || !WebPPictureInit(&original_picture) ||
!WebPConfigInit(&config)) { !WebPConfigInit(&config)) {
fprintf(stderr, "Error! Version mismatch!\n"); fprintf(stderr, "Error! Version mismatch!\n");
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
if (argc == 1) { if (argc == 1) {
HelpShort(); HelpShort();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(0);
} }
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
int parse_error = 0; int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
HelpShort(); HelpShort();
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) { } else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
HelpLong(); HelpLong();
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-o") && c + 1 < argc) { } else if (!strcmp(argv[c], "-o") && c < argc - 1) {
out_file = (const char*)GET_WARGV(argv, ++c); out_file = (const char*)GET_WARGV(argv, ++c);
} else if (!strcmp(argv[c], "-d") && c + 1 < argc) { } else if (!strcmp(argv[c], "-d") && c < argc - 1) {
dump_file = (const char*)GET_WARGV(argv, ++c); dump_file = (const char*)GET_WARGV(argv, ++c);
config.show_compressed = 1; config.show_compressed = 1;
} else if (!strcmp(argv[c], "-print_psnr")) { } else if (!strcmp(argv[c], "-print_psnr")) {
@ -761,7 +707,7 @@ int main(int argc, const char* argv[]) {
print_distortion = 2; print_distortion = 2;
} else if (!strcmp(argv[c], "-short")) { } else if (!strcmp(argv[c], "-short")) {
++short_output; ++short_output;
} else if (!strcmp(argv[c], "-s") && c + 2 < argc) { } else if (!strcmp(argv[c], "-s") && c < argc - 2) {
picture.width = ExUtilGetInt(argv[++c], 0, &parse_error); picture.width = ExUtilGetInt(argv[++c], 0, &parse_error);
picture.height = ExUtilGetInt(argv[++c], 0, &parse_error); picture.height = ExUtilGetInt(argv[++c], 0, &parse_error);
if (picture.width > WEBP_MAX_DIMENSION || picture.width < 0 || if (picture.width > WEBP_MAX_DIMENSION || picture.width < 0 ||
@ -771,30 +717,30 @@ int main(int argc, const char* argv[]) {
picture.width, picture.height); picture.width, picture.height);
goto Error; goto Error;
} }
} else if (!strcmp(argv[c], "-m") && c + 1 < argc) { } else if (!strcmp(argv[c], "-m") && c < argc - 1) {
config.method = ExUtilGetInt(argv[++c], 0, &parse_error); config.method = ExUtilGetInt(argv[++c], 0, &parse_error);
use_lossless_preset = 0; // disable -z option use_lossless_preset = 0; // disable -z option
} else if (!strcmp(argv[c], "-q") && c + 1 < argc) { } else if (!strcmp(argv[c], "-q") && c < argc - 1) {
config.quality = ExUtilGetFloat(argv[++c], &parse_error); config.quality = ExUtilGetFloat(argv[++c], &parse_error);
use_lossless_preset = 0; // disable -z option use_lossless_preset = 0; // disable -z option
} else if (!strcmp(argv[c], "-z") && c + 1 < argc) { } else if (!strcmp(argv[c], "-z") && c < argc - 1) {
lossless_preset = ExUtilGetInt(argv[++c], 0, &parse_error); lossless_preset = ExUtilGetInt(argv[++c], 0, &parse_error);
if (use_lossless_preset != 0) use_lossless_preset = 1; if (use_lossless_preset != 0) use_lossless_preset = 1;
} else if (!strcmp(argv[c], "-alpha_q") && c + 1 < argc) { } else if (!strcmp(argv[c], "-alpha_q") && c < argc - 1) {
config.alpha_quality = ExUtilGetInt(argv[++c], 0, &parse_error); config.alpha_quality = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-alpha_method") && c + 1 < argc) { } else if (!strcmp(argv[c], "-alpha_method") && c < argc - 1) {
config.alpha_compression = ExUtilGetInt(argv[++c], 0, &parse_error); config.alpha_compression = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-alpha_cleanup")) { } else if (!strcmp(argv[c], "-alpha_cleanup")) {
// This flag is obsolete, does opposite of -exact. // This flag is obsolete, does opposite of -exact.
config.exact = 0; config.exact = 0;
} else if (!strcmp(argv[c], "-exact")) { } else if (!strcmp(argv[c], "-exact")) {
config.exact = 1; config.exact = 1;
} else if (!strcmp(argv[c], "-blend_alpha") && c + 1 < argc) { } else if (!strcmp(argv[c], "-blend_alpha") && c < argc - 1) {
blend_alpha = 1; blend_alpha = 1;
// background color is given in hex with an optional '0x' prefix // background color is given in hex with an optional '0x' prefix
background_color = ExUtilGetInt(argv[++c], 16, &parse_error); background_color = ExUtilGetInt(argv[++c], 16, &parse_error);
background_color = background_color & 0x00ffffffu; background_color = background_color & 0x00ffffffu;
} else if (!strcmp(argv[c], "-alpha_filter") && c + 1 < argc) { } else if (!strcmp(argv[c], "-alpha_filter") && c < argc - 1) {
++c; ++c;
if (!strcmp(argv[c], "none")) { if (!strcmp(argv[c], "none")) {
config.alpha_filtering = 0; config.alpha_filtering = 0;
@ -810,10 +756,10 @@ int main(int argc, const char* argv[]) {
keep_alpha = 0; keep_alpha = 0;
} else if (!strcmp(argv[c], "-lossless")) { } else if (!strcmp(argv[c], "-lossless")) {
config.lossless = 1; config.lossless = 1;
} else if (!strcmp(argv[c], "-near_lossless") && c + 1 < argc) { } else if (!strcmp(argv[c], "-near_lossless") && c < argc - 1) {
config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error); config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error);
config.lossless = 1; // use near-lossless only with lossless config.lossless = 1; // use near-lossless only with lossless
} else if (!strcmp(argv[c], "-hint") && c + 1 < argc) { } else if (!strcmp(argv[c], "-hint") && c < argc - 1) {
++c; ++c;
if (!strcmp(argv[c], "photo")) { if (!strcmp(argv[c], "photo")) {
config.image_hint = WEBP_HINT_PHOTO; config.image_hint = WEBP_HINT_PHOTO;
@ -825,13 +771,13 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error! Unrecognized image hint: %s\n", argv[c]); fprintf(stderr, "Error! Unrecognized image hint: %s\n", argv[c]);
goto Error; goto Error;
} }
} else if (!strcmp(argv[c], "-size") && c + 1 < argc) { } else if (!strcmp(argv[c], "-size") && c < argc - 1) {
config.target_size = ExUtilGetInt(argv[++c], 0, &parse_error); config.target_size = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-psnr") && c + 1 < argc) { } else if (!strcmp(argv[c], "-psnr") && c < argc - 1) {
config.target_PSNR = ExUtilGetFloat(argv[++c], &parse_error); config.target_PSNR = ExUtilGetFloat(argv[++c], &parse_error);
} else if (!strcmp(argv[c], "-sns") && c + 1 < argc) { } else if (!strcmp(argv[c], "-sns") && c < argc - 1) {
config.sns_strength = ExUtilGetInt(argv[++c], 0, &parse_error); config.sns_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-f") && c + 1 < argc) { } else if (!strcmp(argv[c], "-f") && c < argc - 1) {
config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error); config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-af")) { } else if (!strcmp(argv[c], "-af")) {
config.autofilter = 1; config.autofilter = 1;
@ -845,64 +791,43 @@ int main(int argc, const char* argv[]) {
config.filter_type = 1; config.filter_type = 1;
} else if (!strcmp(argv[c], "-nostrong")) { } else if (!strcmp(argv[c], "-nostrong")) {
config.filter_type = 0; config.filter_type = 0;
} else if (!strcmp(argv[c], "-sharpness") && c + 1 < argc) { } else if (!strcmp(argv[c], "-sharpness") && c < argc - 1) {
config.filter_sharpness = ExUtilGetInt(argv[++c], 0, &parse_error); config.filter_sharpness = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-sharp_yuv")) { } else if (!strcmp(argv[c], "-sharp_yuv")) {
config.use_sharp_yuv = 1; config.use_sharp_yuv = 1;
} else if (!strcmp(argv[c], "-pass") && c + 1 < argc) { } else if (!strcmp(argv[c], "-pass") && c < argc - 1) {
config.pass = ExUtilGetInt(argv[++c], 0, &parse_error); config.pass = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-qrange") && c + 2 < argc) { } else if (!strcmp(argv[c], "-pre") && c < argc - 1) {
config.qmin = ExUtilGetInt(argv[++c], 0, &parse_error);
config.qmax = ExUtilGetInt(argv[++c], 0, &parse_error);
if (config.qmin < 0) config.qmin = 0;
if (config.qmax > 100) config.qmax = 100;
} else if (!strcmp(argv[c], "-pre") && c + 1 < argc) {
config.preprocessing = ExUtilGetInt(argv[++c], 0, &parse_error); config.preprocessing = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-segments") && c + 1 < argc) { } else if (!strcmp(argv[c], "-segments") && c < argc - 1) {
config.segments = ExUtilGetInt(argv[++c], 0, &parse_error); config.segments = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-partition_limit") && c + 1 < argc) { } else if (!strcmp(argv[c], "-partition_limit") && c < argc - 1) {
config.partition_limit = ExUtilGetInt(argv[++c], 0, &parse_error); config.partition_limit = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-map") && c + 1 < argc) { } else if (!strcmp(argv[c], "-map") && c < argc - 1) {
picture.extra_info_type = ExUtilGetInt(argv[++c], 0, &parse_error); picture.extra_info_type = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-crop") && c + 4 < argc) { } else if (!strcmp(argv[c], "-crop") && c < argc - 4) {
crop = 1; crop = 1;
crop_x = ExUtilGetInt(argv[++c], 0, &parse_error); crop_x = ExUtilGetInt(argv[++c], 0, &parse_error);
crop_y = ExUtilGetInt(argv[++c], 0, &parse_error); crop_y = ExUtilGetInt(argv[++c], 0, &parse_error);
crop_w = ExUtilGetInt(argv[++c], 0, &parse_error); crop_w = ExUtilGetInt(argv[++c], 0, &parse_error);
crop_h = ExUtilGetInt(argv[++c], 0, &parse_error); crop_h = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-resize") && c + 2 < argc) { } else if (!strcmp(argv[c], "-resize") && c < argc - 2) {
resize_w = ExUtilGetInt(argv[++c], 0, &parse_error); resize_w = ExUtilGetInt(argv[++c], 0, &parse_error);
resize_h = ExUtilGetInt(argv[++c], 0, &parse_error); resize_h = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-resize_mode") && c + 1 < argc) {
++c;
if (!strcmp(argv[c], "down_only")) {
resize_mode = RESIZE_MODE_DOWN_ONLY;
} else if (!strcmp(argv[c], "up_only")) {
resize_mode = RESIZE_MODE_UP_ONLY;
} else if (!strcmp(argv[c], "always")) {
resize_mode = RESIZE_MODE_ALWAYS;
} else {
fprintf(stderr, "Error! Unrecognized resize mode: %s\n", argv[c]);
goto Error;
}
#ifndef WEBP_DLL #ifndef WEBP_DLL
} else if (!strcmp(argv[c], "-noasm")) { } else if (!strcmp(argv[c], "-noasm")) {
VP8GetCPUInfo = NULL; VP8GetCPUInfo = NULL;
#endif #endif
} else if (!strcmp(argv[c], "-version")) { } else if (!strcmp(argv[c], "-version")) {
const int version = WebPGetEncoderVersion(); const int version = WebPGetEncoderVersion();
const int sharpyuv_version = SharpYuvGetVersion();
printf("%d.%d.%d\n", printf("%d.%d.%d\n",
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
printf("libsharpyuv: %d.%d.%d\n", FREE_WARGV_AND_RETURN(0);
(sharpyuv_version >> 24) & 0xff, (sharpyuv_version >> 16) & 0xffff,
sharpyuv_version & 0xff);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-progress")) { } else if (!strcmp(argv[c], "-progress")) {
show_progress = 1; show_progress = 1;
} else if (!strcmp(argv[c], "-quiet")) { } else if (!strcmp(argv[c], "-quiet")) {
quiet = 1; quiet = 1;
} else if (!strcmp(argv[c], "-preset") && c + 1 < argc) { } else if (!strcmp(argv[c], "-preset") && c < argc - 1) {
WebPPreset preset; WebPPreset preset;
++c; ++c;
if (!strcmp(argv[c], "default")) { if (!strcmp(argv[c], "default")) {
@ -925,7 +850,7 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error! Could initialize configuration with preset.\n"); fprintf(stderr, "Error! Could initialize configuration with preset.\n");
goto Error; goto Error;
} }
} else if (!strcmp(argv[c], "-metadata") && c + 1 < argc) { } else if (!strcmp(argv[c], "-metadata") && c < argc - 1) {
static const struct { static const struct {
const char* option; const char* option;
int flag; int flag;
@ -959,7 +884,7 @@ int main(int argc, const char* argv[]) {
if (i == kNumTokens) { if (i == kNumTokens) {
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n", fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
(int)(token - start), start); (int)(token - start), start);
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
start = token + 1; start = token + 1;
} }
@ -973,19 +898,19 @@ int main(int argc, const char* argv[]) {
} else if (!strcmp(argv[c], "-v")) { } else if (!strcmp(argv[c], "-v")) {
verbose = 1; verbose = 1;
} else if (!strcmp(argv[c], "--")) { } else if (!strcmp(argv[c], "--")) {
if (c + 1 < argc) in_file = (const char*)GET_WARGV(argv, ++c); if (c < argc - 1) in_file = (const char*)GET_WARGV(argv, ++c);
break; break;
} else if (argv[c][0] == '-') { } else if (argv[c][0] == '-') {
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]); fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
HelpLong(); HelpLong();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} else { } else {
in_file = (const char*)GET_WARGV(argv, c); in_file = (const char*)GET_WARGV(argv, c);
} }
if (parse_error) { if (parse_error) {
HelpLong(); HelpLong();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
} }
if (in_file == NULL) { if (in_file == NULL) {
@ -1049,14 +974,6 @@ int main(int argc, const char* argv[]) {
const double read_time = StopwatchReadAndReset(&stop_watch); const double read_time = StopwatchReadAndReset(&stop_watch);
fprintf(stderr, "Time to read input: %.3fs\n", read_time); fprintf(stderr, "Time to read input: %.3fs\n", read_time);
} }
// The bitstream should be kept in memory when metadata must be appended
// before writing it to a file/stream, and/or when the near-losslessly encoded
// bitstream must be decoded for distortion computation (lossy will modify the
// 'picture' but not the lossless pipeline).
// Otherwise directly write the bitstream to a file.
use_memory_writer = (out_file != NULL && keep_metadata) ||
(!quiet && print_distortion >= 0 && config.lossless &&
config.near_lossless < 100);
// Open the output // Open the output
if (out_file != NULL) { if (out_file != NULL) {
@ -1071,19 +988,15 @@ int main(int argc, const char* argv[]) {
WFPRINTF(stderr, "Saving file '%s'\n", (const W_CHAR*)out_file); WFPRINTF(stderr, "Saving file '%s'\n", (const W_CHAR*)out_file);
} }
} }
if (use_memory_writer) { if (keep_metadata == 0) {
picture.writer = WebPMemoryWrite;
picture.custom_ptr = (void*)&memory_writer;
} else {
picture.writer = MyWriter; picture.writer = MyWriter;
picture.custom_ptr = (void*)out; picture.custom_ptr = (void*)out;
} else {
picture.writer = WebPMemoryWrite;
picture.custom_ptr = (void*)&memory_writer;
} }
} else { } else {
out = NULL; out = NULL;
if (use_memory_writer) {
picture.writer = WebPMemoryWrite;
picture.custom_ptr = (void*)&memory_writer;
}
if (!quiet && !short_output) { if (!quiet && !short_output) {
fprintf(stderr, "No output file specified (no -o flag). Encoding will\n"); fprintf(stderr, "No output file specified (no -o flag). Encoding will\n");
fprintf(stderr, "be performed, but its results discarded.\n\n"); fprintf(stderr, "be performed, but its results discarded.\n\n");
@ -1105,7 +1018,6 @@ int main(int argc, const char* argv[]) {
goto Error; goto Error;
} }
} }
ApplyResizeMode(resize_mode, &picture, &resize_w, &resize_h);
if ((resize_w | resize_h) > 0) { if ((resize_w | resize_h) > 0) {
WebPPicture picture_no_alpha; WebPPicture picture_no_alpha;
if (config.exact) { if (config.exact) {
@ -1163,12 +1075,8 @@ int main(int argc, const char* argv[]) {
if (picture.extra_info_type > 0) { if (picture.extra_info_type > 0) {
AllocExtraInfo(&picture); AllocExtraInfo(&picture);
} }
// Save original picture for later comparison. Only for lossy as lossless does if (print_distortion >= 0) { // Save original picture for later comparison
// not modify 'picture' (even near-lossless). WebPPictureCopy(&picture, &original_picture);
if (print_distortion >= 0 && !config.lossless &&
!WebPPictureCopy(&picture, &original_picture)) {
fprintf(stderr, "Error! Cannot copy temporary picture\n");
goto Error;
} }
// Compress. // Compress.
@ -1186,39 +1094,7 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Time to encode picture: %.3fs\n", encode_time); fprintf(stderr, "Time to encode picture: %.3fs\n", encode_time);
} }
// Get the decompressed image for the lossless pipeline. // Write info
if (!quiet && print_distortion >= 0 && config.lossless) {
if (config.near_lossless == 100) {
// Pure lossless: image was not modified, make 'original_picture' a view
// of 'picture' by copying all members except the freeable pointers.
original_picture = picture;
original_picture.memory_ = original_picture.memory_argb_ = NULL;
} else {
// Decode the bitstream stored in 'memory_writer' to get the altered image
// to 'picture'; save the 'original_picture' beforehand.
assert(use_memory_writer);
original_picture = picture;
if (!WebPPictureInit(&picture)) { // Do not free 'picture'.
fprintf(stderr, "Error! Version mismatch!\n");
goto Error;
}
picture.use_argb = 1;
if (!ReadWebP(
memory_writer.mem, memory_writer.size, &picture,
/*keep_alpha=*/WebPPictureHasTransparency(&original_picture),
/*metadata=*/NULL)) {
fprintf(stderr, "Error! Cannot decode encoded WebP bitstream\n");
fprintf(stderr, "Error code: %d (%s)\n", picture.error_code,
kErrorMessages[picture.error_code]);
goto Error;
}
picture.stats = original_picture.stats;
}
original_picture.stats = NULL;
}
// Write the YUV planes to a PGM file. Only available for lossy.
if (dump_file) { if (dump_file) {
if (picture.use_argb) { if (picture.use_argb) {
fprintf(stderr, "Warning: can't dump file (-d option) " fprintf(stderr, "Warning: can't dump file (-d option) "
@ -1229,29 +1105,31 @@ int main(int argc, const char* argv[]) {
} }
} }
if (use_memory_writer && out != NULL && if (keep_metadata != 0) {
!WriteWebPWithMetadata(out, &picture, &memory_writer, &metadata, if (out != NULL) {
keep_metadata, &metadata_written)) { if (!WriteWebPWithMetadata(out, &picture, &memory_writer,
fprintf(stderr, "Error writing WebP file!\n"); &metadata, keep_metadata, &metadata_written)) {
goto Error; fprintf(stderr, "Error writing WebP file with metadata!\n");
} goto Error;
}
} else { // output is disabled, just display the metadata stats.
const struct {
const MetadataPayload* const payload;
int flag;
} *iter, info[] = {
{ &metadata.exif, METADATA_EXIF },
{ &metadata.iccp, METADATA_ICC },
{ &metadata.xmp, METADATA_XMP },
{ NULL, 0 }
};
uint32_t unused1 = 0;
uint64_t unused2 = 0;
if (out == NULL && keep_metadata) { for (iter = info; iter->payload != NULL; ++iter) {
// output is disabled, just display the metadata stats. if (UpdateFlagsAndSize(iter->payload, !!(keep_metadata & iter->flag),
const struct { 0, &unused1, &unused2)) {
const MetadataPayload* const payload; metadata_written |= iter->flag;
int flag; }
} *iter, info[] = {{&metadata.exif, METADATA_EXIF},
{&metadata.iccp, METADATA_ICC},
{&metadata.xmp, METADATA_XMP},
{NULL, 0}};
uint32_t unused1 = 0;
uint64_t unused2 = 0;
for (iter = info; iter->payload != NULL; ++iter) {
if (UpdateFlagsAndSize(iter->payload, !!(keep_metadata & iter->flag),
/*flag=*/0, &unused1, &unused2)) {
metadata_written |= iter->flag;
} }
} }
} }
@ -1287,7 +1165,7 @@ int main(int argc, const char* argv[]) {
PrintMetadataInfo(&metadata, metadata_written); PrintMetadataInfo(&metadata, metadata_written);
} }
} }
return_value = EXIT_SUCCESS; return_value = 0;
Error: Error:
WebPMemoryWriterClear(&memory_writer); WebPMemoryWriterClear(&memory_writer);

View File

@ -25,8 +25,6 @@
#include "../imageio/webpdec.h" #include "../imageio/webpdec.h"
#include "./stopwatch.h" #include "./stopwatch.h"
#include "./unicode.h" #include "./unicode.h"
#include "webp/decode.h"
#include "webp/types.h"
static int verbose = 0; static int verbose = 0;
static int quiet = 0; static int quiet = 0;
@ -78,8 +76,7 @@ static int SaveOutput(const WebPDecBuffer* const buffer,
static void Help(void) { static void Help(void) {
printf("Usage: dwebp in_file [options] [-o out_file]\n\n" printf("Usage: dwebp in_file [options] [-o out_file]\n\n"
"Decodes the WebP image file to PNG format [Default].\n" "Decodes the WebP image file to PNG format [Default]\n"
"Note: Animated WebP files are not supported.\n\n"
"Use following options to convert into alternate image formats:\n" "Use following options to convert into alternate image formats:\n"
" -pam ......... save the raw RGBA samples as a color PAM\n" " -pam ......... save the raw RGBA samples as a color PAM\n"
" -ppm ......... save the raw RGB samples as a color PPM\n" " -ppm ......... save the raw RGB samples as a color PPM\n"
@ -98,7 +95,7 @@ static void Help(void) {
" -alpha_dither use alpha-plane dithering if needed\n" " -alpha_dither use alpha-plane dithering if needed\n"
" -mt .......... use multi-threading\n" " -mt .......... use multi-threading\n"
" -crop <x> <y> <w> <h> ... crop output with the given rectangle\n" " -crop <x> <y> <w> <h> ... crop output with the given rectangle\n"
" -resize <w> <h> ......... resize output (*after* any cropping)\n" " -resize <w> <h> ......... scale the output (*after* any cropping)\n"
" -flip ........ flip the output vertically\n" " -flip ........ flip the output vertically\n"
" -alpha ....... only save the alpha plane\n" " -alpha ....... only save the alpha plane\n"
" -incremental . use incremental decoding (useful for tests)\n" " -incremental . use incremental decoding (useful for tests)\n"
@ -179,7 +176,6 @@ static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
return external_buffer; return external_buffer;
} }
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
int ok = 0; int ok = 0;
const char* in_file = NULL; const char* in_file = NULL;
@ -200,14 +196,14 @@ int main(int argc, const char* argv[]) {
if (!WebPInitDecoderConfig(&config)) { if (!WebPInitDecoderConfig(&config)) {
fprintf(stderr, "Library version mismatch!\n"); fprintf(stderr, "Library version mismatch!\n");
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
int parse_error = 0; int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-o") && c < argc - 1) { } else if (!strcmp(argv[c], "-o") && c < argc - 1) {
out_file = (const char*)GET_WARGV(argv, ++c); out_file = (const char*)GET_WARGV(argv, ++c);
} else if (!strcmp(argv[c], "-alpha")) { } else if (!strcmp(argv[c], "-alpha")) {
@ -230,7 +226,7 @@ int main(int argc, const char* argv[]) {
const int version = WebPGetDecoderVersion(); const int version = WebPGetDecoderVersion();
printf("%d.%d.%d\n", printf("%d.%d.%d\n",
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-pgm")) { } else if (!strcmp(argv[c], "-pgm")) {
format = PGM; format = PGM;
} else if (!strcmp(argv[c], "-yuv")) { } else if (!strcmp(argv[c], "-yuv")) {
@ -296,21 +292,21 @@ int main(int argc, const char* argv[]) {
} else if (argv[c][0] == '-') { } else if (argv[c][0] == '-') {
fprintf(stderr, "Unknown option '%s'\n", argv[c]); fprintf(stderr, "Unknown option '%s'\n", argv[c]);
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} else { } else {
in_file = (const char*)GET_WARGV(argv, c); in_file = (const char*)GET_WARGV(argv, c);
} }
if (parse_error) { if (parse_error) {
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
} }
if (in_file == NULL) { if (in_file == NULL) {
fprintf(stderr, "missing input file!!\n"); fprintf(stderr, "missing input file!!\n");
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
if (quiet) verbose = 0; if (quiet) verbose = 0;
@ -319,7 +315,7 @@ int main(int argc, const char* argv[]) {
VP8StatusCode status = VP8_STATUS_OK; VP8StatusCode status = VP8_STATUS_OK;
size_t data_size = 0; size_t data_size = 0;
if (!LoadWebP(in_file, &data, &data_size, bitstream)) { if (!LoadWebP(in_file, &data, &data_size, bitstream)) {
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
switch (format) { switch (format) {
@ -418,7 +414,7 @@ int main(int argc, const char* argv[]) {
WebPFreeDecBuffer(output_buffer); WebPFreeDecBuffer(output_buffer);
WebPFree((void*)external_buffer); WebPFree((void*)external_buffer);
WebPFree((void*)data); WebPFree((void*)data);
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE); FREE_WARGV_AND_RETURN(ok ? 0 : -1);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -17,9 +17,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "../imageio/imageio_util.h"
#include "webp/mux_types.h" #include "webp/mux_types.h"
#include "webp/types.h" #include "../imageio/imageio_util.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// String parsing // String parsing
@ -67,17 +66,17 @@ float ExUtilGetFloat(const char* const v, int* const error) {
static void ResetCommandLineArguments(int argc, const char* argv[], static void ResetCommandLineArguments(int argc, const char* argv[],
CommandLineArguments* const args) { CommandLineArguments* const args) {
assert(args != NULL); assert(args != NULL);
args->argc = argc; args->argc_ = argc;
args->argv = argv; args->argv_ = argv;
args->own_argv = 0; args->own_argv_ = 0;
WebPDataInit(&args->argv_data); WebPDataInit(&args->argv_data_);
} }
void ExUtilDeleteCommandLineArguments(CommandLineArguments* const args) { void ExUtilDeleteCommandLineArguments(CommandLineArguments* const args) {
if (args != NULL) { if (args != NULL) {
if (args->own_argv) { if (args->own_argv_) {
WebPFree((void*)args->argv); WebPFree((void*)args->argv_);
WebPDataClear(&args->argv_data); WebPDataClear(&args->argv_data_);
} }
ResetCommandLineArguments(0, NULL, args); ResetCommandLineArguments(0, NULL, args);
} }
@ -99,29 +98,25 @@ int ExUtilInitCommandLineArguments(int argc, const char* argv[],
return 0; return 0;
#endif #endif
if (!ExUtilReadFileToWebPData(argv[0], &args->argv_data)) { if (!ExUtilReadFileToWebPData(argv[0], &args->argv_data_)) {
return 0;
}
args->own_argv = 1;
args->argv = (const char**)WebPMalloc(MAX_ARGC * sizeof(*args->argv));
if (args->argv == NULL) {
ExUtilDeleteCommandLineArguments(args);
return 0; return 0;
} }
args->own_argv_ = 1;
args->argv_ = (const char**)WebPMalloc(MAX_ARGC * sizeof(*args->argv_));
if (args->argv_ == NULL) return 0;
argc = 0; argc = 0;
for (cur = strtok((char*)args->argv_data.bytes, sep); for (cur = strtok((char*)args->argv_data_.bytes, sep);
cur != NULL; cur != NULL;
cur = strtok(NULL, sep)) { cur = strtok(NULL, sep)) {
if (argc == MAX_ARGC) { if (argc == MAX_ARGC) {
fprintf(stderr, "ERROR: Arguments limit %d reached\n", MAX_ARGC); fprintf(stderr, "ERROR: Arguments limit %d reached\n", MAX_ARGC);
ExUtilDeleteCommandLineArguments(args);
return 0; return 0;
} }
assert(strlen(cur) != 0); assert(strlen(cur) != 0);
args->argv[argc++] = cur; args->argv_[argc++] = cur;
} }
args->argc = argc; args->argc_ = argc;
} }
return 1; return 1;
} }

View File

@ -45,10 +45,10 @@ int ExUtilReadFileToWebPData(const char* const filename,
// Command-line arguments // Command-line arguments
typedef struct { typedef struct {
int argc; int argc_;
const char** argv; const char** argv_;
WebPData argv_data; WebPData argv_data_;
int own_argv; int own_argv_;
} CommandLineArguments; } CommandLineArguments;
// Initializes the structure from the command-line parameters. If there is // Initializes the structure from the command-line parameters. If there is

View File

@ -28,7 +28,6 @@
#endif #endif
#include <gif_lib.h> #include <gif_lib.h>
#include "sharpyuv/sharpyuv.h"
#include "webp/encode.h" #include "webp/encode.h"
#include "webp/mux.h" #include "webp/mux.h"
#include "../examples/example_util.h" #include "../examples/example_util.h"
@ -71,14 +70,8 @@ static void Help(void) {
printf(" -lossy ................. encode image using lossy compression\n"); printf(" -lossy ................. encode image using lossy compression\n");
printf(" -mixed ................. for each frame in the image, pick lossy\n" printf(" -mixed ................. for each frame in the image, pick lossy\n"
" or lossless compression heuristically\n"); " or lossless compression heuristically\n");
printf(" -near_lossless <int> ... use near-lossless image preprocessing\n"
" (0..100=off), default=100\n");
printf(" -sharp_yuv ............. use sharper (and slower) RGB->YUV "
"conversion\n"
" (lossy only)\n");
printf(" -q <float> ............. quality factor (0:small..100:big)\n"); printf(" -q <float> ............. quality factor (0:small..100:big)\n");
printf(" -m <int> ............... compression method (0=fast, 6=slowest), " printf(" -m <int> ............... compression method (0=fast, 6=slowest)\n");
"default=4\n");
printf(" -min_size .............. minimize output size (default:off)\n" printf(" -min_size .............. minimize output size (default:off)\n"
" lossless compression by default; can be\n" " lossless compression by default; can be\n"
" combined with -q, -m, -lossy or -mixed\n" " combined with -q, -m, -lossy or -mixed\n"
@ -103,7 +96,6 @@ static void Help(void) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
int verbose = 0; int verbose = 0;
int gif_error = GIF_ERROR; int gif_error = GIF_ERROR;
@ -148,7 +140,7 @@ int main(int argc, const char* argv[]) {
!WebPPictureInit(&frame) || !WebPPictureInit(&curr_canvas) || !WebPPictureInit(&frame) || !WebPPictureInit(&curr_canvas) ||
!WebPPictureInit(&prev_canvas)) { !WebPPictureInit(&prev_canvas)) {
fprintf(stderr, "Error! Version mismatch!\n"); fprintf(stderr, "Error! Version mismatch!\n");
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
config.lossless = 1; // Use lossless compression by default. config.lossless = 1; // Use lossless compression by default.
@ -158,14 +150,14 @@ int main(int argc, const char* argv[]) {
if (argc == 1) { if (argc == 1) {
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(0);
} }
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
int parse_error = 0; int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-o") && c < argc - 1) { } else if (!strcmp(argv[c], "-o") && c < argc - 1) {
out_file = GET_WARGV(argv, ++c); out_file = GET_WARGV(argv, ++c);
} else if (!strcmp(argv[c], "-lossy")) { } else if (!strcmp(argv[c], "-lossy")) {
@ -173,10 +165,6 @@ int main(int argc, const char* argv[]) {
} else if (!strcmp(argv[c], "-mixed")) { } else if (!strcmp(argv[c], "-mixed")) {
enc_options.allow_mixed = 1; enc_options.allow_mixed = 1;
config.lossless = 0; config.lossless = 0;
} else if (!strcmp(argv[c], "-near_lossless") && c < argc - 1) {
config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-sharp_yuv")) {
config.use_sharp_yuv = 1;
} else if (!strcmp(argv[c], "-loop_compatibility")) { } else if (!strcmp(argv[c], "-loop_compatibility")) {
loop_compatibility = 1; loop_compatibility = 1;
} else if (!strcmp(argv[c], "-q") && c < argc - 1) { } else if (!strcmp(argv[c], "-q") && c < argc - 1) {
@ -228,7 +216,7 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n", fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
(int)(token - start), start); (int)(token - start), start);
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
start = token + 1; start = token + 1;
} }
@ -237,14 +225,11 @@ int main(int argc, const char* argv[]) {
} else if (!strcmp(argv[c], "-version")) { } else if (!strcmp(argv[c], "-version")) {
const int enc_version = WebPGetEncoderVersion(); const int enc_version = WebPGetEncoderVersion();
const int mux_version = WebPGetMuxVersion(); const int mux_version = WebPGetMuxVersion();
const int sharpyuv_version = SharpYuvGetVersion();
printf("WebP Encoder version: %d.%d.%d\nWebP Mux version: %d.%d.%d\n", printf("WebP Encoder version: %d.%d.%d\nWebP Mux version: %d.%d.%d\n",
(enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff, (enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff,
enc_version & 0xff, (mux_version >> 16) & 0xff, enc_version & 0xff, (mux_version >> 16) & 0xff,
(mux_version >> 8) & 0xff, mux_version & 0xff); (mux_version >> 8) & 0xff, mux_version & 0xff);
printf("libsharpyuv: %d.%d.%d\n", (sharpyuv_version >> 24) & 0xff, FREE_WARGV_AND_RETURN(0);
(sharpyuv_version >> 16) & 0xffff, sharpyuv_version & 0xff);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-quiet")) { } else if (!strcmp(argv[c], "-quiet")) {
quiet = 1; quiet = 1;
enc_options.verbose = 0; enc_options.verbose = 0;
@ -257,14 +242,14 @@ int main(int argc, const char* argv[]) {
} else if (argv[c][0] == '-') { } else if (argv[c][0] == '-') {
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]); fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} else { } else {
in_file = GET_WARGV(argv, c); in_file = GET_WARGV(argv, c);
} }
if (parse_error) { if (parse_error) {
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
} }
@ -329,11 +314,8 @@ int main(int argc, const char* argv[]) {
frame.use_argb = 1; frame.use_argb = 1;
if (!WebPPictureAlloc(&frame)) goto End; if (!WebPPictureAlloc(&frame)) goto End;
GIFClearPic(&frame, NULL); GIFClearPic(&frame, NULL);
if (!(WebPPictureCopy(&frame, &curr_canvas) && WebPPictureCopy(&frame, &curr_canvas);
WebPPictureCopy(&frame, &prev_canvas))) { WebPPictureCopy(&frame, &prev_canvas);
fprintf(stderr, "Error allocating canvas.\n");
goto End;
}
// Background color. // Background color.
GIFGetBackgroundColor(gif->SColorMap, gif->SBackGroundColor, GIFGetBackgroundColor(gif->SColorMap, gif->SBackGroundColor,
@ -483,10 +465,8 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "%s\n", WebPAnimEncoderGetError(enc)); fprintf(stderr, "%s\n", WebPAnimEncoderGetError(enc));
goto End; goto End;
} }
// If there's only one frame, we don't need to handle loop count.
if (frame_number == 1) { if (!loop_compatibility) {
loop_count = 0;
} else if (!loop_compatibility) {
if (!stored_loop_count) { if (!stored_loop_count) {
// if no loop-count element is seen, the default is '1' (loop-once) // if no loop-count element is seen, the default is '1' (loop-once)
// and we need to signal it explicitly in WebP. Note however that // and we need to signal it explicitly in WebP. Note however that
@ -608,7 +588,7 @@ int main(int argc, const char* argv[]) {
#endif #endif
} }
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE); FREE_WARGV_AND_RETURN(!ok);
} }
#else // !WEBP_HAVE_GIF #else // !WEBP_HAVE_GIF
@ -616,7 +596,7 @@ int main(int argc, const char* argv[]) {
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
fprintf(stderr, "GIF support not enabled in %s.\n", argv[0]); fprintf(stderr, "GIF support not enabled in %s.\n", argv[0]);
(void)argc; (void)argc;
return EXIT_FAILURE; return 0;
} }
#endif #endif

View File

@ -19,7 +19,6 @@
#include <string.h> #include <string.h>
#include "webp/encode.h" #include "webp/encode.h"
#include "webp/types.h"
#include "webp/mux_types.h" #include "webp/mux_types.h"
#define GIF_TRANSPARENT_COLOR 0x00000000u #define GIF_TRANSPARENT_COLOR 0x00000000u
@ -318,7 +317,7 @@ void GIFDisplayError(const GifFileType* const gif, int gif_error) {
#else // !WEBP_HAVE_GIF #else // !WEBP_HAVE_GIF
static void ErrorGIFNotAvailable(void) { static void ErrorGIFNotAvailable() {
fprintf(stderr, "GIF support not compiled. Please install the libgif-dev " fprintf(stderr, "GIF support not compiled. Please install the libgif-dev "
"package before building.\n"); "package before building.\n");
} }

View File

@ -13,7 +13,6 @@
#define WEBP_EXAMPLES_GIFDEC_H_ #define WEBP_EXAMPLES_GIFDEC_H_
#include <stdio.h> #include <stdio.h>
#include "webp/types.h" #include "webp/types.h"
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H

View File

@ -28,32 +28,25 @@
#include "../imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "./stopwatch.h" #include "./stopwatch.h"
#include "./unicode.h" #include "./unicode.h"
#include "sharpyuv/sharpyuv.h"
#include "webp/encode.h" #include "webp/encode.h"
#include "webp/mux.h" #include "webp/mux.h"
#include "webp/mux_types.h"
#include "webp/types.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static void Help(void) { static void Help(void) {
printf("Usage:\n\n"); printf("Usage:\n\n");
printf(" img2webp [file_options] [[frame_options] frame_file]..."); printf(" img2webp [file-level options] [image files...] "
printf(" [-o webp_file]\n\n"); "[per-frame options...]\n");
printf("\n");
printf("File-level options (only used at the start of compression):\n"); printf("File-level options (only used at the start of compression):\n");
printf(" -min_size ............ minimize size\n"); printf(" -min_size ............ minimize size\n");
printf(" -loop <int> .......... loop count (default: 0, = infinite loop)\n");
printf(" -kmax <int> .......... maximum number of frame between key-frames\n" printf(" -kmax <int> .......... maximum number of frame between key-frames\n"
" (0=only keyframes)\n"); " (0=only keyframes)\n");
printf(" -kmin <int> .......... minimum number of frame between key-frames\n" printf(" -kmin <int> .......... minimum number of frame between key-frames\n"
" (0=disable key-frames altogether)\n"); " (0=disable key-frames altogether)\n");
printf(" -mixed ............... use mixed lossy/lossless automatic mode\n"); printf(" -mixed ............... use mixed lossy/lossless automatic mode\n");
printf(" -near_lossless <int> . use near-lossless image preprocessing\n"
" (0..100=off), default=100\n");
printf(" -sharp_yuv ........... use sharper (and slower) RGB->YUV "
"conversion\n "
"(lossy only)\n");
printf(" -loop <int> .......... loop count (default: 0, = infinite loop)\n");
printf(" -v ................... verbose mode\n"); printf(" -v ................... verbose mode\n");
printf(" -h ................... this help\n"); printf(" -h ................... this help\n");
printf(" -version ............. print version number and exit\n"); printf(" -version ............. print version number and exit\n");
@ -61,15 +54,10 @@ static void Help(void) {
printf("Per-frame options (only used for subsequent images input):\n"); printf("Per-frame options (only used for subsequent images input):\n");
printf(" -d <int> ............. frame duration in ms (default: 100)\n"); printf(" -d <int> ............. frame duration in ms (default: 100)\n");
printf(" -lossless ............ use lossless mode (default)\n"); printf(" -lossless ........... use lossless mode (default)\n");
printf(" -lossy ............... use lossy mode\n"); printf(" -lossy ... ........... use lossy mode\n");
printf(" -q <float> ........... quality\n"); printf(" -q <float> ........... quality\n");
printf(" -m <int> ............. compression method (0=fast, 6=slowest), " printf(" -m <int> ............. method to use\n");
"default=4\n");
printf(" -exact, -noexact ..... preserve or alter RGB values in transparent "
"area\n"
" (default: -noexact, may cause artifacts\n"
" with lossy animations)\n");
printf("\n"); printf("\n");
printf("example: img2webp -loop 2 in0.png -lossy in1.jpg\n" printf("example: img2webp -loop 2 in0.png -lossy in1.jpg\n"
@ -78,8 +66,6 @@ static void Help(void) {
"arguments will be\n"); "arguments will be\n");
printf("tokenized from this file. The file name must not start with " printf("tokenized from this file. The file name must not start with "
"the character '-'.\n"); "the character '-'.\n");
printf("\nSupported input formats:\n %s\n",
WebPGetEnabledInputFileFormats());
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -98,7 +84,7 @@ static int ReadImage(const char filename[], WebPPicture* const pic) {
if (!ImgIoUtilReadFile(filename, &data, &data_size)) return 0; if (!ImgIoUtilReadFile(filename, &data, &data_size)) return 0;
reader = WebPGuessImageReader(data, data_size); reader = WebPGuessImageReader(data, data_size);
ok = reader(data, data_size, pic, 1, NULL); ok = reader(data, data_size, pic, 1, NULL);
WebPFree((void*)data); free((void*)data);
return ok; return ok;
} }
@ -137,7 +123,6 @@ static int SetLoopCount(int loop_count, WebPData* const webp_data) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
const char* output = NULL; const char* output = NULL;
WebPAnimEncoder* enc = NULL; WebPAnimEncoder* enc = NULL;
@ -153,17 +138,16 @@ int main(int argc, const char* argv[]) {
WebPData webp_data; WebPData webp_data;
int c; int c;
int have_input = 0; int have_input = 0;
int last_input_index = 0;
CommandLineArguments cmd_args; CommandLineArguments cmd_args;
int ok; int ok;
INIT_WARGV(argc, argv); INIT_WARGV(argc, argv);
ok = ExUtilInitCommandLineArguments(argc - 1, argv + 1, &cmd_args); ok = ExUtilInitCommandLineArguments(argc - 1, argv + 1, &cmd_args);
if (!ok) FREE_WARGV_AND_RETURN(EXIT_FAILURE); if (!ok) FREE_WARGV_AND_RETURN(1);
argc = cmd_args.argc; argc = cmd_args.argc_;
argv = cmd_args.argv; argv = cmd_args.argv_;
WebPDataInit(&webp_data); WebPDataInit(&webp_data);
if (!WebPAnimEncoderOptionsInit(&anim_config) || if (!WebPAnimEncoderOptionsInit(&anim_config) ||
@ -199,26 +183,18 @@ int main(int argc, const char* argv[]) {
} else if (!strcmp(argv[c], "-mixed")) { } else if (!strcmp(argv[c], "-mixed")) {
anim_config.allow_mixed = 1; anim_config.allow_mixed = 1;
config.lossless = 0; config.lossless = 0;
} else if (!strcmp(argv[c], "-near_lossless") && c + 1 < argc) {
argv[c] = NULL;
config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-sharp_yuv")) {
config.use_sharp_yuv = 1;
} else if (!strcmp(argv[c], "-v")) { } else if (!strcmp(argv[c], "-v")) {
verbose = 1; verbose = 1;
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); goto End;
} else if (!strcmp(argv[c], "-version")) { } else if (!strcmp(argv[c], "-version")) {
const int enc_version = WebPGetEncoderVersion(); const int enc_version = WebPGetEncoderVersion();
const int mux_version = WebPGetMuxVersion(); const int mux_version = WebPGetMuxVersion();
const int sharpyuv_version = SharpYuvGetVersion();
printf("WebP Encoder version: %d.%d.%d\nWebP Mux version: %d.%d.%d\n", printf("WebP Encoder version: %d.%d.%d\nWebP Mux version: %d.%d.%d\n",
(enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff, (enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff,
enc_version & 0xff, (mux_version >> 16) & 0xff, enc_version & 0xff, (mux_version >> 16) & 0xff,
(mux_version >> 8) & 0xff, mux_version & 0xff); (mux_version >> 8) & 0xff, mux_version & 0xff);
printf("libsharpyuv: %d.%d.%d\n", (sharpyuv_version >> 24) & 0xff,
(sharpyuv_version >> 16) & 0xffff, sharpyuv_version & 0xff);
goto End; goto End;
} else { } else {
continue; continue;
@ -232,8 +208,6 @@ int main(int argc, const char* argv[]) {
} }
if (!have_input) { if (!have_input) {
fprintf(stderr, "No input file(s) for generating animation!\n"); fprintf(stderr, "No input file(s) for generating animation!\n");
ok = 0;
Help();
goto End; goto End;
} }
@ -258,10 +232,6 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Invalid negative duration (%d)\n", duration); fprintf(stderr, "Invalid negative duration (%d)\n", duration);
parse_error = 1; parse_error = 1;
} }
} else if (!strcmp(argv[c], "-exact")) {
config.exact = 1;
} else if (!strcmp(argv[c], "-noexact")) {
config.exact = 0;
} else { } else {
parse_error = 1; // shouldn't be here. parse_error = 1; // shouldn't be here.
fprintf(stderr, "Unknown option [%s]\n", argv[c]); fprintf(stderr, "Unknown option [%s]\n", argv[c]);
@ -282,7 +252,6 @@ int main(int argc, const char* argv[]) {
// read next input image // read next input image
pic.use_argb = 1; pic.use_argb = 1;
ok = ReadImage((const char*)GET_WARGV_SHIFTED(argv, c), &pic); ok = ReadImage((const char*)GET_WARGV_SHIFTED(argv, c), &pic);
last_input_index = c;
if (!ok) goto End; if (!ok) goto End;
if (enc == NULL) { if (enc == NULL) {
@ -321,13 +290,6 @@ int main(int argc, const char* argv[]) {
++pic_num; ++pic_num;
} }
for (c = last_input_index + 1; c < argc; ++c) {
if (argv[c] != NULL) {
fprintf(stderr, "Warning: unused option [%s]!"
" Frame options go before the input frame.\n", argv[c]);
}
}
// add a last fake frame to signal the last duration // add a last fake frame to signal the last duration
ok = ok && WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL); ok = ok && WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL);
ok = ok && WebPAnimEncoderAssemble(enc, &webp_data); ok = ok && WebPAnimEncoderAssemble(enc, &webp_data);
@ -358,5 +320,5 @@ int main(int argc, const char* argv[]) {
} }
WebPDataClear(&webp_data); WebPDataClear(&webp_data);
ExUtilDeleteCommandLineArguments(&cmd_args); ExUtilDeleteCommandLineArguments(&cmd_args);
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE); FREE_WARGV_AND_RETURN(ok ? 0 : 1);
} }

View File

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

View File

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

View File

@ -18,7 +18,6 @@
#define _POSIX_C_SOURCE 200112L // for setenv #define _POSIX_C_SOURCE 200112L // for setenv
#endif #endif
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -293,19 +292,6 @@ 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) { static float GetColorf(uint32_t color, int shift) {
return ((color >> shift) & 0xff) / 255.f; return ((color >> shift) & 0xff) / 255.f;
} }
@ -410,7 +396,7 @@ static void HandleDisplay(void) {
glColor4f(0.90f, 0.0f, 0.90f, 1.0f); glColor4f(0.90f, 0.0f, 0.90f, 1.0f);
glRasterPos2f(-0.95f, 0.90f); glRasterPos2f(-0.95f, 0.90f);
PrintStringW(kParams.file_name); PrintString(kParams.file_name);
snprintf(tmp, sizeof(tmp), "Dimension:%d x %d", pic->width, pic->height); snprintf(tmp, sizeof(tmp), "Dimension:%d x %d", pic->width, pic->height);
glColor4f(0.90f, 0.0f, 0.90f, 1.0f); glColor4f(0.90f, 0.0f, 0.90f, 1.0f);
@ -431,13 +417,10 @@ static void HandleDisplay(void) {
#endif #endif
} }
static void StartDisplay(const char* filename) { static void StartDisplay(void) {
int width = kParams.canvas_width; int width = kParams.canvas_width;
int height = kParams.canvas_height; int height = kParams.canvas_height;
int screen_width, screen_height; int screen_width, screen_height;
const char viewername[] = " - WebP viewer";
// max linux file len + viewername string
char title[4096 + sizeof(viewername)] = "";
// TODO(webp:365) GLUT_DOUBLE results in flickering / old frames to be // TODO(webp:365) GLUT_DOUBLE results in flickering / old frames to be
// partially displayed with animated webp + alpha. // partially displayed with animated webp + alpha.
#if defined(__APPLE__) || defined(_WIN32) #if defined(__APPLE__) || defined(_WIN32)
@ -457,9 +440,8 @@ static void StartDisplay(const char* filename) {
height = screen_height; height = screen_height;
} }
} }
snprintf(title, sizeof(title), "%s%s", filename, viewername);
glutInitWindowSize(width, height); glutInitWindowSize(width, height);
glutCreateWindow(title); glutCreateWindow("WebP viewer");
glutDisplayFunc(HandleDisplay); glutDisplayFunc(HandleDisplay);
glutReshapeFunc(HandleReshape); glutReshapeFunc(HandleReshape);
glutIdleFunc(NULL); glutIdleFunc(NULL);
@ -498,7 +480,7 @@ static void Help(void) {
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
int c, file_name_argv_index = 1; int c;
WebPDecoderConfig* const config = &kParams.config; WebPDecoderConfig* const config = &kParams.config;
WebPIterator* const curr = &kParams.curr_frame; WebPIterator* const curr = &kParams.curr_frame;
@ -506,7 +488,7 @@ int main(int argc, char* argv[]) {
if (!WebPInitDecoderConfig(config)) { if (!WebPInitDecoderConfig(config)) {
fprintf(stderr, "Library version mismatch!\n"); fprintf(stderr, "Library version mismatch!\n");
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
config->options.dithering_strength = 50; config->options.dithering_strength = 50;
config->options.alpha_dithering_strength = 100; config->options.alpha_dithering_strength = 100;
@ -518,7 +500,7 @@ int main(int argc, char* argv[]) {
int parse_error = 0; int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-noicc")) { } else if (!strcmp(argv[c], "-noicc")) {
kParams.use_color_profile = 0; kParams.use_color_profile = 0;
} else if (!strcmp(argv[c], "-nofancy")) { } else if (!strcmp(argv[c], "-nofancy")) {
@ -541,34 +523,30 @@ int main(int argc, char* argv[]) {
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff, (dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
dec_version & 0xff, (dmux_version >> 16) & 0xff, dec_version & 0xff, (dmux_version >> 16) & 0xff,
(dmux_version >> 8) & 0xff, dmux_version & 0xff); (dmux_version >> 8) & 0xff, dmux_version & 0xff);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-mt")) { } else if (!strcmp(argv[c], "-mt")) {
config->options.use_threads = 1; config->options.use_threads = 1;
} else if (!strcmp(argv[c], "--")) { } else if (!strcmp(argv[c], "--")) {
if (c < argc - 1) { if (c < argc - 1) kParams.file_name = (const char*)GET_WARGV(argv, ++c);
kParams.file_name = (const char*)GET_WARGV(argv, ++c);
file_name_argv_index = c;
}
break; break;
} else if (argv[c][0] == '-') { } else if (argv[c][0] == '-') {
printf("Unknown option '%s'\n", argv[c]); printf("Unknown option '%s'\n", argv[c]);
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} else { } else {
kParams.file_name = (const char*)GET_WARGV(argv, c); kParams.file_name = (const char*)GET_WARGV(argv, c);
file_name_argv_index = c;
} }
if (parse_error) { if (parse_error) {
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
} }
if (kParams.file_name == NULL) { if (kParams.file_name == NULL) {
printf("missing input file!!\n"); printf("missing input file!!\n");
Help(); Help();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(0);
} }
if (!ImgIoUtilReadFile(kParams.file_name, if (!ImgIoUtilReadFile(kParams.file_name,
@ -622,7 +600,7 @@ int main(int argc, char* argv[]) {
// Position iterator to last frame. Next call to HandleDisplay will wrap over. // Position iterator to last frame. Next call to HandleDisplay will wrap over.
// We take this into account by bumping up loop_count. // We take this into account by bumping up loop_count.
if (!WebPDemuxGetFrame(kParams.dmux, 0, curr)) goto Error; WebPDemuxGetFrame(kParams.dmux, 0, curr);
if (kParams.loop_count) ++kParams.loop_count; if (kParams.loop_count) ++kParams.loop_count;
#if defined(__unix__) || defined(__CYGWIN__) #if defined(__unix__) || defined(__CYGWIN__)
@ -636,18 +614,18 @@ int main(int argc, char* argv[]) {
#ifdef FREEGLUT #ifdef FREEGLUT
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION); glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
#endif #endif
StartDisplay(argv[file_name_argv_index]); StartDisplay();
if (kParams.has_animation) glutTimerFunc(0, decode_callback, 0); if (kParams.has_animation) glutTimerFunc(0, decode_callback, 0);
glutMainLoop(); glutMainLoop();
// Should only be reached when using FREEGLUT: // Should only be reached when using FREEGLUT:
ClearParams(); ClearParams();
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); FREE_WARGV_AND_RETURN(0);
Error: Error:
ClearParams(); ClearParams();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(-1);
} }
#else // !WEBP_HAVE_GL #else // !WEBP_HAVE_GL
@ -655,7 +633,7 @@ int main(int argc, char* argv[]) {
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
fprintf(stderr, "OpenGL support not enabled in %s.\n", argv[0]); fprintf(stderr, "OpenGL support not enabled in %s.\n", argv[0]);
(void)argc; (void)argc;
return EXIT_FAILURE; return 0;
} }
#endif #endif

View File

@ -14,8 +14,6 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "webp/config.h" #include "webp/config.h"
@ -26,7 +24,6 @@
#include "webp/decode.h" #include "webp/decode.h"
#include "webp/format_constants.h" #include "webp/format_constants.h"
#include "webp/mux_types.h" #include "webp/mux_types.h"
#include "webp/types.h"
#if defined(_MSC_VER) && _MSC_VER < 1900 #if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf #define snprintf _snprintf
@ -34,17 +31,16 @@
#define LOG_ERROR(MESSAGE) \ #define LOG_ERROR(MESSAGE) \
do { \ do { \
if (webp_info->show_diagnosis) { \ if (webp_info->show_diagnosis_) { \
fprintf(stderr, "Error: %s\n", MESSAGE); \ fprintf(stderr, "Error: %s\n", MESSAGE); \
} \ } \
} while (0) } while (0)
#define LOG_WARN(MESSAGE) \ #define LOG_WARN(MESSAGE) \
do { \ do { \
if (webp_info->show_diagnosis) { \ if (webp_info->show_diagnosis_) { \
fprintf(stderr, "Warning: %s\n", MESSAGE); \ fprintf(stderr, "Warning: %s\n", MESSAGE); \
} \ } \
++webp_info->num_warnings; \
} while (0) } while (0)
static const char* const kFormats[3] = { static const char* const kFormats[3] = {
@ -92,52 +88,51 @@ typedef enum ChunkID {
} ChunkID; } ChunkID;
typedef struct { typedef struct {
size_t start; size_t start_;
size_t end; size_t end_;
const uint8_t* buf; const uint8_t* buf_;
} MemBuffer; } MemBuffer;
typedef struct { typedef struct {
size_t offset; size_t offset_;
size_t size; size_t size_;
const uint8_t* payload; const uint8_t* payload_;
ChunkID id; ChunkID id_;
} ChunkData; } ChunkData;
typedef struct WebPInfo { typedef struct WebPInfo {
int canvas_width; int canvas_width_;
int canvas_height; int canvas_height_;
int loop_count; int loop_count_;
int num_frames; int num_frames_;
int chunk_counts[CHUNK_TYPES]; int chunk_counts_[CHUNK_TYPES];
int anmf_subchunk_counts[3]; // 0 VP8; 1 VP8L; 2 ALPH. int anmf_subchunk_counts_[3]; // 0 VP8; 1 VP8L; 2 ALPH.
uint32_t bgcolor; uint32_t bgcolor_;
int feature_flags; int feature_flags_;
int has_alpha; int has_alpha_;
// Used for parsing ANMF chunks. // Used for parsing ANMF chunks.
int frame_width, frame_height; int frame_width_, frame_height_;
size_t anim_frame_data_size; size_t anim_frame_data_size_;
int is_processing_anim_frame, seen_alpha_subchunk, seen_image_subchunk; int is_processing_anim_frame_, seen_alpha_subchunk_, seen_image_subchunk_;
// Print output control. // Print output control.
int quiet, show_diagnosis, show_summary; int quiet_, show_diagnosis_, show_summary_;
int num_warnings; int parse_bitstream_;
int parse_bitstream;
} WebPInfo; } WebPInfo;
static void WebPInfoInit(WebPInfo* const webp_info) { static void WebPInfoInit(WebPInfo* const webp_info) {
memset(webp_info, 0, sizeof(*webp_info)); memset(webp_info, 0, sizeof(*webp_info));
} }
static const uint32_t kWebPChunkTags[CHUNK_TYPES] = { static const char kWebPChunkTags[CHUNK_TYPES][4] = {
MKFOURCC('V', 'P', '8', ' '), { 'V', 'P', '8', ' ' },
MKFOURCC('V', 'P', '8', 'L'), { 'V', 'P', '8', 'L' },
MKFOURCC('V', 'P', '8', 'X'), { 'V', 'P', '8', 'X' },
MKFOURCC('A', 'L', 'P', 'H'), { 'A', 'L', 'P', 'H' },
MKFOURCC('A', 'N', 'I', 'M'), { 'A', 'N', 'I', 'M' },
MKFOURCC('A', 'N', 'M', 'F'), { 'A', 'N', 'M', 'F' },
MKFOURCC('I', 'C', 'C', 'P'), { 'I', 'C', 'C', 'P' },
MKFOURCC('E', 'X', 'I', 'F'), { 'E', 'X', 'I', 'F' },
MKFOURCC('X', 'M', 'P', ' '), { 'X', 'M', 'P', ' ' },
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -187,25 +182,25 @@ static int ReadFileToWebPData(const char* const filename,
// MemBuffer object. // MemBuffer object.
static void InitMemBuffer(MemBuffer* const mem, const WebPData* webp_data) { static void InitMemBuffer(MemBuffer* const mem, const WebPData* webp_data) {
mem->buf = webp_data->bytes; mem->buf_ = webp_data->bytes;
mem->start = 0; mem->start_ = 0;
mem->end = webp_data->size; mem->end_ = webp_data->size;
} }
static size_t MemDataSize(const MemBuffer* const mem) { static size_t MemDataSize(const MemBuffer* const mem) {
return (mem->end - mem->start); return (mem->end_ - mem->start_);
} }
static const uint8_t* GetBuffer(MemBuffer* const mem) { static const uint8_t* GetBuffer(MemBuffer* const mem) {
return mem->buf + mem->start; return mem->buf_ + mem->start_;
} }
static void Skip(MemBuffer* const mem, size_t size) { static void Skip(MemBuffer* const mem, size_t size) {
mem->start += size; mem->start_ += size;
} }
static uint32_t ReadMemBufLE32(MemBuffer* const mem) { static uint32_t ReadMemBufLE32(MemBuffer* const mem) {
const uint8_t* const data = mem->buf + mem->start; const uint8_t* const data = mem->buf_ + mem->start_;
const uint32_t val = GetLE32(data); const uint32_t val = GetLE32(data);
assert(MemDataSize(mem) >= 4); assert(MemDataSize(mem) >= 4);
Skip(mem, 4); Skip(mem, 4);
@ -336,8 +331,8 @@ static WebPInfoStatus ParseLossyFilterHeader(const WebPInfo* const webp_info,
static WebPInfoStatus ParseLossyHeader(const ChunkData* const chunk_data, static WebPInfoStatus ParseLossyHeader(const ChunkData* const chunk_data,
const WebPInfo* const webp_info) { const WebPInfo* const webp_info) {
const uint8_t* data = chunk_data->payload; const uint8_t* data = chunk_data->payload_;
size_t data_size = chunk_data->size - CHUNK_HEADER_SIZE; size_t data_size = chunk_data->size_ - CHUNK_HEADER_SIZE;
const uint32_t bits = (uint32_t)data[0] | (data[1] << 8) | (data[2] << 16); const uint32_t bits = (uint32_t)data[0] | (data[1] << 8) | (data[2] << 16);
const int key_frame = !(bits & 1); const int key_frame = !(bits & 1);
const int profile = (bits >> 1) & 7; const int profile = (bits >> 1) & 7;
@ -349,7 +344,7 @@ static WebPInfoStatus ParseLossyHeader(const ChunkData* const chunk_data,
int colorspace, clamp_type; int colorspace, clamp_type;
printf(" Parsing lossy bitstream...\n"); printf(" Parsing lossy bitstream...\n");
// Calling WebPGetFeatures() in ProcessImageChunk() should ensure this. // Calling WebPGetFeatures() in ProcessImageChunk() should ensure this.
assert(chunk_data->size >= CHUNK_HEADER_SIZE + 10); assert(chunk_data->size_ >= CHUNK_HEADER_SIZE + 10);
if (profile > 3) { if (profile > 3) {
LOG_ERROR("Unknown profile."); LOG_ERROR("Unknown profile.");
return WEBP_INFO_BITSTREAM_ERROR; return WEBP_INFO_BITSTREAM_ERROR;
@ -360,12 +355,12 @@ static WebPInfoStatus ParseLossyHeader(const ChunkData* const chunk_data,
} }
data += 3; data += 3;
data_size -= 3; data_size -= 3;
printf( printf(" Key frame: %s\n"
" Key frame: %s\n" " Profile: %d\n"
" Profile: %d\n" " Display: %s\n"
" Display: Yes\n" " Part. 0 length: %d\n",
" Part. 0 length: %d\n", key_frame ? "Yes" : "No", profile,
key_frame ? "Yes" : "No", profile, partition0_length); display ? "Yes" : "No", partition0_length);
if (key_frame) { if (key_frame) {
if (!(data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a)) { if (!(data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a)) {
LOG_ERROR("Invalid lossy bitstream signature."); LOG_ERROR("Invalid lossy bitstream signature.");
@ -507,8 +502,8 @@ static WebPInfoStatus ParseLosslessTransform(WebPInfo* const webp_info,
static WebPInfoStatus ParseLosslessHeader(const ChunkData* const chunk_data, static WebPInfoStatus ParseLosslessHeader(const ChunkData* const chunk_data,
WebPInfo* const webp_info) { WebPInfo* const webp_info) {
const uint8_t* data = chunk_data->payload; const uint8_t* data = chunk_data->payload_;
size_t data_size = chunk_data->size - CHUNK_HEADER_SIZE; size_t data_size = chunk_data->size_ - CHUNK_HEADER_SIZE;
uint64_t bit_position = 0; uint64_t bit_position = 0;
uint64_t* const bit_pos = &bit_position; uint64_t* const bit_pos = &bit_position;
WebPInfoStatus status; WebPInfoStatus status;
@ -543,8 +538,8 @@ static WebPInfoStatus ParseLosslessHeader(const ChunkData* const chunk_data,
static WebPInfoStatus ParseAlphaHeader(const ChunkData* const chunk_data, static WebPInfoStatus ParseAlphaHeader(const ChunkData* const chunk_data,
WebPInfo* const webp_info) { WebPInfo* const webp_info) {
const uint8_t* data = chunk_data->payload; const uint8_t* data = chunk_data->payload_;
size_t data_size = chunk_data->size - CHUNK_HEADER_SIZE; size_t data_size = chunk_data->size_ - CHUNK_HEADER_SIZE;
if (data_size <= ALPHA_HEADER_LEN) { if (data_size <= ALPHA_HEADER_LEN) {
LOG_ERROR("Truncated ALPH chunk."); LOG_ERROR("Truncated ALPH chunk.");
return WEBP_INFO_TRUNCATED_DATA; return WEBP_INFO_TRUNCATED_DATA;
@ -585,7 +580,7 @@ static WebPInfoStatus ParseAlphaHeader(const ChunkData* const chunk_data,
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Chunk parsing. // Chunk parsing.
static WebPInfoStatus ParseRIFFHeader(WebPInfo* const webp_info, static WebPInfoStatus ParseRIFFHeader(const WebPInfo* const webp_info,
MemBuffer* const mem) { MemBuffer* const mem) {
const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE; const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE;
size_t riff_size; size_t riff_size;
@ -609,14 +604,14 @@ static WebPInfoStatus ParseRIFFHeader(WebPInfo* const webp_info,
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
riff_size += CHUNK_HEADER_SIZE; riff_size += CHUNK_HEADER_SIZE;
if (!webp_info->quiet) { if (!webp_info->quiet_) {
printf("RIFF HEADER:\n"); printf("RIFF HEADER:\n");
printf(" File size: %6d\n", (int)riff_size); printf(" File size: %6d\n", (int)riff_size);
} }
if (riff_size < mem->end) { if (riff_size < mem->end_) {
LOG_WARN("RIFF size is smaller than the file size."); LOG_WARN("RIFF size is smaller than the file size.");
mem->end = riff_size; mem->end_ = riff_size;
} else if (riff_size > mem->end) { } else if (riff_size > mem->end_) {
LOG_ERROR("Truncated data detected when parsing RIFF payload."); LOG_ERROR("Truncated data detected when parsing RIFF payload.");
return WEBP_INFO_TRUNCATED_DATA; return WEBP_INFO_TRUNCATED_DATA;
} }
@ -632,7 +627,7 @@ static WebPInfoStatus ParseChunk(const WebPInfo* const webp_info,
LOG_ERROR("Truncated data detected when parsing chunk header."); LOG_ERROR("Truncated data detected when parsing chunk header.");
return WEBP_INFO_TRUNCATED_DATA; return WEBP_INFO_TRUNCATED_DATA;
} else { } else {
const size_t chunk_start_offset = mem->start; const size_t chunk_start_offset = mem->start_;
const uint32_t fourcc = ReadMemBufLE32(mem); const uint32_t fourcc = ReadMemBufLE32(mem);
const uint32_t payload_size = ReadMemBufLE32(mem); const uint32_t payload_size = ReadMemBufLE32(mem);
const uint32_t payload_size_padded = payload_size + (payload_size & 1); const uint32_t payload_size_padded = payload_size + (payload_size & 1);
@ -647,13 +642,13 @@ static WebPInfoStatus ParseChunk(const WebPInfo* const webp_info,
return WEBP_INFO_TRUNCATED_DATA; return WEBP_INFO_TRUNCATED_DATA;
} }
for (i = 0; i < CHUNK_TYPES; ++i) { for (i = 0; i < CHUNK_TYPES; ++i) {
if (kWebPChunkTags[i] == fourcc) break; if (!memcmp(kWebPChunkTags[i], &fourcc, TAG_SIZE)) break;
} }
chunk_data->offset = chunk_start_offset; chunk_data->offset_ = chunk_start_offset;
chunk_data->size = chunk_size; chunk_data->size_ = chunk_size;
chunk_data->id = (ChunkID)i; chunk_data->id_ = (ChunkID)i;
chunk_data->payload = GetBuffer(mem); chunk_data->payload_ = GetBuffer(mem);
if (chunk_data->id == CHUNK_ANMF) { if (chunk_data->id_ == CHUNK_ANMF) {
if (payload_size != payload_size_padded) { if (payload_size != payload_size_padded) {
LOG_ERROR("ANMF chunk size should always be even."); LOG_ERROR("ANMF chunk size should always be even.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
@ -672,39 +667,39 @@ static WebPInfoStatus ParseChunk(const WebPInfo* const webp_info,
static WebPInfoStatus ProcessVP8XChunk(const ChunkData* const chunk_data, static WebPInfoStatus ProcessVP8XChunk(const ChunkData* const chunk_data,
WebPInfo* const webp_info) { WebPInfo* const webp_info) {
const uint8_t* data = chunk_data->payload; const uint8_t* data = chunk_data->payload_;
if (webp_info->chunk_counts[CHUNK_VP8] || if (webp_info->chunk_counts_[CHUNK_VP8] ||
webp_info->chunk_counts[CHUNK_VP8L] || webp_info->chunk_counts_[CHUNK_VP8L] ||
webp_info->chunk_counts[CHUNK_VP8X]) { webp_info->chunk_counts_[CHUNK_VP8X]) {
LOG_ERROR("Already seen a VP8/VP8L/VP8X chunk when parsing VP8X chunk."); LOG_ERROR("Already seen a VP8/VP8L/VP8X chunk when parsing VP8X chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (chunk_data->size != VP8X_CHUNK_SIZE + CHUNK_HEADER_SIZE) { if (chunk_data->size_ != VP8X_CHUNK_SIZE + CHUNK_HEADER_SIZE) {
LOG_ERROR("Corrupted VP8X chunk."); LOG_ERROR("Corrupted VP8X chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
++webp_info->chunk_counts[CHUNK_VP8X]; ++webp_info->chunk_counts_[CHUNK_VP8X];
webp_info->feature_flags = *data; webp_info->feature_flags_ = *data;
data += 4; data += 4;
webp_info->canvas_width = 1 + ReadLE24(&data); webp_info->canvas_width_ = 1 + ReadLE24(&data);
webp_info->canvas_height = 1 + ReadLE24(&data); webp_info->canvas_height_ = 1 + ReadLE24(&data);
if (!webp_info->quiet) { if (!webp_info->quiet_) {
printf(" ICCP: %d\n Alpha: %d\n EXIF: %d\n XMP: %d\n Animation: %d\n", printf(" ICCP: %d\n Alpha: %d\n EXIF: %d\n XMP: %d\n Animation: %d\n",
(webp_info->feature_flags & ICCP_FLAG) != 0, (webp_info->feature_flags_ & ICCP_FLAG) != 0,
(webp_info->feature_flags & ALPHA_FLAG) != 0, (webp_info->feature_flags_ & ALPHA_FLAG) != 0,
(webp_info->feature_flags & EXIF_FLAG) != 0, (webp_info->feature_flags_ & EXIF_FLAG) != 0,
(webp_info->feature_flags & XMP_FLAG) != 0, (webp_info->feature_flags_ & XMP_FLAG) != 0,
(webp_info->feature_flags & ANIMATION_FLAG) != 0); (webp_info->feature_flags_ & ANIMATION_FLAG) != 0);
printf(" Canvas size %d x %d\n", printf(" Canvas size %d x %d\n",
webp_info->canvas_width, webp_info->canvas_height); webp_info->canvas_width_, webp_info->canvas_height_);
} }
if (webp_info->canvas_width > MAX_CANVAS_SIZE) { if (webp_info->canvas_width_ > MAX_CANVAS_SIZE) {
LOG_WARN("Canvas width is out of range in VP8X chunk."); LOG_WARN("Canvas width is out of range in VP8X chunk.");
} }
if (webp_info->canvas_height > MAX_CANVAS_SIZE) { if (webp_info->canvas_height_ > MAX_CANVAS_SIZE) {
LOG_WARN("Canvas height is out of range in VP8X chunk."); LOG_WARN("Canvas height is out of range in VP8X chunk.");
} }
if ((uint64_t)webp_info->canvas_width * webp_info->canvas_height > if ((uint64_t)webp_info->canvas_width_ * webp_info->canvas_height_ >
MAX_IMAGE_AREA) { MAX_IMAGE_AREA) {
LOG_WARN("Canvas area is out of range in VP8X chunk."); LOG_WARN("Canvas area is out of range in VP8X chunk.");
} }
@ -713,27 +708,27 @@ static WebPInfoStatus ProcessVP8XChunk(const ChunkData* const chunk_data,
static WebPInfoStatus ProcessANIMChunk(const ChunkData* const chunk_data, static WebPInfoStatus ProcessANIMChunk(const ChunkData* const chunk_data,
WebPInfo* const webp_info) { WebPInfo* const webp_info) {
const uint8_t* data = chunk_data->payload; const uint8_t* data = chunk_data->payload_;
if (!webp_info->chunk_counts[CHUNK_VP8X]) { if (!webp_info->chunk_counts_[CHUNK_VP8X]) {
LOG_ERROR("ANIM chunk detected before VP8X chunk."); LOG_ERROR("ANIM chunk detected before VP8X chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (chunk_data->size != ANIM_CHUNK_SIZE + CHUNK_HEADER_SIZE) { if (chunk_data->size_ != ANIM_CHUNK_SIZE + CHUNK_HEADER_SIZE) {
LOG_ERROR("Corrupted ANIM chunk."); LOG_ERROR("Corrupted ANIM chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
webp_info->bgcolor = ReadLE32(&data); webp_info->bgcolor_ = ReadLE32(&data);
webp_info->loop_count = ReadLE16(&data); webp_info->loop_count_ = ReadLE16(&data);
++webp_info->chunk_counts[CHUNK_ANIM]; ++webp_info->chunk_counts_[CHUNK_ANIM];
if (!webp_info->quiet) { if (!webp_info->quiet_) {
printf(" Background color:(ARGB) %02x %02x %02x %02x\n", printf(" Background color:(ARGB) %02x %02x %02x %02x\n",
(webp_info->bgcolor >> 24) & 0xff, (webp_info->bgcolor_ >> 24) & 0xff,
(webp_info->bgcolor >> 16) & 0xff, (webp_info->bgcolor_ >> 16) & 0xff,
(webp_info->bgcolor >> 8) & 0xff, (webp_info->bgcolor_ >> 8) & 0xff,
webp_info->bgcolor & 0xff); webp_info->bgcolor_ & 0xff);
printf(" Loop count : %d\n", webp_info->loop_count); printf(" Loop count : %d\n", webp_info->loop_count_);
} }
if (webp_info->loop_count > MAX_LOOP_COUNT) { if (webp_info->loop_count_ > MAX_LOOP_COUNT) {
LOG_WARN("Loop count is out of range in ANIM chunk."); LOG_WARN("Loop count is out of range in ANIM chunk.");
} }
return WEBP_INFO_OK; return WEBP_INFO_OK;
@ -741,17 +736,17 @@ static WebPInfoStatus ProcessANIMChunk(const ChunkData* const chunk_data,
static WebPInfoStatus ProcessANMFChunk(const ChunkData* const chunk_data, static WebPInfoStatus ProcessANMFChunk(const ChunkData* const chunk_data,
WebPInfo* const webp_info) { WebPInfo* const webp_info) {
const uint8_t* data = chunk_data->payload; const uint8_t* data = chunk_data->payload_;
int offset_x, offset_y, width, height, duration, blend, dispose, temp; int offset_x, offset_y, width, height, duration, blend, dispose, temp;
if (webp_info->is_processing_anim_frame) { if (webp_info->is_processing_anim_frame_) {
LOG_ERROR("ANMF chunk detected within another ANMF chunk."); LOG_ERROR("ANMF chunk detected within another ANMF chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (!webp_info->chunk_counts[CHUNK_ANIM]) { if (!webp_info->chunk_counts_[CHUNK_ANIM]) {
LOG_ERROR("ANMF chunk detected before ANIM chunk."); LOG_ERROR("ANMF chunk detected before ANIM chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (chunk_data->size <= CHUNK_HEADER_SIZE + ANMF_CHUNK_SIZE) { if (chunk_data->size_ <= CHUNK_HEADER_SIZE + ANMF_CHUNK_SIZE) {
LOG_ERROR("Truncated data detected when parsing ANMF chunk."); LOG_ERROR("Truncated data detected when parsing ANMF chunk.");
return WEBP_INFO_TRUNCATED_DATA; return WEBP_INFO_TRUNCATED_DATA;
} }
@ -763,8 +758,8 @@ static WebPInfoStatus ProcessANMFChunk(const ChunkData* const chunk_data,
temp = *data; temp = *data;
dispose = temp & 1; dispose = temp & 1;
blend = (temp >> 1) & 1; blend = (temp >> 1) & 1;
++webp_info->chunk_counts[CHUNK_ANMF]; ++webp_info->chunk_counts_[CHUNK_ANMF];
if (!webp_info->quiet) { if (!webp_info->quiet_) {
printf(" Offset_X: %d\n Offset_Y: %d\n Width: %d\n Height: %d\n" printf(" Offset_X: %d\n Offset_Y: %d\n Width: %d\n Height: %d\n"
" Duration: %d\n Dispose: %d\n Blend: %d\n", " Duration: %d\n Dispose: %d\n Blend: %d\n",
offset_x, offset_y, width, height, duration, dispose, blend); offset_x, offset_y, width, height, duration, dispose, blend);
@ -777,92 +772,92 @@ static WebPInfoStatus ProcessANMFChunk(const ChunkData* const chunk_data,
LOG_ERROR("Invalid offset parameters in ANMF chunk."); LOG_ERROR("Invalid offset parameters in ANMF chunk.");
return WEBP_INFO_INVALID_PARAM; return WEBP_INFO_INVALID_PARAM;
} }
if ((uint64_t)offset_x + width > (uint64_t)webp_info->canvas_width || if ((uint64_t)offset_x + width > (uint64_t)webp_info->canvas_width_ ||
(uint64_t)offset_y + height > (uint64_t)webp_info->canvas_height) { (uint64_t)offset_y + height > (uint64_t)webp_info->canvas_height_) {
LOG_ERROR("Frame exceeds canvas in ANMF chunk."); LOG_ERROR("Frame exceeds canvas in ANMF chunk.");
return WEBP_INFO_INVALID_PARAM; return WEBP_INFO_INVALID_PARAM;
} }
webp_info->is_processing_anim_frame = 1; webp_info->is_processing_anim_frame_ = 1;
webp_info->seen_alpha_subchunk = 0; webp_info->seen_alpha_subchunk_ = 0;
webp_info->seen_image_subchunk = 0; webp_info->seen_image_subchunk_ = 0;
webp_info->frame_width = width; webp_info->frame_width_ = width;
webp_info->frame_height = height; webp_info->frame_height_ = height;
webp_info->anim_frame_data_size = webp_info->anim_frame_data_size_ =
chunk_data->size - CHUNK_HEADER_SIZE - ANMF_CHUNK_SIZE; chunk_data->size_ - CHUNK_HEADER_SIZE - ANMF_CHUNK_SIZE;
return WEBP_INFO_OK; return WEBP_INFO_OK;
} }
static WebPInfoStatus ProcessImageChunk(const ChunkData* const chunk_data, static WebPInfoStatus ProcessImageChunk(const ChunkData* const chunk_data,
WebPInfo* const webp_info) { WebPInfo* const webp_info) {
const uint8_t* data = chunk_data->payload - CHUNK_HEADER_SIZE; const uint8_t* data = chunk_data->payload_ - CHUNK_HEADER_SIZE;
WebPBitstreamFeatures features; WebPBitstreamFeatures features;
const VP8StatusCode vp8_status = const VP8StatusCode vp8_status =
WebPGetFeatures(data, chunk_data->size, &features); WebPGetFeatures(data, chunk_data->size_, &features);
if (vp8_status != VP8_STATUS_OK) { if (vp8_status != VP8_STATUS_OK) {
LOG_ERROR("VP8/VP8L bitstream error."); LOG_ERROR("VP8/VP8L bitstream error.");
return WEBP_INFO_BITSTREAM_ERROR; return WEBP_INFO_BITSTREAM_ERROR;
} }
if (!webp_info->quiet) { if (!webp_info->quiet_) {
assert(features.format >= 0 && features.format <= 2); assert(features.format >= 0 && features.format <= 2);
printf(" Width: %d\n Height: %d\n Alpha: %d\n Animation: %d\n" printf(" Width: %d\n Height: %d\n Alpha: %d\n Animation: %d\n"
" Format: %s (%d)\n", " Format: %s (%d)\n",
features.width, features.height, features.has_alpha, features.width, features.height, features.has_alpha,
features.has_animation, kFormats[features.format], features.format); features.has_animation, kFormats[features.format], features.format);
} }
if (webp_info->is_processing_anim_frame) { if (webp_info->is_processing_anim_frame_) {
++webp_info->anmf_subchunk_counts[chunk_data->id == CHUNK_VP8 ? 0 : 1]; ++webp_info->anmf_subchunk_counts_[chunk_data->id_ == CHUNK_VP8 ? 0 : 1];
if (chunk_data->id == CHUNK_VP8L && webp_info->seen_alpha_subchunk) { if (chunk_data->id_ == CHUNK_VP8L && webp_info->seen_alpha_subchunk_) {
LOG_ERROR("Both VP8L and ALPH sub-chunks are present in an ANMF chunk."); LOG_ERROR("Both VP8L and ALPH sub-chunks are present in an ANMF chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (webp_info->frame_width != features.width || if (webp_info->frame_width_ != features.width ||
webp_info->frame_height != features.height) { webp_info->frame_height_ != features.height) {
LOG_ERROR("Frame size in VP8/VP8L sub-chunk differs from ANMF header."); LOG_ERROR("Frame size in VP8/VP8L sub-chunk differs from ANMF header.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (webp_info->seen_image_subchunk) { if (webp_info->seen_image_subchunk_) {
LOG_ERROR("Consecutive VP8/VP8L sub-chunks in an ANMF chunk."); LOG_ERROR("Consecutive VP8/VP8L sub-chunks in an ANMF chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
webp_info->seen_image_subchunk = 1; webp_info->seen_image_subchunk_ = 1;
} else { } else {
if (webp_info->chunk_counts[CHUNK_VP8] || if (webp_info->chunk_counts_[CHUNK_VP8] ||
webp_info->chunk_counts[CHUNK_VP8L]) { webp_info->chunk_counts_[CHUNK_VP8L]) {
LOG_ERROR("Multiple VP8/VP8L chunks detected."); LOG_ERROR("Multiple VP8/VP8L chunks detected.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (chunk_data->id == CHUNK_VP8L && if (chunk_data->id_ == CHUNK_VP8L &&
webp_info->chunk_counts[CHUNK_ALPHA]) { webp_info->chunk_counts_[CHUNK_ALPHA]) {
LOG_WARN("Both VP8L and ALPH chunks are detected."); LOG_WARN("Both VP8L and ALPH chunks are detected.");
} }
if (webp_info->chunk_counts[CHUNK_ANIM] || if (webp_info->chunk_counts_[CHUNK_ANIM] ||
webp_info->chunk_counts[CHUNK_ANMF]) { webp_info->chunk_counts_[CHUNK_ANMF]) {
LOG_ERROR("VP8/VP8L chunk and ANIM/ANMF chunk are both detected."); LOG_ERROR("VP8/VP8L chunk and ANIM/ANMF chunk are both detected.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (webp_info->chunk_counts[CHUNK_VP8X]) { if (webp_info->chunk_counts_[CHUNK_VP8X]) {
if (webp_info->canvas_width != features.width || if (webp_info->canvas_width_ != features.width ||
webp_info->canvas_height != features.height) { webp_info->canvas_height_ != features.height) {
LOG_ERROR("Image size in VP8/VP8L chunk differs from VP8X chunk."); LOG_ERROR("Image size in VP8/VP8L chunk differs from VP8X chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
} else { } else {
webp_info->canvas_width = features.width; webp_info->canvas_width_ = features.width;
webp_info->canvas_height = features.height; webp_info->canvas_height_ = features.height;
if (webp_info->canvas_width < 1 || webp_info->canvas_height < 1 || if (webp_info->canvas_width_ < 1 || webp_info->canvas_height_ < 1 ||
webp_info->canvas_width > MAX_CANVAS_SIZE || webp_info->canvas_width_ > MAX_CANVAS_SIZE ||
webp_info->canvas_height > MAX_CANVAS_SIZE || webp_info->canvas_height_ > MAX_CANVAS_SIZE ||
(uint64_t)webp_info->canvas_width * webp_info->canvas_height > (uint64_t)webp_info->canvas_width_ * webp_info->canvas_height_ >
MAX_IMAGE_AREA) { MAX_IMAGE_AREA) {
LOG_WARN("Invalid parameters in VP8/VP8L chunk."); LOG_WARN("Invalid parameters in VP8/VP8L chunk.");
} }
} }
++webp_info->chunk_counts[chunk_data->id]; ++webp_info->chunk_counts_[chunk_data->id_];
} }
++webp_info->num_frames; ++webp_info->num_frames_;
webp_info->has_alpha |= features.has_alpha; webp_info->has_alpha_ |= features.has_alpha;
if (webp_info->parse_bitstream) { if (webp_info->parse_bitstream_) {
const int is_lossy = (chunk_data->id == CHUNK_VP8); const int is_lossy = (chunk_data->id_ == CHUNK_VP8);
const WebPInfoStatus status = const WebPInfoStatus status =
is_lossy ? ParseLossyHeader(chunk_data, webp_info) is_lossy ? ParseLossyHeader(chunk_data, webp_info)
: ParseLosslessHeader(chunk_data, webp_info); : ParseLosslessHeader(chunk_data, webp_info);
@ -873,41 +868,41 @@ static WebPInfoStatus ProcessImageChunk(const ChunkData* const chunk_data,
static WebPInfoStatus ProcessALPHChunk(const ChunkData* const chunk_data, static WebPInfoStatus ProcessALPHChunk(const ChunkData* const chunk_data,
WebPInfo* const webp_info) { WebPInfo* const webp_info) {
if (webp_info->is_processing_anim_frame) { if (webp_info->is_processing_anim_frame_) {
++webp_info->anmf_subchunk_counts[2]; ++webp_info->anmf_subchunk_counts_[2];
if (webp_info->seen_alpha_subchunk) { if (webp_info->seen_alpha_subchunk_) {
LOG_ERROR("Consecutive ALPH sub-chunks in an ANMF chunk."); LOG_ERROR("Consecutive ALPH sub-chunks in an ANMF chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
webp_info->seen_alpha_subchunk = 1; webp_info->seen_alpha_subchunk_ = 1;
if (webp_info->seen_image_subchunk) { if (webp_info->seen_image_subchunk_) {
LOG_ERROR("ALPHA sub-chunk detected after VP8 sub-chunk " LOG_ERROR("ALPHA sub-chunk detected after VP8 sub-chunk "
"in an ANMF chunk."); "in an ANMF chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
} else { } else {
if (webp_info->chunk_counts[CHUNK_ANIM] || if (webp_info->chunk_counts_[CHUNK_ANIM] ||
webp_info->chunk_counts[CHUNK_ANMF]) { webp_info->chunk_counts_[CHUNK_ANMF]) {
LOG_ERROR("ALPHA chunk and ANIM/ANMF chunk are both detected."); LOG_ERROR("ALPHA chunk and ANIM/ANMF chunk are both detected.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (!webp_info->chunk_counts[CHUNK_VP8X]) { if (!webp_info->chunk_counts_[CHUNK_VP8X]) {
LOG_ERROR("ALPHA chunk detected before VP8X chunk."); LOG_ERROR("ALPHA chunk detected before VP8X chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (webp_info->chunk_counts[CHUNK_VP8]) { if (webp_info->chunk_counts_[CHUNK_VP8]) {
LOG_ERROR("ALPHA chunk detected after VP8 chunk."); LOG_ERROR("ALPHA chunk detected after VP8 chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (webp_info->chunk_counts[CHUNK_ALPHA]) { if (webp_info->chunk_counts_[CHUNK_ALPHA]) {
LOG_ERROR("Multiple ALPHA chunks detected."); LOG_ERROR("Multiple ALPHA chunks detected.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
++webp_info->chunk_counts[CHUNK_ALPHA]; ++webp_info->chunk_counts_[CHUNK_ALPHA];
} }
webp_info->has_alpha = 1; webp_info->has_alpha_ = 1;
if (webp_info->parse_bitstream) { if (webp_info->parse_bitstream_) {
const WebPInfoStatus status = ParseAlphaHeader(chunk_data, webp_info); const WebPInfoStatus status = ParseAlphaHeader(chunk_data, webp_info);
if (status != WEBP_INFO_OK) return status; if (status != WEBP_INFO_OK) return status;
} }
@ -917,41 +912,35 @@ static WebPInfoStatus ProcessALPHChunk(const ChunkData* const chunk_data,
static WebPInfoStatus ProcessICCPChunk(const ChunkData* const chunk_data, static WebPInfoStatus ProcessICCPChunk(const ChunkData* const chunk_data,
WebPInfo* const webp_info) { WebPInfo* const webp_info) {
(void)chunk_data; (void)chunk_data;
if (!webp_info->chunk_counts[CHUNK_VP8X]) { if (!webp_info->chunk_counts_[CHUNK_VP8X]) {
LOG_ERROR("ICCP chunk detected before VP8X chunk."); LOG_ERROR("ICCP chunk detected before VP8X chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (webp_info->chunk_counts[CHUNK_VP8] || if (webp_info->chunk_counts_[CHUNK_VP8] ||
webp_info->chunk_counts[CHUNK_VP8L] || webp_info->chunk_counts_[CHUNK_VP8L] ||
webp_info->chunk_counts[CHUNK_ANIM]) { webp_info->chunk_counts_[CHUNK_ANIM]) {
LOG_ERROR("ICCP chunk detected after image data."); LOG_ERROR("ICCP chunk detected after image data.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
++webp_info->chunk_counts[CHUNK_ICCP]; ++webp_info->chunk_counts_[CHUNK_ICCP];
return WEBP_INFO_OK; return WEBP_INFO_OK;
} }
static WebPInfoStatus ProcessChunk(const ChunkData* const chunk_data, static WebPInfoStatus ProcessChunk(const ChunkData* const chunk_data,
WebPInfo* const webp_info) { WebPInfo* const webp_info) {
WebPInfoStatus status = WEBP_INFO_OK; WebPInfoStatus status = WEBP_INFO_OK;
ChunkID id = chunk_data->id; ChunkID id = chunk_data->id_;
if (chunk_data->id == CHUNK_UNKNOWN) { if (chunk_data->id_ == CHUNK_UNKNOWN) {
char error_message[50]; char error_message[50];
snprintf(error_message, 50, "Unknown chunk at offset %6d, length %6d", snprintf(error_message, 50, "Unknown chunk at offset %6d, length %6d",
(int)chunk_data->offset, (int)chunk_data->size); (int)chunk_data->offset_, (int)chunk_data->size_);
LOG_WARN(error_message); LOG_WARN(error_message);
} else { } else {
if (!webp_info->quiet) { if (!webp_info->quiet_) {
char tag[4]; const char* tag = kWebPChunkTags[chunk_data->id_];
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", printf("Chunk %c%c%c%c at offset %6d, length %6d\n",
tag[0], tag[1], tag[2], tag[3], (int)chunk_data->offset, tag[0], tag[1], tag[2], tag[3], (int)chunk_data->offset_,
(int)chunk_data->size); (int)chunk_data->size_);
} }
} }
switch (id) { switch (id) {
@ -976,21 +965,21 @@ static WebPInfoStatus ProcessChunk(const ChunkData* const chunk_data,
break; break;
case CHUNK_EXIF: case CHUNK_EXIF:
case CHUNK_XMP: case CHUNK_XMP:
++webp_info->chunk_counts[id]; ++webp_info->chunk_counts_[id];
break; break;
case CHUNK_UNKNOWN: case CHUNK_UNKNOWN:
default: default:
break; break;
} }
if (webp_info->is_processing_anim_frame && id != CHUNK_ANMF) { if (webp_info->is_processing_anim_frame_ && id != CHUNK_ANMF) {
if (webp_info->anim_frame_data_size == chunk_data->size) { if (webp_info->anim_frame_data_size_ == chunk_data->size_) {
if (!webp_info->seen_image_subchunk) { if (!webp_info->seen_image_subchunk_) {
LOG_ERROR("No VP8/VP8L chunk detected in an ANMF chunk."); LOG_ERROR("No VP8/VP8L chunk detected in an ANMF chunk.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
webp_info->is_processing_anim_frame = 0; webp_info->is_processing_anim_frame_ = 0;
} else if (webp_info->anim_frame_data_size > chunk_data->size) { } else if (webp_info->anim_frame_data_size_ > chunk_data->size_) {
webp_info->anim_frame_data_size -= chunk_data->size; webp_info->anim_frame_data_size_ -= chunk_data->size_;
} else { } else {
LOG_ERROR("Truncated data detected when parsing ANMF chunk."); LOG_ERROR("Truncated data detected when parsing ANMF chunk.");
return WEBP_INFO_TRUNCATED_DATA; return WEBP_INFO_TRUNCATED_DATA;
@ -999,56 +988,56 @@ static WebPInfoStatus ProcessChunk(const ChunkData* const chunk_data,
return status; return status;
} }
static WebPInfoStatus Validate(WebPInfo* const webp_info) { static WebPInfoStatus Validate(const WebPInfo* const webp_info) {
if (webp_info->num_frames < 1) { if (webp_info->num_frames_ < 1) {
LOG_ERROR("No image/frame detected."); LOG_ERROR("No image/frame detected.");
return WEBP_INFO_MISSING_DATA; return WEBP_INFO_MISSING_DATA;
} }
if (webp_info->chunk_counts[CHUNK_VP8X]) { if (webp_info->chunk_counts_[CHUNK_VP8X]) {
const int iccp = !!(webp_info->feature_flags & ICCP_FLAG); const int iccp = !!(webp_info->feature_flags_ & ICCP_FLAG);
const int exif = !!(webp_info->feature_flags & EXIF_FLAG); const int exif = !!(webp_info->feature_flags_ & EXIF_FLAG);
const int xmp = !!(webp_info->feature_flags & XMP_FLAG); const int xmp = !!(webp_info->feature_flags_ & XMP_FLAG);
const int animation = !!(webp_info->feature_flags & ANIMATION_FLAG); const int animation = !!(webp_info->feature_flags_ & ANIMATION_FLAG);
const int alpha = !!(webp_info->feature_flags & ALPHA_FLAG); const int alpha = !!(webp_info->feature_flags_ & ALPHA_FLAG);
if (!alpha && webp_info->has_alpha) { if (!alpha && webp_info->has_alpha_) {
LOG_ERROR("Unexpected alpha data detected."); LOG_ERROR("Unexpected alpha data detected.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (alpha && !webp_info->has_alpha) { if (alpha && !webp_info->has_alpha_) {
LOG_WARN("Alpha flag is set with no alpha data present."); LOG_WARN("Alpha flag is set with no alpha data present.");
} }
if (iccp && !webp_info->chunk_counts[CHUNK_ICCP]) { if (iccp && !webp_info->chunk_counts_[CHUNK_ICCP]) {
LOG_ERROR("Missing ICCP chunk."); LOG_ERROR("Missing ICCP chunk.");
return WEBP_INFO_MISSING_DATA; return WEBP_INFO_MISSING_DATA;
} }
if (exif && !webp_info->chunk_counts[CHUNK_EXIF]) { if (exif && !webp_info->chunk_counts_[CHUNK_EXIF]) {
LOG_ERROR("Missing EXIF chunk."); LOG_ERROR("Missing EXIF chunk.");
return WEBP_INFO_MISSING_DATA; return WEBP_INFO_MISSING_DATA;
} }
if (xmp && !webp_info->chunk_counts[CHUNK_XMP]) { if (xmp && !webp_info->chunk_counts_[CHUNK_XMP]) {
LOG_ERROR("Missing XMP chunk."); LOG_ERROR("Missing XMP chunk.");
return WEBP_INFO_MISSING_DATA; return WEBP_INFO_MISSING_DATA;
} }
if (!iccp && webp_info->chunk_counts[CHUNK_ICCP]) { if (!iccp && webp_info->chunk_counts_[CHUNK_ICCP]) {
LOG_ERROR("Unexpected ICCP chunk detected."); LOG_ERROR("Unexpected ICCP chunk detected.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (!exif && webp_info->chunk_counts[CHUNK_EXIF]) { if (!exif && webp_info->chunk_counts_[CHUNK_EXIF]) {
LOG_ERROR("Unexpected EXIF chunk detected."); LOG_ERROR("Unexpected EXIF chunk detected.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (!xmp && webp_info->chunk_counts[CHUNK_XMP]) { if (!xmp && webp_info->chunk_counts_[CHUNK_XMP]) {
LOG_ERROR("Unexpected XMP chunk detected."); LOG_ERROR("Unexpected XMP chunk detected.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
// Incomplete animation frame. // Incomplete animation frame.
if (webp_info->is_processing_anim_frame) return WEBP_INFO_MISSING_DATA; if (webp_info->is_processing_anim_frame_) return WEBP_INFO_MISSING_DATA;
if (!animation && webp_info->num_frames > 1) { if (!animation && webp_info->num_frames_ > 1) {
LOG_ERROR("More than 1 frame detected in non-animation file."); LOG_ERROR("More than 1 frame detected in non-animation file.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
if (animation && (!webp_info->chunk_counts[CHUNK_ANIM] || if (animation && (!webp_info->chunk_counts_[CHUNK_ANIM] ||
!webp_info->chunk_counts[CHUNK_ANMF])) { !webp_info->chunk_counts_[CHUNK_ANMF])) {
LOG_ERROR("No ANIM/ANMF chunk detected in animation file."); LOG_ERROR("No ANIM/ANMF chunk detected in animation file.");
return WEBP_INFO_PARSE_ERROR; return WEBP_INFO_PARSE_ERROR;
} }
@ -1059,17 +1048,17 @@ static WebPInfoStatus Validate(WebPInfo* const webp_info) {
static void ShowSummary(const WebPInfo* const webp_info) { static void ShowSummary(const WebPInfo* const webp_info) {
int i; int i;
printf("Summary:\n"); printf("Summary:\n");
printf("Number of frames: %d\n", webp_info->num_frames); printf("Number of frames: %d\n", webp_info->num_frames_);
printf("Chunk type : VP8 VP8L VP8X ALPH ANIM ANMF(VP8 /VP8L/ALPH) ICCP " printf("Chunk type : VP8 VP8L VP8X ALPH ANIM ANMF(VP8 /VP8L/ALPH) ICCP "
"EXIF XMP\n"); "EXIF XMP\n");
printf("Chunk counts: "); printf("Chunk counts: ");
for (i = 0; i < CHUNK_TYPES; ++i) { for (i = 0; i < CHUNK_TYPES; ++i) {
printf("%4d ", webp_info->chunk_counts[i]); printf("%4d ", webp_info->chunk_counts_[i]);
if (i == CHUNK_ANMF) { if (i == CHUNK_ANMF) {
printf("%4d %4d %4d ", printf("%4d %4d %4d ",
webp_info->anmf_subchunk_counts[0], webp_info->anmf_subchunk_counts_[0],
webp_info->anmf_subchunk_counts[1], webp_info->anmf_subchunk_counts_[1],
webp_info->anmf_subchunk_counts[2]); webp_info->anmf_subchunk_counts_[2]);
} }
} }
printf("\n"); printf("\n");
@ -1092,26 +1081,28 @@ static WebPInfoStatus AnalyzeWebP(WebPInfo* const webp_info,
webp_info_status = ProcessChunk(&chunk_data, webp_info); webp_info_status = ProcessChunk(&chunk_data, webp_info);
} }
if (webp_info_status != WEBP_INFO_OK) goto Error; if (webp_info_status != WEBP_INFO_OK) goto Error;
if (webp_info->show_summary) ShowSummary(webp_info); if (webp_info->show_summary_) ShowSummary(webp_info);
// Final check. // Final check.
webp_info_status = Validate(webp_info); webp_info_status = Validate(webp_info);
Error: Error:
if (!webp_info->quiet) { if (!webp_info->quiet_) {
if (webp_info_status == WEBP_INFO_OK) { if (webp_info_status == WEBP_INFO_OK) {
printf("No error detected.\n"); printf("No error detected.\n");
} else { } else {
printf("Errors detected.\n"); 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; return webp_info_status;
} }
static void Help(void) { static void HelpShort(void) {
printf("Usage: webpinfo [options] in_files\n"
"Try -longhelp for an exhaustive list of options.\n");
}
static void HelpLong(void) {
printf("Usage: webpinfo [options] in_files\n" printf("Usage: webpinfo [options] in_files\n"
"Note: there could be multiple input files;\n" "Note: there could be multiple input files;\n"
" options must come before input files.\n" " options must come before input files.\n"
@ -1123,7 +1114,6 @@ static void Help(void) {
" -bitstream_info .... Parse bitstream header.\n"); " -bitstream_info .... Parse bitstream header.\n");
} }
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
int c, quiet = 0, show_diag = 0, show_summary = 0; int c, quiet = 0, show_diag = 0, show_summary = 0;
int parse_bitstream = 0; int parse_bitstream = 0;
@ -1133,16 +1123,18 @@ int main(int argc, const char* argv[]) {
INIT_WARGV(argc, argv); INIT_WARGV(argc, argv);
if (argc == 1) { if (argc == 1) {
Help(); HelpShort();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(WEBP_INFO_OK);
} }
// Parse command-line input. // Parse command-line input.
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help") || if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) { HelpShort();
Help(); FREE_WARGV_AND_RETURN(WEBP_INFO_OK);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); } else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
HelpLong();
FREE_WARGV_AND_RETURN(WEBP_INFO_OK);
} else if (!strcmp(argv[c], "-quiet")) { } else if (!strcmp(argv[c], "-quiet")) {
quiet = 1; quiet = 1;
} else if (!strcmp(argv[c], "-diag")) { } else if (!strcmp(argv[c], "-diag")) {
@ -1155,15 +1147,15 @@ int main(int argc, const char* argv[]) {
const int version = WebPGetDecoderVersion(); const int version = WebPGetDecoderVersion();
printf("WebP Decoder version: %d.%d.%d\n", printf("WebP Decoder version: %d.%d.%d\n",
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); FREE_WARGV_AND_RETURN(0);
} else { // Assume the remaining are all input files. } else { // Assume the remaining are all input files.
break; break;
} }
} }
if (c == argc) { if (c == argc) {
Help(); HelpShort();
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(WEBP_INFO_INVALID_COMMAND);
} }
// Process input files one by one. // Process input files one by one.
@ -1171,10 +1163,10 @@ int main(int argc, const char* argv[]) {
WebPData webp_data; WebPData webp_data;
const W_CHAR* in_file = NULL; const W_CHAR* in_file = NULL;
WebPInfoInit(&webp_info); WebPInfoInit(&webp_info);
webp_info.quiet = quiet; webp_info.quiet_ = quiet;
webp_info.show_diagnosis = show_diag; webp_info.show_diagnosis_ = show_diag;
webp_info.show_summary = show_summary; webp_info.show_summary_ = show_summary;
webp_info.parse_bitstream = parse_bitstream; webp_info.parse_bitstream_ = parse_bitstream;
in_file = GET_WARGV(argv, c); in_file = GET_WARGV(argv, c);
if (in_file == NULL || if (in_file == NULL ||
!ReadFileToWebPData((const char*)in_file, &webp_data)) { !ReadFileToWebPData((const char*)in_file, &webp_data)) {
@ -1182,10 +1174,9 @@ int main(int argc, const char* argv[]) {
WFPRINTF(stderr, "Failed to open input file %s.\n", in_file); WFPRINTF(stderr, "Failed to open input file %s.\n", in_file);
continue; continue;
} }
if (!webp_info.quiet) WPRINTF("File: %s\n", in_file); if (!webp_info.quiet_) WPRINTF("File: %s\n", in_file);
webp_info_status = AnalyzeWebP(&webp_info, &webp_data); webp_info_status = AnalyzeWebP(&webp_info, &webp_data);
WebPDataClear(&webp_data); WebPDataClear(&webp_data);
} }
FREE_WARGV_AND_RETURN((webp_info_status == WEBP_INFO_OK) ? EXIT_SUCCESS FREE_WARGV_AND_RETURN(webp_info_status);
: EXIT_FAILURE);
} }

View File

@ -26,7 +26,6 @@
webpmux -set icc image_profile.icc in.webp -o out_icc_container.webp webpmux -set icc image_profile.icc in.webp -o out_icc_container.webp
webpmux -set exif image_metadata.exif in.webp -o out_exif_container.webp webpmux -set exif image_metadata.exif in.webp -o out_exif_container.webp
webpmux -set xmp image_metadata.xmp in.webp -o out_xmp_container.webp webpmux -set xmp image_metadata.xmp in.webp -o out_xmp_container.webp
webpmux -set loop 1 in.webp -o out_looped.webp
Extract relevant data from WebP container file: Extract relevant data from WebP container file:
webpmux -get frame n in.webp -o out_frame.webp webpmux -get frame n in.webp -o out_frame.webp
@ -59,14 +58,11 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "webp/decode.h"
#include "webp/mux.h"
#include "../examples/example_util.h" #include "../examples/example_util.h"
#include "../imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "./unicode.h" #include "./unicode.h"
#include "webp/decode.h"
#include "webp/mux.h"
#include "webp/mux_types.h"
#include "webp/types.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Config object to parse command-line arguments. // Config object to parse command-line arguments.
@ -89,9 +85,9 @@ typedef enum {
} FeatureSubType; } FeatureSubType;
typedef struct { typedef struct {
FeatureSubType subtype; FeatureSubType subtype_;
const char* filename; const char* filename_;
const char* params; const char* params_;
} FeatureArg; } FeatureArg;
typedef enum { typedef enum {
@ -101,8 +97,6 @@ typedef enum {
FEATURE_ICCP, FEATURE_ICCP,
FEATURE_ANMF, FEATURE_ANMF,
FEATURE_DURATION, FEATURE_DURATION,
FEATURE_LOOP,
FEATURE_BGCOLOR,
LAST_FEATURE LAST_FEATURE
} FeatureType; } FeatureType;
@ -116,14 +110,14 @@ static const char* const kDescriptions[LAST_FEATURE] = {
}; };
typedef struct { typedef struct {
CommandLineArguments cmd_args; CommandLineArguments cmd_args_;
ActionType action_type; ActionType action_type_;
const char* input; const char* input_;
const char* output; const char* output_;
FeatureType type; FeatureType type_;
FeatureArg* args; FeatureArg* args_;
int arg_count; int arg_count_;
} Config; } Config;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -134,8 +128,8 @@ static int CountOccurrences(const CommandLineArguments* const args,
int i; int i;
int num_occurences = 0; int num_occurences = 0;
for (i = 0; i < args->argc; ++i) { for (i = 0; i < args->argc_; ++i) {
if (!strcmp(args->argv[i], arg)) { if (!strcmp(args->argv_[i], arg)) {
++num_occurences; ++num_occurences;
} }
} }
@ -153,20 +147,16 @@ static const char* ErrorString(WebPMuxError err) {
} }
#define RETURN_IF_ERROR(ERR_MSG) \ #define RETURN_IF_ERROR(ERR_MSG) \
do { \ if (err != WEBP_MUX_OK) { \
if (err != WEBP_MUX_OK) { \ fprintf(stderr, ERR_MSG); \
fprintf(stderr, ERR_MSG); \ return err; \
return err; \ }
} \
} while (0)
#define RETURN_IF_ERROR3(ERR_MSG, FORMAT_STR1, FORMAT_STR2) \ #define RETURN_IF_ERROR3(ERR_MSG, FORMAT_STR1, FORMAT_STR2) \
do { \ if (err != WEBP_MUX_OK) { \
if (err != WEBP_MUX_OK) { \ fprintf(stderr, ERR_MSG, FORMAT_STR1, FORMAT_STR2); \
fprintf(stderr, ERR_MSG, FORMAT_STR1, FORMAT_STR2); \ return err; \
return err; \ }
} \
} while (0)
#define ERROR_GOTO1(ERR_MSG, LABEL) \ #define ERROR_GOTO1(ERR_MSG, LABEL) \
do { \ do { \
@ -323,12 +313,10 @@ static void PrintHelp(void) {
printf("\n"); printf("\n");
printf("SET_OPTIONS:\n"); printf("SET_OPTIONS:\n");
printf(" Set color profile/metadata/parameters:\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(" bgcolor BACKGROUND_COLOR set the animation background color\n"); printf(" exif file.exif set EXIF metadata\n");
printf(" icc file.icc set ICC profile\n"); printf(" xmp file.xmp set XMP metadata\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(" where: 'file.icc' contains the ICC profile to be set,\n");
printf(" 'file.exif' contains the EXIF metadata 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"); printf(" 'file.xmp' contains the XMP metadata to be set\n");
@ -336,7 +324,7 @@ static void PrintHelp(void) {
printf("\n"); printf("\n");
printf("DURATION_OPTIONS:\n"); printf("DURATION_OPTIONS:\n");
printf(" Set duration of selected frames:\n"); printf(" Set duration of selected frames:\n");
printf(" duration set duration for all frames\n"); printf(" duration set duration for each frames\n");
printf(" duration,frame set duration of a particular frame\n"); printf(" duration,frame set duration of a particular frame\n");
printf(" duration,start,end set duration of frames in the\n"); printf(" duration,start,end set duration of frames in the\n");
printf(" interval [start,end])\n"); printf(" interval [start,end])\n");
@ -355,7 +343,7 @@ static void PrintHelp(void) {
printf("\n"); printf("\n");
printf("FRAME_OPTIONS(i):\n"); printf("FRAME_OPTIONS(i):\n");
printf(" Create animation:\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(" where: 'file_i' is the i'th animation frame (WebP format),\n");
printf(" 'di' is the pause duration before next frame,\n"); printf(" 'di' is the pause duration before next frame,\n");
printf(" 'xi','yi' specify the image offset for this frame,\n"); printf(" 'xi','yi' specify the image offset for this frame,\n");
@ -467,8 +455,7 @@ static WebPMux* DuplicateMuxHeader(const WebPMux* const mux) {
if (err == WEBP_MUX_OK && metadata.size > 0) { if (err == WEBP_MUX_OK && metadata.size > 0) {
err = WebPMuxSetChunk(new_mux, kFourccList[i], &metadata, 1); err = WebPMuxSetChunk(new_mux, kFourccList[i], &metadata, 1);
if (err != WEBP_MUX_OK) { if (err != WEBP_MUX_OK) {
ERROR_GOTO1("Error transferring metadata in DuplicateMuxHeader().", ERROR_GOTO1("Error transferring metadata in DuplicateMux().", End);
End);
} }
} }
} }
@ -482,11 +469,11 @@ static WebPMux* DuplicateMuxHeader(const WebPMux* const mux) {
} }
static int ParseFrameArgs(const char* args, WebPMuxFrameInfo* const info) { static int ParseFrameArgs(const char* args, WebPMuxFrameInfo* const info) {
int dispose_method, unused; int dispose_method, dummy;
char plus_minus, blend_method; char plus_minus, blend_method;
const int num_args = sscanf(args, "+%d+%d+%d+%d%c%c+%d", &info->duration, const int num_args = sscanf(args, "+%d+%d+%d+%d%c%c+%d", &info->duration,
&info->x_offset, &info->y_offset, &dispose_method, &info->x_offset, &info->y_offset, &dispose_method,
&plus_minus, &blend_method, &unused); &plus_minus, &blend_method, &dummy);
switch (num_args) { switch (num_args) {
case 1: case 1:
info->x_offset = info->y_offset = 0; // fall through info->x_offset = info->y_offset = 0; // fall through
@ -505,7 +492,7 @@ static int ParseFrameArgs(const char* args, WebPMuxFrameInfo* const info) {
WarnAboutOddOffset(info); WarnAboutOddOffset(info);
// Note: The validity of the following conversion is checked by // Note: The sanity of the following conversion is checked by
// WebPMuxPushFrame(). // WebPMuxPushFrame().
info->dispose_method = (WebPMuxAnimDispose)dispose_method; info->dispose_method = (WebPMuxAnimDispose)dispose_method;
@ -529,8 +516,8 @@ static int ParseBgcolorArgs(const char* args, uint32_t* const bgcolor) {
static void DeleteConfig(Config* const config) { static void DeleteConfig(Config* const config) {
if (config != NULL) { if (config != NULL) {
free(config->args); free(config->args_);
ExUtilDeleteCommandLineArguments(&config->cmd_args); ExUtilDeleteCommandLineArguments(&config->cmd_args_);
memset(config, 0, sizeof(*config)); memset(config, 0, sizeof(*config));
} }
} }
@ -607,31 +594,25 @@ static int ValidateCommandLine(const CommandLineArguments* const cmd_args,
return ok; return ok;
} }
#define ACTION_IS_NIL (config->action_type == NIL_ACTION) #define ACTION_IS_NIL (config->action_type_ == NIL_ACTION)
#define FEATURETYPE_IS_NIL (config->type == NIL_FEATURE) #define FEATURETYPE_IS_NIL (config->type_ == NIL_FEATURE)
#define CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL) \ #define CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL) \
do { \ if (argc < i + (NUM)) { \
if (argc < i + (NUM)) { \ fprintf(stderr, "ERROR: Too few arguments for '%s'.\n", argv[i]); \
fprintf(stderr, "ERROR: Too few arguments for '%s'.\n", argv[i]); \ goto LABEL; \
goto LABEL; \ }
} \
} while (0)
#define CHECK_NUM_ARGS_AT_MOST(NUM, LABEL) \ #define CHECK_NUM_ARGS_AT_MOST(NUM, LABEL) \
do { \ if (argc > i + (NUM)) { \
if (argc > i + (NUM)) { \ fprintf(stderr, "ERROR: Too many arguments for '%s'.\n", argv[i]); \
fprintf(stderr, "ERROR: Too many arguments for '%s'.\n", argv[i]); \ goto LABEL; \
goto LABEL; \ }
} \
} while (0)
#define CHECK_NUM_ARGS_EXACTLY(NUM, LABEL) \ #define CHECK_NUM_ARGS_EXACTLY(NUM, LABEL) \
do { \ CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL); \
CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL); \ CHECK_NUM_ARGS_AT_MOST(NUM, LABEL);
CHECK_NUM_ARGS_AT_MOST(NUM, LABEL); \
} while (0)
// Parses command-line arguments to fill up config object. Also performs some // Parses command-line arguments to fill up config object. Also performs some
// semantic checks. unicode_argv contains wchar_t arguments or is null. // semantic checks. unicode_argv contains wchar_t arguments or is null.
@ -639,97 +620,98 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
int i = 0; int i = 0;
int feature_arg_index = 0; int feature_arg_index = 0;
int ok = 1; int ok = 1;
int argc = config->cmd_args.argc; int argc = config->cmd_args_.argc_;
const char* const* argv = config->cmd_args.argv; const char* const* argv = config->cmd_args_.argv_;
// Unicode file paths will be used if available. // Unicode file paths will be used if available.
const char* const* wargv = const char* const* wargv =
(unicode_argv != NULL) ? (const char**)(unicode_argv + 1) : argv; (unicode_argv != NULL) ? (const char**)(unicode_argv + 1) : argv;
while (i < argc) { while (i < argc) {
FeatureArg* const arg = &config->args[feature_arg_index]; FeatureArg* const arg = &config->args_[feature_arg_index];
if (argv[i][0] == '-') { // One of the action types or output. if (argv[i][0] == '-') { // One of the action types or output.
if (!strcmp(argv[i], "-set")) { if (!strcmp(argv[i], "-set")) {
if (ACTION_IS_NIL) { if (ACTION_IS_NIL) {
config->action_type = ACTION_SET; config->action_type_ = ACTION_SET;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
++i; ++i;
} else if (!strcmp(argv[i], "-duration")) { } else if (!strcmp(argv[i], "-duration")) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
if (ACTION_IS_NIL || config->action_type == ACTION_DURATION) { if (ACTION_IS_NIL || config->action_type_ == ACTION_DURATION) {
config->action_type = ACTION_DURATION; config->action_type_ = ACTION_DURATION;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
if (FEATURETYPE_IS_NIL || config->type == FEATURE_DURATION) { if (FEATURETYPE_IS_NIL || config->type_ == FEATURE_DURATION) {
config->type = FEATURE_DURATION; config->type_ = FEATURE_DURATION;
} else { } else {
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
} }
arg->params = argv[i + 1]; arg->params_ = argv[i + 1];
++feature_arg_index; ++feature_arg_index;
i += 2; i += 2;
} else if (!strcmp(argv[i], "-get")) { } else if (!strcmp(argv[i], "-get")) {
if (ACTION_IS_NIL) { if (ACTION_IS_NIL) {
config->action_type = ACTION_GET; config->action_type_ = ACTION_GET;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
++i; ++i;
} else if (!strcmp(argv[i], "-strip")) { } else if (!strcmp(argv[i], "-strip")) {
if (ACTION_IS_NIL) { if (ACTION_IS_NIL) {
config->action_type = ACTION_STRIP; config->action_type_ = ACTION_STRIP;
config->arg_count_ = 0;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
++i; ++i;
} else if (!strcmp(argv[i], "-frame")) { } else if (!strcmp(argv[i], "-frame")) {
CHECK_NUM_ARGS_AT_LEAST(3, ErrParse); CHECK_NUM_ARGS_AT_LEAST(3, ErrParse);
if (ACTION_IS_NIL || config->action_type == ACTION_SET) { if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) {
config->action_type = ACTION_SET; config->action_type_ = ACTION_SET;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
if (FEATURETYPE_IS_NIL || config->type == FEATURE_ANMF) { if (FEATURETYPE_IS_NIL || config->type_ == FEATURE_ANMF) {
config->type = FEATURE_ANMF; config->type_ = FEATURE_ANMF;
} else { } else {
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
} }
arg->subtype = SUBTYPE_ANMF; arg->subtype_ = SUBTYPE_ANMF;
arg->filename = wargv[i + 1]; arg->filename_ = argv[i + 1];
arg->params = argv[i + 2]; arg->params_ = argv[i + 2];
++feature_arg_index; ++feature_arg_index;
i += 3; i += 3;
} else if (!strcmp(argv[i], "-loop") || !strcmp(argv[i], "-bgcolor")) { } else if (!strcmp(argv[i], "-loop") || !strcmp(argv[i], "-bgcolor")) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
if (ACTION_IS_NIL || config->action_type == ACTION_SET) { if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) {
config->action_type = ACTION_SET; config->action_type_ = ACTION_SET;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
if (FEATURETYPE_IS_NIL || config->type == FEATURE_ANMF) { if (FEATURETYPE_IS_NIL || config->type_ == FEATURE_ANMF) {
config->type = FEATURE_ANMF; config->type_ = FEATURE_ANMF;
} else { } else {
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
} }
arg->subtype = arg->subtype_ =
!strcmp(argv[i], "-loop") ? SUBTYPE_LOOP : SUBTYPE_BGCOLOR; !strcmp(argv[i], "-loop") ? SUBTYPE_LOOP : SUBTYPE_BGCOLOR;
arg->params = argv[i + 1]; arg->params_ = argv[i + 1];
++feature_arg_index; ++feature_arg_index;
i += 2; i += 2;
} else if (!strcmp(argv[i], "-o")) { } else if (!strcmp(argv[i], "-o")) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
config->output = wargv[i + 1]; config->output_ = wargv[i + 1];
i += 2; i += 2;
} else if (!strcmp(argv[i], "-info")) { } else if (!strcmp(argv[i], "-info")) {
CHECK_NUM_ARGS_EXACTLY(2, ErrParse); CHECK_NUM_ARGS_EXACTLY(2, ErrParse);
if (config->action_type != NIL_ACTION) { if (config->action_type_ != NIL_ACTION) {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} else { } else {
config->action_type = ACTION_INFO; config->action_type_ = ACTION_INFO;
config->arg_count = 0; config->arg_count_ = 0;
config->input = wargv[i + 1]; config->input_ = wargv[i + 1];
} }
i += 2; i += 2;
} else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help")) { } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help")) {
@ -747,8 +729,8 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
} else if (!strcmp(argv[i], "--")) { } else if (!strcmp(argv[i], "--")) {
if (i < argc - 1) { if (i < argc - 1) {
++i; ++i;
if (config->input == NULL) { if (config->input_ == NULL) {
config->input = wargv[i]; config->input_ = wargv[i];
} else { } else {
ERROR_GOTO2("ERROR at '%s': Multiple input files specified.\n", ERROR_GOTO2("ERROR at '%s': Multiple input files specified.\n",
argv[i], ErrParse); argv[i], ErrParse);
@ -759,65 +741,36 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
ERROR_GOTO2("ERROR: Unknown option: '%s'.\n", argv[i], ErrParse); ERROR_GOTO2("ERROR: Unknown option: '%s'.\n", argv[i], ErrParse);
} }
} else { // One of the feature types or input. } else { // One of the feature types or input.
// After consuming the arguments to -get/-set/-strip, treat any remaining
// arguments as input. This allows files that are named the same as the
// keywords used with these options.
int is_input = feature_arg_index == config->arg_count;
if (ACTION_IS_NIL) { if (ACTION_IS_NIL) {
ERROR_GOTO1("ERROR: Action must be specified before other arguments.\n", ERROR_GOTO1("ERROR: Action must be specified before other arguments.\n",
ErrParse); ErrParse);
} }
if (!is_input) { if (!strcmp(argv[i], "icc") || !strcmp(argv[i], "exif") ||
if (!strcmp(argv[i], "icc") || !strcmp(argv[i], "exif") || !strcmp(argv[i], "xmp")) {
!strcmp(argv[i], "xmp")) { if (FEATURETYPE_IS_NIL) {
if (FEATURETYPE_IS_NIL) { config->type_ = (!strcmp(argv[i], "icc")) ? FEATURE_ICCP :
config->type = (!strcmp(argv[i], "icc")) ? FEATURE_ICCP : (!strcmp(argv[i], "exif")) ? FEATURE_EXIF : FEATURE_XMP;
(!strcmp(argv[i], "exif")) ? FEATURE_EXIF : FEATURE_XMP; } else {
} else { ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); }
} if (config->action_type_ == ACTION_SET) {
if (config->action_type == ACTION_SET) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
arg->filename = wargv[i + 1];
++feature_arg_index;
i += 2;
} else {
// Note: 'arg->params' is not used in this case. 'arg_count' is
// used as a flag to indicate the -get/-strip feature has already
// been consumed, allowing input types to be named the same as the
// feature type.
config->arg_count = 0;
++i;
}
} else if (!strcmp(argv[i], "frame") &&
(config->action_type == ACTION_GET)) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
config->type = FEATURE_ANMF; arg->filename_ = wargv[i + 1];
arg->params = argv[i + 1];
++feature_arg_index;
i += 2;
} else if (!strcmp(argv[i], "loop") &&
(config->action_type == ACTION_SET)) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
config->type = FEATURE_LOOP;
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; ++feature_arg_index;
i += 2; i += 2;
} else { } else {
is_input = 1; ++i;
} }
} } else if (!strcmp(argv[i], "frame") &&
(config->action_type_ == ACTION_GET)) {
if (is_input) { CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
if (config->input == NULL) { config->type_ = FEATURE_ANMF;
config->input = wargv[i]; arg->params_ = argv[i + 1];
++feature_arg_index;
i += 2;
} else { // Assume input file.
if (config->input_ == NULL) {
config->input_ = wargv[i];
} else { } else {
ERROR_GOTO2("ERROR at '%s': Multiple input files specified.\n", ERROR_GOTO2("ERROR at '%s': Multiple input files specified.\n",
argv[i], ErrParse); argv[i], ErrParse);
@ -840,21 +793,21 @@ static int ValidateConfig(Config* const config) {
} }
// Feature type. // Feature type.
if (FEATURETYPE_IS_NIL && config->action_type != ACTION_INFO) { if (FEATURETYPE_IS_NIL && config->action_type_ != ACTION_INFO) {
ERROR_GOTO1("ERROR: No feature specified.\n", ErrValidate2); ERROR_GOTO1("ERROR: No feature specified.\n", ErrValidate2);
} }
// Input file. // Input file.
if (config->input == NULL) { if (config->input_ == NULL) {
if (config->action_type != ACTION_SET) { if (config->action_type_ != ACTION_SET) {
ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2); ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2);
} else if (config->type != FEATURE_ANMF) { } else if (config->type_ != FEATURE_ANMF) {
ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2); ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2);
} }
} }
// Output file. // Output file.
if (config->output == NULL && config->action_type != ACTION_INFO) { if (config->output_ == NULL && config->action_type_ != ACTION_INFO) {
ERROR_GOTO1("ERROR: No output file specified.\n", ErrValidate2); ERROR_GOTO1("ERROR: No output file specified.\n", ErrValidate2);
} }
@ -870,17 +823,17 @@ static int InitializeConfig(int argc, const char* argv[], Config* const config,
memset(config, 0, sizeof(*config)); memset(config, 0, sizeof(*config));
ok = ExUtilInitCommandLineArguments(argc, argv, &config->cmd_args); ok = ExUtilInitCommandLineArguments(argc, argv, &config->cmd_args_);
if (!ok) return 0; if (!ok) return 0;
// Validate command-line arguments. // Validate command-line arguments.
if (!ValidateCommandLine(&config->cmd_args, &num_feature_args)) { if (!ValidateCommandLine(&config->cmd_args_, &num_feature_args)) {
ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1); ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1);
} }
config->arg_count = num_feature_args; config->arg_count_ = num_feature_args;
config->args = (FeatureArg*)calloc(num_feature_args, sizeof(*config->args)); config->args_ = (FeatureArg*)calloc(num_feature_args, sizeof(*config->args_));
if (config->args == NULL) { if (config->args_ == NULL) {
ERROR_GOTO1("ERROR: Memory allocation error.\n", Err1); ERROR_GOTO1("ERROR: Memory allocation error.\n", Err1);
} }
@ -912,7 +865,7 @@ static int GetFrame(const WebPMux* mux, const Config* config) {
WebPMuxFrameInfo info; WebPMuxFrameInfo info;
WebPDataInit(&info.bitstream); WebPDataInit(&info.bitstream);
num = ExUtilGetInt(config->args[0].params, 10, &parse_error); num = ExUtilGetInt(config->args_[0].params_, 10, &parse_error);
if (num < 0) { if (num < 0) {
ERROR_GOTO1("ERROR: Frame/Fragment index must be non-negative.\n", ErrGet); ERROR_GOTO1("ERROR: Frame/Fragment index must be non-negative.\n", ErrGet);
} }
@ -937,7 +890,7 @@ static int GetFrame(const WebPMux* mux, const Config* config) {
ErrorString(err), ErrGet); ErrorString(err), ErrGet);
} }
ok = WriteWebP(mux_single, config->output); ok = WriteWebP(mux_single, config->output_);
ErrGet: ErrGet:
WebPDataClear(&info.bitstream); WebPDataClear(&info.bitstream);
@ -952,11 +905,11 @@ static int Process(const Config* config) {
WebPMuxError err = WEBP_MUX_OK; WebPMuxError err = WEBP_MUX_OK;
int ok = 1; int ok = 1;
switch (config->action_type) { switch (config->action_type_) {
case ACTION_GET: { case ACTION_GET: {
ok = CreateMux(config->input, &mux); ok = CreateMux(config->input_, &mux);
if (!ok) goto Err2; if (!ok) goto Err2;
switch (config->type) { switch (config->type_) {
case FEATURE_ANMF: case FEATURE_ANMF:
ok = GetFrame(mux, config); ok = GetFrame(mux, config);
break; break;
@ -964,12 +917,12 @@ static int Process(const Config* config) {
case FEATURE_ICCP: case FEATURE_ICCP:
case FEATURE_EXIF: case FEATURE_EXIF:
case FEATURE_XMP: case FEATURE_XMP:
err = WebPMuxGetChunk(mux, kFourccList[config->type], &chunk); err = WebPMuxGetChunk(mux, kFourccList[config->type_], &chunk);
if (err != WEBP_MUX_OK) { if (err != WEBP_MUX_OK) {
ERROR_GOTO3("ERROR (%s): Could not get the %s.\n", ERROR_GOTO3("ERROR (%s): Could not get the %s.\n",
ErrorString(err), kDescriptions[config->type], Err2); ErrorString(err), kDescriptions[config->type_], Err2);
} }
ok = WriteData(config->output, &chunk); ok = WriteData(config->output_, &chunk);
break; break;
default: default:
@ -979,7 +932,7 @@ static int Process(const Config* config) {
break; break;
} }
case ACTION_SET: { case ACTION_SET: {
switch (config->type) { switch (config->type_) {
case FEATURE_ANMF: { case FEATURE_ANMF: {
int i; int i;
WebPMuxAnimParams params = { 0xFFFFFFFF, 0 }; WebPMuxAnimParams params = { 0xFFFFFFFF, 0 };
@ -988,11 +941,11 @@ static int Process(const Config* config) {
ERROR_GOTO2("ERROR (%s): Could not allocate a mux object.\n", ERROR_GOTO2("ERROR (%s): Could not allocate a mux object.\n",
ErrorString(WEBP_MUX_MEMORY_ERROR), Err2); ErrorString(WEBP_MUX_MEMORY_ERROR), Err2);
} }
for (i = 0; i < config->arg_count; ++i) { for (i = 0; i < config->arg_count_; ++i) {
switch (config->args[i].subtype) { switch (config->args_[i].subtype_) {
case SUBTYPE_BGCOLOR: { case SUBTYPE_BGCOLOR: {
uint32_t bgcolor; uint32_t bgcolor;
ok = ParseBgcolorArgs(config->args[i].params, &bgcolor); ok = ParseBgcolorArgs(config->args_[i].params_, &bgcolor);
if (!ok) { if (!ok) {
ERROR_GOTO1("ERROR: Could not parse the background color \n", ERROR_GOTO1("ERROR: Could not parse the background color \n",
Err2); Err2);
@ -1003,7 +956,7 @@ static int Process(const Config* config) {
case SUBTYPE_LOOP: { case SUBTYPE_LOOP: {
int parse_error = 0; int parse_error = 0;
const int loop_count = const int loop_count =
ExUtilGetInt(config->args[i].params, 10, &parse_error); ExUtilGetInt(config->args_[i].params_, 10, &parse_error);
if (loop_count < 0 || loop_count > 65535) { if (loop_count < 0 || loop_count > 65535) {
// Note: This is only a 'necessary' condition for loop_count // Note: This is only a 'necessary' condition for loop_count
// to be valid. The 'sufficient' conditioned in checked in // to be valid. The 'sufficient' conditioned in checked in
@ -1019,10 +972,10 @@ static int Process(const Config* config) {
case SUBTYPE_ANMF: { case SUBTYPE_ANMF: {
WebPMuxFrameInfo frame; WebPMuxFrameInfo frame;
frame.id = WEBP_CHUNK_ANMF; frame.id = WEBP_CHUNK_ANMF;
ok = ExUtilReadFileToWebPData(config->args[i].filename, ok = ExUtilReadFileToWebPData(config->args_[i].filename_,
&frame.bitstream); &frame.bitstream);
if (!ok) goto Err2; if (!ok) goto Err2;
ok = ParseFrameArgs(config->args[i].params, &frame); ok = ParseFrameArgs(config->args_[i].params_, &frame);
if (!ok) { if (!ok) {
WebPDataClear(&frame.bitstream); WebPDataClear(&frame.bitstream);
ERROR_GOTO1("ERROR: Could not parse frame properties.\n", ERROR_GOTO1("ERROR: Could not parse frame properties.\n",
@ -1053,64 +1006,15 @@ static int Process(const Config* config) {
case FEATURE_ICCP: case FEATURE_ICCP:
case FEATURE_EXIF: case FEATURE_EXIF:
case FEATURE_XMP: { case FEATURE_XMP: {
ok = CreateMux(config->input, &mux); ok = CreateMux(config->input_, &mux);
if (!ok) goto Err2; if (!ok) goto Err2;
ok = ExUtilReadFileToWebPData(config->args[0].filename, &chunk); ok = ExUtilReadFileToWebPData(config->args_[0].filename_, &chunk);
if (!ok) goto Err2; if (!ok) goto Err2;
err = WebPMuxSetChunk(mux, kFourccList[config->type], &chunk, 1); err = WebPMuxSetChunk(mux, kFourccList[config->type_], &chunk, 1);
WebPDataClear(&chunk); free((void*)chunk.bytes);
if (err != WEBP_MUX_OK) { if (err != WEBP_MUX_OK) {
ERROR_GOTO3("ERROR (%s): Could not set the %s.\n", ERROR_GOTO3("ERROR (%s): Could not set the %s.\n",
ErrorString(err), kDescriptions[config->type], Err2); ErrorString(err), kDescriptions[config->type_], Err2);
}
break;
}
case FEATURE_LOOP: {
WebPMuxAnimParams params = { 0xFFFFFFFF, 0 };
int parse_error = 0;
const int loop_count =
ExUtilGetInt(config->args[0].params, 10, &parse_error);
if (loop_count < 0 || loop_count > 65535 || parse_error) {
ERROR_GOTO1("ERROR: Loop count must be in the range 0 to 65535.\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.loop_count = loop_count;
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;
}
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; break;
} }
@ -1119,12 +1023,12 @@ static int Process(const Config* config) {
break; break;
} }
} }
ok = WriteWebP(mux, config->output); ok = WriteWebP(mux, config->output_);
break; break;
} }
case ACTION_DURATION: { case ACTION_DURATION: {
int num_frames; int num_frames;
ok = CreateMux(config->input, &mux); ok = CreateMux(config->input_, &mux);
if (!ok) goto Err2; if (!ok) goto Err2;
err = WebPMuxNumChunks(mux, WEBP_CHUNK_ANMF, &num_frames); err = WebPMuxNumChunks(mux, WEBP_CHUNK_ANMF, &num_frames);
ok = (err == WEBP_MUX_OK); ok = (err == WEBP_MUX_OK);
@ -1134,7 +1038,7 @@ static int Process(const Config* config) {
if (num_frames == 0) { if (num_frames == 0) {
fprintf(stderr, "Doesn't look like the source is animated. " fprintf(stderr, "Doesn't look like the source is animated. "
"Skipping duration setting.\n"); "Skipping duration setting.\n");
ok = WriteWebP(mux, config->output); ok = WriteWebP(mux, config->output_);
if (!ok) goto Err2; if (!ok) goto Err2;
} else { } else {
int i; int i;
@ -1146,11 +1050,11 @@ static int Process(const Config* config) {
for (i = 0; i < num_frames; ++i) durations[i] = -1; for (i = 0; i < num_frames; ++i) durations[i] = -1;
// Parse intervals to process. // Parse intervals to process.
for (i = 0; i < config->arg_count; ++i) { for (i = 0; i < config->arg_count_; ++i) {
int k; int k;
int args[3]; int args[3];
int duration, start, end; int duration, start, end;
const int nb_args = ExUtilGetInts(config->args[i].params, const int nb_args = ExUtilGetInts(config->args_[i].params_,
10, 3, args); 10, 3, args);
ok = (nb_args >= 1); ok = (nb_args >= 1);
if (!ok) goto Err3; if (!ok) goto Err3;
@ -1194,7 +1098,7 @@ static int Process(const Config* config) {
WebPDataClear(&frame.bitstream); WebPDataClear(&frame.bitstream);
} }
WebPMuxDelete(mux); WebPMuxDelete(mux);
ok = WriteWebP(new_mux, config->output); ok = WriteWebP(new_mux, config->output_);
mux = new_mux; // transfer for the WebPMuxDelete() call mux = new_mux; // transfer for the WebPMuxDelete() call
new_mux = NULL; new_mux = NULL;
@ -1206,24 +1110,24 @@ static int Process(const Config* config) {
break; break;
} }
case ACTION_STRIP: { case ACTION_STRIP: {
ok = CreateMux(config->input, &mux); ok = CreateMux(config->input_, &mux);
if (!ok) goto Err2; if (!ok) goto Err2;
if (config->type == FEATURE_ICCP || config->type == FEATURE_EXIF || if (config->type_ == FEATURE_ICCP || config->type_ == FEATURE_EXIF ||
config->type == FEATURE_XMP) { config->type_ == FEATURE_XMP) {
err = WebPMuxDeleteChunk(mux, kFourccList[config->type]); err = WebPMuxDeleteChunk(mux, kFourccList[config->type_]);
if (err != WEBP_MUX_OK) { if (err != WEBP_MUX_OK) {
ERROR_GOTO3("ERROR (%s): Could not strip the %s.\n", ERROR_GOTO3("ERROR (%s): Could not strip the %s.\n",
ErrorString(err), kDescriptions[config->type], Err2); ErrorString(err), kDescriptions[config->type_], Err2);
} }
} else { } else {
ERROR_GOTO1("ERROR: Invalid feature for action 'strip'.\n", Err2); ERROR_GOTO1("ERROR: Invalid feature for action 'strip'.\n", Err2);
break; break;
} }
ok = WriteWebP(mux, config->output); ok = WriteWebP(mux, config->output_);
break; break;
} }
case ACTION_INFO: { case ACTION_INFO: {
ok = CreateMux(config->input, &mux); ok = CreateMux(config->input_, &mux);
if (!ok) goto Err2; if (!ok) goto Err2;
ok = (DisplayInfo(mux) == WEBP_MUX_OK); ok = (DisplayInfo(mux) == WEBP_MUX_OK);
break; break;
@ -1242,7 +1146,6 @@ static int Process(const Config* config) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Main. // Main.
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
Config config; Config config;
int ok; int ok;
@ -1256,7 +1159,7 @@ int main(int argc, const char* argv[]) {
PrintHelp(); PrintHelp();
} }
DeleteConfig(&config); DeleteConfig(&config);
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE); FREE_WARGV_AND_RETURN(!ok);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -7,7 +7,6 @@ noinst_HEADERS += ../src/webp/types.h
libwebpextras_la_SOURCES = libwebpextras_la_SOURCES =
libwebpextras_la_SOURCES += extras.c extras.h quality_estimate.c libwebpextras_la_SOURCES += extras.c extras.h quality_estimate.c
libwebpextras_la_SOURCES += sharpyuv_risk_table.c sharpyuv_risk_table.h
libwebpextras_la_CPPFLAGS = $(AM_CPPFLAGS) libwebpextras_la_CPPFLAGS = $(AM_CPPFLAGS)
libwebpextras_la_LDFLAGS = -lm libwebpextras_la_LDFLAGS = -lm

View File

@ -11,21 +11,14 @@
// //
#include "extras/extras.h" #include "extras/extras.h"
#include "webp/format_constants.h"
#include "src/dsp/dsp.h"
#include <assert.h> #include <assert.h>
#include <limits.h>
#include <string.h> #include <string.h>
#include "extras/sharpyuv_risk_table.h"
#include "sharpyuv/sharpyuv.h"
#include "src/dsp/dsp.h"
#include "src/utils/utils.h"
#include "src/webp/encode.h"
#include "webp/format_constants.h"
#include "webp/types.h"
#define XTRA_MAJ_VERSION 1 #define XTRA_MAJ_VERSION 1
#define XTRA_MIN_VERSION 6 #define XTRA_MIN_VERSION 1
#define XTRA_REV_VERSION 0 #define XTRA_REV_VERSION 0
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -167,159 +160,3 @@ int WebPUnmultiplyARGB(WebPPicture* pic) {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// 420 risk metric
#define YUV_FIX 16 // fixed-point precision for RGB->YUV
static const int kYuvHalf = 1 << (YUV_FIX - 1);
// Maps a value in [0, (256 << YUV_FIX) - 1] to [0,
// precomputed_scores_table_sampling - 1]. It is important that the extremal
// values are preserved and 1:1 mapped:
// ConvertValue(0) = 0
// ConvertValue((256 << 16) - 1) = rgb_sampling_size - 1
static int SharpYuvConvertValueToSampledIdx(int v, int rgb_sampling_size) {
v = (v + kYuvHalf) >> YUV_FIX;
v = (v < 0) ? 0 : (v > 255) ? 255 : v;
return (v * (rgb_sampling_size - 1)) / 255;
}
#undef YUV_FIX
// For each pixel, computes the index to look up that color in a precomputed
// risk score table where the YUV space is subsampled to a size of
// precomputed_scores_table_sampling^3 (see sharpyuv_risk_table.h)
static int SharpYuvConvertToYuvSharpnessIndex(
int r, int g, int b, const SharpYuvConversionMatrix* matrix,
int precomputed_scores_table_sampling) {
const int y = SharpYuvConvertValueToSampledIdx(
matrix->rgb_to_y[0] * r + matrix->rgb_to_y[1] * g +
matrix->rgb_to_y[2] * b + matrix->rgb_to_y[3],
precomputed_scores_table_sampling);
const int u = SharpYuvConvertValueToSampledIdx(
matrix->rgb_to_u[0] * r + matrix->rgb_to_u[1] * g +
matrix->rgb_to_u[2] * b + matrix->rgb_to_u[3],
precomputed_scores_table_sampling);
const int v = SharpYuvConvertValueToSampledIdx(
matrix->rgb_to_v[0] * r + matrix->rgb_to_v[1] * g +
matrix->rgb_to_v[2] * b + matrix->rgb_to_v[3],
precomputed_scores_table_sampling);
return y + u * precomputed_scores_table_sampling +
v * precomputed_scores_table_sampling *
precomputed_scores_table_sampling;
}
static void SharpYuvRowToYuvSharpnessIndex(
const uint8_t* r_ptr, const uint8_t* g_ptr, const uint8_t* b_ptr,
int rgb_step, int rgb_bit_depth, int width, uint16_t* dst,
const SharpYuvConversionMatrix* matrix,
int precomputed_scores_table_sampling) {
int i;
assert(rgb_bit_depth == 8);
(void)rgb_bit_depth; // Unused for now.
for (i = 0; i < width;
++i, r_ptr += rgb_step, g_ptr += rgb_step, b_ptr += rgb_step) {
dst[i] =
SharpYuvConvertToYuvSharpnessIndex(r_ptr[0], g_ptr[0], b_ptr[0], matrix,
precomputed_scores_table_sampling);
}
}
#define SAFE_ALLOC(W, H, T) ((T*)WebPSafeMalloc((uint64_t)(W) * (H), sizeof(T)))
static int DoEstimateRisk(const uint8_t* r_ptr, const uint8_t* g_ptr,
const uint8_t* b_ptr, int rgb_step, int rgb_stride,
int rgb_bit_depth, int width, int height,
const SharpYuvOptions* options,
const uint8_t precomputed_scores_table[],
int precomputed_scores_table_sampling,
float* score_out) {
const int sampling3 = precomputed_scores_table_sampling *
precomputed_scores_table_sampling *
precomputed_scores_table_sampling;
const int kNoiseLevel = 4;
double total_score = 0;
double count = 0;
// Rows of indices in
uint16_t* row1 = SAFE_ALLOC(width, 1, uint16_t);
uint16_t* row2 = SAFE_ALLOC(width, 1, uint16_t);
uint16_t* tmp;
int i, j;
if (row1 == NULL || row2 == NULL) {
WebPFree(row1);
WebPFree(row2);
return 0;
}
// Convert the first row ahead.
SharpYuvRowToYuvSharpnessIndex(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth,
width, row2, options->yuv_matrix,
precomputed_scores_table_sampling);
for (j = 1; j < height; ++j) {
r_ptr += rgb_stride;
g_ptr += rgb_stride;
b_ptr += rgb_stride;
// Swap row 1 and row 2.
tmp = row1;
row1 = row2;
row2 = tmp;
// Convert the row below.
SharpYuvRowToYuvSharpnessIndex(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth,
width, row2, options->yuv_matrix,
precomputed_scores_table_sampling);
for (i = 0; i < width - 1; ++i) {
const int idx0 = row1[i + 0];
const int idx1 = row1[i + 1];
const int idx2 = row2[i + 0];
const int score = precomputed_scores_table[idx0 + sampling3 * idx1] +
precomputed_scores_table[idx0 + sampling3 * idx2] +
precomputed_scores_table[idx1 + sampling3 * idx2];
if (score > kNoiseLevel) {
total_score += score;
count += 1.0;
}
}
}
if (count > 0.) total_score /= count;
// If less than 1% of pixels were evaluated -> below noise level.
if (100. * count / (width * height) < 1.) total_score = 0.;
// Rescale to [0:100]
total_score = (total_score > 25.) ? 100. : total_score * 100. / 25.;
WebPFree(row1);
WebPFree(row2);
*score_out = (float)total_score;
return 1;
}
#undef SAFE_ALLOC
int SharpYuvEstimate420Risk(const void* r_ptr, const void* g_ptr,
const void* b_ptr, int rgb_step, int rgb_stride,
int rgb_bit_depth, int width, int height,
const SharpYuvOptions* options, float* score) {
if (width < 1 || height < 1 || width == INT_MAX || height == INT_MAX ||
r_ptr == NULL || g_ptr == NULL || b_ptr == NULL || options == NULL ||
score == NULL) {
return 0;
}
if (rgb_bit_depth != 8) {
return 0;
}
if (width <= 4 || height <= 4) {
*score = 0.0f; // too small, no real risk.
return 1;
}
return DoEstimateRisk(
(const uint8_t*)r_ptr, (const uint8_t*)g_ptr, (const uint8_t*)b_ptr,
rgb_step, rgb_stride, rgb_bit_depth, width, height, options,
kSharpYuvPrecomputedRisk, kSharpYuvPrecomputedRiskYuvSampling, score);
}
//------------------------------------------------------------------------------

View File

@ -11,18 +11,15 @@
#ifndef WEBP_EXTRAS_EXTRAS_H_ #ifndef WEBP_EXTRAS_EXTRAS_H_
#define WEBP_EXTRAS_EXTRAS_H_ #define WEBP_EXTRAS_EXTRAS_H_
#include <stddef.h>
#include "webp/types.h" #include "webp/types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "sharpyuv/sharpyuv.h"
#include "webp/encode.h" #include "webp/encode.h"
#define WEBP_EXTRAS_ABI_VERSION 0x0003 // MAJOR(8b) + MINOR(8b) #define WEBP_EXTRAS_ABI_VERSION 0x0002 // MAJOR(8b) + MINOR(8b)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -73,38 +70,6 @@ WEBP_EXTERN int VP8EstimateQuality(const uint8_t* const data, size_t size);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Computes a score between 0 and 100 which represents the risk of having visual
// quality loss from converting an RGB image to YUV420.
// A low score, typically < 40, means there is a low risk of artifacts from
// chroma subsampling and a simple averaging algorithm can be used instead of
// the more expensive SharpYuvConvert function.
// A medium score, typically >= 40 and < 70, means that simple chroma
// subsampling will produce artifacts and it may be advisable to use the more
// costly SharpYuvConvert for YUV420 conversion.
// A high score, typically >= 70, means there is a very high risk of artifacts
// from chroma subsampling even with SharpYuvConvert, and best results might be
// achieved by using YUV444.
// If not using SharpYuvConvert, a threshold of about 50 can be used to decide
// between (simple averaging) 420 and 444.
// r_ptr, g_ptr, b_ptr: pointers to the source r, g and b channels. Should point
// to uint8_t buffers if rgb_bit_depth is 8, or uint16_t buffers otherwise.
// rgb_step: distance in bytes between two horizontally adjacent pixels on the
// r, g and b channels. If rgb_bit_depth is > 8, it should be a
// multiple of 2.
// rgb_stride: distance in bytes between two vertically adjacent pixels on the
// r, g, and b channels. If rgb_bit_depth is > 8, it should be a
// multiple of 2.
// rgb_bit_depth: number of bits for each r/g/b value. Only a value of 8 is
// currently supported.
// width, height: width and height of the image in pixels
// Returns 0 on failure.
WEBP_EXTERN int SharpYuvEstimate420Risk(
const void* r_ptr, const void* g_ptr, const void* b_ptr, int rgb_step,
int rgb_stride, int rgb_bit_depth, int width, int height,
const SharpYuvOptions* options, float* score);
//------------------------------------------------------------------------------
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

View File

@ -23,11 +23,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "../examples/unicode.h" #include "webp/encode.h"
#include "imageio/image_dec.h" #include "imageio/image_dec.h"
#include "imageio/imageio_util.h" #include "imageio/imageio_util.h"
#include "src/webp/types.h" #include "../examples/unicode.h"
#include "webp/encode.h"
static size_t ReadPicture(const char* const filename, WebPPicture* const pic, static size_t ReadPicture(const char* const filename, WebPPicture* const pic,
int keep_alpha) { int keep_alpha) {
@ -224,15 +223,13 @@ static void Help(void) {
" -o <file> . save the diff map as a WebP lossless file\n" " -o <file> . save the diff map as a WebP lossless file\n"
" -scale .... scale the difference map to fit [0..255] range\n" " -scale .... scale the difference map to fit [0..255] range\n"
" -gray ..... use grayscale for difference map (-scale)\n" " -gray ..... use grayscale for difference map (-scale)\n"
"\nSupported input formats:\n %s\n", " Also handles PNG, JPG and TIFF files, in addition to WebP.\n");
WebPGetEnabledInputFileFormats());
} }
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
WebPPicture pic1, pic2; WebPPicture pic1, pic2;
size_t size1 = 0, size2 = 0; size_t size1 = 0, size2 = 0;
int ret = EXIT_FAILURE; int ret = 1;
float disto[5]; float disto[5];
int type = 0; int type = 0;
int c; int c;
@ -248,7 +245,7 @@ int main(int argc, const char* argv[]) {
if (!WebPPictureInit(&pic1) || !WebPPictureInit(&pic2)) { if (!WebPPictureInit(&pic1) || !WebPPictureInit(&pic2)) {
fprintf(stderr, "Can't init pictures\n"); fprintf(stderr, "Can't init pictures\n");
FREE_WARGV_AND_RETURN(EXIT_FAILURE); FREE_WARGV_AND_RETURN(1);
} }
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
@ -264,7 +261,7 @@ int main(int argc, const char* argv[]) {
use_gray = 1; use_gray = 1;
} else if (!strcmp(argv[c], "-h")) { } else if (!strcmp(argv[c], "-h")) {
help = 1; help = 1;
ret = EXIT_SUCCESS; ret = 0;
} else if (!strcmp(argv[c], "-o")) { } else if (!strcmp(argv[c], "-o")) {
if (++c == argc) { if (++c == argc) {
fprintf(stderr, "missing file name after %s option.\n", argv[c - 1]); fprintf(stderr, "missing file name after %s option.\n", argv[c - 1]);
@ -339,8 +336,7 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error during lossless encoding.\n"); fprintf(stderr, "Error during lossless encoding.\n");
goto End; goto End;
} }
ret = ImgIoUtilWriteFile(output, data, data_size) ? EXIT_SUCCESS ret = ImgIoUtilWriteFile(output, data, data_size) ? 0 : 1;
: EXIT_FAILURE;
WebPFree(data); WebPFree(data);
if (ret) goto End; if (ret) goto End;
#else #else
@ -348,10 +344,9 @@ int main(int argc, const char* argv[]) {
(void)data_size; (void)data_size;
fprintf(stderr, "Cannot save the difference map. Please recompile " fprintf(stderr, "Cannot save the difference map. Please recompile "
"without the WEBP_REDUCE_CSP flag.\n"); "without the WEBP_REDUCE_CSP flag.\n");
goto End;
#endif // WEBP_REDUCE_CSP #endif // WEBP_REDUCE_CSP
} }
ret = EXIT_SUCCESS; ret = 0;
End: End:
WebPPictureFree(&pic1); WebPPictureFree(&pic1);

View File

@ -11,13 +11,11 @@
// //
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#include <math.h>
#include <stddef.h>
#include "extras/extras.h" #include "extras/extras.h"
#include "src/webp/types.h"
#include "webp/decode.h" #include "webp/decode.h"
#include <math.h>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#define INVALID_BIT_POS (1ull << 63) #define INVALID_BIT_POS (1ull << 63)
@ -78,7 +76,7 @@ int VP8EstimateQuality(const uint8_t* const data, size_t size) {
GET_BIT(2); // colorspace + clamp type GET_BIT(2); // colorspace + clamp type
// Segment header // Segment header
if (GET_BIT(1)) { // use_segment if (GET_BIT(1)) { // use_segment_
int s; int s;
const int update_map = GET_BIT(1); const int update_map = GET_BIT(1);
if (GET_BIT(1)) { // update data if (GET_BIT(1)) { // update data

File diff suppressed because it is too large Load Diff

View File

@ -1,27 +0,0 @@
// Copyright 2023 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Precomputed data for 420 risk estimation.
#ifndef WEBP_EXTRAS_SHARPYUV_RISK_TABLE_H_
#define WEBP_EXTRAS_SHARPYUV_RISK_TABLE_H_
#include "src/webp/types.h"
extern const int kSharpYuvPrecomputedRiskYuvSampling;
// Table of precomputed risk scores when chroma subsampling images with two
// given colors.
// Since precomputing values for all possible YUV colors would create a huge
// table, the YUV space (i.e. [0, 255]^3) is reduced to
// [0, kSharpYuvPrecomputedRiskYuvSampling-1]^3
// where 255 maps to kSharpYuvPrecomputedRiskYuvSampling-1.
// Table size: kSharpYuvPrecomputedRiskYuvSampling^6 bytes or 114 KiB
extern const uint8_t kSharpYuvPrecomputedRisk[];
#endif // WEBP_EXTRAS_SHARPYUV_RISK_TABLE_H_

View File

@ -15,7 +15,6 @@
// Author: James Zern (jzern@google.com) // Author: James Zern (jzern@google.com)
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "webp/config.h" #include "webp/config.h"
@ -31,7 +30,7 @@
#if defined(WEBP_HAVE_JUST_SDL_H) #if defined(WEBP_HAVE_JUST_SDL_H)
#include <SDL.h> #include <SDL.h>
#else #else
#include <SDL2/SDL.h> #include <SDL/SDL.h>
#endif #endif
static void ProcessEvents(void) { static void ProcessEvents(void) {
@ -50,26 +49,19 @@ static void ProcessEvents(void) {
} }
} }
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
int c; int c;
int ok = 0; int ok = 0;
INIT_WARGV(argc, argv); INIT_WARGV(argc, argv);
if (argc == 1) {
fprintf(stderr, "Usage: %s [-h] image.webp [more_files.webp...]\n",
argv[0]);
goto Error;
}
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
const char* file = NULL; const char* file = NULL;
const uint8_t* webp = NULL; const uint8_t* webp = NULL;
size_t webp_size = 0; size_t webp_size = 0;
if (!strcmp(argv[c], "-h")) { if (!strcmp(argv[c], "-h")) {
printf("Usage: %s [-h] image.webp [more_files.webp...]\n", argv[0]); printf("Usage: %s [-h] image.webp [more_files.webp...]\n", argv[0]);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); FREE_WARGV_AND_RETURN(0);
} else { } else {
file = (const char*)GET_WARGV(argv, c); file = (const char*)GET_WARGV(argv, c);
} }
@ -83,7 +75,7 @@ int main(int argc, char* argv[]) {
fprintf(stderr, "File too large.\n"); fprintf(stderr, "File too large.\n");
goto Error; goto Error;
} }
ok = WebPToSDL((const char*)webp, (int)webp_size); ok = WebpToSDL((const char*)webp, (int)webp_size);
free((void*)webp); free((void*)webp);
if (!ok) { if (!ok) {
WFPRINTF(stderr, "Error decoding file %s\n", (const W_CHAR*)file); WFPRINTF(stderr, "Error decoding file %s\n", (const W_CHAR*)file);
@ -95,7 +87,7 @@ int main(int argc, char* argv[]) {
Error: Error:
SDL_Quit(); SDL_Quit();
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE); FREE_WARGV_AND_RETURN(ok ? 0 : 1);
} }
#else // !WEBP_HAVE_SDL #else // !WEBP_HAVE_SDL

View File

@ -11,12 +11,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "../examples/unicode.h"
#include "src/webp/types.h"
#include "extras/extras.h" #include "extras/extras.h"
#include "imageio/imageio_util.h" #include "imageio/imageio_util.h"
#include "../examples/unicode.h"
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
int c; int c;
int quiet = 0; int quiet = 0;
@ -29,7 +27,7 @@ int main(int argc, const char* argv[]) {
quiet = 1; quiet = 1;
} else if (!strcmp(argv[c], "-help") || !strcmp(argv[c], "-h")) { } else if (!strcmp(argv[c], "-help") || !strcmp(argv[c], "-h")) {
printf("webp_quality [-h][-quiet] webp_files...\n"); printf("webp_quality [-h][-quiet] webp_files...\n");
FREE_WARGV_AND_RETURN(EXIT_SUCCESS); FREE_WARGV_AND_RETURN(0);
} else { } else {
const char* const filename = (const char*)GET_WARGV(argv, c); const char* const filename = (const char*)GET_WARGV(argv, c);
const uint8_t* data = NULL; const uint8_t* data = NULL;
@ -52,5 +50,5 @@ int main(int argc, const char* argv[]) {
free((void*)data); free((void*)data);
} }
} }
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE); FREE_WARGV_AND_RETURN(ok ? 0 : 1);
} }

View File

@ -20,75 +20,88 @@
#include "webp_to_sdl.h" #include "webp_to_sdl.h"
#include <stdio.h> #include <stdio.h>
#include "src/webp/decode.h" #include "src/webp/decode.h"
#if defined(WEBP_HAVE_JUST_SDL_H) #if defined(WEBP_HAVE_JUST_SDL_H)
#include <SDL.h> #include <SDL.h>
#else #else
#include <SDL2/SDL.h> #include <SDL/SDL.h>
#endif #endif
static int init_ok = 0; static int init_ok = 0;
int WebPToSDL(const char* data, unsigned int data_size) { int WebpToSDL(const char* data, unsigned int data_size) {
int ok = 0; int ok = 0;
VP8StatusCode status; VP8StatusCode status;
WebPBitstreamFeatures input; WebPDecoderConfig config;
uint8_t* output = NULL; WebPBitstreamFeatures* const input = &config.input;
SDL_Window* window = NULL; WebPDecBuffer* const output = &config.output;
SDL_Renderer* renderer = NULL; SDL_Surface* screen = NULL;
SDL_Texture* texture = NULL; SDL_Surface* surface = NULL;
int width, height;
if (!WebPInitDecoderConfig(&config)) {
fprintf(stderr, "Library version mismatch!\n");
return 0;
}
if (!init_ok) { if (!init_ok) {
SDL_Init(SDL_INIT_VIDEO); SDL_Init(SDL_INIT_VIDEO);
init_ok = 1; init_ok = 1;
} }
status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &input); status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &config.input);
if (status != VP8_STATUS_OK) goto Error; if (status != VP8_STATUS_OK) goto Error;
width = input.width;
height = input.height;
SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer); screen = SDL_SetVideoMode(input->width, input->height, 32, SDL_SWSURFACE);
if (window == NULL || renderer == NULL) { if (screen == NULL) {
fprintf(stderr, "Unable to create window or renderer!\n"); fprintf(stderr, "Unable to set video mode (32bpp %dx%d)!\n",
input->width, input->height);
goto Error; goto Error;
} }
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY,
"linear"); // make the scaled rendering look smoother.
SDL_RenderSetLogicalSize(renderer, width, height);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
SDL_TEXTUREACCESS_STREAMING, width, height); input->width, input->height, 32,
if (texture == NULL) { 0x000000ffu, // R mask
fprintf(stderr, "Unable to create %dx%d RGBA texture!\n", width, height); 0x0000ff00u, // G mask
0x00ff0000u, // B mask
0xff000000u); // A mask
if (surface == NULL) {
fprintf(stderr, "Unable to create %dx%d RGBA surface!\n",
input->width, input->height);
goto Error; goto Error;
} }
if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN #if SDL_BYTEORDER == SDL_BIG_ENDIAN
output = WebPDecodeBGRA((const uint8_t*)data, (size_t)data_size, &width, output->colorspace = MODE_BGRA;
&height);
#else #else
output = WebPDecodeRGBA((const uint8_t*)data, (size_t)data_size, &width, output->colorspace = MODE_RGBA;
&height);
#endif #endif
if (output == NULL) { output->width = surface->w;
output->height = surface->h;
output->u.RGBA.rgba = surface->pixels;
output->u.RGBA.stride = surface->pitch;
output->u.RGBA.size = surface->pitch * surface->h;
output->is_external_memory = 1;
status = WebPDecode((const uint8_t*)data, (size_t)data_size, &config);
if (status != VP8_STATUS_OK) {
fprintf(stderr, "Error decoding image (%d)\n", status); fprintf(stderr, "Error decoding image (%d)\n", status);
goto Error; goto Error;
} }
SDL_UpdateTexture(texture, NULL, output, width * sizeof(uint32_t)); if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);
SDL_RenderClear(renderer); if (SDL_BlitSurface(surface, NULL, screen, NULL) ||
SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_Flip(screen)) {
SDL_RenderPresent(renderer); goto Error;
}
ok = 1; ok = 1;
Error: Error:
// We should call SDL_DestroyWindow(window) but that makes .js fail. SDL_FreeSurface(surface);
SDL_DestroyRenderer(renderer); SDL_FreeSurface(screen);
SDL_DestroyTexture(texture); WebPFreeDecBuffer(output);
WebPFree(output);
return ok; return ok;
} }

View File

@ -14,9 +14,9 @@
#ifndef WEBP_EXTRAS_WEBP_TO_SDL_H_ #ifndef WEBP_EXTRAS_WEBP_TO_SDL_H_
#define WEBP_EXTRAS_WEBP_TO_SDL_H_ #define WEBP_EXTRAS_WEBP_TO_SDL_H_
// Exports the method WebPToSDL(const char* data, int data_size) which decodes // Exports the method WebpToSDL(const char* data, int data_size) which decodes
// a WebP bitstream into an RGBA SDL surface. // a WebP bitstream into an RGBA SDL surface.
// Return false on failure. // Return false on failure.
extern int WebPToSDL(const char* data, unsigned int data_size); extern int WebpToSDL(const char* data, unsigned int data_size);
#endif // WEBP_EXTRAS_WEBP_TO_SDL_H_ #endif // WEBP_EXTRAS_WEBP_TO_SDL_H_

Binary file not shown.

View File

@ -1,5 +1,6 @@
#Thu May 12 17:06:25 CEST 2016
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip

65
gradlew vendored
View File

@ -1,20 +1,4 @@
#!/usr/bin/env sh #!/usr/bin/env bash
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
############################################################################## ##############################################################################
## ##
@ -44,16 +28,16 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"` APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD="maximum"
warn () { warn ( ) {
echo "$*" echo "$*"
} }
die () { die ( ) {
echo echo
echo "$*" echo "$*"
echo echo
@ -125,8 +109,8 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi fi
# For Cygwin or MSYS, switch paths to Windows format before running java # For Cygwin, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"` JAVACMD=`cygpath --unix "$JAVACMD"`
@ -154,30 +138,27 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
else else
eval `echo args$i`="\"$arg\"" eval `echo args$i`="\"$arg\""
fi fi
i=`expr $i + 1` i=$((i+1))
done done
case $i in case $i in
0) set -- ;; (0) set -- ;;
1) set -- "$args0" ;; (1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;; (2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;; (3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac esac
fi fi
# Escape application args # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
save () { function splitJvmOpts() {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done JVM_OPTS=("$@")
echo " "
} }
APP_ARGS=`save "$@"` eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
# Collect all arguments for the java command, following the shell quoting and substitution rules exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

190
gradlew.bat vendored
View File

@ -1,100 +1,90 @@
@rem @if "%DEBUG%" == "" @echo off
@rem Copyright 2015 the original author or authors. @rem ##########################################################################
@rem @rem
@rem Licensed under the Apache License, Version 2.0 (the "License"); @rem Gradle startup script for Windows
@rem you may not use this file except in compliance with the License. @rem
@rem You may obtain a copy of the License at @rem ##########################################################################
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0 @rem Set local scope for the variables with windows NT shell
@rem if "%OS%"=="Windows_NT" setlocal
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS, set DIRNAME=%~dp0
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. if "%DIRNAME%" == "" set DIRNAME=.
@rem See the License for the specific language governing permissions and set APP_BASE_NAME=%~n0
@rem limitations under the License. set APP_HOME=%DIRNAME%
@rem
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
@if "%DEBUG%" == "" @echo off set DEFAULT_JVM_OPTS=
@rem ##########################################################################
@rem @rem Find java.exe
@rem Gradle startup script for Windows if defined JAVA_HOME goto findJavaFromJavaHome
@rem
@rem ########################################################################## set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
@rem Set local scope for the variables with windows NT shell if "%ERRORLEVEL%" == "0" goto init
if "%OS%"=="Windows_NT" setlocal
echo.
set DIRNAME=%~dp0 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
if "%DIRNAME%" == "" set DIRNAME=. echo.
set APP_BASE_NAME=%~n0 echo Please set the JAVA_HOME variable in your environment to match the
set APP_HOME=%DIRNAME% echo location of your Java installation.
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. goto fail
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
:findJavaFromJavaHome
@rem Find java.exe set JAVA_HOME=%JAVA_HOME:"=%
if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=%JAVA_HOME%/bin/java.exe
set JAVA_EXE=java.exe if exist "%JAVA_EXE%" goto init
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo Please set the JAVA_HOME variable in your environment to match the
echo. echo location of your Java installation.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation. goto fail
goto fail :init
@rem Get command-line arguments, handling Windows variants
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=% if not "%OS%" == "Windows_NT" goto win9xME_args
set JAVA_EXE=%JAVA_HOME%/bin/java.exe if "%@eval[2+2]" == "4" goto 4NT_args
if exist "%JAVA_EXE%" goto init :win9xME_args
@rem Slurp the command line arguments.
echo. set CMD_LINE_ARGS=
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% set _SKIP=2
echo.
echo Please set the JAVA_HOME variable in your environment to match the :win9xME_args_slurp
echo location of your Java installation. if "x%~1" == "x" goto execute
goto fail set CMD_LINE_ARGS=%*
goto execute
:init
@rem Get command-line arguments, handling Windows variants :4NT_args
@rem Get arguments from the 4NT Shell from JP Software
if not "%OS%" == "Windows_NT" goto win9xME_args set CMD_LINE_ARGS=%$
:win9xME_args :execute
@rem Slurp the command line arguments. @rem Setup the command line
set CMD_LINE_ARGS=
set _SKIP=2 set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:win9xME_args_slurp @rem Execute Gradle
if "x%~1" == "x" goto execute "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
set CMD_LINE_ARGS=%* :end
@rem End local scope for the variables with windows NT shell
:execute if "%ERRORLEVEL%"=="0" goto mainEnd
@rem Setup the command line
:fail
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
@rem Execute Gradle if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% exit /b 1
:end :mainEnd
@rem End local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" endlocal
if "%ERRORLEVEL%"=="0" goto mainEnd
:omega
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -1,5 +1,3 @@
# Ignore this file during non-NDK builds.
ifdef NDK_ROOT
LOCAL_PATH := $(call my-dir) LOCAL_PATH := $(call my-dir)
################################################################################ ################################################################################
@ -54,4 +52,3 @@ LOCAL_STATIC_LIBRARIES := imageio_util
LOCAL_MODULE := imageenc LOCAL_MODULE := imageenc
include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY)
endif # NDK_ROOT

View File

@ -9,30 +9,7 @@
// //
// Generic image-type guessing. // Generic image-type guessing.
#include <stddef.h>
#include "./image_dec.h" #include "./image_dec.h"
#include "./metadata.h"
#include "webp/encode.h"
#include "webp/types.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[]) { static WEBP_INLINE uint32_t GetBE32(const uint8_t buf[]) {
return ((uint32_t)buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; return ((uint32_t)buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];

View File

@ -14,8 +14,6 @@
#ifndef WEBP_IMAGEIO_IMAGE_DEC_H_ #ifndef WEBP_IMAGEIO_IMAGE_DEC_H_
#define WEBP_IMAGEIO_IMAGE_DEC_H_ #define WEBP_IMAGEIO_IMAGE_DEC_H_
#include <stddef.h>
#include "webp/types.h" #include "webp/types.h"
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -43,9 +41,6 @@ typedef enum {
WEBP_UNSUPPORTED_FORMAT WEBP_UNSUPPORTED_FORMAT
} WebPInputFileFormat; } 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. // Try to infer the image format. 'data_size' should be larger than 12.
// Returns WEBP_UNSUPPORTED_FORMAT if format can't be guess safely. // Returns WEBP_UNSUPPORTED_FORMAT if format can't be guess safely.
WebPInputFileFormat WebPGuessImageType(const uint8_t* const data, WebPInputFileFormat WebPGuessImageType(const uint8_t* const data,

View File

@ -12,7 +12,6 @@
#include "./image_enc.h" #include "./image_enc.h"
#include <assert.h> #include <assert.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#ifdef WEBP_HAVE_PNG #ifdef WEBP_HAVE_PNG
@ -35,10 +34,8 @@
#include <wincodec.h> #include <wincodec.h>
#endif #endif
#include "../examples/unicode.h"
#include "./imageio_util.h" #include "./imageio_util.h"
#include "webp/decode.h" #include "../examples/unicode.h"
#include "webp/types.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// PNG // PNG
@ -158,8 +155,8 @@ int WebPWritePNG(const char* out_file_name, int use_stdout,
} }
#elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H #elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H
static void PNGAPI PNGErrorFunction(png_structp png, png_const_charp unused) { static void PNGAPI PNGErrorFunction(png_structp png, png_const_charp dummy) {
(void)unused; // remove variable-unused warning (void)dummy; // remove variable-unused warning
longjmp(png_jmpbuf(png), 1); longjmp(png_jmpbuf(png), 1);
} }
@ -263,20 +260,14 @@ int WebPWritePAM(FILE* fout, const WebPDecBuffer* const buffer) {
// Save 16b mode (RGBA4444, RGB565, ...) for debugging purpose. // Save 16b mode (RGBA4444, RGB565, ...) for debugging purpose.
int WebPWrite16bAsPGM(FILE* fout, const WebPDecBuffer* const buffer) { int WebPWrite16bAsPGM(FILE* fout, const WebPDecBuffer* const buffer) {
uint32_t width, height; const uint32_t width = buffer->width;
uint8_t* rgba; const uint32_t height = buffer->height;
int stride; const uint8_t* rgba = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
const uint32_t bytes_per_px = 2; const uint32_t bytes_per_px = 2;
uint32_t y; uint32_t y;
if (fout == NULL || buffer == NULL) return 0; if (fout == NULL || buffer == NULL || rgba == NULL) return 0;
width = buffer->width;
height = buffer->height;
rgba = buffer->u.RGBA.rgba;
stride = buffer->u.RGBA.stride;
if (rgba == NULL) return 0;
fprintf(fout, "P5\n%u %u\n255\n", width * bytes_per_px, height); fprintf(fout, "P5\n%u %u\n255\n", width * bytes_per_px, height);
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
@ -289,7 +280,7 @@ int WebPWrite16bAsPGM(FILE* fout, const WebPDecBuffer* const buffer) {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// BMP (see https://en.wikipedia.org/wiki/BMP_file_format#Pixel_storage) // BMP
static void PutLE16(uint8_t* const dst, uint32_t value) { static void PutLE16(uint8_t* const dst, uint32_t value) {
dst[0] = (value >> 0) & 0xff; dst[0] = (value >> 0) & 0xff;
@ -302,67 +293,49 @@ static void PutLE32(uint8_t* const dst, uint32_t value) {
} }
#define BMP_HEADER_SIZE 54 #define BMP_HEADER_SIZE 54
#define BMP_HEADER_ALPHA_EXTRA_SIZE 16 // for alpha info
int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) { int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
int has_alpha, header_size; const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
uint32_t width, height; const uint32_t width = buffer->width;
uint8_t* rgba; const uint32_t height = buffer->height;
int stride; const uint8_t* rgba = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
const uint32_t bytes_per_px = has_alpha ? 4 : 3;
uint32_t y; uint32_t y;
uint32_t bytes_per_px, line_size, image_size, bmp_stride, total_size; const uint32_t line_size = bytes_per_px * width;
uint8_t bmp_header[BMP_HEADER_SIZE + BMP_HEADER_ALPHA_EXTRA_SIZE] = { 0 }; const uint32_t bmp_stride = (line_size + 3) & ~3; // pad to 4
const uint32_t total_size = bmp_stride * height + BMP_HEADER_SIZE;
uint8_t bmp_header[BMP_HEADER_SIZE] = { 0 };
if (fout == NULL || buffer == NULL) return 0; if (fout == NULL || buffer == NULL || rgba == NULL) return 0;
has_alpha = WebPIsAlphaMode(buffer->colorspace);
header_size = BMP_HEADER_SIZE + (has_alpha ? BMP_HEADER_ALPHA_EXTRA_SIZE : 0);
width = buffer->width;
height = buffer->height;
rgba = buffer->u.RGBA.rgba;
stride = buffer->u.RGBA.stride;
bytes_per_px = has_alpha ? 4 : 3;
line_size = bytes_per_px * width;
bmp_stride = (line_size + 3) & ~3; // pad to 4
image_size = bmp_stride * height;
total_size = image_size + header_size;
if (rgba == NULL) return 0;
// bitmap file header // bitmap file header
PutLE16(bmp_header + 0, 0x4d42); // signature 'BM' PutLE16(bmp_header + 0, 0x4d42); // signature 'BM'
PutLE32(bmp_header + 2, total_size); // size including header PutLE32(bmp_header + 2, total_size); // size including header
PutLE32(bmp_header + 6, 0); // reserved PutLE32(bmp_header + 6, 0); // reserved
PutLE32(bmp_header + 10, header_size); // offset to pixel array PutLE32(bmp_header + 10, BMP_HEADER_SIZE); // offset to pixel array
// bitmap info header // bitmap info header
PutLE32(bmp_header + 14, header_size - 14); // DIB header size PutLE32(bmp_header + 14, 40); // DIB header size
PutLE32(bmp_header + 18, width); // dimensions PutLE32(bmp_header + 18, width); // dimensions
PutLE32(bmp_header + 22, height); // no vertical flip PutLE32(bmp_header + 22, -(int)height); // vertical flip!
PutLE16(bmp_header + 26, 1); // number of planes PutLE16(bmp_header + 26, 1); // number of planes
PutLE16(bmp_header + 28, bytes_per_px * 8); // bits per pixel PutLE16(bmp_header + 28, bytes_per_px * 8); // bits per pixel
PutLE32(bmp_header + 30, has_alpha ? 3 : 0); // BI_BITFIELDS or BI_RGB PutLE32(bmp_header + 30, 0); // no compression (BI_RGB)
PutLE32(bmp_header + 34, image_size); PutLE32(bmp_header + 34, 0); // image size (dummy)
PutLE32(bmp_header + 38, 2400); // x pixels/meter PutLE32(bmp_header + 38, 2400); // x pixels/meter
PutLE32(bmp_header + 42, 2400); // y pixels/meter PutLE32(bmp_header + 42, 2400); // y pixels/meter
PutLE32(bmp_header + 46, 0); // number of palette colors PutLE32(bmp_header + 46, 0); // number of palette colors
PutLE32(bmp_header + 50, 0); // important color count 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 // TODO(skal): color profile
// write header // write header
if (fwrite(bmp_header, header_size, 1, fout) != 1) { if (fwrite(bmp_header, sizeof(bmp_header), 1, fout) != 1) {
return 0; return 0;
} }
// write pixel array, bottom to top // write pixel array
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
const uint8_t* const src = &rgba[(uint64_t)(height - 1 - y) * stride]; if (fwrite(rgba, line_size, 1, fout) != 1) {
if (fwrite(src, line_size, 1, fout) != 1) {
return 0; return 0;
} }
// write padding zeroes // write padding zeroes
@ -372,11 +345,11 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
return 0; return 0;
} }
} }
rgba += stride;
} }
return 1; return 1;
} }
#undef BMP_HEADER_SIZE #undef BMP_HEADER_SIZE
#undef BMP_HEADER_ALPHA_EXTRA_SIZE
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// TIFF // TIFF
@ -388,14 +361,17 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
#define TIFF_HEADER_SIZE (EXTRA_DATA_OFFSET + EXTRA_DATA_SIZE) #define TIFF_HEADER_SIZE (EXTRA_DATA_OFFSET + EXTRA_DATA_SIZE)
int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) { int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
int has_alpha; const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
uint32_t width, height; const uint32_t width = buffer->width;
uint8_t* rgba; const uint32_t height = buffer->height;
int stride; const uint8_t* rgba = buffer->u.RGBA.rgba;
uint8_t bytes_per_px = 0; const int stride = buffer->u.RGBA.stride;
const uint8_t assoc_alpha = 0; const uint8_t bytes_per_px = has_alpha ? 4 : 3;
const uint8_t assoc_alpha =
WebPIsPremultipliedMode(buffer->colorspace) ? 1 : 2;
// For non-alpha case, we omit tag 0x152 (ExtraSamples). // For non-alpha case, we omit tag 0x152 (ExtraSamples).
const uint8_t num_ifd_entries = 0; const uint8_t num_ifd_entries = has_alpha ? NUM_IFD_ENTRIES
: NUM_IFD_ENTRIES - 1;
uint8_t tiff_header[TIFF_HEADER_SIZE] = { uint8_t tiff_header[TIFF_HEADER_SIZE] = {
0x49, 0x49, 0x2a, 0x00, // little endian signature 0x49, 0x49, 0x2a, 0x00, // little endian signature
8, 0, 0, 0, // offset to the unique IFD that follows 8, 0, 0, 0, // offset to the unique IFD that follows
@ -429,20 +405,7 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
}; };
uint32_t y; uint32_t y;
if (fout == NULL || buffer == NULL) return 0; if (fout == NULL || buffer == NULL || rgba == NULL) return 0;
has_alpha = WebPIsAlphaMode(buffer->colorspace);
width = buffer->width;
height = buffer->height;
rgba = buffer->u.RGBA.rgba;
stride = buffer->u.RGBA.stride;
if (rgba == NULL) return 0;
// Update bytes_per_px, num_ifd_entries and assoc_alpha.
tiff_header[38] = tiff_header[102] = bytes_per_px = has_alpha ? 4 : 3;
tiff_header[8] = has_alpha ? NUM_IFD_ENTRIES : NUM_IFD_ENTRIES - 1;
tiff_header[186] = WebPIsPremultipliedMode(buffer->colorspace) ? 1 : 2;
// Fill placeholders in IFD: // Fill placeholders in IFD:
PutLE32(tiff_header + 10 + 8, width); PutLE32(tiff_header + 10 + 8, width);

View File

@ -79,7 +79,7 @@ int WebPWriteTIFF(FILE* fout, const struct WebPDecBuffer* const buffer);
int WebPWriteAlphaPlane(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). // Save as YUV samples as PGM format (using IMC4 layout).
// See: https://www.fourcc.org/yuv.php#IMC4. // See: http://www.fourcc.org/yuv.php#IMC4.
// (very convenient format for viewing the samples, esp. for odd dimensions). // (very convenient format for viewing the samples, esp. for odd dimensions).
int WebPWritePGM(FILE* fout, const struct WebPDecBuffer* const buffer); int WebPWritePGM(FILE* fout, const struct WebPDecBuffer* const buffer);

View File

@ -16,11 +16,8 @@
#include <fcntl.h> // for _O_BINARY #include <fcntl.h> // for _O_BINARY
#include <io.h> // for _setmode() #include <io.h> // for _setmode()
#endif #endif
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "webp/types.h"
#include "../examples/unicode.h" #include "../examples/unicode.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -92,14 +89,9 @@ int ImgIoUtilReadFile(const char* const file_name,
} }
fseek(in, 0, SEEK_END); fseek(in, 0, SEEK_END);
file_size = ftell(in); file_size = ftell(in);
if (file_size == (size_t)-1) {
fclose(in);
WFPRINTF(stderr, "error getting size of '%s'\n", (const W_CHAR*)file_name);
return 0;
}
fseek(in, 0, SEEK_SET); fseek(in, 0, SEEK_SET);
// we allocate one extra byte for the \0 terminator // we allocate one extra byte for the \0 terminator
file_data = (uint8_t*)WebPMalloc(file_size + 1); file_data = (uint8_t*)malloc(file_size + 1);
if (file_data == NULL) { if (file_data == NULL) {
fclose(in); fclose(in);
WFPRINTF(stderr, "memory allocation failure when reading file %s\n", WFPRINTF(stderr, "memory allocation failure when reading file %s\n",
@ -112,7 +104,7 @@ int ImgIoUtilReadFile(const char* const file_name,
if (!ok) { if (!ok) {
WFPRINTF(stderr, "Could not read %d bytes of data from file %s\n", WFPRINTF(stderr, "Could not read %d bytes of data from file %s\n",
(int)file_size, (const W_CHAR*)file_name); (int)file_size, (const W_CHAR*)file_name);
WebPFree(file_data); free(file_data);
return 0; return 0;
} }
file_data[file_size] = '\0'; // convenient 0-terminator file_data[file_size] = '\0'; // convenient 0-terminator
@ -156,11 +148,9 @@ void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t stride, size_t height) { int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) {
const uint64_t total_size = stride * height; const uint64_t total_size = nmemb * size;
int ok = (total_size == (size_t)total_size); int ok = (total_size == (size_t)total_size);
// check that 'stride' is representable as int:
ok = ok && ((uint64_t)(int)stride == stride);
#if defined(WEBP_MAX_IMAGE_SIZE) #if defined(WEBP_MAX_IMAGE_SIZE)
ok = ok && (total_size <= (uint64_t)WEBP_MAX_IMAGE_SIZE); ok = ok && (total_size <= (uint64_t)WEBP_MAX_IMAGE_SIZE);
#endif #endif

View File

@ -14,7 +14,6 @@
#define WEBP_IMAGEIO_IMAGEIO_UTIL_H_ #define WEBP_IMAGEIO_IMAGEIO_UTIL_H_
#include <stdio.h> #include <stdio.h>
#include "webp/types.h" #include "webp/types.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -30,7 +29,7 @@ FILE* ImgIoUtilSetBinaryMode(FILE* file);
// Allocates storage for entire file 'file_name' and returns contents and size // Allocates storage for entire file 'file_name' and returns contents and size
// in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should // in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should
// be deleted using WebPFree(). // be deleted using free().
// Note: for convenience, the data will be null-terminated with an extra byte // Note: for convenience, the data will be null-terminated with an extra byte
// (not accounted for in *data_size), in case the file is text and intended // (not accounted for in *data_size), in case the file is text and intended
// to be used as a C-string. // to be used as a C-string.
@ -55,8 +54,8 @@ void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Returns 0 in case of overflow, memory over-allocation or excessive dimension. // Returns 0 in case of overflow of nmemb * size.
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t stride, size_t height); int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t nmemb, size_t size);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"

View File

@ -24,10 +24,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "webp/encode.h"
#include "./imageio_util.h" #include "./imageio_util.h"
#include "./metadata.h" #include "./metadata.h"
#include "webp/encode.h"
#include "webp/types.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Metadata processing // Metadata processing
@ -207,18 +206,8 @@ struct my_error_mgr {
static void my_error_exit(j_common_ptr dinfo) { static void my_error_exit(j_common_ptr dinfo) {
struct my_error_mgr* myerr = (struct my_error_mgr*)dinfo->err; struct my_error_mgr* myerr = (struct my_error_mgr*)dinfo->err;
// The following code is disabled in fuzzing mode because:
// - the logs can be flooded due to invalid JPEG files
// - msg_code is wrongfully seen as uninitialized by msan when the libjpeg
// dependency is not built with sanitizers enabled
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
const int msg_code = myerr->pub.msg_code;
fprintf(stderr, "libjpeg error: "); fprintf(stderr, "libjpeg error: ");
dinfo->err->output_message(dinfo); dinfo->err->output_message(dinfo);
if (msg_code == JERR_INPUT_EOF || msg_code == JERR_FILE_READ) {
fprintf(stderr, "`jpegtran -copy all` MAY be able to process this file.\n");
}
#endif
longjmp(myerr->setjmp_buffer, 1); longjmp(myerr->setjmp_buffer, 1);
} }
@ -285,7 +274,7 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
ctx.data = data; ctx.data = data;
ctx.data_size = data_size; ctx.data_size = data_size;
memset((j_decompress_ptr)&dinfo, 0, sizeof(dinfo)); // for setjmp safety memset((j_decompress_ptr)&dinfo, 0, sizeof(dinfo)); // for setjmp sanity
dinfo.err = jpeg_std_error(&jerr.pub); dinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit; jerr.pub.error_exit = my_error_exit;
@ -347,11 +336,7 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
pic->width = width; pic->width = width;
pic->height = height; pic->height = height;
ok = WebPPictureImportRGB(pic, rgb, (int)stride); ok = WebPPictureImportRGB(pic, rgb, (int)stride);
if (!ok) { if (!ok) goto Error;
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: End:
free(rgb); free(rgb);

View File

@ -12,8 +12,6 @@
#ifndef WEBP_IMAGEIO_JPEGDEC_H_ #ifndef WEBP_IMAGEIO_JPEGDEC_H_
#define WEBP_IMAGEIO_JPEGDEC_H_ #define WEBP_IMAGEIO_JPEGDEC_H_
#include <stddef.h>
#include "webp/types.h" #include "webp/types.h"
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -13,8 +13,6 @@
#ifndef WEBP_IMAGEIO_METADATA_H_ #ifndef WEBP_IMAGEIO_METADATA_H_
#define WEBP_IMAGEIO_METADATA_H_ #define WEBP_IMAGEIO_METADATA_H_
#include <stddef.h>
#include "webp/types.h" #include "webp/types.h"
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -22,15 +22,13 @@
#define PNG_USER_MEM_SUPPORTED // for png_create_read_struct_2 #define PNG_USER_MEM_SUPPORTED // for png_create_read_struct_2
#endif #endif
#include <png.h> #include <png.h>
#include <setjmp.h> // note: this must be included *after* png.h #include <setjmp.h> // note: this must be included *after* png.h
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "webp/encode.h"
#include "./imageio_util.h" #include "./imageio_util.h"
#include "./metadata.h" #include "./metadata.h"
#include "webp/encode.h"
#include "webp/types.h"
#define LOCAL_PNG_VERSION ((PNG_LIBPNG_VER_MAJOR << 8) | PNG_LIBPNG_VER_MINOR) #define LOCAL_PNG_VERSION ((PNG_LIBPNG_VER_MAJOR << 8) | PNG_LIBPNG_VER_MINOR)
#define LOCAL_PNG_PREREQ(maj, min) \ #define LOCAL_PNG_PREREQ(maj, min) \
@ -135,14 +133,12 @@ static const struct {
MetadataPayload* const payload); MetadataPayload* const payload);
size_t storage_offset; size_t storage_offset;
} kPNGMetadataMap[] = { } kPNGMetadataMap[] = {
// https://exiftool.org/TagNames/PNG.html#TextualData // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PNG.html#TextualData
// See also: ExifTool on CPAN. // See also: ExifTool on CPAN.
{ "Raw profile type exif", ProcessRawProfile, METADATA_OFFSET(exif) }, { "Raw profile type exif", ProcessRawProfile, METADATA_OFFSET(exif) },
{ "Raw profile type xmp", ProcessRawProfile, METADATA_OFFSET(xmp) }, { "Raw profile type xmp", ProcessRawProfile, METADATA_OFFSET(xmp) },
// Exiftool puts exif data in APP1 chunk, too. // Exiftool puts exif data in APP1 chunk, too.
{ "Raw profile type APP1", ProcessRawProfile, METADATA_OFFSET(exif) }, { "Raw profile type APP1", ProcessRawProfile, METADATA_OFFSET(exif) },
// ImageMagick uses lowercase app1.
{ "Raw profile type app1", ProcessRawProfile, METADATA_OFFSET(exif) },
// XMP Specification Part 3, Section 3 #PNG // XMP Specification Part 3, Section 3 #PNG
{ "XML:com.adobe.xmp", MetadataCopy, METADATA_OFFSET(xmp) }, { "XML:com.adobe.xmp", MetadataCopy, METADATA_OFFSET(xmp) },
{ NULL, NULL, 0 }, { NULL, NULL, 0 },
@ -163,20 +159,6 @@ static int ExtractMetadataFromPNG(png_structp png,
png_textp text = NULL; png_textp text = NULL;
const png_uint_32 num = png_get_text(png, info, &text, NULL); const png_uint_32 num = png_get_text(png, info, &text, NULL);
png_uint_32 i; png_uint_32 i;
#ifdef PNG_eXIf_SUPPORTED
// Look for an 'eXIf' tag. Preference is given to this tag as it's newer
// than the TextualData tags.
{
png_bytep exif;
png_uint_32 len;
if (png_get_eXIf_1(png, info, &len, &exif) == PNG_INFO_eXIf) {
if (!MetadataCopy((const char*)exif, len, &metadata->exif)) return 0;
}
}
#endif // PNG_eXIf_SUPPORTED
// Look for EXIF / XMP metadata. // Look for EXIF / XMP metadata.
for (i = 0; i < num; ++i, ++text) { for (i = 0; i < num; ++i, ++text) {
int j; int j;
@ -210,7 +192,6 @@ static int ExtractMetadataFromPNG(png_structp png,
} }
} }
} }
#ifdef PNG_iCCP_SUPPORTED
// Look for an ICC profile. // Look for an ICC profile.
{ {
png_charp name; png_charp name;
@ -227,7 +208,6 @@ static int ExtractMetadataFromPNG(png_structp png,
if (!MetadataCopy((const char*)profile, len, &metadata->iccp)) return 0; if (!MetadataCopy((const char*)profile, len, &metadata->iccp)) return 0;
} }
} }
#endif // PNG_iCCP_SUPPORTED
} }
return 1; return 1;
} }
@ -255,7 +235,7 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
volatile png_infop end_info = NULL; volatile png_infop end_info = NULL;
PNGReadContext context = { NULL, 0, 0 }; PNGReadContext context = { NULL, 0, 0 };
int color_type, bit_depth, interlaced; int color_type, bit_depth, interlaced;
int num_channels; int has_alpha;
int num_passes; int num_passes;
int p; int p;
volatile int ok = 0; volatile int ok = 0;
@ -279,15 +259,6 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
goto End; goto End;
} }
#if LOCAL_PNG_PREREQ(1,5) || \
(LOCAL_PNG_PREREQ(1,4) && PNG_LIBPNG_VER_RELEASE >= 1)
// If it looks like the bitstream is going to need more memory than libpng's
// internal limit (default: 8M), try to (reasonably) raise it.
if (data_size > png_get_chunk_malloc_max(png) && data_size < (1u << 24)) {
png_set_chunk_malloc_max(png, data_size);
}
#endif
info = png_create_info_struct(png); info = png_create_info_struct(png);
if (info == NULL) goto Error; if (info == NULL) goto Error;
end_info = png_create_info_struct(png); end_info = png_create_info_struct(png);
@ -313,6 +284,9 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
} }
if (png_get_valid(png, info, PNG_INFO_tRNS)) { if (png_get_valid(png, info, PNG_INFO_tRNS)) {
png_set_tRNS_to_alpha(png); png_set_tRNS_to_alpha(png);
has_alpha = 1;
} else {
has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
} }
// Apply gamma correction if needed. // Apply gamma correction if needed.
@ -327,16 +301,13 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
if (!keep_alpha) { if (!keep_alpha) {
png_set_strip_alpha(png); png_set_strip_alpha(png);
has_alpha = 0;
} }
num_passes = png_set_interlace_handling(png); num_passes = png_set_interlace_handling(png);
png_read_update_info(png, info); png_read_update_info(png, info);
num_channels = png_get_channels(png, info); stride = (int64_t)(has_alpha ? 4 : 3) * width * sizeof(*rgb);
if (num_channels != 3 && num_channels != 4) {
goto Error;
}
stride = (int64_t)num_channels * width * sizeof(*rgb);
if (stride != (int)stride || if (stride != (int)stride ||
!ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) { !ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) {
goto Error; goto Error;
@ -361,8 +332,8 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
pic->width = (int)width; pic->width = (int)width;
pic->height = (int)height; pic->height = (int)height;
ok = (num_channels == 4) ? WebPPictureImportRGBA(pic, rgb, (int)stride) ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, (int)stride)
: WebPPictureImportRGB(pic, rgb, (int)stride); : WebPPictureImportRGB(pic, rgb, (int)stride);
if (!ok) { if (!ok) {
goto Error; goto Error;

View File

@ -12,8 +12,6 @@
#ifndef WEBP_IMAGEIO_PNGDEC_H_ #ifndef WEBP_IMAGEIO_PNGDEC_H_
#define WEBP_IMAGEIO_PNGDEC_H_ #define WEBP_IMAGEIO_PNGDEC_H_
#include <stddef.h>
#include "webp/types.h" #include "webp/types.h"
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -17,13 +17,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "./imageio_util.h"
#include "webp/encode.h" #include "webp/encode.h"
#include "webp/types.h" #include "./imageio_util.h"
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif
typedef enum { typedef enum {
WIDTH_FLAG = 1 << 0, WIDTH_FLAG = 1 << 0,
@ -38,8 +33,8 @@ typedef struct {
const uint8_t* data; const uint8_t* data;
size_t data_size; size_t data_size;
int width, height; int width, height;
int bytes_per_px; int bytes_per_px; // 1, 3, 4
int depth; // 1 (grayscale), 2 (grayscale + alpha), 3 (rgb), 4 (rgba) int depth;
int max_value; int max_value;
int type; // 5, 6 or 7 int type; // 5, 6 or 7
int seen_flags; int seen_flags;
@ -106,9 +101,6 @@ static size_t ReadPAMFields(PNMInfo* const info, size_t off) {
} else if (!strcmp(out, "TUPLTYPE RGB")) { } else if (!strcmp(out, "TUPLTYPE RGB")) {
expected_depth = 3; expected_depth = 3;
info->seen_flags |= TUPLE_FLAG; info->seen_flags |= TUPLE_FLAG;
} else if (!strcmp(out, "TUPLTYPE GRAYSCALE_ALPHA")) {
expected_depth = 2;
info->seen_flags |= TUPLE_FLAG;
} else if (!strcmp(out, "TUPLTYPE GRAYSCALE")) { } else if (!strcmp(out, "TUPLTYPE GRAYSCALE")) {
expected_depth = 1; expected_depth = 1;
info->seen_flags |= TUPLE_FLAG; info->seen_flags |= TUPLE_FLAG;
@ -116,9 +108,8 @@ static size_t ReadPAMFields(PNMInfo* const info, size_t off) {
break; break;
} else { } else {
static const char kEllipsis[] = " ..."; static const char kEllipsis[] = " ...";
const size_t kLen = strlen(kEllipsis) + 1; // +1 = trailing \0
int i; int i;
if (out_size > 20) snprintf(out + 20 - kLen, kLen, kEllipsis); if (out_size > 20) sprintf(out + 20 - strlen(kEllipsis), kEllipsis);
for (i = 0; i < (int)strlen(out); ++i) { for (i = 0; i < (int)strlen(out); ++i) {
// isprint() might trigger a "char-subscripts" warning if given a char. // isprint() might trigger a "char-subscripts" warning if given a char.
if (!isprint((int)out[i])) out[i] = ' '; if (!isprint((int)out[i])) out[i] = ' ';
@ -175,7 +166,7 @@ static size_t ReadHeader(PNMInfo* const info) {
// perform some basic numerical validation // perform some basic numerical validation
if (info->width <= 0 || info->height <= 0 || if (info->width <= 0 || info->height <= 0 ||
info->type <= 0 || info->type >= 9 || info->type <= 0 || info->type >= 9 ||
info->depth <= 0 || info->depth > 4 || info->depth <= 0 || info->depth == 2 || info->depth > 4 ||
info->max_value <= 0 || info->max_value >= 65536) { info->max_value <= 0 || info->max_value >= 65536) {
return 0; return 0;
} }
@ -188,7 +179,7 @@ int ReadPNM(const uint8_t* const data, size_t data_size,
struct Metadata* const metadata) { struct Metadata* const metadata) {
int ok = 0; int ok = 0;
int i, j; int i, j;
uint64_t stride, pixel_bytes, sample_size, depth; uint64_t stride, pixel_bytes;
uint8_t* rgb = NULL, *tmp_rgb; uint8_t* rgb = NULL, *tmp_rgb;
size_t offset; size_t offset;
PNMInfo info; PNMInfo info;
@ -219,10 +210,8 @@ int ReadPNM(const uint8_t* const data, size_t data_size,
fprintf(stderr, "Truncated PNM file (P%d).\n", info.type); fprintf(stderr, "Truncated PNM file (P%d).\n", info.type);
goto End; goto End;
} }
sample_size = (info.max_value > 255) ? 2 : 1; stride =
// final depth (uint64_t)(info.bytes_per_px < 3 ? 3 : info.bytes_per_px) * info.width;
depth = (info.depth == 1 || info.depth == 3 || !keep_alpha) ? 3 : 4;
stride = depth * info.width;
if (stride != (size_t)stride || if (stride != (size_t)stride ||
!ImgIoUtilCheckSizeArgumentsOverflow(stride, info.height)) { !ImgIoUtilCheckSizeArgumentsOverflow(stride, info.height)) {
goto End; goto End;
@ -231,63 +220,30 @@ int ReadPNM(const uint8_t* const data, size_t data_size,
rgb = (uint8_t*)malloc((size_t)stride * info.height); rgb = (uint8_t*)malloc((size_t)stride * info.height);
if (rgb == NULL) goto End; if (rgb == NULL) goto End;
// Convert input. // Convert input
// We only optimize for the sample_size=1, max_value=255, depth=1 case.
tmp_rgb = rgb; tmp_rgb = rgb;
for (j = 0; j < info.height; ++j) { for (j = 0; j < info.height; ++j) {
const uint8_t* in = data + offset; assert(offset + info.bytes_per_px * info.width <= data_size);
offset += info.bytes_per_px * info.width; if (info.depth == 1) {
assert(offset <= data_size); // convert grayscale -> RGB
if (info.max_value == 255 && info.depth >= 3) { for (i = 0; i < info.width; ++i) {
// RGB or RGBA const uint8_t v = data[offset + i];
if (info.depth == 3 || keep_alpha) { tmp_rgb[3 * i + 0] = tmp_rgb[3 * i + 1] = tmp_rgb[3 * i + 2] = v;
memcpy(tmp_rgb, in, info.depth * info.width * sizeof(*in));
} else {
assert(info.depth == 4 && !keep_alpha);
for (i = 0; i < info.width; ++i) {
tmp_rgb[3 * i + 0] = in[4 * i + 0];
tmp_rgb[3 * i + 1] = in[4 * i + 1];
tmp_rgb[3 * i + 2] = in[4 * i + 2];
}
}
} else {
// Unoptimized case, we need to handle non-trivial operations:
// * convert 16b to 8b (if max_value > 255)
// * rescale to [0..255] range (if max_value != 255)
// * drop the alpha channel (if keep_alpha is false)
const uint32_t round = info.max_value / 2;
int k = 0;
for (i = 0; i < info.width * info.depth; ++i) {
uint32_t v = (sample_size == 2) ? 256u * in[2 * i + 0] + in[2 * i + 1]
: in[i];
if (info.max_value != 255) v = (v * 255u + round) / info.max_value;
if (v > 255u) v = 255u;
if (info.depth > 2) {
if (!keep_alpha && info.depth == 4 && (i % 4) == 3) {
// skip alpha
} else {
tmp_rgb[k] = v;
k += 1;
}
} else if (info.depth == 1 || (i % 2) == 0) {
tmp_rgb[k + 0] = tmp_rgb[k + 1] = tmp_rgb[k + 2] = v;
k += 3;
} else if (keep_alpha && info.depth == 2) {
tmp_rgb[k] = v;
k += 1;
} else {
// skip alpha
}
} }
} else if (info.depth == 3) { // RGB
memcpy(tmp_rgb, data + offset, 3 * info.width * sizeof(*data));
} else if (info.depth == 4) { // RGBA
memcpy(tmp_rgb, data + offset, 4 * info.width * sizeof(*data));
} }
offset += info.bytes_per_px * info.width;
tmp_rgb += stride; tmp_rgb += stride;
} }
// WebP conversion. // WebP conversion.
pic->width = info.width; pic->width = info.width;
pic->height = info.height; pic->height = info.height;
ok = (depth == 4) ? WebPPictureImportRGBA(pic, rgb, (int)stride) ok = (info.depth == 4) ? WebPPictureImportRGBA(pic, rgb, (int)stride)
: WebPPictureImportRGB(pic, rgb, (int)stride); : WebPPictureImportRGB(pic, rgb, (int)stride);
if (!ok) goto End; if (!ok) goto End;
ok = 1; ok = 1;

View File

@ -12,8 +12,6 @@
#ifndef WEBP_IMAGEIO_PNMDEC_H_ #ifndef WEBP_IMAGEIO_PNMDEC_H_
#define WEBP_IMAGEIO_PNMDEC_H_ #define WEBP_IMAGEIO_PNMDEC_H_
#include <stddef.h>
#include "webp/types.h" #include "webp/types.h"
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -22,10 +22,9 @@
#ifdef WEBP_HAVE_TIFF #ifdef WEBP_HAVE_TIFF
#include <tiffio.h> #include <tiffio.h>
#include "webp/encode.h"
#include "./imageio_util.h" #include "./imageio_util.h"
#include "./metadata.h" #include "./metadata.h"
#include "webp/encode.h"
#include "webp/types.h"
static const struct { static const struct {
ttag_t tag; ttag_t tag;
@ -47,7 +46,7 @@ static int ExtractMetadataFromTIFF(TIFF* const tif, Metadata* const metadata) {
(MetadataPayload*)((uint8_t*)metadata + (MetadataPayload*)((uint8_t*)metadata +
kTIFFMetadataMap[i].storage_offset); kTIFFMetadataMap[i].storage_offset);
void* tag_data; void* tag_data;
uint32_t tag_data_len; uint32 tag_data_len;
if (TIFFGetField(tif, kTIFFMetadataMap[i].tag, &tag_data_len, &tag_data) && if (TIFFGetField(tif, kTIFFMetadataMap[i].tag, &tag_data_len, &tag_data) &&
!MetadataCopy((const char*)tag_data, tag_data_len, payload)) { !MetadataCopy((const char*)tag_data, tag_data_len, payload)) {
@ -158,7 +157,6 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
MyData my_data = { data, (toff_t)data_size, 0 }; MyData my_data = { data, (toff_t)data_size, 0 };
TIFF* tif; TIFF* tif;
uint32_t image_width, image_height, tile_width, tile_height; uint32_t image_width, image_height, tile_width, tile_height;
uint64_t stride;
uint16_t samples_per_px = 0; uint16_t samples_per_px = 0;
uint16_t extra_samples = 0; uint16_t extra_samples = 0;
uint16_t* extra_samples_ptr = NULL; uint16_t* extra_samples_ptr = NULL;
@ -189,40 +187,27 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
fprintf(stderr, "Error! Cannot retrieve TIFF samples-per-pixel info.\n"); fprintf(stderr, "Error! Cannot retrieve TIFF samples-per-pixel info.\n");
goto End; goto End;
} }
if (!(samples_per_px == 1 || samples_per_px == 3 || samples_per_px == 4)) { if (samples_per_px < 3 || samples_per_px > 4) goto End; // not supported
goto End; // not supported
}
if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &image_width) && if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &image_width) &&
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &image_height))) { TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &image_height))) {
fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n"); fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n");
goto End; goto End;
} }
stride = (uint64_t)image_width * sizeof(*raster); if (!ImgIoUtilCheckSizeArgumentsOverflow((uint64_t)image_width * image_height,
if (!ImgIoUtilCheckSizeArgumentsOverflow(stride, image_height)) { sizeof(*raster))) {
fprintf(stderr, "Error! TIFF image dimension (%d x %d) is too large.\n",
image_width, image_height);
goto End; goto End;
} }
// According to spec, a tile can be bigger than the image. However it should // According to spec, a tile can be bigger than the image. However it should
// be a multiple of 16 and not way too large, so check that it's not more // be a multiple of 16 and not way too large, so check that it's not more than
// than twice the image size, for dimensions above some arbitrary minimum // twice the image size, for dimensions above some arbitrary minimum 32.
// 32. We also check that they respect WebP's dimension and memory limit. if ((TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width) &&
// Note that a tile can be 6byte/px in some cases. Here we assume tile_width > 32 && tile_width / 2 > image_width) ||
// 4byte/px with sizeof(*raster), to be conservative. (TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height) &&
if (TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width) && tile_height > 32 && tile_height / 2 > image_height)) {
TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height)) { fprintf(stderr, "Error! TIFF tile dimensions are too big.\n");
if ((tile_width > 32 && tile_width / 2 > image_width) || goto End;
(tile_height > 32 && tile_height / 2 > image_height) ||
!ImgIoUtilCheckSizeArgumentsOverflow(
(uint64_t)tile_width * sizeof(*raster), tile_height)) {
fprintf(stderr, "Error! TIFF tile dimension (%d x %d) is too large.\n",
tile_width, tile_height);
goto End;
}
} }
if (samples_per_px > 3 && !TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, if (samples_per_px > 3 && !TIFFGetField(tif, TIFFTAG_EXTRASAMPLES,
&extra_samples, &extra_samples_ptr)) { &extra_samples, &extra_samples_ptr)) {
fprintf(stderr, "Error! Cannot retrieve TIFF ExtraSamples info.\n"); fprintf(stderr, "Error! Cannot retrieve TIFF ExtraSamples info.\n");
@ -230,13 +215,15 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
} }
// _Tiffmalloc uses a signed type for size. // _Tiffmalloc uses a signed type for size.
alloc_size = (int64_t)(stride * image_height); alloc_size =
(int64_t)((uint64_t)image_width * image_height * sizeof(*raster));
if (alloc_size < 0 || alloc_size != (tsize_t)alloc_size) goto End; if (alloc_size < 0 || alloc_size != (tsize_t)alloc_size) goto End;
raster = (uint32_t*)_TIFFmalloc((tsize_t)alloc_size); raster = (uint32*)_TIFFmalloc((tsize_t)alloc_size);
if (raster != NULL) { if (raster != NULL) {
if (TIFFReadRGBAImageOriented(tif, image_width, image_height, raster, if (TIFFReadRGBAImageOriented(tif, image_width, image_height, raster,
ORIENTATION_TOPLEFT, 1)) { ORIENTATION_TOPLEFT, 1)) {
const int stride = image_width * sizeof(*raster);
pic->width = image_width; pic->width = image_width;
pic->height = image_height; pic->height = image_height;
// TIFF data is ABGR // TIFF data is ABGR
@ -254,8 +241,8 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
} }
} }
ok = keep_alpha ok = keep_alpha
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, (int)stride) ? WebPPictureImportRGBA(pic, (const uint8_t*)raster, stride)
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, (int)stride); : WebPPictureImportRGBX(pic, (const uint8_t*)raster, stride);
} }
_TIFFfree(raster); _TIFFfree(raster);
} else { } else {

View File

@ -12,8 +12,6 @@
#ifndef WEBP_IMAGEIO_TIFFDEC_H_ #ifndef WEBP_IMAGEIO_TIFFDEC_H_
#define WEBP_IMAGEIO_TIFFDEC_H_ #define WEBP_IMAGEIO_TIFFDEC_H_
#include <stddef.h>
#include "webp/types.h" #include "webp/types.h"
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -13,19 +13,18 @@
#include "webp/config.h" #include "webp/config.h"
#endif #endif
#include "./webpdec.h"
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "../examples/unicode.h"
#include "./imageio_util.h"
#include "./metadata.h"
#include "./webpdec.h"
#include "webp/decode.h" #include "webp/decode.h"
#include "webp/demux.h" #include "webp/demux.h"
#include "webp/encode.h" #include "webp/encode.h"
#include "webp/mux_types.h" #include "../examples/unicode.h"
#include "webp/types.h" #include "./imageio_util.h"
#include "./metadata.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// WebP decoding // WebP decoding
@ -66,7 +65,7 @@ int LoadWebP(const char* const in_file,
status = WebPGetFeatures(*data, *data_size, bitstream); status = WebPGetFeatures(*data, *data_size, bitstream);
if (status != VP8_STATUS_OK) { if (status != VP8_STATUS_OK) {
WebPFree((void*)*data); free((void*)*data);
*data = NULL; *data = NULL;
*data_size = 0; *data_size = 0;
PrintWebPError(in_file, status); PrintWebPError(in_file, status);
@ -96,7 +95,7 @@ VP8StatusCode DecodeWebPIncremental(
{ {
WebPIDecoder* const idec = WebPIDecode(data, data_size, config); WebPIDecoder* const idec = WebPIDecode(data, data_size, config);
if (idec == NULL) { if (idec == NULL) {
fprintf(stderr, "Failed during WebPIDecode().\n"); fprintf(stderr, "Failed during WebPINewDecoder().\n");
return VP8_STATUS_OUT_OF_MEMORY; return VP8_STATUS_OUT_OF_MEMORY;
} else { } else {
status = WebPIUpdate(idec, data, data_size); status = WebPIUpdate(idec, data, data_size);

View File

@ -12,10 +12,7 @@
#ifndef WEBP_IMAGEIO_WEBPDEC_H_ #ifndef WEBP_IMAGEIO_WEBPDEC_H_
#define WEBP_IMAGEIO_WEBPDEC_H_ #define WEBP_IMAGEIO_WEBPDEC_H_
#include <stddef.h>
#include "webp/decode.h" #include "webp/decode.h"
#include "webp/types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -134,10 +134,7 @@ static HRESULT ExtractICCP(IWICImagingFactory* const factory,
IWICColorContext** color_contexts; IWICColorContext** color_contexts;
IFS(IWICBitmapFrameDecode_GetColorContexts(frame, 0, NULL, &count)); IFS(IWICBitmapFrameDecode_GetColorContexts(frame, 0, NULL, &count));
if (FAILED(hr) || count == 0) { if (FAILED(hr) || count == 0) return hr;
// Treat unsupported operation as a non-fatal error. See crbug.com/webp/506.
return (hr == WINCODEC_ERR_UNSUPPORTEDOPERATION) ? S_OK : hr;
}
color_contexts = (IWICColorContext**)calloc(count, sizeof(*color_contexts)); color_contexts = (IWICColorContext**)calloc(count, sizeof(*color_contexts));
if (color_contexts == NULL) return E_OUTOFMEMORY; if (color_contexts == NULL) return E_OUTOFMEMORY;
@ -273,15 +270,10 @@ int ReadPictureWithWIC(const char* const filename,
WICPixelFormatGUID src_pixel_format = GUID_WICPixelFormatUndefined; WICPixelFormatGUID src_pixel_format = GUID_WICPixelFormatUndefined;
const WICFormatImporter* importer = NULL; const WICFormatImporter* importer = NULL;
GUID src_container_format = GUID_NULL_; GUID src_container_format = GUID_NULL_;
// From Windows Kits\10\Include\10.0.19041.0\um\wincodec.h
WEBP_DEFINE_GUID(GUID_ContainerFormatWebp_,
0xe094b0e2, 0x67f2, 0x45b3,
0xb0, 0xea, 0x11, 0x53, 0x37, 0xca, 0x7c, 0xf3);
static const GUID* kAlphaContainers[] = { static const GUID* kAlphaContainers[] = {
&GUID_ContainerFormatBmp, &GUID_ContainerFormatBmp,
&GUID_ContainerFormatPng, &GUID_ContainerFormatPng,
&GUID_ContainerFormatTiff, &GUID_ContainerFormatTiff,
&GUID_ContainerFormatWebp_,
NULL NULL
}; };
int has_alpha = 0; int has_alpha = 0;
@ -306,15 +298,9 @@ int ReadPictureWithWIC(const char* const filename,
factory, stream, NULL, factory, stream, NULL,
WICDecodeMetadataCacheOnDemand, &decoder)); WICDecodeMetadataCacheOnDemand, &decoder));
IFS(IWICBitmapDecoder_GetFrameCount(decoder, &frame_count)); IFS(IWICBitmapDecoder_GetFrameCount(decoder, &frame_count));
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr) && frame_count == 0) {
if (frame_count == 0) { fprintf(stderr, "No frame found in input file.\n");
fprintf(stderr, "No frame found in input file.\n"); hr = E_FAIL;
hr = E_FAIL;
} else if (frame_count > 1) {
// WIC will be tried before native WebP decoding so avoid duplicating the
// error message.
hr = E_FAIL;
}
} }
IFS(IWICBitmapDecoder_GetFrame(decoder, 0, &frame)); IFS(IWICBitmapDecoder_GetFrame(decoder, 0, &frame));
IFS(IWICBitmapFrameDecode_GetPixelFormat(frame, &src_pixel_format)); IFS(IWICBitmapFrameDecode_GetPixelFormat(frame, &src_pixel_format));

View File

@ -1,106 +0,0 @@
# 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}" ]]
}

View File

@ -1,401 +0,0 @@
#!/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

View File

@ -1,224 +0,0 @@
#!/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

View File

@ -1,75 +0,0 @@
#!/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

View File

@ -1,98 +0,0 @@
#!/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

@ -1,21 +1,17 @@
#!/bin/bash #!/bin/bash
# #
# This script generates 'WebP.framework' and 'WebPDecoder.framework', # This script generates 'WebP.framework' and 'WebPDecoder.framework'. An iOS
# 'WebPDemux.framework' and 'WebPMux.framework'. # app can decode WebP images by including 'WebPDecoder.framework' and both
# An iOS app can decode WebP images by including 'WebPDecoder.framework' and # encode and decode WebP images by including 'WebP.framework'.
# both encode and decode WebP images by including 'WebP.framework'.
# #
# Run ./iosbuild.sh to generate the frameworks under the current directory # Run ./iosbuild.sh to generate the frameworks under the current directory
# (the previous build will be erased if it exists). # (the previous build will be erased if it exists).
# #
# This script is inspired by the build script written by Carson McDonald. # This script is inspired by the build script written by Carson McDonald.
# (https://www.ioncannon.net/programming/1483/using-webp-to-reduce-native-ios-app-size/). # (http://www.ioncannon.net/programming/1483/using-webp-to-reduce-native-ios-app-size/).
set -e set -e
# Set this variable based on the desired minimum deployment target.
readonly IOS_MIN_VERSION=6.0
# Extract the latest SDK version from the final field of the form: iphoneosX.Y # Extract the latest SDK version from the final field of the form: iphoneosX.Y
readonly SDK=$(xcodebuild -showsdks \ readonly SDK=$(xcodebuild -showsdks \
| grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}' | grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}'
@ -41,7 +37,6 @@ readonly TARGETDIR="${TOPDIR}/WebP.framework"
readonly DECTARGETDIR="${TOPDIR}/WebPDecoder.framework" readonly DECTARGETDIR="${TOPDIR}/WebPDecoder.framework"
readonly MUXTARGETDIR="${TOPDIR}/WebPMux.framework" readonly MUXTARGETDIR="${TOPDIR}/WebPMux.framework"
readonly DEMUXTARGETDIR="${TOPDIR}/WebPDemux.framework" readonly DEMUXTARGETDIR="${TOPDIR}/WebPDemux.framework"
readonly SHARPYUVTARGETDIR="${TOPDIR}/SharpYuv.framework"
readonly DEVELOPER=$(xcode-select --print-path) readonly DEVELOPER=$(xcode-select --print-path)
readonly PLATFORMSROOT="${DEVELOPER}/Platforms" readonly PLATFORMSROOT="${DEVELOPER}/Platforms"
readonly LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo) readonly LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
@ -53,45 +48,28 @@ DEMUXLIBLIST=''
if [[ -z "${SDK}" ]]; then if [[ -z "${SDK}" ]]; then
echo "iOS SDK not available" echo "iOS SDK not available"
exit 1 exit 1
elif [[ ${SDK%%.*} -gt 8 && "${XCODE%%.*}" -lt 16 ]]; then elif [[ ${SDK%%.*} -gt 8 ]]; then
EXTRA_CFLAGS="-fembed-bitcode" EXTRA_CFLAGS="-fembed-bitcode"
elif [[ ${SDK%%.*} -le 6 ]]; then elif [[ ${SDK} < 6.0 ]]; then
echo "You need iOS SDK version 6.0 or above" echo "You need iOS SDK version 6.0 or above"
exit 1 exit 1
else
echo "iOS SDK Version ${SDK}"
fi fi
echo "Xcode Version: ${XCODE}"
echo "iOS SDK Version: ${SDK}"
if [[ -e "${BUILDDIR}" || -e "${TARGETDIR}" || -e "${DECTARGETDIR}" \
|| -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" \
|| -e "${SHARPYUVTARGETDIR}" ]]; then
cat << EOF
WARNING: The following directories will be deleted:
WARNING: ${BUILDDIR}
WARNING: ${TARGETDIR}
WARNING: ${DECTARGETDIR}
WARNING: ${MUXTARGETDIR}
WARNING: ${DEMUXTARGETDIR}
WARNING: ${SHARPYUVTARGETDIR}
WARNING: The build will continue in 5 seconds...
EOF
sleep 5
fi
rm -rf ${BUILDDIR} ${TARGETDIR} ${DECTARGETDIR} \ rm -rf ${BUILDDIR} ${TARGETDIR} ${DECTARGETDIR} \
${MUXTARGETDIR} ${DEMUXTARGETDIR} ${SHARPYUVTARGETDIR} ${MUXTARGETDIR} ${DEMUXTARGETDIR}
mkdir -p ${BUILDDIR} ${TARGETDIR}/Headers/ ${DECTARGETDIR}/Headers/ \ mkdir -p ${BUILDDIR} ${TARGETDIR}/Headers/ ${DECTARGETDIR}/Headers/ \
${MUXTARGETDIR}/Headers/ ${DEMUXTARGETDIR}/Headers/ \ ${MUXTARGETDIR}/Headers/ ${DEMUXTARGETDIR}/Headers/
${SHARPYUVTARGETDIR}/Headers/
if [[ ! -e ${SRCDIR}/configure ]]; then if [[ ! -e ${SRCDIR}/configure ]]; then
if ! (cd ${SRCDIR} && sh autogen.sh); then if ! (cd ${SRCDIR} && sh autogen.sh); then
cat << EOF cat <<EOT
Error creating configure script! Error creating configure script!
This script requires the autoconf/automake and libtool to build. MacPorts can This script requires the autoconf/automake and libtool to build. MacPorts can
be used to obtain these: be used to obtain these:
https://www.macports.org/install.php http://www.macports.org/install.php
EOF EOT
exit 1 exit 1
fi fi
fi fi
@ -125,7 +103,7 @@ for PLATFORM in ${PLATFORMS}; do
SDKROOT="${PLATFORMSROOT}/" SDKROOT="${PLATFORMSROOT}/"
SDKROOT+="${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/" SDKROOT+="${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/"
CFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT} -O3 -DNDEBUG" CFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT} -O3 -DNDEBUG"
CFLAGS+=" -miphoneos-version-min=${IOS_MIN_VERSION} ${EXTRA_CFLAGS}" CFLAGS+=" -miphoneos-version-min=6.0 ${EXTRA_CFLAGS}"
set -x set -x
export PATH="${DEVROOT}/usr/bin:${OLDPATH}" export PATH="${DEVROOT}/usr/bin:${OLDPATH}"
@ -137,17 +115,18 @@ for PLATFORM in ${PLATFORMS}; do
CFLAGS="${CFLAGS}" CFLAGS="${CFLAGS}"
set +x set +x
# Build only the libraries, skip the examples. # run make only in the src/ directory to create libwebp.a/libwebpdecoder.a
make V=0 -C sharpyuv install cd src/
make V=0 -C src install make V=0
make install
LIBLIST+=" ${ROOTDIR}/lib/libwebp.a" LIBLIST+=" ${ROOTDIR}/lib/libwebp.a"
DECLIBLIST+=" ${ROOTDIR}/lib/libwebpdecoder.a" DECLIBLIST+=" ${ROOTDIR}/lib/libwebpdecoder.a"
MUXLIBLIST+=" ${ROOTDIR}/lib/libwebpmux.a" MUXLIBLIST+=" ${ROOTDIR}/lib/libwebpmux.a"
DEMUXLIBLIST+=" ${ROOTDIR}/lib/libwebpdemux.a" DEMUXLIBLIST+=" ${ROOTDIR}/lib/libwebpdemux.a"
SHARPYUVLIBLIST+=" ${ROOTDIR}/lib/libsharpyuv.a"
make clean make clean
cd ..
export PATH=${OLDPATH} export PATH=${OLDPATH}
done done
@ -169,10 +148,3 @@ echo "DEMUXLIBLIST = ${DEMUXLIBLIST}"
cp -a ${SRCDIR}/src/webp/{decode,types,mux_types,demux}.h \ cp -a ${SRCDIR}/src/webp/{decode,types,mux_types,demux}.h \
${DEMUXTARGETDIR}/Headers/ ${DEMUXTARGETDIR}/Headers/
${LIPO} -create ${DEMUXLIBLIST} -output ${DEMUXTARGETDIR}/WebPDemux ${LIPO} -create ${DEMUXLIBLIST} -output ${DEMUXTARGETDIR}/WebPDemux
echo "SHARPYUVLIBLIST = ${SHARPYUVLIBLIST}"
cp -a ${SRCDIR}/sharpyuv/{sharpyuv,sharpyuv_csp}.h \
${SHARPYUVTARGETDIR}/Headers/
${LIPO} -create ${SHARPYUVLIBLIST} -output ${SHARPYUVTARGETDIR}/SharpYuv
echo "SUCCESS"

View File

@ -3,8 +3,7 @@
# It will not install the libraries system-wide, but just create the 'cwebp' # It will not install the libraries system-wide, but just create the 'cwebp'
# and 'dwebp' tools in the examples/ directory, along with the static # and 'dwebp' tools in the examples/ directory, along with the static
# libraries 'src/libwebp.a', 'src/libwebpdecoder.a', 'src/mux/libwebpmux.a', # libraries 'src/libwebp.a', 'src/libwebpdecoder.a', 'src/mux/libwebpmux.a',
# 'src/demux/libwebpdemux.a', 'extras/libwebpextras.a' and # 'src/demux/libwebpdemux.a' and 'extras/libwebpextras.a'.
# 'sharpyuv/libsharpyuv.a'.
# #
# To build the library and examples, use: # To build the library and examples, use:
# make -f makefile.unix # make -f makefile.unix
@ -37,18 +36,18 @@ else
endif endif
# SDL flags: use sdl-config if it exists # SDL flags: use sdl-config if it exists
SDL_CONFIG = $(shell sdl2-config --version 2> /dev/null) SDL_CONFIG = $(shell sdl-config --version 2> /dev/null)
ifneq ($(SDL_CONFIG),) ifneq ($(SDL_CONFIG),)
SDL_LIBS = $(shell sdl2-config --libs) SDL_LIBS = $(shell sdl-config --libs)
SDL_FLAGS = $(shell sdl2-config --cflags) SDL_FLAGS = $(shell sdl-config --cflags)
else else
# use best-guess # use best-guess
SDL_LIBS = -lSDL2 SDL_LIBS = -lSDL
SDL_FLAGS = SDL_FLAGS =
endif endif
# To install libraries on Mac OS X: # To install libraries on Mac OS X:
# 1. Install MacPorts (https://www.macports.org/install.php) # 1. Install MacPorts (http://www.macports.org/install.php)
# 2. Run "sudo port install jpeg" # 2. Run "sudo port install jpeg"
# 3. Run "sudo port install libpng" # 3. Run "sudo port install libpng"
# 4. Run "sudo port install tiff" # 4. Run "sudo port install tiff"
@ -126,15 +125,6 @@ endif
ANIM_UTIL_OBJS = \ ANIM_UTIL_OBJS = \
examples/anim_util.o \ examples/anim_util.o \
SHARPYUV_OBJS = \
sharpyuv/sharpyuv.o \
sharpyuv/sharpyuv_cpu.o \
sharpyuv/sharpyuv_csp.o \
sharpyuv/sharpyuv_dsp.o \
sharpyuv/sharpyuv_gamma.o \
sharpyuv/sharpyuv_neon.o \
sharpyuv/sharpyuv_sse2.o \
DEC_OBJS = \ DEC_OBJS = \
src/dec/alpha_dec.o \ src/dec/alpha_dec.o \
src/dec/buffer_dec.o \ src/dec/buffer_dec.o \
@ -176,7 +166,6 @@ DSP_DEC_OBJS = \
src/dsp/lossless_msa.o \ src/dsp/lossless_msa.o \
src/dsp/lossless_neon.o \ src/dsp/lossless_neon.o \
src/dsp/lossless_sse2.o \ src/dsp/lossless_sse2.o \
src/dsp/lossless_sse41.o \
src/dsp/rescaler.o \ src/dsp/rescaler.o \
src/dsp/rescaler_mips32.o \ src/dsp/rescaler_mips32.o \
src/dsp/rescaler_mips_dsp_r2.o \ src/dsp/rescaler_mips_dsp_r2.o \
@ -276,7 +265,6 @@ UTILS_DEC_OBJS = \
src/utils/color_cache_utils.o \ src/utils/color_cache_utils.o \
src/utils/filters_utils.o \ src/utils/filters_utils.o \
src/utils/huffman_utils.o \ src/utils/huffman_utils.o \
src/utils/palette.o \
src/utils/quant_levels_dec_utils.o \ src/utils/quant_levels_dec_utils.o \
src/utils/random_utils.o \ src/utils/random_utils.o \
src/utils/rescaler_utils.o \ src/utils/rescaler_utils.o \
@ -291,15 +279,13 @@ UTILS_ENC_OBJS = \
EXTRA_OBJS = \ EXTRA_OBJS = \
extras/extras.o \ extras/extras.o \
extras/quality_estimate.o \ extras/quality_estimate.o \
extras/sharpyuv_risk_table.o \
LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS) LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) \ LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
$(DSP_ENC_OBJS) $(UTILS_ENC_OBJS) $(UTILS_ENC_OBJS)
LIBWEBPMUX_OBJS = $(MUX_OBJS) LIBWEBPMUX_OBJS = $(MUX_OBJS)
LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS) LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS)
LIBWEBPEXTRA_OBJS = $(EXTRA_OBJS) LIBWEBPEXTRA_OBJS = $(EXTRA_OBJS)
LIBSHARPYUV_OBJS = $(SHARPYUV_OBJS)
HDRS_INSTALLED = \ HDRS_INSTALLED = \
src/webp/decode.h \ src/webp/decode.h \
@ -309,11 +295,6 @@ HDRS_INSTALLED = \
src/webp/mux_types.h \ src/webp/mux_types.h \
src/webp/types.h \ src/webp/types.h \
SHARPYUV_HDRS_INSTALLED = \
sharpyuv/sharpyuv.h \
sharpyuv/sharpyuv_cpu.h \
sharpyuv/sharpyuv_csp.h \
HDRS = \ HDRS = \
src/dec/alphai_dec.h \ src/dec/alphai_dec.h \
src/dec/common_dec.h \ src/dec/common_dec.h \
@ -322,7 +303,6 @@ HDRS = \
src/dec/vp8li_dec.h \ src/dec/vp8li_dec.h \
src/dec/webpi_dec.h \ src/dec/webpi_dec.h \
src/dsp/common_sse2.h \ src/dsp/common_sse2.h \
src/dsp/cpu.h \
src/dsp/dsp.h \ src/dsp/dsp.h \
src/dsp/lossless.h \ src/dsp/lossless.h \
src/dsp/lossless_common.h \ src/dsp/lossless_common.h \
@ -345,7 +325,6 @@ HDRS = \
src/utils/filters_utils.h \ src/utils/filters_utils.h \
src/utils/huffman_utils.h \ src/utils/huffman_utils.h \
src/utils/huffman_encode_utils.h \ src/utils/huffman_encode_utils.h \
src/utils/palette.h \
src/utils/quant_levels_utils.h \ src/utils/quant_levels_utils.h \
src/utils/quant_levels_dec_utils.h \ src/utils/quant_levels_dec_utils.h \
src/utils/random_utils.h \ src/utils/random_utils.h \
@ -354,7 +333,6 @@ HDRS = \
src/utils/utils.h \ src/utils/utils.h \
src/webp/format_constants.h \ src/webp/format_constants.h \
$(HDRS_INSTALLED) \ $(HDRS_INSTALLED) \
$(SHARPYUV_HDRS_INSTALLED) \
OUT_LIBS = examples/libexample_util.a OUT_LIBS = examples/libexample_util.a
OUT_LIBS += imageio/libimageio_util.a OUT_LIBS += imageio/libimageio_util.a
@ -362,7 +340,6 @@ OUT_LIBS += imageio/libimagedec.a
OUT_LIBS += imageio/libimageenc.a OUT_LIBS += imageio/libimageenc.a
OUT_LIBS += src/libwebpdecoder.a OUT_LIBS += src/libwebpdecoder.a
OUT_LIBS += src/libwebp.a OUT_LIBS += src/libwebp.a
OUT_LIBS += sharpyuv/libsharpyuv.a
EXTRA_LIB = extras/libwebpextras.a EXTRA_LIB = extras/libwebpextras.a
OUT_EXAMPLES = examples/cwebp examples/dwebp OUT_EXAMPLES = examples/cwebp examples/dwebp
EXTRA_EXAMPLES = examples/gif2webp examples/vwebp examples/webpmux \ EXTRA_EXAMPLES = examples/gif2webp examples/vwebp examples/webpmux \
@ -408,7 +385,6 @@ src/libwebpdecoder.a: $(LIBWEBPDECODER_OBJS)
src/libwebp.a: $(LIBWEBP_OBJS) src/libwebp.a: $(LIBWEBP_OBJS)
src/mux/libwebpmux.a: $(LIBWEBPMUX_OBJS) src/mux/libwebpmux.a: $(LIBWEBPMUX_OBJS)
src/demux/libwebpdemux.a: $(LIBWEBPDEMUX_OBJS) src/demux/libwebpdemux.a: $(LIBWEBPDEMUX_OBJS)
sharpyuv/libsharpyuv.a: $(LIBSHARPYUV_OBJS)
%.a: %.a:
$(AR) $(ARFLAGS) $@ $^ $(AR) $(ARFLAGS) $@ $^
@ -426,7 +402,6 @@ examples/webpinfo: examples/webpinfo.o
examples/anim_diff: examples/libanim_util.a examples/libgifdec.a examples/anim_diff: examples/libanim_util.a examples/libgifdec.a
examples/anim_diff: src/demux/libwebpdemux.a examples/libexample_util.a examples/anim_diff: src/demux/libwebpdemux.a examples/libexample_util.a
examples/anim_diff: imageio/libimageio_util.a src/libwebp.a examples/anim_diff: imageio/libimageio_util.a src/libwebp.a
examples/anim_diff: sharpyuv/libsharpyuv.a
examples/anim_diff: override EXTRA_LIBS += $(GIF_LIBS) examples/anim_diff: override EXTRA_LIBS += $(GIF_LIBS)
examples/anim_diff: EXTRA_FLAGS += -DWEBP_HAVE_GIF examples/anim_diff: EXTRA_FLAGS += -DWEBP_HAVE_GIF
examples/anim_dump: examples/libanim_util.a examples/libgifdec.a examples/anim_dump: examples/libanim_util.a examples/libgifdec.a
@ -435,14 +410,12 @@ examples/anim_dump: examples/libexample_util.a
examples/anim_dump: imageio/libimageio_util.a examples/anim_dump: imageio/libimageio_util.a
examples/anim_dump: imageio/libimageenc.a examples/anim_dump: imageio/libimageenc.a
examples/anim_dump: src/libwebp.a examples/anim_dump: src/libwebp.a
examples/anim_dump: sharpyuv/libsharpyuv.a
examples/anim_dump: override EXTRA_LIBS += $(GIF_LIBS) $(DWEBP_LIBS) examples/anim_dump: override EXTRA_LIBS += $(GIF_LIBS) $(DWEBP_LIBS)
examples/cwebp: examples/libexample_util.a examples/cwebp: examples/libexample_util.a
examples/cwebp: imageio/libimagedec.a examples/cwebp: imageio/libimagedec.a
examples/cwebp: src/demux/libwebpdemux.a examples/cwebp: src/demux/libwebpdemux.a
examples/cwebp: imageio/libimageio_util.a examples/cwebp: imageio/libimageio_util.a
examples/cwebp: src/libwebp.a examples/cwebp: src/libwebp.a
examples/cwebp: sharpyuv/libsharpyuv.a
examples/cwebp: override EXTRA_LIBS += $(CWEBP_LIBS) examples/cwebp: override EXTRA_LIBS += $(CWEBP_LIBS)
examples/dwebp: examples/libexample_util.a examples/dwebp: examples/libexample_util.a
examples/dwebp: imageio/libimagedec.a examples/dwebp: imageio/libimagedec.a
@ -450,16 +423,13 @@ examples/dwebp: src/demux/libwebpdemux.a
examples/dwebp: imageio/libimageenc.a examples/dwebp: imageio/libimageenc.a
examples/dwebp: imageio/libimageio_util.a examples/dwebp: imageio/libimageio_util.a
examples/dwebp: src/libwebp.a examples/dwebp: src/libwebp.a
examples/dwebp: sharpyuv/libsharpyuv.a
examples/dwebp: override EXTRA_LIBS += $(DWEBP_LIBS) examples/dwebp: override EXTRA_LIBS += $(DWEBP_LIBS)
examples/gif2webp: examples/libexample_util.a imageio/libimageio_util.a examples/gif2webp: examples/libexample_util.a imageio/libimageio_util.a
examples/gif2webp: examples/libgifdec.a src/mux/libwebpmux.a src/libwebp.a examples/gif2webp: examples/libgifdec.a src/mux/libwebpmux.a src/libwebp.a
examples/gif2webp: sharpyuv/libsharpyuv.a
examples/gif2webp: override EXTRA_LIBS += $(GIF_LIBS) examples/gif2webp: override EXTRA_LIBS += $(GIF_LIBS)
examples/gif2webp: EXTRA_FLAGS += -DWEBP_HAVE_GIF examples/gif2webp: EXTRA_FLAGS += -DWEBP_HAVE_GIF
examples/vwebp: examples/libexample_util.a src/demux/libwebpdemux.a examples/vwebp: examples/libexample_util.a src/demux/libwebpdemux.a
examples/vwebp: imageio/libimageio_util.a src/libwebp.a examples/vwebp: imageio/libimageio_util.a src/libwebp.a
examples/vwebp: sharpyuv/libsharpyuv.a
examples/vwebp: override EXTRA_LIBS += $(GL_LIBS) examples/vwebp: override EXTRA_LIBS += $(GL_LIBS)
examples/vwebp: EXTRA_FLAGS += -DWEBP_HAVE_GL examples/vwebp: EXTRA_FLAGS += -DWEBP_HAVE_GL
examples/webpmux: examples/libexample_util.a imageio/libimageio_util.a examples/webpmux: examples/libexample_util.a imageio/libimageio_util.a
@ -467,9 +437,7 @@ examples/webpmux: src/mux/libwebpmux.a src/libwebpdecoder.a
examples/img2webp: examples/libexample_util.a imageio/libimageio_util.a examples/img2webp: examples/libexample_util.a imageio/libimageio_util.a
examples/img2webp: imageio/libimagedec.a examples/img2webp: imageio/libimagedec.a
examples/img2webp: src/demux/libwebpdemux.a examples/img2webp: src/demux/libwebpdemux.a
examples/img2webp: src/mux/libwebpmux.a examples/img2webp: src/mux/libwebpmux.a src/libwebp.a
examples/img2webp: src/libwebp.a
examples/img2webp: sharpyuv/libsharpyuv.a
examples/img2webp: override EXTRA_LIBS += $(CWEBP_LIBS) examples/img2webp: override EXTRA_LIBS += $(CWEBP_LIBS)
examples/webpinfo: examples/libexample_util.a imageio/libimageio_util.a examples/webpinfo: examples/libexample_util.a imageio/libimageio_util.a
examples/webpinfo: src/libwebpdecoder.a examples/webpinfo: src/libwebpdecoder.a
@ -479,19 +447,16 @@ extras/get_disto: imageio/libimagedec.a
extras/get_disto: src/demux/libwebpdemux.a extras/get_disto: src/demux/libwebpdemux.a
extras/get_disto: imageio/libimageio_util.a extras/get_disto: imageio/libimageio_util.a
extras/get_disto: src/libwebp.a extras/get_disto: src/libwebp.a
extras/get_disto: sharpyuv/libsharpyuv.a
extras/get_disto: override EXTRA_LIBS += $(CWEBP_LIBS) extras/get_disto: override EXTRA_LIBS += $(CWEBP_LIBS)
extras/webp_quality: extras/webp_quality.o extras/webp_quality: extras/webp_quality.o
extras/webp_quality: imageio/libimageio_util.a extras/webp_quality: imageio/libimageio_util.a
extras/webp_quality: $(EXTRA_LIB) src/libwebp.a extras/webp_quality: $(EXTRA_LIB) src/libwebp.a
extras/webp_quality: sharpyuv/libsharpyuv.a
extras/vwebp_sdl: extras/vwebp_sdl.o extras/vwebp_sdl: extras/vwebp_sdl.o
extras/vwebp_sdl: extras/webp_to_sdl.o extras/vwebp_sdl: extras/webp_to_sdl.o
extras/vwebp_sdl: imageio/libimageio_util.a extras/vwebp_sdl: imageio/libimageio_util.a
extras/vwebp_sdl: src/libwebp.a extras/vwebp_sdl: src/libwebp.a
extras/vwebp_sdl: sharpyuv/libsharpyuv.a
extras/vwebp_sdl: EXTRA_FLAGS += -DWEBP_HAVE_SDL $(SDL_FLAGS) extras/vwebp_sdl: EXTRA_FLAGS += -DWEBP_HAVE_SDL $(SDL_FLAGS)
extras/vwebp_sdl: override EXTRA_LIBS += $(SDL_LIBS) extras/vwebp_sdl: override EXTRA_LIBS += $(SDL_LIBS)
@ -502,15 +467,12 @@ dist: DESTDIR := dist
dist: OUT_EXAMPLES += $(EXTRA_EXAMPLES) dist: OUT_EXAMPLES += $(EXTRA_EXAMPLES)
dist: all dist: all
$(INSTALL) -m755 -d $(DESTDIR)/include/webp \ $(INSTALL) -m755 -d $(DESTDIR)/include/webp \
$(DESTDIR)/include/webp/sharpyuv \ $(DESTDIR)/bin $(DESTDIR)/doc $(DESTDIR)/lib
$(DESTDIR)/bin $(DESTDIR)/doc $(DESTDIR)/lib
$(INSTALL) -m755 -s $(OUT_EXAMPLES) $(DESTDIR)/bin $(INSTALL) -m755 -s $(OUT_EXAMPLES) $(DESTDIR)/bin
$(INSTALL) -m644 $(HDRS_INSTALLED) $(DESTDIR)/include/webp $(INSTALL) -m644 $(HDRS_INSTALLED) $(DESTDIR)/include/webp
$(INSTALL) -m644 $(SHARPYUV_HDRS_INSTALLED) $(DESTDIR)/include/webp/sharpyuv
$(INSTALL) -m644 src/libwebp.a $(DESTDIR)/lib $(INSTALL) -m644 src/libwebp.a $(DESTDIR)/lib
$(INSTALL) -m644 src/demux/libwebpdemux.a $(DESTDIR)/lib $(INSTALL) -m644 src/demux/libwebpdemux.a $(DESTDIR)/lib
$(INSTALL) -m644 src/mux/libwebpmux.a $(DESTDIR)/lib $(INSTALL) -m644 src/mux/libwebpmux.a $(DESTDIR)/lib
$(INSTALL) -m644 sharpyuv/libsharpyuv.a $(DESTDIR)/lib
umask 022; \ umask 022; \
for m in man/[cdv]webp.1 man/gif2webp.1 man/webpmux.1 \ for m in man/[cdv]webp.1 man/gif2webp.1 man/webpmux.1 \
man/img2webp.1 man/webpinfo.1; do \ man/img2webp.1 man/webpinfo.1; do \
@ -526,7 +488,6 @@ clean:
examples/*.o examples/*~ \ examples/*.o examples/*~ \
extras/*.o extras/*~ \ extras/*.o extras/*~ \
imageio/*.o imageio/*~ \ imageio/*.o imageio/*~ \
sharpyuv/*.o sharpyuv/*~ \
src/dec/*.o src/dec/*~ \ src/dec/*.o src/dec/*~ \
src/demux/*.o src/demux/*~ \ src/demux/*.o src/demux/*~ \
src/dsp/*.o src/dsp/*~ \ src/dsp/*.o src/dsp/*~ \

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH CWEBP 1 "April 10, 2025" .TH CWEBP 1 "January 11, 2019"
.SH NAME .SH NAME
cwebp \- compress an image file to a WebP file cwebp \- compress an image file to a WebP file
.SH SYNOPSIS .SH SYNOPSIS
@ -13,7 +13,6 @@ command.
.PP .PP
\fBcwebp\fP compresses an image using the WebP format. \fBcwebp\fP compresses an image using the WebP format.
Input format can be either PNG, JPEG, TIFF, WebP or raw Y'CbCr samples. Input format can be either PNG, JPEG, TIFF, WebP or raw Y'CbCr samples.
Note: Animated PNG and WebP files are not supported.
.SH OPTIONS .SH OPTIONS
The basic options are: The basic options are:
.TP .TP
@ -90,25 +89,15 @@ additional encoding possibilities and decide on the quality gain.
Lower value can result in faster processing time at the expense of Lower value can result in faster processing time at the expense of
larger file size and lower compression quality. larger file size and lower compression quality.
.TP .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 .BI \-crop " x_position y_position width height
Crop the source to a rectangle with top\-left corner at coordinates 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. (\fBx_position\fP, \fBy_position\fP) and size \fBwidth\fP x \fBheight\fP.
This cropping area must be fully contained within the source rectangle. 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
.BI \-resize_mode " string
Specify the behavior of the \fB\-resize\fP option. Possible values are:
\fBdown_only\fP, \fBup_only\fP, \fBalways\fP (default). \fBdown_only\fP will
use the values specified by \fB\-resize\fP if \fIeither\fP the input width or
height are larger than the given dimensions. Similarly, \fBup_only\fP will only
resize if \fIeither\fP the input width or height are smaller than the given
dimensions.
.TP .TP
.B \-mt .B \-mt
Use multi\-threading for encoding, if possible. Use multi\-threading for encoding, if possible.
@ -143,16 +132,7 @@ are used, \fB\-size\fP value will prevail.
Set a maximum number of passes to use during the dichotomy used by Set a maximum number of passes to use during the dichotomy used by
options \fB\-size\fP or \fB\-psnr\fP. Maximum value is 10, default is 1. options \fB\-size\fP or \fB\-psnr\fP. Maximum value is 10, default is 1.
If options \fB\-size\fP or \fB\-psnr\fP were used, but \fB\-pass\fP wasn't If options \fB\-size\fP or \fB\-psnr\fP were used, but \fB\-pass\fP wasn't
specified, a default value of '6' passes will be used. If \fB\-pass\fP is specified, a default value of '6' passes will be used.
specified, but neither \fB-size\fP nor \fB-psnr\fP are, a target PSNR of 40dB
will be used.
.TP
.BI \-qrange " int int
Specifies the permissible interval for the quality factor. This is particularly
useful when using multi-pass (\fB\-size\fP or \fB\-psnr\fP options).
Default is 0 100.
If the quality factor is outside this range, it will be clamped.
If the minimum value must be less or equal to the maximum one.
.TP .TP
.B \-af .B \-af
Turns auto\-filter on. This algorithm will spend additional time optimizing Turns auto\-filter on. This algorithm will spend additional time optimizing
@ -188,8 +168,8 @@ Disable strong filtering (if filtering is being used thanks to the
\fB\-f\fP option) and use simple filtering instead. \fB\-f\fP option) and use simple filtering instead.
.TP .TP
.B \-sharp_yuv .B \-sharp_yuv
Use more accurate and sharper RGB->YUV conversion. Note that this process is Use more accurate and sharper RGB->YUV conversion if needed. Note that this
slower than the default 'fast' RGB->YUV conversion. process is slower than the default 'fast' RGB->YUV conversion.
.TP .TP
.BI \-sns " int .BI \-sns " int
Specify the amplitude of the spatial noise shaping. Spatial noise shaping Specify the amplitude of the spatial noise shaping. Spatial noise shaping
@ -212,8 +192,7 @@ In the VP8 format, the so\-called control partition has a limit of 512k and
is used to store the following information: whether the macroblock is skipped, is used to store the following information: whether the macroblock is skipped,
which segment it belongs to, whether it is coded as intra 4x4 or intra 16x16 which segment it belongs to, whether it is coded as intra 4x4 or intra 16x16
mode, and finally the prediction modes to use for each of the sub\-blocks. mode, and finally the prediction modes to use for each of the sub\-blocks.
For a very large image, 512k only leaves room for a few bits per 16x16 For a very large image, 512k only leaves room to few bits per 16x16 macroblock.
macroblock.
The absolute minimum is 4 bits per macroblock. Skip, segment, and mode The absolute minimum is 4 bits per macroblock. Skip, segment, and mode
information can use up almost all these 4 bits (although the case is unlikely), information can use up almost all these 4 bits (although the case is unlikely),
which is problematic for very large images. The partition_limit factor controls which is problematic for very large images. The partition_limit factor controls
@ -222,8 +201,7 @@ useful in case the 512k limit is reached and the following message is displayed:
\fIError code: 6 (PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k)\fP. \fIError code: 6 (PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k)\fP.
If using \fB\-partition_limit\fP is not enough to meet the 512k constraint, one If using \fB\-partition_limit\fP is not enough to meet the 512k constraint, one
should use less segments in order to save more header bits per macroblock. should use less segments in order to save more header bits per macroblock.
See the \fB\-segments\fP option. Note the \fB-m\fP and \fB-q\fP options also See the \fB\-segments\fP option.
influence the encoder's decisions and ability to hit this limit.
.SS LOGGING OPTIONS .SS LOGGING OPTIONS
These options control the level of output: These options control the level of output:
@ -236,7 +214,7 @@ Compute and report average PSNR (Peak\-Signal\-To\-Noise ratio).
.TP .TP
.B \-print_ssim .B \-print_ssim
Compute and report average SSIM (structural similarity Compute and report average SSIM (structural similarity
metric, see https://en.wikipedia.org/wiki/SSIM for additional details). metric, see http://en.wikipedia.org/wiki/SSIM for additional details).
.TP .TP
.B \-print_lsim .B \-print_lsim
Compute and report local similarity metric (sum of lowest error amongst the Compute and report local similarity metric (sum of lowest error amongst the
@ -307,12 +285,12 @@ Note: each input format may not support all combinations.
.B \-noasm .B \-noasm
Disable all assembly optimizations. Disable all assembly optimizations.
.SH EXIT STATUS .SH BUGS
If there were no problems during execution, \fBcwebp\fP exits with the value of Please report all bugs to the issue tracker:
the C constant \fBEXIT_SUCCESS\fP. This is usually zero. https://bugs.chromium.org/p/webp
.PP .br
If an error occurs, \fBcwebp\fP exits with the value of the C constant Patches welcome! See this page to get started:
\fBEXIT_FAILURE\fP. This is usually one. http://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXAMPLES .SH EXAMPLES
cwebp \-q 50 -lossless picture.png \-o picture_lossless.webp cwebp \-q 50 -lossless picture.png \-o picture_lossless.webp
@ -332,16 +310,9 @@ https://chromium.googlesource.com/webm/libwebp
This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>, This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>,
for the Debian project (and may be used by others). for the Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO .SH SEE ALSO
.BR dwebp (1), .BR dwebp (1),
.BR gif2webp (1) .BR gif2webp (1)
.br .br
Please refer to https://developers.google.com/speed/webp/ for additional Please refer to http://developers.google.com/speed/webp/ for additional
information. information.

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH DWEBP 1 "July 18, 2024" .TH DWEBP 1 "June 23, 2016"
.SH NAME .SH NAME
dwebp \- decompress a WebP file to an image file dwebp \- decompress a WebP file to an image file
.SH SYNOPSIS .SH SYNOPSIS
@ -12,7 +12,6 @@ This manual page documents the
command. command.
.PP .PP
\fBdwebp\fP decompresses WebP files into PNG, PAM, PPM or PGM images. \fBdwebp\fP decompresses WebP files into PNG, PAM, PPM or PGM images.
Note: Animated WebP files are not supported.
.SH OPTIONS .SH OPTIONS
The basic options are: The basic options are:
.TP .TP
@ -108,12 +107,12 @@ Print extra information (decoding time in particular).
.B \-noasm .B \-noasm
Disable all assembly optimizations. Disable all assembly optimizations.
.SH EXIT STATUS .SH BUGS
If there were no problems during execution, \fBdwebp\fP exits with the value of Please report all bugs to the issue tracker:
the C constant \fBEXIT_SUCCESS\fP. This is usually zero. https://bugs.chromium.org/p/webp
.PP .br
If an error occurs, \fBdwebp\fP exits with the value of the C constant Patches welcome! See this page to get started:
\fBEXIT_FAILURE\fP. This is usually one. http://www.webmproject.org/code/contribute/submitting-patches/
.SH EXAMPLES .SH EXAMPLES
dwebp picture.webp \-o output.png dwebp picture.webp \-o output.png
@ -133,19 +132,12 @@ https://chromium.googlesource.com/webm/libwebp
This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>, This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>,
for the Debian project (and may be used by others). for the Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO .SH SEE ALSO
.BR cwebp (1), .BR cwebp (1),
.BR gif2webp (1), .BR gif2webp (1),
.BR webpmux (1) .BR webpmux (1)
.br .br
Please refer to https://developers.google.com/speed/webp/ for additional Please refer to http://developers.google.com/speed/webp/ for additional
information. information.
.SS Output file format details .SS Output file format details
PAM: http://netpbm.sourceforge.net/doc/pam.html PAM: http://netpbm.sourceforge.net/doc/pam.html

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH GIF2WEBP 1 "November 4, 2024" .TH GIF2WEBP 1 "January 25, 2018"
.SH NAME .SH NAME
gif2webp \- Convert a GIF image to WebP gif2webp \- Convert a GIF image to WebP
.SH SYNOPSIS .SH SYNOPSIS
@ -39,18 +39,6 @@ Encode the image using lossy compression.
Mixed compression mode: optimize compression of the image by picking either Mixed compression mode: optimize compression of the image by picking either
lossy or lossless compression for each frame heuristically. lossy or lossless compression for each frame heuristically.
.TP .TP
.BI \-near_lossless " int
Specify the level of near\-lossless image preprocessing. This option adjusts
pixel values to help compressibility, but has minimal impact on the visual
quality. It triggers lossless compression mode automatically. The range is 0
(maximum preprocessing) to 100 (no preprocessing, the default). The typical
value is around 60. Note that lossy with \fB\-q 100\fP can at times yield
better results.
.TP
.B \-sharp_yuv
Use more accurate and sharper RGB->YUV conversion. Note that this process is
slower than the default 'fast' RGB->YUV conversion.
.TP
.BI \-q " float .BI \-q " float
Specify the compression factor for RGB channels between 0 and 100. The default Specify the compression factor for RGB channels between 0 and 100. The default
is 75. is 75.
@ -74,9 +62,9 @@ larger file size and lower compression quality.
.TP .TP
.BI \-min_size .BI \-min_size
Encode image to achieve smallest size. This disables key frame insertion and Encode image to achieve smallest size. This disables key frame insertion and
picks the dispose method resulting in the smallest output for each frame. It picks the dispose method resulting in smallest output for each frame. It uses
uses lossless compression by default, but can be combined with \-q, \-m, lossless compression by default, but can be combined with \-q, \-m, \-lossy or
\-lossy or \-mixed options. \-mixed options.
.TP .TP
.BI \-kmin " int .BI \-kmin " int
.TP .TP
@ -138,12 +126,12 @@ Print extra information.
.B \-quiet .B \-quiet
Do not print anything. Do not print anything.
.SH EXIT STATUS .SH BUGS
If there were no problems during execution, \fBgif2webp\fP exits with the value Please report all bugs to the issue tracker:
of the C constant \fBEXIT_SUCCESS\fP. This is usually zero. https://bugs.chromium.org/p/webp
.PP .br
If an error occurs, \fBgif2webp\fP exits with the value of the C constant Patches welcome! See this page to get started:
\fBEXIT_FAILURE\fP. This is usually one. http://www.webmproject.org/code/contribute/submitting-patches/
.SH EXAMPLES .SH EXAMPLES
gif2webp picture.gif \-o picture.webp gif2webp picture.gif \-o picture.webp
@ -167,17 +155,10 @@ https://chromium.googlesource.com/webm/libwebp
This manual page was written by Urvang Joshi <urvang@google.com>, for the This manual page was written by Urvang Joshi <urvang@google.com>, for the
Debian project (and may be used by others). Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO .SH SEE ALSO
.BR cwebp (1), .BR cwebp (1),
.BR dwebp (1), .BR dwebp (1),
.BR webpmux (1) .BR webpmux (1)
.br .br
Please refer to https://developers.google.com/speed/webp/ for additional Please refer to http://developers.google.com/speed/webp/ for additional
information. information.

View File

@ -1,10 +1,10 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH IMG2WEBP 1 "November 26, 2024" .TH IMG2WEBP 1 "April 3, 2018"
.SH NAME .SH NAME
img2webp \- create animated WebP file from a sequence of input images. img2webp \- create animated WebP file from a sequence of input images.
.SH SYNOPSIS .SH SYNOPSIS
.B img2webp .B img2webp
[file_options] [[frame_options] frame_file]... [\-o webp_file] [file_level_options] [files] [per_frame_options...]
.br .br
.B img2webp argument_file_name .B img2webp argument_file_name
.br .br
@ -16,8 +16,8 @@ command.
\fBimg2webp\fP compresses a sequence of images using the animated WebP format. \fBimg2webp\fP compresses a sequence of images using the animated WebP format.
Input images can either be PNG, JPEG, TIFF or WebP. Input images can either be PNG, JPEG, TIFF or WebP.
If a single file name (not starting with the character '\-') is supplied as If a single file name (not starting with the character '\-') is supplied as
the argument, the command line arguments are actually tokenized from this file. the argument, the command line argument are actually tokenized from this file.
This allows for easy scripting or using a large number of arguments. This allows for easy scripting or using large number of arguments.
.SH FILE-LEVEL OPTIONS .SH FILE-LEVEL OPTIONS
The file-level options are applied at the beginning of the compression process, The file-level options are applied at the beginning of the compression process,
before the input frames are read. before the input frames are read.
@ -27,7 +27,7 @@ Specify the name of the output WebP file.
.TP .TP
.BI \-min_size .BI \-min_size
Encode images to achieve smallest size. This disables key frame insertion and Encode images to achieve smallest size. This disables key frame insertion and
picks the parameters resulting in the smallest output for each frame. It uses picks the parameters resulting in smallest output for each frame. It uses
lossless compression by default, but can be combined with \-q, \-m, \-lossy or lossless compression by default, but can be combined with \-q, \-m, \-lossy or
\-mixed options. \-mixed options.
.TP .TP
@ -44,18 +44,6 @@ Mixed compression mode: optimize compression of the image by picking either
lossy or lossless compression for each frame heuristically. This global lossy or lossless compression for each frame heuristically. This global
option disables the local option \fB-lossy\fP and \fB-lossless\fP . option disables the local option \fB-lossy\fP and \fB-lossless\fP .
.TP .TP
.BI \-near_lossless " int
Specify the level of near\-lossless image preprocessing. This option adjusts
pixel values to help compressibility, but has minimal impact on the visual
quality. It triggers lossless compression mode automatically. The range is 0
(maximum preprocessing) to 100 (no preprocessing, the default). The typical
value is around 60. Note that lossy with \fB\-q 100\fP can at times yield
better results.
.TP
.B \-sharp_yuv
Use more accurate and sharper RGB->YUV conversion. Note that this process is
slower than the default 'fast' RGB->YUV conversion.
.TP
.BI \-loop " int .BI \-loop " int
Specifies the number of times the animation should loop. Using '0' Specifies the number of times the animation should loop. Using '0'
means 'loop indefinitely'. means 'loop indefinitely'.
@ -88,27 +76,18 @@ Specify the compression factor between 0 and 100. The default is 75.
Specify the compression method to use. This parameter controls the Specify the compression method to use. This parameter controls the
trade off between encoding speed and the compressed file size and quality. trade off between encoding speed and the compressed file size and quality.
Possible values range from 0 to 6. Default value is 4. Possible values range from 0 to 6. Default value is 4.
When higher values are used, the encoder will spend more time inspecting
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
.B \-exact, \-noexact
Preserve or alter RGB values in transparent area. The default is
\fB-noexact\fP, to help compressibility. Note \fB\-noexact\fP may cause
artifacts in frames compressed with \fB\-lossy\fP.
.SH EXIT STATUS
If there were no problems during execution, \fBimg2webp\fP exits with the value
of the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
.PP
If an error occurs, \fBimg2webp\fP exits with the value of the C constant
\fBEXIT_FAILURE\fP. This is usually one.
.SH EXAMPLE .SH EXAMPLE
img2webp -loop 2 in0.png -lossy in1.jpg -d 80 in2.tiff -o out.webp img2webp -loop 2 in0.png -lossy in1.jpg -d 80 in2.tiff -o out.webp
.br .br
.SH BUGS
Please report all bugs to the issue tracker:
https://bugs.chromium.org/p/webp
.br
Patches welcome! See this page to get started:
http://www.webmproject.org/code/contribute/submitting\-patches/
.SH AUTHORS .SH AUTHORS
\fBimg2webp\fP is a part of libwebp and was written by the WebP team. \fBimg2webp\fP is a part of libwebp and was written by the WebP team.
.br .br
@ -118,16 +97,9 @@ https://chromium.googlesource.com/webm/libwebp
This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>, This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>,
for the Debian project (and may be used by others). for the Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO .SH SEE ALSO
.BR webpmux (1), .BR webpmux (1),
.BR gif2webp (1) .BR gif2webp (1)
.br .br
Please refer to https://developers.google.com/speed/webp/ for additional Please refer to http://developers.google.com/speed/webp/ for additional
information. information.

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH VWEBP 1 "July 18, 2024" .TH VWEBP 1 "June 5, 2019"
.SH NAME .SH NAME
vwebp \- decompress a WebP file and display it in a window vwebp \- decompress a WebP file and display it in a window
.SH SYNOPSIS .SH SYNOPSIS
@ -72,12 +72,12 @@ Disable blending and disposal process, for debugging purposes.
.B 'q' / 'Q' / ESC .B 'q' / 'Q' / ESC
Quit. Quit.
.SH EXIT STATUS .SH BUGS
If there were no problems during execution, \fBvwebp\fP exits with the value of Please report all bugs to the issue tracker:
the C constant \fBEXIT_SUCCESS\fP. This is usually zero. https://bugs.chromium.org/p/webp
.PP .br
If an error occurs, \fBvwebp\fP exits with the value of the C constant Patches welcome! See this page to get started:
\fBEXIT_FAILURE\fP. This is usually one. http://www.webmproject.org/code/contribute/submitting-patches/
.SH EXAMPLES .SH EXAMPLES
vwebp picture.webp vwebp picture.webp
@ -94,15 +94,8 @@ https://chromium.googlesource.com/webm/libwebp
.PP .PP
This manual page was written for the Debian project (and may be used by others). This manual page was written for the Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO .SH SEE ALSO
.BR dwebp (1) .BR dwebp (1)
.br .br
Please refer to https://developers.google.com/speed/webp/ for additional Please refer to http://developers.google.com/speed/webp/ for additional
information. information.

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH WEBPINFO 1 "July 18, 2024" .TH WEBPINFO 1 "November 24, 2017"
.SH NAME .SH NAME
webpinfo \- print out the chunk level structure of WebP files webpinfo \- print out the chunk level structure of WebP files
along with basic integrity checks. along with basic integrity checks.
@ -47,12 +47,12 @@ Detailed usage instructions.
Input files in WebP format. Input files must come last, following Input files in WebP format. Input files must come last, following
options (if any). There can be multiple input files. options (if any). There can be multiple input files.
.SH EXIT STATUS .SH BUGS
If there were no problems during execution, \fBwebpinfo\fP exits with the value Please report all bugs to the issue tracker:
of the C constant \fBEXIT_SUCCESS\fP. This is usually zero. https://bugs.chromium.org/p/webp
.PP .br
If an error occurs, \fBwebpinfo\fP exits with the value of the C constant Patches welcome! See this page to get started:
\fBEXIT_FAILURE\fP. This is usually one. http://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXAMPLES .SH EXAMPLES
.br .br
@ -73,15 +73,8 @@ https://chromium.googlesource.com/webm/libwebp
This manual page was written by Hui Su <huisu@google.com>, This manual page was written by Hui Su <huisu@google.com>,
for the Debian project (and may be used by others). for the Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO .SH SEE ALSO
.BR webpmux (1) .BR webpmux (1)
.br .br
Please refer to https://developers.google.com/speed/webp/ for additional Please refer to http://developers.google.com/speed/webp/ for additional
information. information.

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH WEBPMUX 1 "July 18, 2024" .TH WEBPMUX 1 "April 23, 2018"
.SH NAME .SH NAME
webpmux \- create animated WebP files from non\-animated WebP images, extract webpmux \- create animated WebP files from non\-animated WebP images, extract
frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile. frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
@ -59,7 +59,7 @@ command.
to add/extract/strip XMP/EXIF metadata and ICC profile. to add/extract/strip XMP/EXIF metadata and ICC profile.
If a single file name (not starting with the character '\-') is supplied as If a single file name (not starting with the character '\-') is supplied as
the argument, the command line arguments are actually tokenized from this file. the argument, the command line arguments are actually tokenized from this file.
This allows for easy scripting or using a large number of arguments. This allows for easy scripting or using large number of arguments.
.SH OPTIONS .SH OPTIONS
.SS GET_OPTIONS (\-get): .SS GET_OPTIONS (\-get):
.TP .TP
@ -77,17 +77,6 @@ Get nth frame from an animated image. (n = 0 has a special meaning: last frame).
.SS SET_OPTIONS (\-set) .SS SET_OPTIONS (\-set)
.TP .TP
.BI loop " loop_count
Set loop count on an animated file.
.P
Where: 'loop_count' must be in range [0, 65535].
.TP
.BI bgcolor " A,R,G,B
Set the background color of the canvas on an animated file.
.P
where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying the
Alpha, Red, Green and Blue component values respectively.
.TP
.BI icc " file.icc .BI icc " file.icc
Set ICC profile. Set ICC profile.
.P .P
@ -186,12 +175,12 @@ Output file in WebP format.
.TP .TP
The nature of EXIF, XMP and ICC data is not checked and is assumed to be valid. The nature of EXIF, XMP and ICC data is not checked and is assumed to be valid.
.SH EXIT STATUS .SH BUGS
If there were no problems during execution, \fBwebpmux\fP exits with the value Please report all bugs to the issue tracker:
of the C constant \fBEXIT_SUCCESS\fP. This is usually zero. https://bugs.chromium.org/p/webp
.PP .br
If an error occurs, \fBwebpmux\fP exits with the value of the C constant Patches welcome! See this page to get started:
\fBEXIT_FAILURE\fP. This is usually one. http://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXAMPLES .SH EXAMPLES
.P .P
@ -262,17 +251,10 @@ https://chromium.googlesource.com/webm/libwebp
This manual page was written by Vikas Arora <vikaas.arora@gmail.com>, This manual page was written by Vikas Arora <vikaas.arora@gmail.com>,
for the Debian project (and may be used by others). for the Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO .SH SEE ALSO
.BR cwebp (1), .BR cwebp (1),
.BR dwebp (1), .BR dwebp (1),
.BR gif2webp (1) .BR gif2webp (1)
.br .br
Please refer to https://developers.google.com/speed/webp/ for additional Please refer to http://developers.google.com/speed/webp/ for additional
information. information.

View File

@ -1,41 +0,0 @@
AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir)
AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src
lib_LTLIBRARIES = libsharpyuv.la
noinst_LTLIBRARIES =
noinst_LTLIBRARIES += libsharpyuv_sse2.la
noinst_LTLIBRARIES += libsharpyuv_neon.la
libsharpyuvinclude_HEADERS =
libsharpyuvinclude_HEADERS += sharpyuv.h
libsharpyuvinclude_HEADERS += sharpyuv_csp.h
noinst_HEADERS =
noinst_HEADERS += ../src/dsp/cpu.c
noinst_HEADERS += ../src/dsp/cpu.h
noinst_HEADERS += ../src/webp/types.h
libsharpyuv_sse2_la_SOURCES =
libsharpyuv_sse2_la_SOURCES += sharpyuv_sse2.c
libsharpyuv_sse2_la_CPPFLAGS = $(libsharpyuv_la_CPPFLAGS)
libsharpyuv_sse2_la_CFLAGS = $(AM_CFLAGS) $(SSE2_FLAGS)
libsharpyuv_neon_la_SOURCES =
libsharpyuv_neon_la_SOURCES += sharpyuv_neon.c
libsharpyuv_neon_la_CPPFLAGS = $(libsharpyuv_la_CPPFLAGS)
libsharpyuv_neon_la_CFLAGS = $(AM_CFLAGS) $(NEON_FLAGS)
libsharpyuv_la_SOURCES =
libsharpyuv_la_SOURCES += sharpyuv_cpu.c sharpyuv_cpu.h
libsharpyuv_la_SOURCES += sharpyuv_csp.c sharpyuv_csp.h
libsharpyuv_la_SOURCES += sharpyuv_dsp.c sharpyuv_dsp.h
libsharpyuv_la_SOURCES += sharpyuv_gamma.c sharpyuv_gamma.h
libsharpyuv_la_SOURCES += sharpyuv.c sharpyuv.h
libsharpyuv_la_CPPFLAGS = $(AM_CPPFLAGS)
libsharpyuv_la_LDFLAGS = -no-undefined -version-info 1:2:1 -lm
libsharpyuv_la_LIBADD =
libsharpyuv_la_LIBADD += libsharpyuv_sse2.la
libsharpyuv_la_LIBADD += libsharpyuv_neon.la
libsharpyuvincludedir = $(includedir)/webp/sharpyuv
pkgconfig_DATA = libsharpyuv.pc

View File

@ -1,11 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@/webp
Name: libsharpyuv
Description: Library for sharp RGB to YUV conversion
Version: @PACKAGE_VERSION@
Cflags: -I${includedir}
Libs: -L${libdir} -l@webp_libname_prefix@sharpyuv
Libs.private: -lm @PTHREAD_CFLAGS@ @PTHREAD_LIBS@

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