mirror of
https://github.com/webmproject/libwebp.git
synced 2025-12-24 14:06:27 +01:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4422702d0 | ||
|
|
ed665a15e8 |
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
Language: Cpp
|
|
||||||
BasedOnStyle: Google
|
|
||||||
DerivePointerAlignment: false
|
|
||||||
240
.cmake-format.py
240
.cmake-format.py
@@ -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 = {}
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,9 +3,7 @@
|
|||||||
*.pc
|
*.pc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.deps
|
.deps
|
||||||
.idea
|
|
||||||
.libs
|
.libs
|
||||||
.vscode
|
|
||||||
/aclocal.m4
|
/aclocal.m4
|
||||||
/ar-lib
|
/ar-lib
|
||||||
/autom4te.cache
|
/autom4te.cache
|
||||||
@@ -52,6 +50,5 @@ tests/fuzzer/animdecoder_fuzzer
|
|||||||
tests/fuzzer/animencoder_fuzzer
|
tests/fuzzer/animencoder_fuzzer
|
||||||
tests/fuzzer/demux_api_fuzzer
|
tests/fuzzer/demux_api_fuzzer
|
||||||
tests/fuzzer/enc_dec_fuzzer
|
tests/fuzzer/enc_dec_fuzzer
|
||||||
tests/fuzzer/huffman_fuzzer
|
|
||||||
tests/fuzzer/mux_demux_api_fuzzer
|
tests/fuzzer/mux_demux_api_fuzzer
|
||||||
tests/fuzzer/simple_api_fuzzer
|
tests/fuzzer/simple_api_fuzzer
|
||||||
|
|||||||
6
.mailmap
6
.mailmap
@@ -8,13 +8,7 @@ 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>
|
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>
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
[style]
|
[style]
|
||||||
based_on_style = yapf
|
based_on_style = chromium
|
||||||
21
AUTHORS
21
AUTHORS
@@ -1,32 +1,19 @@
|
|||||||
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)
|
- Christopher Degawa (ccom at randomderp dot com)
|
||||||
- Clement Courbet (courbet at google 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)
|
- Ilya Kurdyukov (jpegqs at gmail dot com)
|
||||||
- Ingvar Stepanyan (rreverser at google 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 +22,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 +40,12 @@ 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)
|
- 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)
|
- Zhi An Ng (zhin at chromium dot org)
|
||||||
|
|||||||
16
Android.mk
16
Android.mk
@@ -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 \
|
||||||
@@ -164,7 +153,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 +204,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 +279,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
|
|
||||||
|
|||||||
696
CMakeLists.txt
696
CMakeLists.txt
@@ -6,23 +6,15 @@
|
|||||||
# in the file PATENTS. All contributing project authors may
|
# in the file PATENTS. All contributing project authors may
|
||||||
# be found in the AUTHORS file in the root of the source tree.
|
# be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
if(APPLE)
|
cmake_minimum_required(VERSION 3.7)
|
||||||
cmake_minimum_required(VERSION 3.17)
|
|
||||||
else()
|
if(POLICY CMP0072)
|
||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_policy(SET CMP0072 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(WebP C)
|
project(WebP C)
|
||||||
|
|
||||||
# Options for coder / decoder executables.
|
# Options for coder / decoder executables.
|
||||||
if(BUILD_SHARED_LIBS)
|
|
||||||
set(WEBP_LINK_STATIC_DEFAULT OFF)
|
|
||||||
else()
|
|
||||||
set(WEBP_LINK_STATIC_DEFAULT ON)
|
|
||||||
endif()
|
|
||||||
option(WEBP_LINK_STATIC
|
|
||||||
"Link using static libraries. If OFF, use dynamic libraries."
|
|
||||||
${WEBP_LINK_STATIC_DEFAULT})
|
|
||||||
if(NOT EMSCRIPTEN)
|
if(NOT EMSCRIPTEN)
|
||||||
# Disable SIMD on Emscripten by default, as it's a new unstable Wasm feature.
|
# 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.
|
# Users can still explicitly opt-in to make a SIMD-enabled build.
|
||||||
@@ -30,6 +22,9 @@ if(NOT EMSCRIPTEN)
|
|||||||
endif()
|
endif()
|
||||||
option(WEBP_ENABLE_SIMD "Enable any SIMD optimization."
|
option(WEBP_ENABLE_SIMD "Enable any SIMD optimization."
|
||||||
${WEBP_ENABLE_SIMD_DEFAULT})
|
${WEBP_ENABLE_SIMD_DEFAULT})
|
||||||
|
# Emscripten supports SSE builds using its compatibility headers, by default it
|
||||||
|
# will use SSE4 if WEBP_ENABLE_WASM_SIMD is OFF and WEBP_ENABLE_SIMD is ON.
|
||||||
|
option(WEBP_ENABLE_WASM_SIMD "Enable WebAssembly SIMD optimizations" OFF)
|
||||||
option(WEBP_BUILD_ANIM_UTILS "Build animation utilities." ON)
|
option(WEBP_BUILD_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)
|
||||||
@@ -41,31 +36,12 @@ 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_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)
|
||||||
option(
|
|
||||||
WEBP_ENABLE_FBOUNDS_SAFETY
|
|
||||||
"Enable -fbounds-safety for the part of the codebase which supports it. This expects an experimental toolchain."
|
|
||||||
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)
|
||||||
@@ -75,7 +51,6 @@ endif()
|
|||||||
if(WEBP_BUILD_WEBP_JS)
|
if(WEBP_BUILD_WEBP_JS)
|
||||||
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_GIF2WEBP OFF)
|
set(WEBP_BUILD_GIF2WEBP OFF)
|
||||||
set(WEBP_BUILD_IMG2WEBP OFF)
|
set(WEBP_BUILD_IMG2WEBP OFF)
|
||||||
set(WEBP_BUILD_VWEBP OFF)
|
set(WEBP_BUILD_VWEBP OFF)
|
||||||
@@ -85,22 +60,10 @@ if(WEBP_BUILD_WEBP_JS)
|
|||||||
set(WEBP_USE_THREAD OFF)
|
set(WEBP_USE_THREAD OFF)
|
||||||
|
|
||||||
if(WEBP_ENABLE_SIMD)
|
if(WEBP_ENABLE_SIMD)
|
||||||
message(NOTICE
|
message("wasm2js does not support SIMD, disabling webp.js generation.")
|
||||||
"wasm2js does not support SIMD, disabling webp.js generation.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT EMSCRIPTEN_VERSION)
|
|
||||||
message(
|
|
||||||
WARNING
|
|
||||||
"EMSCRIPTEN_VERSION not detected!\n"
|
|
||||||
"WEBP_BUILD_WEBP_JS is only supported with emcmake/emmake.\n"
|
|
||||||
"The build may fail if those tools are not used. See webp_js/README.md."
|
|
||||||
)
|
|
||||||
endif()
|
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)
|
||||||
|
|
||||||
@@ -111,30 +74,17 @@ if(NOT CMAKE_BUILD_TYPE)
|
|||||||
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)
|
||||||
add_definitions(-DWEBP_SWAP_16BIT_CSP=1)
|
add_definitions(-DWEBP_SWAP_16BIT_CSP=1)
|
||||||
endif()
|
endif()
|
||||||
|
if(WEBP_ENABLE_WASM_SIMD)
|
||||||
|
add_definitions(-DWEBP_ENABLE_WASM_SIMD_INTRINSICS)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT WEBP_BITTRACE STREQUAL "0")
|
if(NOT WEBP_BITTRACE STREQUAL "0")
|
||||||
add_definitions(-DBITTRACE=${WEBP_BITTRACE})
|
add_definitions(-DBITTRACE=${WEBP_BITTRACE})
|
||||||
@@ -145,73 +95,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()
|
|
||||||
|
|
||||||
# Compatibility with autoconf configure script's way of setting this
|
|
||||||
if(CMAKE_C_BYTE_ORDER STREQUAL "BIG_ENDIAN")
|
|
||||||
set(WORDS_BIGENDIAN TRUE)
|
|
||||||
elseif(CMAKE_C_BYTE_ORDER STREQUAL "LITTLE_ENDIAN")
|
|
||||||
set(WORDS_BIGENDIAN FALSE)
|
|
||||||
else()
|
|
||||||
set(WORDS_BIGENDIAN FALSE)
|
|
||||||
message(WARNING "Endianness could not be determined.")
|
|
||||||
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()
|
||||||
@@ -220,7 +121,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
|
||||||
@@ -229,8 +130,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()
|
||||||
|
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
@@ -240,15 +143,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()
|
||||||
@@ -277,17 +188,161 @@ 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)
|
||||||
|
|
||||||
|
# ##############################################################################
|
||||||
|
# Build the webpdecoder library.
|
||||||
|
|
||||||
|
# Creates a source file with an unused stub function in $CMAKE_BINARY_DIR and
|
||||||
|
# adds it to the specified target. Currently used only with Xcode.
|
||||||
|
#
|
||||||
|
# See also:
|
||||||
|
# https://cmake.org/cmake/help/v3.18/command/add_library.html#object-libraries
|
||||||
|
# "Some native build systems (such as Xcode) may not like targets that have
|
||||||
|
# only object files, so consider adding at least one real source file to any
|
||||||
|
# target that references $<TARGET_OBJECTS:objlib>."
|
||||||
|
function(libwebp_add_stub_file TARGET)
|
||||||
|
set(stub_source_dir "${CMAKE_BINARY_DIR}")
|
||||||
|
set(stub_source_file
|
||||||
|
"${stub_source_dir}/libwebp_${TARGET}_stub.c")
|
||||||
|
set(stub_source_code
|
||||||
|
"// Generated file. DO NOT EDIT!\n"
|
||||||
|
"// C source file created for target ${TARGET}.\n"
|
||||||
|
"void libwebp_${TARGET}_stub_function(void)\;\n"
|
||||||
|
"void libwebp_${TARGET}_stub_function(void) {}\n")
|
||||||
|
file(WRITE "${stub_source_file}" ${stub_source_code})
|
||||||
|
|
||||||
|
target_sources(${TARGET} PRIVATE ${stub_source_file})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
# avoid security warnings for e.g., fopen() used in the examples.
|
||||||
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
else()
|
||||||
|
add_definitions(-Wall)
|
||||||
|
endif()
|
||||||
|
include_directories(${WEBP_DEP_INCLUDE_DIRS})
|
||||||
|
add_library(webpdecode OBJECT ${WEBP_DEC_SRCS})
|
||||||
|
target_include_directories(webpdecode
|
||||||
|
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
add_library(webpdspdecode OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS})
|
||||||
|
target_include_directories(webpdspdecode
|
||||||
|
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
add_library(webputilsdecode
|
||||||
|
OBJECT
|
||||||
|
${WEBP_UTILS_COMMON_SRCS}
|
||||||
|
${WEBP_UTILS_DEC_SRCS})
|
||||||
|
target_include_directories(webputilsdecode
|
||||||
|
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
add_library(webpdecoder
|
||||||
|
$<TARGET_OBJECTS:webpdecode>
|
||||||
|
$<TARGET_OBJECTS:webpdspdecode>
|
||||||
|
$<TARGET_OBJECTS:webputilsdecode>)
|
||||||
|
if(XCODE)
|
||||||
|
libwebp_add_stub_file(webpdecoder)
|
||||||
|
endif()
|
||||||
|
target_link_libraries(webpdecoder ${WEBP_DEP_LIBRARIES})
|
||||||
|
target_include_directories(
|
||||||
|
webpdecoder
|
||||||
|
PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||||
|
set_target_properties(
|
||||||
|
webpdecoder
|
||||||
|
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
||||||
|
|
||||||
|
configure_pkg_config("src/libwebpdecoder.pc")
|
||||||
|
|
||||||
|
# Build the webp library.
|
||||||
|
add_library(webpencode OBJECT ${WEBP_ENC_SRCS})
|
||||||
|
target_include_directories(webpencode
|
||||||
|
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
add_library(webpdsp
|
||||||
|
OBJECT
|
||||||
|
${WEBP_DSP_COMMON_SRCS}
|
||||||
|
${WEBP_DSP_DEC_SRCS}
|
||||||
|
${WEBP_DSP_ENC_SRCS})
|
||||||
|
target_include_directories(webpdsp
|
||||||
|
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
add_library(webputils
|
||||||
|
OBJECT
|
||||||
|
${WEBP_UTILS_COMMON_SRCS}
|
||||||
|
${WEBP_UTILS_DEC_SRCS}
|
||||||
|
${WEBP_UTILS_ENC_SRCS})
|
||||||
|
target_include_directories(webputils
|
||||||
|
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
add_library(webp
|
||||||
|
$<TARGET_OBJECTS:webpdecode>
|
||||||
|
$<TARGET_OBJECTS:webpdsp>
|
||||||
|
$<TARGET_OBJECTS:webpencode>
|
||||||
|
$<TARGET_OBJECTS:webputils>)
|
||||||
|
if(XCODE)
|
||||||
|
libwebp_add_stub_file(webp)
|
||||||
|
endif()
|
||||||
|
target_link_libraries(webp ${WEBP_DEP_LIBRARIES})
|
||||||
|
target_include_directories(
|
||||||
|
webp
|
||||||
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
||||||
|
$<INSTALL_INTERFACE:include>)
|
||||||
|
set_target_properties(
|
||||||
|
webp
|
||||||
|
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/encode.h;\
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
||||||
|
|
||||||
|
# Make sure the OBJECT libraries are built with position independent code (it is
|
||||||
|
# not ON by default).
|
||||||
|
set_target_properties(webpdecode
|
||||||
|
webpdspdecode
|
||||||
|
webputilsdecode
|
||||||
|
webpencode
|
||||||
|
webpdsp
|
||||||
|
webputils
|
||||||
|
PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||||
|
configure_pkg_config("src/libwebp.pc")
|
||||||
|
|
||||||
|
# Build the webp demux library.
|
||||||
|
add_library(webpdemux ${WEBP_DEMUX_SRCS})
|
||||||
|
target_link_libraries(webpdemux webp)
|
||||||
|
target_include_directories(webpdemux
|
||||||
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
PUBLIC $<INSTALL_INTERFACE:include>)
|
||||||
|
set_target_properties(
|
||||||
|
webpdemux
|
||||||
|
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/demux.h;\
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
||||||
|
|
||||||
|
configure_pkg_config("src/demux/libwebpdemux.pc")
|
||||||
|
|
||||||
# Set the version numbers.
|
# Set the version numbers.
|
||||||
macro(set_version FILE TARGET_NAME NAME_IN_MAKEFILE)
|
macro(set_version FILE TARGET_NAME NAME_IN_MAKEFILE)
|
||||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} SOURCE_FILE)
|
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/src/${FILE} SOURCE_FILE)
|
||||||
string(REGEX MATCH
|
string(REGEX MATCH
|
||||||
"${NAME_IN_MAKEFILE}_la_LDFLAGS[^\n]* -version-info [0-9:]+" TMP
|
"${NAME_IN_MAKEFILE}_la_LDFLAGS[^\n]* -version-info [0-9:]+"
|
||||||
|
TMP
|
||||||
${SOURCE_FILE})
|
${SOURCE_FILE})
|
||||||
string(REGEX MATCH "[0-9:]+" TMP ${TMP})
|
string(REGEX MATCH
|
||||||
string(REGEX REPLACE ":" " " LT_VERSION ${TMP})
|
"[0-9:]+"
|
||||||
|
TMP
|
||||||
|
${TMP})
|
||||||
|
string(REGEX
|
||||||
|
REPLACE ":"
|
||||||
|
" "
|
||||||
|
LT_VERSION
|
||||||
|
${TMP})
|
||||||
|
|
||||||
# See the libtool docs for more information:
|
# See the libtool docs for more information:
|
||||||
# https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
|
# https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
|
||||||
@@ -306,175 +361,23 @@ macro(set_version FILE TARGET_NAME NAME_IN_MAKEFILE)
|
|||||||
|
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
${TARGET_NAME}
|
${TARGET_NAME}
|
||||||
PROPERTIES VERSION ${LT_CURRENT_MINUS_AGE}.${LT_AGE}.${LT_REVISION}
|
PROPERTIES VERSION
|
||||||
SOVERSION ${LT_CURRENT_MINUS_AGE})
|
${LT_CURRENT_MINUS_AGE}.${LT_AGE}.${LT_REVISION}
|
||||||
if(APPLE)
|
SOVERSION
|
||||||
# For compatibility, set MACHO_COMPATIBILITY_VERSION and
|
${LT_CURRENT_MINUS_AGE})
|
||||||
# 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()
|
endmacro()
|
||||||
|
set_version(Makefile.am webp webp)
|
||||||
# ##############################################################################
|
set_version(Makefile.am webpdecoder webpdecoder)
|
||||||
# Build the webpdecoder library.
|
set_version(demux/Makefile.am webpdemux webpdemux)
|
||||||
|
|
||||||
# Creates a source file with an unused stub function in $CMAKE_BINARY_DIR and
|
|
||||||
# adds it to the specified target. Currently used only with Xcode.
|
|
||||||
#
|
|
||||||
# See also:
|
|
||||||
# https://cmake.org/cmake/help/v3.18/command/add_library.html#object-libraries
|
|
||||||
# "Some native build systems (such as Xcode) may not like targets that have only
|
|
||||||
# object files, so consider adding at least one real source file to any target
|
|
||||||
# that references $<TARGET_OBJECTS:objlib>."
|
|
||||||
function(libwebp_add_stub_file TARGET)
|
|
||||||
set(stub_source_dir "${CMAKE_BINARY_DIR}")
|
|
||||||
set(stub_source_file "${stub_source_dir}/libwebp_${TARGET}_stub.c")
|
|
||||||
set(stub_source_code
|
|
||||||
"// Generated file. DO NOT EDIT!\n"
|
|
||||||
"// C source file created for target ${TARGET}.\n"
|
|
||||||
"void libwebp_${TARGET}_stub_function(void)\;\n"
|
|
||||||
"void libwebp_${TARGET}_stub_function(void) {}\n")
|
|
||||||
file(WRITE "${stub_source_file}" ${stub_source_code})
|
|
||||||
|
|
||||||
target_sources(${TARGET} PRIVATE ${stub_source_file})
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv "WEBP_SHARPYUV_SRCS" "")
|
|
||||||
add_library(sharpyuv ${WEBP_SHARPYUV_SRCS})
|
|
||||||
target_link_libraries(sharpyuv ${SHARPYUV_DEP_LIBRARIES})
|
|
||||||
set_version(sharpyuv/Makefile.am sharpyuv sharpyuv)
|
|
||||||
target_include_directories(
|
|
||||||
sharpyuv PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src)
|
|
||||||
set_target_properties(
|
|
||||||
sharpyuv
|
|
||||||
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/sharpyuv.h;\
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/sharpyuv_csp.h")
|
|
||||||
configure_pkg_config("sharpyuv/libsharpyuv.pc")
|
|
||||||
install(
|
|
||||||
TARGETS sharpyuv
|
|
||||||
EXPORT ${PROJECT_NAME}Targets
|
|
||||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webp/sharpyuv
|
|
||||||
INCLUDES
|
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
|
||||||
${CMAKE_INSTALL_INCLUDEDIR}/webp
|
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
|
||||||
|
|
||||||
if(MSVC)
|
|
||||||
# avoid security warnings for e.g., fopen() used in the examples.
|
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
|
||||||
else()
|
|
||||||
add_compile_options(-Wall)
|
|
||||||
endif()
|
|
||||||
include_directories(${WEBP_DEP_INCLUDE_DIRS})
|
|
||||||
add_library(webpdecode OBJECT ${WEBP_DEC_SRCS})
|
|
||||||
target_include_directories(webpdecode PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
add_library(webpdspdecode OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS})
|
|
||||||
target_include_directories(webpdspdecode PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
add_library(webputilsdecode OBJECT ${WEBP_UTILS_COMMON_SRCS}
|
|
||||||
${WEBP_UTILS_DEC_SRCS})
|
|
||||||
target_include_directories(webputilsdecode PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
add_library(
|
|
||||||
webpdecoder $<TARGET_OBJECTS:webpdecode> $<TARGET_OBJECTS:webpdspdecode>
|
|
||||||
$<TARGET_OBJECTS:webputilsdecode>)
|
|
||||||
if(XCODE)
|
|
||||||
libwebp_add_stub_file(webpdecoder)
|
|
||||||
endif()
|
|
||||||
target_link_libraries(webpdecoder ${WEBP_DEP_LIBRARIES})
|
|
||||||
target_include_directories(
|
|
||||||
webpdecoder
|
|
||||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
INTERFACE
|
|
||||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_BINARY_DIR}>"
|
|
||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
|
||||||
set_target_properties(
|
|
||||||
webpdecoder
|
|
||||||
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
|
||||||
|
|
||||||
configure_pkg_config("src/libwebpdecoder.pc")
|
|
||||||
|
|
||||||
# Build the webp library.
|
|
||||||
add_library(webpencode OBJECT ${WEBP_ENC_SRCS})
|
|
||||||
target_include_directories(
|
|
||||||
webpencode PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src)
|
|
||||||
add_library(webpdsp OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS}
|
|
||||||
${WEBP_DSP_ENC_SRCS})
|
|
||||||
target_include_directories(webpdsp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
add_library(webputils OBJECT ${WEBP_UTILS_COMMON_SRCS} ${WEBP_UTILS_DEC_SRCS}
|
|
||||||
${WEBP_UTILS_ENC_SRCS})
|
|
||||||
target_include_directories(webputils PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
add_library(webp $<TARGET_OBJECTS:webpdecode> $<TARGET_OBJECTS:webpdsp>
|
|
||||||
$<TARGET_OBJECTS:webpencode> $<TARGET_OBJECTS:webputils>)
|
|
||||||
if(WEBP_ENABLE_FBOUNDS_SAFETY)
|
|
||||||
# Enable -fbounds-safety only for webputils and webpdecode(r) for now.
|
|
||||||
add_definitions(-DWEBP_SUPPORT_FBOUNDS_SAFETY=1)
|
|
||||||
target_compile_options(webputils PRIVATE -fbounds-safety)
|
|
||||||
target_compile_options(webputilsdecode PRIVATE -fbounds-safety)
|
|
||||||
target_compile_options(webpdecode PRIVATE -fbounds-safety)
|
|
||||||
target_compile_options(webpdecoder PRIVATE -fbounds-safety)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_link_libraries(webp sharpyuv)
|
|
||||||
if(XCODE)
|
|
||||||
libwebp_add_stub_file(webp)
|
|
||||||
endif()
|
|
||||||
target_link_libraries(webp ${WEBP_DEP_LIBRARIES})
|
|
||||||
target_include_directories(
|
|
||||||
webp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
|
||||||
$<INSTALL_INTERFACE:include>)
|
|
||||||
set_target_properties(
|
|
||||||
webp
|
|
||||||
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/encode.h;\
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
|
||||||
|
|
||||||
# Make sure the OBJECT libraries are built with position independent code (it is
|
|
||||||
# not ON by default).
|
|
||||||
set_target_properties(webpdecode webpdspdecode webputilsdecode webpencode
|
|
||||||
webpdsp webputils PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
|
||||||
configure_pkg_config("src/libwebp.pc")
|
|
||||||
|
|
||||||
# Build the webp demux library.
|
|
||||||
add_library(webpdemux ${WEBP_DEMUX_SRCS})
|
|
||||||
target_link_libraries(webpdemux webp)
|
|
||||||
target_include_directories(
|
|
||||||
webpdemux PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
PUBLIC $<INSTALL_INTERFACE:include>)
|
|
||||||
set_target_properties(
|
|
||||||
webpdemux
|
|
||||||
PROPERTIES
|
|
||||||
PUBLIC_HEADER
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/demux.h;\
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
|
||||||
|
|
||||||
configure_pkg_config("src/demux/libwebpdemux.pc")
|
|
||||||
|
|
||||||
set_version(src/Makefile.am webp webp)
|
|
||||||
set_version(src/Makefile.am webpdecoder webpdecoder)
|
|
||||||
set_version(src/demux/Makefile.am webpdemux webpdemux)
|
|
||||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_FILE)
|
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)
|
||||||
@@ -487,7 +390,9 @@ 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}
|
||||||
|
PROPERTIES
|
||||||
|
COMPILE_FLAGS
|
||||||
${SIMD_COMPILE_FLAG})
|
${SIMD_COMPILE_FLAG})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
@@ -509,32 +414,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.
|
||||||
@@ -543,12 +448,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
|
||||||
|
imagedec
|
||||||
|
imageenc
|
||||||
PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src
|
PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/src)
|
${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||||
target_include_directories(imagedec PRIVATE ${WEBP_DEP_IMG_INCLUDE_DIRS})
|
|
||||||
target_include_directories(imageenc PRIVATE ${WEBP_DEP_IMG_INCLUDE_DIRS})
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WEBP_BUILD_DWEBP)
|
if(WEBP_BUILD_DWEBP)
|
||||||
@@ -565,8 +470,7 @@ 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()
|
||||||
|
|
||||||
@@ -574,12 +478,13 @@ if(WEBP_BUILD_LIBWEBPMUX)
|
|||||||
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
|
||||||
|
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR})
|
${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
set_version(src/mux/Makefile.am libwebpmux webpmux)
|
set_version(mux/Makefile.am libwebpmux webpmux)
|
||||||
set_target_properties(
|
set_target_properties(libwebpmux
|
||||||
libwebpmux
|
PROPERTIES PUBLIC_HEADER
|
||||||
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux.h;\
|
"${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)
|
||||||
@@ -593,10 +498,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()
|
||||||
|
|
||||||
@@ -606,10 +514,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()
|
||||||
|
|
||||||
@@ -620,16 +531,16 @@ 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
|
${GLUT_glut_LIBRARY}
|
||||||
imageioutil
|
imageioutil
|
||||||
webp
|
webp
|
||||||
webpdemux)
|
webpdemux)
|
||||||
target_include_directories(
|
target_include_directories(vwebp
|
||||||
vwebp PRIVATE ${GLUT_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/src
|
PRIVATE ${GLUT_INCLUDE_DIR}
|
||||||
|
${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")
|
||||||
@@ -648,8 +559,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()
|
||||||
|
|
||||||
@@ -670,101 +580,61 @@ 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
|
||||||
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/src)
|
${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||||
|
|
||||||
# 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
|
||||||
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${CMAKE_CURRENT_BINARY_DIR})
|
${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
# 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_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)
|
||||||
|
|
||||||
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
|
|
||||||
# https://crbug.com/webp/614.
|
|
||||||
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.27")
|
|
||||||
# TOTAL_STACK size was renamed to STACK_SIZE in 3.1.27. The old name was
|
|
||||||
# kept for compatibility, but prefer the new one in case it is removed in
|
|
||||||
# the future.
|
|
||||||
set(emscripten_stack_size "-sSTACK_SIZE=5MB")
|
|
||||||
else()
|
|
||||||
set(emscripten_stack_size "-sTOTAL_STACK=5MB")
|
|
||||||
endif()
|
|
||||||
find_package(SDL2 REQUIRED)
|
|
||||||
# wasm2js does not support SIMD.
|
# wasm2js does not support SIMD.
|
||||||
if(NOT WEBP_ENABLE_SIMD)
|
if(NOT WEBP_ENABLE_SIMD)
|
||||||
# JavaScript version
|
# JavaScript version
|
||||||
add_executable(webp_js ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
|
add_executable(webp_js ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
|
||||||
target_link_libraries(webp_js webpdecoder SDL2)
|
target_link_libraries(webp_js webpdecoder SDL)
|
||||||
target_include_directories(webp_js PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
target_include_directories(webp_js PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
set(WEBP_HAVE_SDL 1)
|
set(WEBP_HAVE_SDL 1)
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
webp_js
|
webp_js
|
||||||
PROPERTIES
|
PROPERTIES LINK_FLAGS "-s WASM=0 \
|
||||||
# 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 EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
|
||||||
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)
|
set_target_properties(webp_js PROPERTIES OUTPUT_NAME webp)
|
||||||
target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
|
target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
|
||||||
endif()
|
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 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)
|
||||||
@@ -776,8 +646,7 @@ 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
|
||||||
@@ -792,8 +661,7 @@ 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
|
||||||
@@ -804,13 +672,8 @@ if(WEBP_BUILD_ANIM_UTILS)
|
|||||||
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(
|
install(TARGETS ${INSTALLED_LIBRARIES}
|
||||||
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
|
||||||
@@ -819,36 +682,24 @@ install(
|
|||||||
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"
|
||||||
@@ -880,6 +731,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()
|
||||||
|
|||||||
@@ -19,58 +19,10 @@ again.
|
|||||||
|
|
||||||
All submissions, including submissions by project members, require review. We
|
All submissions, including submissions by project members, require review. We
|
||||||
use a [Gerrit](https://www.gerritcodereview.com) instance hosted at
|
use a [Gerrit](https://www.gerritcodereview.com) instance hosted at
|
||||||
https://chromium-review.googlesource.com for this purpose.
|
https://chromium-review.googlesource.com for this purpose. See the
|
||||||
|
|
||||||
## 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/)
|
[WebM Project page](https://www.webmproject.org/code/contribute/submitting-patches/)
|
||||||
for additional details.
|
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
|
|
||||||
the formatting is enforced using `clang-format --style=Google`.
|
|
||||||
|
|
||||||
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
|
## Community Guidelines
|
||||||
|
|
||||||
This project follows
|
This project follows
|
||||||
|
|||||||
751
ChangeLog
751
ChangeLog
@@ -1,752 +1,7 @@
|
|||||||
370aa581 webp_js/README.md: add some more code formatting (``)
|
|
||||||
f83c6b32 CMakeLists: add warning for incorrect emscripten config
|
|
||||||
6a3e656b update ChangeLog (tag: v1.6.0-rc1)
|
|
||||||
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 & 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
|
d9191588 fuzzer/*: normalize src/ includes
|
||||||
c5bc3624 fuzzer/*: normalize src/ includes
|
|
||||||
53b6f762 fix indent
|
53b6f762 fix indent
|
||||||
d2caaba4 fix indent
|
|
||||||
731246ba update ChangeLog (tag: v1.2.1-rc2)
|
731246ba update ChangeLog (tag: v1.2.1-rc2)
|
||||||
d250f01d dsp/*: use WEBP_HAVE_* to determine Init availability
|
d250f01d dsp/*: use WEBP_HAVE_* to determine Init availability
|
||||||
1fe31625 dsp/*: use WEBP_HAVE_* to determine Init availability
|
|
||||||
3a4d3ecd update NEWS
|
3a4d3ecd update NEWS
|
||||||
b2bc8093 bump version to 1.2.1
|
b2bc8093 bump version to 1.2.1
|
||||||
e542fc7a update AUTHORS
|
e542fc7a update AUTHORS
|
||||||
@@ -918,7 +173,7 @@ a99078c1 remove call to MBAnalyzeBestIntra4Mode for method >= 5
|
|||||||
6a0ff358 Enc: add a qmin / qmax range for quality factor
|
6a0ff358 Enc: add a qmin / qmax range for quality factor
|
||||||
0fa56f30 Merge tag 'v1.1.0'
|
0fa56f30 Merge tag 'v1.1.0'
|
||||||
6cf504d0 PNM decoding: handle max_value != 255
|
6cf504d0 PNM decoding: handle max_value != 255
|
||||||
d7844e97 update ChangeLog (tag: v1.1.0-rc2, tag: v1.1.0)
|
d7844e97 update ChangeLog (tag: v1.1.0-rc2, tag: v1.1.0, origin/1.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
|
cf047e83 Makefile.vc: fix webp_quality.exe link
|
||||||
c074c653 update NEWS
|
c074c653 update NEWS
|
||||||
@@ -1563,7 +818,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++.
|
||||||
@@ -1850,7 +1105,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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
76
Makefile.vc
76
Makefile.vc
@@ -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
|
||||||
@@ -32,13 +29,14 @@ 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 /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 \
|
||||||
@@ -231,7 +216,6 @@ DSP_DEC_OBJS = \
|
|||||||
$(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_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 +255,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 +308,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 +323,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 +335,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 +368,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 +386,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 +409,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 +429,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 +450,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 +482,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 +502,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
|
||||||
|
|||||||
99
NEWS
99
NEWS
@@ -1,102 +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
|
- 7/20/2021: version 1.2.1
|
||||||
This is a binary compatible release.
|
This is a binary compatible release.
|
||||||
* minor lossless encoder improvements and x86 color conversion speed up
|
* minor lossless encoder improvements and x86 color conversion speed up
|
||||||
|
|||||||
62
PRESUBMIT.py
62
PRESUBMIT.py
@@ -33,75 +33,15 @@ See https://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
|
|||||||
details on the presubmit API built into depot_tools.
|
details on the presubmit API built into depot_tools.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
|
||||||
import subprocess2
|
import subprocess2
|
||||||
|
|
||||||
USE_PYTHON3 = True
|
USE_PYTHON3 = True
|
||||||
_BASH_INDENTATION = "2"
|
_BASH_INDENTATION = "2"
|
||||||
_GIT_COMMIT_SUBJECT_LENGTH = 65
|
|
||||||
_INCLUDE_BASH_FILES_ONLY = [r".*\.sh$"]
|
_INCLUDE_BASH_FILES_ONLY = [r".*\.sh$"]
|
||||||
_INCLUDE_MAN_FILES_ONLY = [r"man/.+\.1$"]
|
_INCLUDE_MAN_FILES_ONLY = [r"man/.+\.1$"]
|
||||||
_INCLUDE_SOURCE_FILES_ONLY = [r".*\.[ch]$"]
|
|
||||||
_LIBWEBP_MAX_LINE_LENGTH = 80
|
_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):
|
def _GetFilesToSkip(input_api):
|
||||||
return list(input_api.DEFAULT_FILES_TO_SKIP) + [
|
return list(input_api.DEFAULT_FILES_TO_SKIP) + [
|
||||||
r"swig/.*\.py$",
|
r"swig/.*\.py$",
|
||||||
@@ -183,8 +123,6 @@ def _CommonChecks(input_api, output_api):
|
|||||||
results.extend(
|
results.extend(
|
||||||
input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
|
input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
|
||||||
input_api, output_api))
|
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(
|
source_file_filter = lambda x: input_api.FilterSourceFile(
|
||||||
x, files_to_skip=_GetFilesToSkip(input_api))
|
x, files_to_skip=_GetFilesToSkip(input_api))
|
||||||
|
|||||||
795
README
Normal file
795
README
Normal file
@@ -0,0 +1,795 @@
|
|||||||
|
__ __ ____ ____ ____
|
||||||
|
/ \\/ \/ _ \/ _ )/ _ \
|
||||||
|
\ / __/ _ \ __/
|
||||||
|
\__\__/\____/\_____/__/ ____ ___
|
||||||
|
/ _/ / \ \ / _ \/ _/
|
||||||
|
/ \_/ / / \ \ __/ \__
|
||||||
|
\____/____/\_____/_____/____/v1.2.1
|
||||||
|
|
||||||
|
Description:
|
||||||
|
============
|
||||||
|
|
||||||
|
WebP codec: library to encode and decode images in WebP format. This package
|
||||||
|
contains the library that can be used in other programs to add WebP support,
|
||||||
|
as well as the command line tools 'cwebp' and 'dwebp'.
|
||||||
|
|
||||||
|
See http://developers.google.com/speed/webp
|
||||||
|
|
||||||
|
The latest source tree is available at
|
||||||
|
https://chromium.googlesource.com/webm/libwebp
|
||||||
|
|
||||||
|
It is released under the same license as the WebM project.
|
||||||
|
See http://www.webmproject.org/license/software/ or the
|
||||||
|
"COPYING" file for details. An additional intellectual
|
||||||
|
property rights grant can be found in the file PATENTS.
|
||||||
|
|
||||||
|
Building:
|
||||||
|
=========
|
||||||
|
|
||||||
|
Windows build:
|
||||||
|
--------------
|
||||||
|
|
||||||
|
By running:
|
||||||
|
|
||||||
|
nmake /f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output
|
||||||
|
|
||||||
|
the directory output\release-static\(x64|x86)\bin will contain the tools
|
||||||
|
cwebp.exe and dwebp.exe. The directory output\release-static\(x64|x86)\lib will
|
||||||
|
contain the libwebp static library.
|
||||||
|
The target architecture (x86/x64) is detected by Makefile.vc from the Visual
|
||||||
|
Studio compiler (cl.exe) available in the system path.
|
||||||
|
|
||||||
|
Unix build using makefile.unix:
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
On platforms with GNU tools installed (gcc and make), running
|
||||||
|
|
||||||
|
make -f makefile.unix
|
||||||
|
|
||||||
|
will build the binaries examples/cwebp and examples/dwebp, along
|
||||||
|
with the static library src/libwebp.a. No system-wide installation
|
||||||
|
is supplied, as this is a simple alternative to the full installation
|
||||||
|
system based on the autoconf tools (see below).
|
||||||
|
Please refer to makefile.unix for additional details and customizations.
|
||||||
|
|
||||||
|
Using autoconf tools:
|
||||||
|
---------------------
|
||||||
|
Prerequisites:
|
||||||
|
A compiler (e.g., gcc), make, autoconf, automake, libtool.
|
||||||
|
On a Debian-like system the following should install everything you need for a
|
||||||
|
minimal build:
|
||||||
|
$ sudo apt-get install gcc make autoconf automake libtool
|
||||||
|
|
||||||
|
When building from git sources, you will need to run autogen.sh to generate the
|
||||||
|
configure script.
|
||||||
|
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
|
||||||
|
should be all you need to have the following files
|
||||||
|
|
||||||
|
/usr/local/include/webp/decode.h
|
||||||
|
/usr/local/include/webp/encode.h
|
||||||
|
/usr/local/include/webp/types.h
|
||||||
|
/usr/local/lib/libwebp.*
|
||||||
|
/usr/local/bin/cwebp
|
||||||
|
/usr/local/bin/dwebp
|
||||||
|
|
||||||
|
installed.
|
||||||
|
|
||||||
|
Note: A decode-only library, libwebpdecoder, is available using the
|
||||||
|
'--enable-libwebpdecoder' flag. The encode library is built separately and can
|
||||||
|
be installed independently using a minor modification in the corresponding
|
||||||
|
Makefile.am configure files (see comments there). See './configure --help' for
|
||||||
|
more options.
|
||||||
|
|
||||||
|
Building for MIPS Linux:
|
||||||
|
------------------------
|
||||||
|
MIPS Linux toolchain stable available releases can be found at:
|
||||||
|
https://community.imgtec.com/developers/mips/tools/codescape-mips-sdk/available-releases/
|
||||||
|
|
||||||
|
# Add toolchain to PATH
|
||||||
|
export PATH=$PATH:/path/to/toolchain/bin
|
||||||
|
|
||||||
|
# 32-bit build for mips32r5 (p5600)
|
||||||
|
HOST=mips-mti-linux-gnu
|
||||||
|
MIPS_CFLAGS="-O3 -mips32r5 -mabi=32 -mtune=p5600 -mmsa -mfp64 \
|
||||||
|
-msched-weight -mload-store-pairs -fPIE"
|
||||||
|
MIPS_LDFLAGS="-mips32r5 -mabi=32 -mmsa -mfp64 -pie"
|
||||||
|
|
||||||
|
# 64-bit build for mips64r6 (i6400)
|
||||||
|
HOST=mips-img-linux-gnu
|
||||||
|
MIPS_CFLAGS="-O3 -mips64r6 -mabi=64 -mtune=i6400 -mmsa -mfp64 \
|
||||||
|
-msched-weight -mload-store-pairs -fPIE"
|
||||||
|
MIPS_LDFLAGS="-mips64r6 -mabi=64 -mmsa -mfp64 -pie"
|
||||||
|
|
||||||
|
./configure --host=${HOST} --build=`config.guess` \
|
||||||
|
CC="${HOST}-gcc -EL" \
|
||||||
|
CFLAGS="$MIPS_CFLAGS" \
|
||||||
|
LDFLAGS="$MIPS_LDFLAGS"
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
|
||||||
|
CMake:
|
||||||
|
------
|
||||||
|
With CMake, you can compile libwebp, cwebp, dwebp, gif2webp, img2webp, webpinfo
|
||||||
|
and the JS bindings.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
A compiler (e.g., gcc with autotools) and CMake.
|
||||||
|
On a Debian-like system the following should install everything you need for a
|
||||||
|
minimal build:
|
||||||
|
$ sudo apt-get install build-essential cmake
|
||||||
|
|
||||||
|
When building from git sources, you will need to run cmake to generate the
|
||||||
|
makefiles.
|
||||||
|
|
||||||
|
mkdir build && cd build && cmake ../
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
|
||||||
|
If you also want any of the executables, you will need to enable them through
|
||||||
|
CMake, e.g.:
|
||||||
|
|
||||||
|
cmake -DWEBP_BUILD_CWEBP=ON -DWEBP_BUILD_DWEBP=ON ../
|
||||||
|
|
||||||
|
or through your favorite interface (like ccmake or cmake-qt-gui).
|
||||||
|
|
||||||
|
Use option -DWEBP_UNICODE=ON for Unicode support on Windows (with chcp 65001).
|
||||||
|
|
||||||
|
Finally, once installed, you can also use WebP in your CMake project by doing:
|
||||||
|
|
||||||
|
find_package(WebP)
|
||||||
|
|
||||||
|
which will define the CMake variables WebP_INCLUDE_DIRS and WebP_LIBRARIES.
|
||||||
|
|
||||||
|
Gradle:
|
||||||
|
-------
|
||||||
|
The support for Gradle is minimal: it only helps you compile libwebp, cwebp and
|
||||||
|
dwebp and webpmux_example.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
A compiler (e.g., gcc with autotools) and gradle.
|
||||||
|
On a Debian-like system the following should install everything you need for a
|
||||||
|
minimal build:
|
||||||
|
$ sudo apt-get install build-essential gradle
|
||||||
|
|
||||||
|
When building from git sources, you will need to run the Gradle wrapper with the
|
||||||
|
appropriate target, e.g. :
|
||||||
|
|
||||||
|
./gradlew buildAllExecutables
|
||||||
|
|
||||||
|
SWIG bindings:
|
||||||
|
--------------
|
||||||
|
|
||||||
|
To generate language bindings from swig/libwebp.swig at least swig-1.3
|
||||||
|
(http://www.swig.org) is required.
|
||||||
|
|
||||||
|
Currently the following functions are mapped:
|
||||||
|
Decode:
|
||||||
|
WebPGetDecoderVersion
|
||||||
|
WebPGetInfo
|
||||||
|
WebPDecodeRGBA
|
||||||
|
WebPDecodeARGB
|
||||||
|
WebPDecodeBGRA
|
||||||
|
WebPDecodeBGR
|
||||||
|
WebPDecodeRGB
|
||||||
|
|
||||||
|
Encode:
|
||||||
|
WebPGetEncoderVersion
|
||||||
|
WebPEncodeRGBA
|
||||||
|
WebPEncodeBGRA
|
||||||
|
WebPEncodeRGB
|
||||||
|
WebPEncodeBGR
|
||||||
|
WebPEncodeLosslessRGBA
|
||||||
|
WebPEncodeLosslessBGRA
|
||||||
|
WebPEncodeLosslessRGB
|
||||||
|
WebPEncodeLosslessBGR
|
||||||
|
|
||||||
|
See swig/README for more detailed build instructions.
|
||||||
|
|
||||||
|
Java bindings:
|
||||||
|
|
||||||
|
To build the swig-generated JNI wrapper code at least JDK-1.5 (or equivalent)
|
||||||
|
is necessary for enum support. The output is intended to be a shared object /
|
||||||
|
DLL that can be loaded via System.loadLibrary("webp_jni").
|
||||||
|
|
||||||
|
Python bindings:
|
||||||
|
|
||||||
|
To build the swig-generated Python extension code at least Python 2.6 is
|
||||||
|
required. Python < 2.6 may build with some minor changes to libwebp.swig or the
|
||||||
|
generated code, but is untested.
|
||||||
|
|
||||||
|
Encoding tool:
|
||||||
|
==============
|
||||||
|
|
||||||
|
The examples/ directory contains tools for encoding (cwebp) and
|
||||||
|
decoding (dwebp) images.
|
||||||
|
|
||||||
|
The easiest use should look like:
|
||||||
|
cwebp input.png -q 80 -o output.webp
|
||||||
|
which will convert the input file to a WebP file using a quality factor of 80
|
||||||
|
on a 0->100 scale (0 being the lowest quality, 100 being the best. Default
|
||||||
|
value is 75).
|
||||||
|
You might want to try the -lossless flag too, which will compress the source
|
||||||
|
(in RGBA format) without any loss. The -q quality parameter will in this case
|
||||||
|
control the amount of processing time spent trying to make the output file as
|
||||||
|
small as possible.
|
||||||
|
|
||||||
|
A longer list of options is available using the -longhelp command line flag:
|
||||||
|
|
||||||
|
> cwebp -longhelp
|
||||||
|
Usage:
|
||||||
|
cwebp [-preset <...>] [options] in_file [-o out_file]
|
||||||
|
|
||||||
|
If input size (-s) for an image is not specified, it is
|
||||||
|
assumed to be a PNG, JPEG, TIFF or WebP file.
|
||||||
|
Note: Animated PNG and WebP files are not supported.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h / -help ............. short help
|
||||||
|
-H / -longhelp ......... long help
|
||||||
|
-q <float> ............. quality factor (0:small..100:big), default=75
|
||||||
|
-alpha_q <int> ......... transparency-compression quality (0..100),
|
||||||
|
default=100
|
||||||
|
-preset <string> ....... preset setting, one of:
|
||||||
|
default, photo, picture,
|
||||||
|
drawing, icon, text
|
||||||
|
-preset must come first, as it overwrites other parameters
|
||||||
|
-z <int> ............... activates lossless preset with given
|
||||||
|
level in [0:fast, ..., 9:slowest]
|
||||||
|
|
||||||
|
-m <int> ............... compression method (0=fast, 6=slowest), default=4
|
||||||
|
-segments <int> ........ number of segments to use (1..4), default=4
|
||||||
|
-size <int> ............ target size (in bytes)
|
||||||
|
-psnr <float> .......... target PSNR (in dB. typically: 42)
|
||||||
|
|
||||||
|
-s <int> <int> ......... input size (width x height) for YUV
|
||||||
|
-sns <int> ............. spatial noise shaping (0:off, 100:max), default=50
|
||||||
|
-f <int> ............... filter strength (0=off..100), default=60
|
||||||
|
-sharpness <int> ....... filter sharpness (0:most .. 7:least sharp), default=0
|
||||||
|
-strong ................ use strong filter instead of simple (default)
|
||||||
|
-nostrong .............. use simple filter instead of strong
|
||||||
|
-sharp_yuv ............. use sharper (and slower) RGB->YUV conversion
|
||||||
|
-partition_limit <int> . limit quality to fit the 512k limit on
|
||||||
|
the first partition (0=no degradation ... 100=full)
|
||||||
|
-pass <int> ............ analysis pass number (1..10)
|
||||||
|
-qrange <min> <max> .... specifies the permissible quality range
|
||||||
|
(default: 0 100)
|
||||||
|
-crop <x> <y> <w> <h> .. crop picture with the given rectangle
|
||||||
|
-resize <w> <h> ........ resize picture (after any cropping)
|
||||||
|
-mt .................... use multi-threading if available
|
||||||
|
-low_memory ............ reduce memory usage (slower encoding)
|
||||||
|
-map <int> ............. print map of extra info
|
||||||
|
-print_psnr ............ prints averaged PSNR distortion
|
||||||
|
-print_ssim ............ prints averaged SSIM distortion
|
||||||
|
-print_lsim ............ prints local-similarity distortion
|
||||||
|
-d <file.pgm> .......... dump the compressed output (PGM file)
|
||||||
|
-alpha_method <int> .... transparency-compression method (0..1), default=1
|
||||||
|
-alpha_filter <string> . predictive filtering for alpha plane,
|
||||||
|
one of: none, fast (default) or best
|
||||||
|
-exact ................. preserve RGB values in transparent area, default=off
|
||||||
|
-blend_alpha <hex> ..... blend colors against background color
|
||||||
|
expressed as RGB values written in
|
||||||
|
hexadecimal, e.g. 0xc0e0d0 for red=0xc0
|
||||||
|
green=0xe0 and blue=0xd0
|
||||||
|
-noalpha ............... discard any transparency information
|
||||||
|
-lossless .............. encode image losslessly, default=off
|
||||||
|
-near_lossless <int> ... use near-lossless image
|
||||||
|
preprocessing (0..100=off), default=100
|
||||||
|
-hint <string> ......... specify image characteristics hint,
|
||||||
|
one of: photo, picture or graph
|
||||||
|
|
||||||
|
-metadata <string> ..... comma separated list of metadata to
|
||||||
|
copy from the input to the output if present.
|
||||||
|
Valid values: all, none (default), exif, icc, xmp
|
||||||
|
|
||||||
|
-short ................. condense printed message
|
||||||
|
-quiet ................. don't print anything
|
||||||
|
-version ............... print version number and exit
|
||||||
|
-noasm ................. disable all assembly optimizations
|
||||||
|
-v ..................... verbose, e.g. print encoding/decoding times
|
||||||
|
-progress .............. report encoding progress
|
||||||
|
|
||||||
|
Experimental Options:
|
||||||
|
-jpeg_like ............. roughly match expected JPEG size
|
||||||
|
-af .................... auto-adjust filter strength
|
||||||
|
-pre <int> ............. pre-processing filter
|
||||||
|
|
||||||
|
|
||||||
|
The main options you might want to try in order to further tune the
|
||||||
|
visual quality are:
|
||||||
|
-preset
|
||||||
|
-sns
|
||||||
|
-f
|
||||||
|
-m
|
||||||
|
|
||||||
|
Namely:
|
||||||
|
* 'preset' will set up a default encoding configuration targeting a
|
||||||
|
particular type of input. It should appear first in the list of options,
|
||||||
|
so that subsequent options can take effect on top of this preset.
|
||||||
|
Default value is 'default'.
|
||||||
|
* 'sns' will progressively turn on (when going from 0 to 100) some additional
|
||||||
|
visual optimizations (like: segmentation map re-enforcement). This option
|
||||||
|
will balance the bit allocation differently. It tries to take bits from the
|
||||||
|
"easy" parts of the picture and use them in the "difficult" ones instead.
|
||||||
|
Usually, raising the sns value (at fixed -q value) leads to larger files,
|
||||||
|
but with better quality.
|
||||||
|
Typical value is around '75'.
|
||||||
|
* 'f' option directly links to the filtering strength used by the codec's
|
||||||
|
in-loop processing. The higher the value, the smoother the
|
||||||
|
highly-compressed area will look. This is particularly useful when aiming
|
||||||
|
at very small files. Typical values are around 20-30. Note that using the
|
||||||
|
option -strong/-nostrong will change the type of filtering. Use "-f 0" to
|
||||||
|
turn filtering off.
|
||||||
|
* 'm' controls the trade-off between encoding speed and quality. Default is 4.
|
||||||
|
You can try -m 5 or -m 6 to explore more (time-consuming) encoding
|
||||||
|
possibilities. A lower value will result in faster encoding at the expense
|
||||||
|
of quality.
|
||||||
|
|
||||||
|
Decoding tool:
|
||||||
|
==============
|
||||||
|
|
||||||
|
There is a decoding sample in examples/dwebp.c which will take
|
||||||
|
a .webp file and decode it to a PNG image file (amongst other formats).
|
||||||
|
This is simply to demonstrate the use of the API. You can verify the
|
||||||
|
file test.webp decodes to exactly the same as test_ref.ppm by using:
|
||||||
|
|
||||||
|
cd examples
|
||||||
|
./dwebp test.webp -ppm -o test.ppm
|
||||||
|
diff test.ppm test_ref.ppm
|
||||||
|
|
||||||
|
The full list of options is available using -h:
|
||||||
|
|
||||||
|
> dwebp -h
|
||||||
|
Usage: dwebp in_file [options] [-o out_file]
|
||||||
|
|
||||||
|
Decodes the WebP image file to PNG format [Default].
|
||||||
|
Note: Animated WebP files are not supported.
|
||||||
|
|
||||||
|
Use following options to convert into alternate image formats:
|
||||||
|
-pam ......... save the raw RGBA samples as a color PAM
|
||||||
|
-ppm ......... save the raw RGB samples as a color PPM
|
||||||
|
-bmp ......... save as uncompressed BMP format
|
||||||
|
-tiff ........ save as uncompressed TIFF format
|
||||||
|
-pgm ......... save the raw YUV samples as a grayscale PGM
|
||||||
|
file with IMC4 layout
|
||||||
|
-yuv ......... save the raw YUV samples in flat layout
|
||||||
|
|
||||||
|
Other options are:
|
||||||
|
-version ..... print version number and exit
|
||||||
|
-nofancy ..... don't use the fancy YUV420 upscaler
|
||||||
|
-nofilter .... disable in-loop filtering
|
||||||
|
-nodither .... disable dithering
|
||||||
|
-dither <d> .. dithering strength (in 0..100)
|
||||||
|
-alpha_dither use alpha-plane dithering if needed
|
||||||
|
-mt .......... use multi-threading
|
||||||
|
-crop <x> <y> <w> <h> ... crop output with the given rectangle
|
||||||
|
-resize <w> <h> ......... scale the output (*after* any cropping)
|
||||||
|
-flip ........ flip the output vertically
|
||||||
|
-alpha ....... only save the alpha plane
|
||||||
|
-incremental . use incremental decoding (useful for tests)
|
||||||
|
-h ........... this help message
|
||||||
|
-v ........... verbose (e.g. print encoding/decoding times)
|
||||||
|
-quiet ....... quiet mode, don't print anything
|
||||||
|
-noasm ....... disable all assembly optimizations
|
||||||
|
|
||||||
|
WebP file analysis tool:
|
||||||
|
========================
|
||||||
|
|
||||||
|
'webpinfo' can be used to print out the chunk level structure and bitstream
|
||||||
|
header information of WebP files. It can also check if the files are of valid
|
||||||
|
WebP format.
|
||||||
|
|
||||||
|
Usage: webpinfo [options] in_files
|
||||||
|
Note: there could be multiple input files;
|
||||||
|
options must come before input files.
|
||||||
|
Options:
|
||||||
|
-version ........... Print version number and exit.
|
||||||
|
-quiet ............. Do not show chunk parsing information.
|
||||||
|
-diag .............. Show parsing error diagnosis.
|
||||||
|
-summary ........... Show chunk stats summary.
|
||||||
|
-bitstream_info .... Parse bitstream header.
|
||||||
|
|
||||||
|
Visualization tool:
|
||||||
|
===================
|
||||||
|
|
||||||
|
There's a little self-serve visualization tool called 'vwebp' under the
|
||||||
|
examples/ directory. It uses OpenGL to open a simple drawing window and show
|
||||||
|
a decoded WebP file. It's not yet integrated in the automake build system, but
|
||||||
|
you can try to manually compile it using the recommendations below.
|
||||||
|
|
||||||
|
Usage: vwebp in_file [options]
|
||||||
|
|
||||||
|
Decodes the WebP image file and visualize it using OpenGL
|
||||||
|
Options are:
|
||||||
|
-version ..... print version number and exit
|
||||||
|
-noicc ....... don't use the icc profile if present
|
||||||
|
-nofancy ..... don't use the fancy YUV420 upscaler
|
||||||
|
-nofilter .... disable in-loop filtering
|
||||||
|
-dither <int> dithering strength (0..100), default=50
|
||||||
|
-noalphadither disable alpha plane dithering
|
||||||
|
-usebgcolor .. display background color
|
||||||
|
-mt .......... use multi-threading
|
||||||
|
-info ........ print info
|
||||||
|
-h ........... this help message
|
||||||
|
|
||||||
|
Keyboard shortcuts:
|
||||||
|
'c' ................ toggle use of color profile
|
||||||
|
'b' ................ toggle background color display
|
||||||
|
'i' ................ overlay file information
|
||||||
|
'd' ................ disable blending & disposal (debug)
|
||||||
|
'q' / 'Q' / ESC .... quit
|
||||||
|
|
||||||
|
Building:
|
||||||
|
---------
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
1) OpenGL & OpenGL Utility Toolkit (GLUT)
|
||||||
|
Linux:
|
||||||
|
$ sudo apt-get install freeglut3-dev mesa-common-dev
|
||||||
|
Mac + Xcode:
|
||||||
|
- These libraries should be available in the OpenGL / GLUT frameworks.
|
||||||
|
Windows:
|
||||||
|
http://freeglut.sourceforge.net/index.php#download
|
||||||
|
|
||||||
|
2) (Optional) qcms (Quick Color Management System)
|
||||||
|
i. Download qcms from Mozilla / Chromium:
|
||||||
|
http://hg.mozilla.org/mozilla-central/file/0e7639e3bdfb/gfx/qcms
|
||||||
|
http://src.chromium.org/viewvc/chrome/trunk/src/third_party/qcms
|
||||||
|
ii. Build and archive the source files as libqcms.a / qcms.lib
|
||||||
|
iii. Update makefile.unix / Makefile.vc
|
||||||
|
a) Define WEBP_HAVE_QCMS
|
||||||
|
b) Update include / library paths to reference the qcms directory.
|
||||||
|
|
||||||
|
Build using makefile.unix / Makefile.vc:
|
||||||
|
$ make -f makefile.unix examples/vwebp
|
||||||
|
> nmake /f Makefile.vc CFG=release-static \
|
||||||
|
../obj/x64/release-static/bin/vwebp.exe
|
||||||
|
|
||||||
|
Animation creation tool:
|
||||||
|
========================
|
||||||
|
The utility 'img2webp' can turn a sequence of input images (PNG, JPEG, ...)
|
||||||
|
into an animated WebP file. It offers fine control over duration, encoding
|
||||||
|
modes, etc.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
img2webp [file-level options] [image files...] [per-frame options...]
|
||||||
|
|
||||||
|
File-level options (only used at the start of compression):
|
||||||
|
-min_size ............ minimize size
|
||||||
|
-loop <int> .......... loop count (default: 0, = infinite loop)
|
||||||
|
-kmax <int> .......... maximum number of frame between key-frames
|
||||||
|
(0=only keyframes)
|
||||||
|
-kmin <int> .......... minimum number of frame between key-frames
|
||||||
|
(0=disable key-frames altogether)
|
||||||
|
-mixed ............... use mixed lossy/lossless automatic mode
|
||||||
|
-v ................... verbose mode
|
||||||
|
-h ................... this help
|
||||||
|
-version ............. print version number and exit
|
||||||
|
|
||||||
|
Per-frame options (only used for subsequent images input):
|
||||||
|
-d <int> ............. frame duration in ms (default: 100)
|
||||||
|
-lossless ........... use lossless mode (default)
|
||||||
|
-lossy ... ........... use lossy mode
|
||||||
|
-q <float> ........... quality
|
||||||
|
-m <int> ............. method to use
|
||||||
|
|
||||||
|
example: img2webp -loop 2 in0.png -lossy in1.jpg
|
||||||
|
-d 80 in2.tiff -o out.webp
|
||||||
|
|
||||||
|
Note: if a single file name is passed as the argument, the arguments will be
|
||||||
|
tokenized from this file. The file name must not start with the character '-'.
|
||||||
|
|
||||||
|
Animated GIF conversion:
|
||||||
|
========================
|
||||||
|
Animated GIF files can be converted to WebP files with animation using the
|
||||||
|
gif2webp utility available under examples/. The files can then be viewed using
|
||||||
|
vwebp.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
gif2webp [options] gif_file -o webp_file
|
||||||
|
Options:
|
||||||
|
-h / -help ............. this help
|
||||||
|
-lossy ................. encode image using lossy compression
|
||||||
|
-mixed ................. for each frame in the image, pick lossy
|
||||||
|
or lossless compression heuristically
|
||||||
|
-q <float> ............. quality factor (0:small..100:big)
|
||||||
|
-m <int> ............... compression method (0=fast, 6=slowest)
|
||||||
|
-min_size .............. minimize output size (default:off)
|
||||||
|
lossless compression by default; can be
|
||||||
|
combined with -q, -m, -lossy or -mixed
|
||||||
|
options
|
||||||
|
-kmin <int> ............ min distance between key frames
|
||||||
|
-kmax <int> ............ max distance between key frames
|
||||||
|
-f <int> ............... filter strength (0=off..100)
|
||||||
|
-metadata <string> ..... comma separated list of metadata to
|
||||||
|
copy from the input to the output if present
|
||||||
|
Valid values: all, none, icc, xmp (default)
|
||||||
|
-loop_compatibility .... use compatibility mode for Chrome
|
||||||
|
version prior to M62 (inclusive)
|
||||||
|
-mt .................... use multi-threading if available
|
||||||
|
|
||||||
|
-version ............... print version number and exit
|
||||||
|
-v ..................... verbose
|
||||||
|
-quiet ................. don't print anything
|
||||||
|
|
||||||
|
Building:
|
||||||
|
---------
|
||||||
|
With the libgif development files installed, gif2webp can be built using
|
||||||
|
makefile.unix:
|
||||||
|
$ make -f makefile.unix examples/gif2webp
|
||||||
|
|
||||||
|
or using autoconf:
|
||||||
|
$ ./configure --enable-everything
|
||||||
|
$ make
|
||||||
|
|
||||||
|
Comparison of animated images:
|
||||||
|
==============================
|
||||||
|
Test utility anim_diff under examples/ can be used to compare two animated
|
||||||
|
images (each can be GIF or WebP).
|
||||||
|
|
||||||
|
Usage: anim_diff <image1> <image2> [options]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-dump_frames <folder> dump decoded frames in PAM format
|
||||||
|
-min_psnr <float> ... minimum per-frame PSNR
|
||||||
|
-raw_comparison ..... if this flag is not used, RGB is
|
||||||
|
premultiplied before comparison
|
||||||
|
-max_diff <int> ..... maximum allowed difference per channel
|
||||||
|
between corresponding pixels in subsequent
|
||||||
|
frames
|
||||||
|
-h .................. this help
|
||||||
|
-version ............ print version number and exit
|
||||||
|
|
||||||
|
Building:
|
||||||
|
---------
|
||||||
|
With the libgif development files and a C++ compiler installed, anim_diff can
|
||||||
|
be built using makefile.unix:
|
||||||
|
$ make -f makefile.unix examples/anim_diff
|
||||||
|
|
||||||
|
or using autoconf:
|
||||||
|
$ ./configure --enable-everything
|
||||||
|
$ make
|
||||||
|
|
||||||
|
Encoding API:
|
||||||
|
=============
|
||||||
|
|
||||||
|
The main encoding functions are available in the header src/webp/encode.h
|
||||||
|
The ready-to-use ones are:
|
||||||
|
size_t WebPEncodeRGB(const uint8_t* rgb, int width, int height, int stride,
|
||||||
|
float quality_factor, uint8_t** output);
|
||||||
|
size_t WebPEncodeBGR(const uint8_t* bgr, int width, int height, int stride,
|
||||||
|
float quality_factor, uint8_t** output);
|
||||||
|
size_t WebPEncodeRGBA(const uint8_t* rgba, int width, int height, int stride,
|
||||||
|
float quality_factor, uint8_t** output);
|
||||||
|
size_t WebPEncodeBGRA(const uint8_t* bgra, int width, int height, int stride,
|
||||||
|
float quality_factor, uint8_t** output);
|
||||||
|
|
||||||
|
They will convert raw RGB samples to a WebP data. The only control supplied
|
||||||
|
is the quality factor.
|
||||||
|
|
||||||
|
There are some variants for using the lossless format:
|
||||||
|
|
||||||
|
size_t WebPEncodeLosslessRGB(const uint8_t* rgb, int width, int height,
|
||||||
|
int stride, uint8_t** output);
|
||||||
|
size_t WebPEncodeLosslessBGR(const uint8_t* bgr, int width, int height,
|
||||||
|
int stride, uint8_t** output);
|
||||||
|
size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, int width, int height,
|
||||||
|
int stride, uint8_t** output);
|
||||||
|
size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, int width, int height,
|
||||||
|
int stride, uint8_t** output);
|
||||||
|
|
||||||
|
Of course in this case, no quality factor is needed since the compression
|
||||||
|
occurs without loss of the input values, at the expense of larger output sizes.
|
||||||
|
|
||||||
|
Advanced encoding API:
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
A more advanced API is based on the WebPConfig and WebPPicture structures.
|
||||||
|
|
||||||
|
WebPConfig contains the encoding settings and is not tied to a particular
|
||||||
|
picture.
|
||||||
|
WebPPicture contains input data, on which some WebPConfig will be used for
|
||||||
|
compression.
|
||||||
|
The encoding flow looks like:
|
||||||
|
|
||||||
|
-------------------------------------- BEGIN PSEUDO EXAMPLE
|
||||||
|
|
||||||
|
#include <webp/encode.h>
|
||||||
|
|
||||||
|
// Setup a config, starting form a preset and tuning some additional
|
||||||
|
// parameters
|
||||||
|
WebPConfig config;
|
||||||
|
if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) {
|
||||||
|
return 0; // version error
|
||||||
|
}
|
||||||
|
// ... additional tuning
|
||||||
|
config.sns_strength = 90;
|
||||||
|
config.filter_sharpness = 6;
|
||||||
|
config_error = WebPValidateConfig(&config); // not mandatory, but useful
|
||||||
|
|
||||||
|
// Setup the input data
|
||||||
|
WebPPicture pic;
|
||||||
|
if (!WebPPictureInit(&pic)) {
|
||||||
|
return 0; // version error
|
||||||
|
}
|
||||||
|
pic.width = width;
|
||||||
|
pic.height = height;
|
||||||
|
// allocated picture of dimension width x height
|
||||||
|
if (!WebPPictureAlloc(&pic)) {
|
||||||
|
return 0; // memory error
|
||||||
|
}
|
||||||
|
// at this point, 'pic' has been initialized as a container,
|
||||||
|
// and can receive the Y/U/V samples.
|
||||||
|
// Alternatively, one could use ready-made import functions like
|
||||||
|
// WebPPictureImportRGB(), which will take care of memory allocation.
|
||||||
|
// In any case, past this point, one will have to call
|
||||||
|
// WebPPictureFree(&pic) to reclaim memory.
|
||||||
|
|
||||||
|
// Set up a byte-output write method. WebPMemoryWriter, for instance.
|
||||||
|
WebPMemoryWriter wrt;
|
||||||
|
WebPMemoryWriterInit(&wrt); // initialize 'wrt'
|
||||||
|
|
||||||
|
pic.writer = MyFileWriter;
|
||||||
|
pic.custom_ptr = my_opaque_structure_to_make_MyFileWriter_work;
|
||||||
|
|
||||||
|
// Compress!
|
||||||
|
int ok = WebPEncode(&config, &pic); // ok = 0 => error occurred!
|
||||||
|
WebPPictureFree(&pic); // must be called independently of the 'ok' result.
|
||||||
|
|
||||||
|
// output data should have been handled by the writer at that point.
|
||||||
|
// -> compressed data is the memory buffer described by wrt.mem / wrt.size
|
||||||
|
|
||||||
|
// deallocate the memory used by compressed data
|
||||||
|
WebPMemoryWriterClear(&wrt);
|
||||||
|
|
||||||
|
-------------------------------------- END PSEUDO EXAMPLE
|
||||||
|
|
||||||
|
Decoding API:
|
||||||
|
=============
|
||||||
|
|
||||||
|
This is mainly just one function to call:
|
||||||
|
|
||||||
|
#include "webp/decode.h"
|
||||||
|
uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size,
|
||||||
|
int* width, int* height);
|
||||||
|
|
||||||
|
Please have a look at the file src/webp/decode.h for the details.
|
||||||
|
There are variants for decoding in BGR/RGBA/ARGB/BGRA order, along with
|
||||||
|
decoding to raw Y'CbCr samples. One can also decode the image directly into a
|
||||||
|
pre-allocated buffer.
|
||||||
|
|
||||||
|
To detect a WebP file and gather the picture's dimensions, the function:
|
||||||
|
int WebPGetInfo(const uint8_t* data, size_t data_size,
|
||||||
|
int* width, int* height);
|
||||||
|
is supplied. No decoding is involved when using it.
|
||||||
|
|
||||||
|
Incremental decoding API:
|
||||||
|
=========================
|
||||||
|
|
||||||
|
In the case when data is being progressively transmitted, pictures can still
|
||||||
|
be incrementally decoded using a slightly more complicated API. Decoder state
|
||||||
|
is stored into an instance of the WebPIDecoder object. This object can be
|
||||||
|
created with the purpose of decoding either RGB or Y'CbCr samples.
|
||||||
|
For instance:
|
||||||
|
|
||||||
|
WebPDecBuffer buffer;
|
||||||
|
WebPInitDecBuffer(&buffer);
|
||||||
|
buffer.colorspace = MODE_BGR;
|
||||||
|
...
|
||||||
|
WebPIDecoder* idec = WebPINewDecoder(&buffer);
|
||||||
|
|
||||||
|
As data is made progressively available, this incremental-decoder object
|
||||||
|
can be used to decode the picture further. There are two (mutually exclusive)
|
||||||
|
ways to pass freshly arrived data:
|
||||||
|
|
||||||
|
either by appending the fresh bytes:
|
||||||
|
|
||||||
|
WebPIAppend(idec, fresh_data, size_of_fresh_data);
|
||||||
|
|
||||||
|
or by just mentioning the new size of the transmitted data:
|
||||||
|
|
||||||
|
WebPIUpdate(idec, buffer, size_of_transmitted_buffer);
|
||||||
|
|
||||||
|
Note that 'buffer' can be modified between each call to WebPIUpdate, in
|
||||||
|
particular when the buffer is resized to accommodate larger data.
|
||||||
|
|
||||||
|
These functions will return the decoding status: either VP8_STATUS_SUSPENDED if
|
||||||
|
decoding is not finished yet or VP8_STATUS_OK when decoding is done. Any other
|
||||||
|
status is an error condition.
|
||||||
|
|
||||||
|
The 'idec' object must always be released (even upon an error condition) by
|
||||||
|
calling: WebPDelete(idec).
|
||||||
|
|
||||||
|
To retrieve partially decoded picture samples, one must use the corresponding
|
||||||
|
method: WebPIDecGetRGB or WebPIDecGetYUVA.
|
||||||
|
It will return the last displayable pixel row.
|
||||||
|
|
||||||
|
Lastly, note that decoding can also be performed into a pre-allocated pixel
|
||||||
|
buffer. This buffer must be passed when creating a WebPIDecoder, calling
|
||||||
|
WebPINewRGB() or WebPINewYUVA().
|
||||||
|
|
||||||
|
Please have a look at the src/webp/decode.h header for further details.
|
||||||
|
|
||||||
|
Advanced Decoding API:
|
||||||
|
======================
|
||||||
|
|
||||||
|
WebP decoding supports an advanced API which provides on-the-fly cropping and
|
||||||
|
rescaling, something of great usefulness on memory-constrained environments like
|
||||||
|
mobile phones. Basically, the memory usage will scale with the output's size,
|
||||||
|
not the input's, when one only needs a quick preview or a zoomed in portion of
|
||||||
|
an otherwise too-large picture. Some CPU can be saved too, incidentally.
|
||||||
|
|
||||||
|
-------------------------------------- BEGIN PSEUDO EXAMPLE
|
||||||
|
// A) Init a configuration object
|
||||||
|
WebPDecoderConfig config;
|
||||||
|
CHECK(WebPInitDecoderConfig(&config));
|
||||||
|
|
||||||
|
// B) optional: retrieve the bitstream's features.
|
||||||
|
CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
|
||||||
|
|
||||||
|
// C) Adjust 'config' options, if needed
|
||||||
|
config.options.no_fancy_upsampling = 1;
|
||||||
|
config.options.use_scaling = 1;
|
||||||
|
config.options.scaled_width = scaledWidth();
|
||||||
|
config.options.scaled_height = scaledHeight();
|
||||||
|
// etc.
|
||||||
|
|
||||||
|
// D) Specify 'config' output options for specifying output colorspace.
|
||||||
|
// Optionally the external image decode buffer can also be specified.
|
||||||
|
config.output.colorspace = MODE_BGRA;
|
||||||
|
// Optionally, the config.output can be pointed to an external buffer as
|
||||||
|
// well for decoding the image. This externally supplied memory buffer
|
||||||
|
// should be big enough to store the decoded picture.
|
||||||
|
config.output.u.RGBA.rgba = (uint8_t*) memory_buffer;
|
||||||
|
config.output.u.RGBA.stride = scanline_stride;
|
||||||
|
config.output.u.RGBA.size = total_size_of_the_memory_buffer;
|
||||||
|
config.output.is_external_memory = 1;
|
||||||
|
|
||||||
|
// E) Decode the WebP image. There are two variants w.r.t decoding image.
|
||||||
|
// The first one (E.1) decodes the full image and the second one (E.2) is
|
||||||
|
// used to incrementally decode the image using small input buffers.
|
||||||
|
// Any one of these steps can be used to decode the WebP image.
|
||||||
|
|
||||||
|
// E.1) Decode full image.
|
||||||
|
CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK);
|
||||||
|
|
||||||
|
// E.2) Decode image incrementally.
|
||||||
|
WebPIDecoder* const idec = WebPIDecode(NULL, NULL, &config);
|
||||||
|
CHECK(idec != NULL);
|
||||||
|
while (bytes_remaining > 0) {
|
||||||
|
VP8StatusCode status = WebPIAppend(idec, input, bytes_read);
|
||||||
|
if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) {
|
||||||
|
bytes_remaining -= bytes_read;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WebPIDelete(idec);
|
||||||
|
|
||||||
|
// F) Decoded image is now in config.output (and config.output.u.RGBA).
|
||||||
|
// It can be saved, displayed or otherwise processed.
|
||||||
|
|
||||||
|
// G) Reclaim memory allocated in config's object. It's safe to call
|
||||||
|
// this function even if the memory is external and wasn't allocated
|
||||||
|
// by WebPDecode().
|
||||||
|
WebPFreeDecBuffer(&config.output);
|
||||||
|
|
||||||
|
-------------------------------------- END PSEUDO EXAMPLE
|
||||||
|
|
||||||
|
Bugs:
|
||||||
|
=====
|
||||||
|
|
||||||
|
Please report all bugs to the issue tracker:
|
||||||
|
https://bugs.chromium.org/p/webp
|
||||||
|
Patches welcome! See this page to get started:
|
||||||
|
http://www.webmproject.org/code/contribute/submitting-patches/
|
||||||
|
|
||||||
|
Discuss:
|
||||||
|
========
|
||||||
|
|
||||||
|
Email: webp-discuss@webmproject.org
|
||||||
|
Web: http://groups.google.com/a/webmproject.org/group/webp-discuss
|
||||||
54
README.md
54
README.md
@@ -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
|
|
||||||
258
README.mux
Normal file
258
README.mux
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
__ __ ____ ____ ____ __ __ _ __ __
|
||||||
|
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
|
||||||
|
\ / __/ _ \ __/ / / (_/ /__
|
||||||
|
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v1.2.1
|
||||||
|
|
||||||
|
|
||||||
|
Description:
|
||||||
|
============
|
||||||
|
|
||||||
|
WebPMux: set of two libraries 'Mux' and 'Demux' for creation, extraction and
|
||||||
|
manipulation of an extended format WebP file, which can have features like
|
||||||
|
color profile, metadata and animation. Reference command-line tools 'webpmux'
|
||||||
|
and 'vwebp' as well as the WebP container specification
|
||||||
|
'doc/webp-container-spec.txt' are also provided in this package.
|
||||||
|
|
||||||
|
WebP Mux tool:
|
||||||
|
==============
|
||||||
|
|
||||||
|
The examples/ directory contains a tool (webpmux) for manipulating WebP
|
||||||
|
files. The webpmux tool can be used to create an extended format WebP file and
|
||||||
|
also to extract or strip relevant data from such a file.
|
||||||
|
|
||||||
|
A list of options is available using the -help command line flag:
|
||||||
|
|
||||||
|
> webpmux -help
|
||||||
|
Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT
|
||||||
|
webpmux -set SET_OPTIONS INPUT -o OUTPUT
|
||||||
|
webpmux -duration DURATION_OPTIONS [-duration ...]
|
||||||
|
INPUT -o OUTPUT
|
||||||
|
webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT
|
||||||
|
webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]
|
||||||
|
[-bgcolor BACKGROUND_COLOR] -o OUTPUT
|
||||||
|
webpmux -info INPUT
|
||||||
|
webpmux [-h|-help]
|
||||||
|
webpmux -version
|
||||||
|
webpmux argument_file_name
|
||||||
|
|
||||||
|
GET_OPTIONS:
|
||||||
|
Extract relevant data:
|
||||||
|
icc get ICC profile
|
||||||
|
exif get EXIF metadata
|
||||||
|
xmp get XMP metadata
|
||||||
|
frame n get nth frame
|
||||||
|
|
||||||
|
SET_OPTIONS:
|
||||||
|
Set color profile/metadata/parameters:
|
||||||
|
loop LOOP_COUNT set the loop count
|
||||||
|
bgcolor BACKGROUND_COLOR set the animation background color
|
||||||
|
icc file.icc set ICC profile
|
||||||
|
exif file.exif set EXIF metadata
|
||||||
|
xmp file.xmp set XMP metadata
|
||||||
|
where: 'file.icc' contains the ICC profile to be set,
|
||||||
|
'file.exif' contains the EXIF metadata to be set
|
||||||
|
'file.xmp' contains the XMP metadata to be set
|
||||||
|
|
||||||
|
DURATION_OPTIONS:
|
||||||
|
Set duration of selected frames:
|
||||||
|
duration set duration for each frames
|
||||||
|
duration,frame set duration of a particular frame
|
||||||
|
duration,start,end set duration of frames in the
|
||||||
|
interval [start,end])
|
||||||
|
where: 'duration' is the duration in milliseconds
|
||||||
|
'start' is the start frame index
|
||||||
|
'end' is the inclusive end frame index
|
||||||
|
The special 'end' value '0' means: last frame.
|
||||||
|
|
||||||
|
STRIP_OPTIONS:
|
||||||
|
Strip color profile/metadata:
|
||||||
|
icc strip ICC profile
|
||||||
|
exif strip EXIF metadata
|
||||||
|
xmp strip XMP metadata
|
||||||
|
|
||||||
|
FRAME_OPTIONS(i):
|
||||||
|
Create animation:
|
||||||
|
file_i +di+[xi+yi[+mi[bi]]]
|
||||||
|
where: 'file_i' is the i'th animation frame (WebP format),
|
||||||
|
'di' is the pause duration before next frame,
|
||||||
|
'xi','yi' specify the image offset for this frame,
|
||||||
|
'mi' is the dispose method for this frame (0 or 1),
|
||||||
|
'bi' is the blending method for this frame (+b or -b)
|
||||||
|
|
||||||
|
LOOP_COUNT:
|
||||||
|
Number of times to repeat the animation.
|
||||||
|
Valid range is 0 to 65535 [Default: 0 (infinite)].
|
||||||
|
|
||||||
|
BACKGROUND_COLOR:
|
||||||
|
Background color of the canvas.
|
||||||
|
A,R,G,B
|
||||||
|
where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying
|
||||||
|
the Alpha, Red, Green and Blue component values respectively
|
||||||
|
[Default: 255,255,255,255]
|
||||||
|
|
||||||
|
INPUT & OUTPUT are in WebP format.
|
||||||
|
|
||||||
|
Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be
|
||||||
|
valid.
|
||||||
|
|
||||||
|
Note: if a single file name is passed as the argument, the arguments will be
|
||||||
|
tokenized from this file. The file name must not start with the character '-'.
|
||||||
|
|
||||||
|
Visualization tool:
|
||||||
|
===================
|
||||||
|
|
||||||
|
The examples/ directory also contains a tool (vwebp) for viewing WebP files.
|
||||||
|
It decodes the image and visualizes it using OpenGL. See the libwebp README
|
||||||
|
for details on building and running this program.
|
||||||
|
|
||||||
|
Mux API:
|
||||||
|
========
|
||||||
|
The Mux API contains methods for adding data to and reading data from WebP
|
||||||
|
files. This API currently supports XMP/EXIF metadata, ICC profile and animation.
|
||||||
|
Other features may be added in subsequent releases.
|
||||||
|
|
||||||
|
Example#1 (pseudo code): Creating a WebPMux object with image data, color
|
||||||
|
profile and XMP metadata.
|
||||||
|
|
||||||
|
int copy_data = 0;
|
||||||
|
WebPMux* mux = WebPMuxNew();
|
||||||
|
// ... (Prepare image data).
|
||||||
|
WebPMuxSetImage(mux, &image, copy_data);
|
||||||
|
// ... (Prepare ICC profile data).
|
||||||
|
WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data);
|
||||||
|
// ... (Prepare XMP metadata).
|
||||||
|
WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data);
|
||||||
|
// Get data from mux in WebP RIFF format.
|
||||||
|
WebPMuxAssemble(mux, &output_data);
|
||||||
|
WebPMuxDelete(mux);
|
||||||
|
// ... (Consume output_data; e.g. write output_data.bytes to file).
|
||||||
|
WebPDataClear(&output_data);
|
||||||
|
|
||||||
|
|
||||||
|
Example#2 (pseudo code): Get image and color profile data from a WebP file.
|
||||||
|
|
||||||
|
int copy_data = 0;
|
||||||
|
// ... (Read data from file).
|
||||||
|
WebPMux* mux = WebPMuxCreate(&data, copy_data);
|
||||||
|
WebPMuxGetFrame(mux, 1, &image);
|
||||||
|
// ... (Consume image; e.g. call WebPDecode() to decode the data).
|
||||||
|
WebPMuxGetChunk(mux, "ICCP", &icc_profile);
|
||||||
|
// ... (Consume icc_profile).
|
||||||
|
WebPMuxDelete(mux);
|
||||||
|
free(data);
|
||||||
|
|
||||||
|
|
||||||
|
For a detailed Mux API reference, please refer to the header file
|
||||||
|
(src/webp/mux.h).
|
||||||
|
|
||||||
|
Demux API:
|
||||||
|
==========
|
||||||
|
The Demux API enables extraction of images and extended format data from
|
||||||
|
WebP files. This API currently supports reading of XMP/EXIF metadata, ICC
|
||||||
|
profile and animated images. Other features may be added in subsequent
|
||||||
|
releases.
|
||||||
|
|
||||||
|
Code example: Demuxing WebP data to extract all the frames, ICC profile
|
||||||
|
and EXIF/XMP metadata.
|
||||||
|
|
||||||
|
WebPDemuxer* demux = WebPDemux(&webp_data);
|
||||||
|
uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
|
||||||
|
uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
|
||||||
|
// ... (Get information about the features present in the WebP file).
|
||||||
|
uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS);
|
||||||
|
|
||||||
|
// ... (Iterate over all frames).
|
||||||
|
WebPIterator iter;
|
||||||
|
if (WebPDemuxGetFrame(demux, 1, &iter)) {
|
||||||
|
do {
|
||||||
|
// ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(),
|
||||||
|
// ... and get other frame properties like width, height, offsets etc.
|
||||||
|
// ... see 'struct WebPIterator' below for more info).
|
||||||
|
} while (WebPDemuxNextFrame(&iter));
|
||||||
|
WebPDemuxReleaseIterator(&iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... (Extract metadata).
|
||||||
|
WebPChunkIterator chunk_iter;
|
||||||
|
if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter);
|
||||||
|
// ... (Consume the ICC profile in 'chunk_iter.chunk').
|
||||||
|
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
||||||
|
if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter);
|
||||||
|
// ... (Consume the EXIF metadata in 'chunk_iter.chunk').
|
||||||
|
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
||||||
|
if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter);
|
||||||
|
// ... (Consume the XMP metadata in 'chunk_iter.chunk').
|
||||||
|
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
||||||
|
WebPDemuxDelete(demux);
|
||||||
|
|
||||||
|
|
||||||
|
For a detailed Demux API reference, please refer to the header file
|
||||||
|
(src/webp/demux.h).
|
||||||
|
|
||||||
|
AnimEncoder API:
|
||||||
|
================
|
||||||
|
The AnimEncoder API can be used to create animated WebP images.
|
||||||
|
|
||||||
|
Code example:
|
||||||
|
|
||||||
|
WebPAnimEncoderOptions enc_options;
|
||||||
|
WebPAnimEncoderOptionsInit(&enc_options);
|
||||||
|
// ... (Tune 'enc_options' as needed).
|
||||||
|
WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options);
|
||||||
|
while(<there are more frames>) {
|
||||||
|
WebPConfig config;
|
||||||
|
WebPConfigInit(&config);
|
||||||
|
// ... (Tune 'config' as needed).
|
||||||
|
WebPAnimEncoderAdd(enc, frame, duration, &config);
|
||||||
|
}
|
||||||
|
WebPAnimEncoderAssemble(enc, webp_data);
|
||||||
|
WebPAnimEncoderDelete(enc);
|
||||||
|
// ... (Write the 'webp_data' to a file, or re-mux it further).
|
||||||
|
|
||||||
|
|
||||||
|
For a detailed AnimEncoder API reference, please refer to the header file
|
||||||
|
(src/webp/mux.h).
|
||||||
|
|
||||||
|
AnimDecoder API:
|
||||||
|
================
|
||||||
|
This AnimDecoder API allows decoding (possibly) animated WebP images.
|
||||||
|
|
||||||
|
Code Example:
|
||||||
|
|
||||||
|
WebPAnimDecoderOptions dec_options;
|
||||||
|
WebPAnimDecoderOptionsInit(&dec_options);
|
||||||
|
// Tune 'dec_options' as needed.
|
||||||
|
WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options);
|
||||||
|
WebPAnimInfo anim_info;
|
||||||
|
WebPAnimDecoderGetInfo(dec, &anim_info);
|
||||||
|
for (uint32_t i = 0; i < anim_info.loop_count; ++i) {
|
||||||
|
while (WebPAnimDecoderHasMoreFrames(dec)) {
|
||||||
|
uint8_t* buf;
|
||||||
|
int timestamp;
|
||||||
|
WebPAnimDecoderGetNext(dec, &buf, ×tamp);
|
||||||
|
// ... (Render 'buf' based on 'timestamp').
|
||||||
|
// ... (Do NOT free 'buf', as it is owned by 'dec').
|
||||||
|
}
|
||||||
|
WebPAnimDecoderReset(dec);
|
||||||
|
}
|
||||||
|
const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec);
|
||||||
|
// ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data).
|
||||||
|
WebPAnimDecoderDelete(dec);
|
||||||
|
|
||||||
|
For a detailed AnimDecoder API reference, please refer to the header file
|
||||||
|
(src/webp/demux.h).
|
||||||
|
|
||||||
|
|
||||||
|
Bugs:
|
||||||
|
=====
|
||||||
|
|
||||||
|
Please report all bugs to the issue tracker:
|
||||||
|
https://bugs.chromium.org/p/webp
|
||||||
|
Patches welcome! See this page to get started:
|
||||||
|
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
|
||||||
75
README.webp_js
Normal file
75
README.webp_js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
__ __ ____ ____ ____ __ ____
|
||||||
|
/ \\/ \ _ \ _ \ _ \ (__)/ __\
|
||||||
|
\ / __/ _ \ __/ _) \_ \
|
||||||
|
\__\__/_____/____/_/ /____/____/
|
||||||
|
|
||||||
|
Description:
|
||||||
|
============
|
||||||
|
|
||||||
|
This file describes the compilation of libwebp into a JavaScript decoder
|
||||||
|
using Emscripten and CMake.
|
||||||
|
|
||||||
|
- install the Emscripten SDK following the procedure described at:
|
||||||
|
https://emscripten.org/docs/getting_started/downloads.html#installation-instructions-using-the-emsdk-recommended
|
||||||
|
After installation, you should have some global variable positioned to the
|
||||||
|
location of the SDK. In particular, $EMSDK should point to the
|
||||||
|
top-level directory containing Emscripten tools.
|
||||||
|
|
||||||
|
- configure the project 'WEBP_JS' with CMake using:
|
||||||
|
|
||||||
|
cd webp_js && \
|
||||||
|
emcmake cmake -DWEBP_BUILD_WEBP_JS=ON \
|
||||||
|
../
|
||||||
|
|
||||||
|
- compile webp.js using 'emmake make'.
|
||||||
|
|
||||||
|
- that's it! Upon completion, you should have the webp.js and
|
||||||
|
webp.wasm files generated.
|
||||||
|
|
||||||
|
The callable JavaScript function is WebPToSDL(), which decodes a raw WebP
|
||||||
|
bitstream into a canvas. See webp_js/index.html for a simple usage sample
|
||||||
|
(see below for instructions).
|
||||||
|
|
||||||
|
Demo HTML page:
|
||||||
|
===============
|
||||||
|
|
||||||
|
The HTML page webp_js/index.html requires an HTTP server to serve the WebP
|
||||||
|
image example. It's easy to just use Python for that.
|
||||||
|
|
||||||
|
cd webp_js && python -m SimpleHTTPServer 8080
|
||||||
|
|
||||||
|
and then navigate to http://localhost:8080 in your favorite browser.
|
||||||
|
|
||||||
|
|
||||||
|
Web-Assembly (WASM) version:
|
||||||
|
============================
|
||||||
|
|
||||||
|
CMakeLists.txt is configured to build the WASM version when using
|
||||||
|
the option WEBP_BUILD_WEBP_JS=ON. The compilation step will assemble
|
||||||
|
the files 'webp_wasm.js', 'webp_wasm.wasm' in the webp_js/ directory.
|
||||||
|
See webp_js/index_wasm.html for a simple demo page using the WASM version
|
||||||
|
of the library.
|
||||||
|
|
||||||
|
You will need a fairly recent version of Emscripten (at least 2.0.18,
|
||||||
|
latest-upstream is recommended) and of your WASM-enabled browser to run this
|
||||||
|
version.
|
||||||
|
|
||||||
|
Caveat:
|
||||||
|
=======
|
||||||
|
|
||||||
|
- First decoding using the library is usually slower, due to just-in-time
|
||||||
|
compilation.
|
||||||
|
|
||||||
|
- Some versions of llvm produce the following compile error when SSE2 is
|
||||||
|
enabled.
|
||||||
|
|
||||||
|
"Unsupported: %516 = bitcast <8 x i16> %481 to i128
|
||||||
|
LLVM ERROR: BitCast Instruction not yet supported for integer types larger than 64 bits"
|
||||||
|
|
||||||
|
The corresponding Emscripten bug is at:
|
||||||
|
https://github.com/kripken/emscripten/issues/3788
|
||||||
|
|
||||||
|
Therefore, SSE2 optimization is currently disabled in CMakeLists.txt.
|
||||||
|
|
||||||
|
- If WEBP_ENABLE_SIMD is set to 1 the JavaScript version (webp.js) will be
|
||||||
|
disabled as wasm2js does not support SIMD.
|
||||||
@@ -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"
|
||||||
@@ -173,7 +165,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"
|
||||||
|
|||||||
@@ -3,17 +3,9 @@ set(WEBP_VERSION ${WebP_VERSION})
|
|||||||
|
|
||||||
@PACKAGE_INIT@
|
@PACKAGE_INIT@
|
||||||
|
|
||||||
if(@WEBP_USE_THREAD@)
|
|
||||||
include(CMakeFindDependencyMacro)
|
|
||||||
find_dependency(Threads REQUIRED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||||
|
|
||||||
set_and_check(WebP_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
|
set(WebP_INCLUDE_DIRS "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
|
||||||
set(WebP_INCLUDE_DIRS ${WebP_INCLUDE_DIR})
|
set(WEBP_INCLUDE_DIRS ${WebP_INCLUDE_DIRS})
|
||||||
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)
|
|
||||||
|
|||||||
@@ -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,9 @@
|
|||||||
/* 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 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@"
|
||||||
|
|
||||||
@@ -75,6 +108,9 @@
|
|||||||
/* Set to 1 if JPEG library is installed */
|
/* Set to 1 if JPEG library is installed */
|
||||||
#cmakedefine WEBP_HAVE_JPEG 1
|
#cmakedefine WEBP_HAVE_JPEG 1
|
||||||
|
|
||||||
|
/* Set to 1 if Wasm SIMD is supported */
|
||||||
|
#cmakedefine WEBP_HAVE_WASM_SIMD
|
||||||
|
|
||||||
/* Set to 1 if NEON is supported */
|
/* Set to 1 if NEON is supported */
|
||||||
#cmakedefine WEBP_HAVE_NEON
|
#cmakedefine WEBP_HAVE_NEON
|
||||||
|
|
||||||
@@ -94,9 +130,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
|
||||||
|
|
||||||
@@ -108,4 +141,12 @@
|
|||||||
|
|
||||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||||
#cmakedefine WORDS_BIGENDIAN 1
|
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||||
|
# if defined __BIG_ENDIAN__
|
||||||
|
# define WORDS_BIGENDIAN 1
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# ifndef WORDS_BIGENDIAN
|
||||||
|
# undef WORDS_BIGENDIAN
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -18,42 +18,15 @@ 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("
|
||||||
# If building a universal binary on macOS, we need to check if one of the
|
|
||||||
# architectures supports the SIMD flag.
|
|
||||||
set(OSX_CHECK "")
|
|
||||||
if(APPLE AND CMAKE_OSX_ARCHITECTURES)
|
|
||||||
list(LENGTH CMAKE_OSX_ARCHITECTURES ARCH_COUNT)
|
|
||||||
if(ARCH_COUNT EQUAL 2)
|
|
||||||
set(OSX_CHECK "defined(WEBP_CAN_HAVE_${WEBP_SIMD_FLAG}) &&")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
check_c_source_compiles(
|
|
||||||
"
|
|
||||||
#include \"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/dsp.h\"
|
#include \"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/dsp.h\"
|
||||||
#if defined(__APPLE__)
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
#define WEBP_CAN_HAVE_SSE2
|
|
||||||
#define WEBP_CAN_HAVE_SSE41
|
|
||||||
#define WEBP_CAN_HAVE_AVX2
|
|
||||||
#elif defined(__aarch64__)
|
|
||||||
#define WEBP_CAN_HAVE_NEON
|
|
||||||
#endif
|
|
||||||
// MIPS intrinsics are not supported on macOS, but we have to define them
|
|
||||||
// so that the check happens.
|
|
||||||
#define WEBP_CAN_HAVE_MIPS32
|
|
||||||
#define WEBP_CAN_HAVE_MIPS_DSP_R2
|
|
||||||
#define WEBP_CAN_HAVE_MSA
|
|
||||||
#endif
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
#if ${OSX_CHECK} !defined(WEBP_USE_${WEBP_SIMD_FLAG})
|
#if !defined(WEBP_USE_${WEBP_SIMD_FLAG})
|
||||||
this is not valid code
|
this is not valid code
|
||||||
#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)
|
||||||
@@ -63,9 +36,9 @@ 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 "WASM_SIMD;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")
|
"_wasm.c;_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c")
|
||||||
if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
||||||
# With at least Visual Studio 12 (2013)+ /arch is not necessary to build SSE2
|
# With at least Visual Studio 12 (2013)+ /arch is not necessary to build SSE2
|
||||||
# or SSE4 code unless a lesser /arch is forced. MSVC does not have a SSE4
|
# or SSE4 code unless a lesser /arch is forced. MSVC does not have a SSE4
|
||||||
@@ -75,20 +48,21 @@ if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
|||||||
if(MSVC_VERSION GREATER_EQUAL 1800 AND NOT CMAKE_C_FLAGS MATCHES "/arch:")
|
if(MSVC_VERSION GREATER_EQUAL 1800 AND NOT CMAKE_C_FLAGS MATCHES "/arch:")
|
||||||
set(SIMD_ENABLE_FLAGS)
|
set(SIMD_ENABLE_FLAGS)
|
||||||
else()
|
else()
|
||||||
set(SIMD_ENABLE_FLAGS "/arch:AVX2;/arch:AVX;/arch:SSE2;;;;")
|
set(SIMD_ENABLE_FLAGS "/arch:AVX;/arch:SSE2;;;;")
|
||||||
endif()
|
endif()
|
||||||
set(SIMD_DISABLE_FLAGS)
|
set(SIMD_DISABLE_FLAGS)
|
||||||
else()
|
else()
|
||||||
set(SIMD_ENABLE_FLAGS
|
set(SIMD_ENABLE_FLAGS
|
||||||
"-mavx2;-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa")
|
"-msimd128;-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa")
|
||||||
set(SIMD_DISABLE_FLAGS
|
set(SIMD_DISABLE_FLAGS
|
||||||
"-mno-avx2;-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa")
|
"-mno-simd128;-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
|
||||||
@@ -101,9 +75,14 @@ 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")
|
||||||
|
|
||||||
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
|
# With Emscripten 2.0.9 -msimd128 -mfpu=neon will enable NEON, but the
|
||||||
# will fail to compile.
|
# source will fail to compile.
|
||||||
if(EMSCRIPTEN AND ${I_SIMD} GREATER_EQUAL 2)
|
if(EMSCRIPTEN AND ${I_SIMD} GREATER_EQUAL 5)
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
# Emscripten supports SSE via compat headers, if WEBP_ENABLED_WASM_SIMD is
|
||||||
|
# specified skip testing those (because it will succeed).
|
||||||
|
if (EMSCRIPTEN AND ${I_SIMD} GREATER_EQUAL 1 AND ${WEBP_ENABLE_WASM_SIMD})
|
||||||
break()
|
break()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -117,6 +96,7 @@ 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)
|
||||||
|
# This enables using Emscripten's SSE compatibility headers.
|
||||||
if(EMSCRIPTEN)
|
if(EMSCRIPTEN)
|
||||||
set(SIMD_COMPILE_FLAG "-msimd128 ${SIMD_COMPILE_FLAG}")
|
set(SIMD_COMPILE_FLAG "-msimd128 ${SIMD_COMPILE_FLAG}")
|
||||||
endif()
|
endif()
|
||||||
@@ -133,9 +113,8 @@ 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})
|
||||||
# Memorize the file and flags.
|
# Memorize the file and flags.
|
||||||
foreach(FILE ${SIMD_FILES})
|
foreach(FILE ${SIMD_FILES})
|
||||||
@@ -169,9 +148,11 @@ 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)
|
||||||
unset(HAS_COMPILE_FLAG CACHE)
|
unset(HAS_COMPILE_FLAG CACHE)
|
||||||
|
|||||||
@@ -10,30 +10,24 @@
|
|||||||
|
|
||||||
# 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)
|
if(WEBP_USE_THREAD)
|
||||||
@@ -43,7 +37,15 @@ if(WEBP_USE_THREAD)
|
|||||||
if(CMAKE_USE_PTHREADS_INIT AND NOT CMAKE_SYSTEM_NAME STREQUAL "QNX")
|
if(CMAKE_USE_PTHREADS_INIT AND NOT CMAKE_SYSTEM_NAME STREQUAL "QNX")
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
|
||||||
endif()
|
endif()
|
||||||
list(APPEND WEBP_DEP_LIBRARIES Threads::Threads)
|
check_c_source_compiles("
|
||||||
|
#include <pthread.h>
|
||||||
|
int main (void) {
|
||||||
|
int attr = PTHREAD_PRIO_INHERIT;
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
" FLAG_HAVE_PTHREAD_PRIO_INHERIT)
|
||||||
|
set(HAVE_PTHREAD_PRIO_INHERIT ${FLAG_HAVE_PTHREAD_PRIO_INHERIT})
|
||||||
|
list(APPEND WEBP_DEP_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
|
||||||
endif()
|
endif()
|
||||||
set(WEBP_USE_THREAD ${Threads_FOUND})
|
set(WEBP_USE_THREAD ${Threads_FOUND})
|
||||||
endif()
|
endif()
|
||||||
@@ -57,30 +59,21 @@ 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)
|
||||||
# Disable tiff when compiling in static mode as it is failing on Ubuntu.
|
|
||||||
if(WEBP_LINK_STATIC AND ${I_LIB} STREQUAL "TIFF")
|
|
||||||
message(STATUS "TIFF is disabled when statically linking.")
|
|
||||||
continue()
|
|
||||||
endif()
|
|
||||||
find_package(${I_LIB})
|
find_package(${I_LIB})
|
||||||
set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND})
|
set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND})
|
||||||
if(${I_LIB}_FOUND)
|
if(${I_LIB}_FOUND)
|
||||||
@@ -102,20 +95,18 @@ if(WEBP_FIND_IMG_LIBS)
|
|||||||
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})
|
||||||
@@ -124,21 +115,33 @@ if(WEBP_FIND_IMG_LIBS)
|
|||||||
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 +153,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()
|
||||||
|
|
||||||
|
|||||||
49
configure.ac
49
configure.ac
@@ -1,6 +1,6 @@
|
|||||||
AC_INIT([libwebp], [1.6.0],
|
AC_INIT([libwebp], [1.2.1],
|
||||||
[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,8 +27,7 @@ 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])])
|
||||||
@@ -106,7 +104,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])
|
||||||
@@ -114,10 +111,8 @@ TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-declarations])
|
|||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-prototypes])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-prototypes])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wold-style-definition])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wold-style-definition])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wparentheses-equality])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wparentheses-equality])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wself-assign])
|
|
||||||
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-aggressive])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code])
|
||||||
@@ -162,25 +157,6 @@ AS_IF([test "$GCC" = "yes" ], [
|
|||||||
AC_SUBST([AM_CFLAGS])
|
AC_SUBST([AM_CFLAGS])
|
||||||
|
|
||||||
dnl === Check for machine specific flags
|
dnl === Check for machine specific flags
|
||||||
AC_ARG_ENABLE([avx2],
|
|
||||||
AS_HELP_STRING([--disable-avx2],
|
|
||||||
[Disable detection of AVX2 support
|
|
||||||
@<:@default=auto@:>@]))
|
|
||||||
|
|
||||||
AS_IF([test "x$enable_avx2" != "xno" -a "x$enable_sse4_1" != "xno"
|
|
||||||
-a "x$enable_sse2" != "xno"], [
|
|
||||||
AVX2_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
|
||||||
@@ -486,7 +462,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`"
|
||||||
@@ -496,12 +472,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(
|
||||||
@@ -770,21 +747,17 @@ fi
|
|||||||
|
|
||||||
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
29
doc/README
Normal 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/
|
||||||
392
doc/api.md
392
doc/api.md
@@ -1,392 +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.
|
|
||||||
|
|
||||||
Note these functions, like the lossy versions, use the library's default
|
|
||||||
settings. For lossless this means 'exact' is disabled. RGB values in fully
|
|
||||||
transparent areas (that is, areas with alpha values equal to `0`) will be
|
|
||||||
modified to improve compression. To avoid this, use `WebPEncode()` and set
|
|
||||||
`WebPConfig::exact` to `1`.
|
|
||||||
|
|
||||||
### 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, ×tamp);
|
|
||||||
// ... (Render 'buf' based on 'timestamp').
|
|
||||||
// ... (Do NOT free 'buf', as it is owned by 'dec').
|
|
||||||
}
|
|
||||||
WebPAnimDecoderReset(dec);
|
|
||||||
}
|
|
||||||
const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec);
|
|
||||||
// ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data).
|
|
||||||
WebPAnimDecoderDelete(dec);
|
|
||||||
```
|
|
||||||
|
|
||||||
For a detailed AnimDecoder API reference, please refer to the header file
|
|
||||||
(src/webp/demux.h).
|
|
||||||
231
doc/building.md
231
doc/building.md
@@ -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)
|
|
||||||
@@ -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.
|
|
||||||
524
doc/tools.md
524
doc/tools.md
@@ -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 '-'.
|
|
||||||
```
|
|
||||||
@@ -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,46 @@ 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][].
|
||||||
|
|
||||||
|
Terminology & Basics
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
A WebP file contains either a still image (i.e., an encoded matrix of pixels)
|
||||||
|
or an [animation](#animation). Optionally, it can also contain transparency
|
||||||
|
information, color profile and metadata. In case we need to refer only to the
|
||||||
|
matrix of pixels, we will call it the _canvas_ of the image.
|
||||||
|
|
||||||
Below are additional terms used throughout this document:
|
Below are additional terms used throughout this document:
|
||||||
|
|
||||||
@@ -84,25 +82,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 +106,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 +115,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 +149,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 4GiB 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 +180,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 +221,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,21 +249,21 @@ 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).
|
||||||
|
|
||||||
@@ -290,18 +277,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 +293,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 +306,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 +327,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 +368,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 +379,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 +394,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 +409,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 +418,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 +471,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 +493,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 +512,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 +521,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 +564,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 +592,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 +630,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,110 +662,85 @@ 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
|
||||||
|
|
||||||
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
|
||||||
@@ -799,33 +749,27 @@ for loop = 0..loop_count - 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":
|
||||||
bitstream subchunks not found in 'Frame Data' earlier MUST
|
assert bitstream subchunks not found in 'Frame Data' earlier
|
||||||
be TRUE
|
|
||||||
frame_params.bitstream = bitstream_data
|
frame_params.bitstream = bitstream_data
|
||||||
apply dispose_method.
|
render frame with frame_params.alpha and frame_params.bitstream on
|
||||||
render frame with frame_params.alpha and frame_params.bitstream
|
canvas with top-left corner at (frame_params.frameX,
|
||||||
on canvas with top-left corner at (frame_params.frameX,
|
frame_params.frameY), using dispose method dispose_method.
|
||||||
frame_params.frameY), using Blending method
|
|
||||||
frame_params.blendingMethod.
|
|
||||||
canvas contains the decoded image.
|
canvas contains the decoded image.
|
||||||
Show the contents of the canvas for
|
Show the contents of the canvas for frame_params.frameDuration * 1ms.
|
||||||
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 +778,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 +798,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 +811,9 @@ RIFF/WEBP
|
|||||||
+- EXIF (metadata)
|
+- EXIF (metadata)
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
[vp8spec]: http://tools.ietf.org/html/rfc6386
|
||||||
[webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/webp-lossless-bitstream-spec.txt
|
[webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/webp-lossless-bitstream-spec.txt
|
||||||
[iccspec]: https://www.color.org/icc_specs2.xalter
|
[iccspec]: http://www.color.org/icc_specs2.xalter
|
||||||
[metadata]: https://web.archive.org/web/20180919181934/http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
|
[metadata]: http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
|
||||||
[rec601]: https://www.itu.int/rec/R-REC-BT.601
|
[rfc 1166]: http://tools.ietf.org/html/rfc1166
|
||||||
[rfc 1166]: https://datatracker.ietf.org/doc/html/rfc1166
|
[rfc 2119]: http://tools.ietf.org/html/rfc2119
|
||||||
[rfc 2119]: https://datatracker.ietf.org/doc/html/rfc2119
|
|
||||||
[rfc 6386]: https://datatracker.ietf.org/doc/html/rfc6386
|
|
||||||
[rfc 8174]: https://datatracker.ietf.org/doc/html/rfc8174
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,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
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -57,8 +56,8 @@ static WEBP_INLINE int PixelsAreSimilar(uint32_t src, uint32_t dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int FramesAreSimilar(const uint8_t* const rgba1,
|
static int FramesAreSimilar(const uint8_t* const rgba1,
|
||||||
const uint8_t* const rgba2, int width, int height,
|
const uint8_t* const rgba2,
|
||||||
int max_allowed_diff) {
|
int width, int height, int max_allowed_diff) {
|
||||||
int i, j;
|
int i, j;
|
||||||
assert(max_allowed_diff > 0);
|
assert(max_allowed_diff > 0);
|
||||||
for (j = 0; j < height; ++j) {
|
for (j = 0; j < height; ++j) {
|
||||||
@@ -120,7 +119,8 @@ static int CompareBackgroundColor(uint32_t bg1, uint32_t bg2, int premultiply) {
|
|||||||
if (alpha1 == 0 && alpha2 == 0) return 1;
|
if (alpha1 == 0 && alpha2 == 0) return 1;
|
||||||
}
|
}
|
||||||
if (bg1 != bg2) {
|
if (bg1 != bg2) {
|
||||||
fprintf(stderr, "Background color mismatch: 0x%08x vs 0x%08x\n", bg1, bg2);
|
fprintf(stderr, "Background color mismatch: 0x%08x vs 0x%08x\n",
|
||||||
|
bg1, bg2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -130,17 +130,18 @@ static int CompareBackgroundColor(uint32_t bg1, uint32_t bg2, int premultiply) {
|
|||||||
// is OK for other aspects like offsets, dispose/blend method to vary.
|
// is OK for other aspects like offsets, dispose/blend method to vary.
|
||||||
static int CompareAnimatedImagePair(const AnimatedImage* const img1,
|
static int CompareAnimatedImagePair(const AnimatedImage* const img1,
|
||||||
const AnimatedImage* const img2,
|
const AnimatedImage* const img2,
|
||||||
int premultiply, double min_psnr) {
|
int premultiply,
|
||||||
|
double min_psnr) {
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
const int is_multi_frame_image = (img1->num_frames > 1);
|
const int is_multi_frame_image = (img1->num_frames > 1);
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
ok &= CompareValues(img1->canvas_width, img2->canvas_width,
|
ok = CompareValues(img1->canvas_width, img2->canvas_width,
|
||||||
"Canvas width mismatch");
|
"Canvas width mismatch") && ok;
|
||||||
ok &= CompareValues(img1->canvas_height, img2->canvas_height,
|
ok = CompareValues(img1->canvas_height, img2->canvas_height,
|
||||||
"Canvas height mismatch");
|
"Canvas height mismatch") && ok;
|
||||||
ok &=
|
ok = CompareValues(img1->num_frames, img2->num_frames,
|
||||||
CompareValues(img1->num_frames, img2->num_frames, "Frame count mismatch");
|
"Frame count mismatch") && ok;
|
||||||
if (!ok) return 0; // These are fatal failures, can't proceed.
|
if (!ok) return 0; // These are fatal failures, can't proceed.
|
||||||
|
|
||||||
if (is_multi_frame_image) { // Checks relevant for multi-frame images only.
|
if (is_multi_frame_image) { // Checks relevant for multi-frame images only.
|
||||||
@@ -153,10 +154,11 @@ static int CompareAnimatedImagePair(const AnimatedImage* const img1,
|
|||||||
img2->format == ANIM_GIF && img2->loop_count == 65536)) {
|
img2->format == ANIM_GIF && img2->loop_count == 65536)) {
|
||||||
max_loop_count_workaround = 1;
|
max_loop_count_workaround = 1;
|
||||||
}
|
}
|
||||||
ok &= (max_loop_count_workaround ||
|
ok = (max_loop_count_workaround ||
|
||||||
CompareValues(img1->loop_count, img2->loop_count,
|
CompareValues(img1->loop_count, img2->loop_count,
|
||||||
"Loop count mismatch"));
|
"Loop count mismatch")) && ok;
|
||||||
ok &= CompareBackgroundColor(img1->bgcolor, img2->bgcolor, premultiply);
|
ok = CompareBackgroundColor(img1->bgcolor, img2->bgcolor,
|
||||||
|
premultiply) && ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < img1->num_frames; ++i) {
|
for (i = 0; i < img1->num_frames; ++i) {
|
||||||
@@ -176,8 +178,8 @@ static int CompareAnimatedImagePair(const AnimatedImage* const img1,
|
|||||||
premultiply, &max_diff, &psnr);
|
premultiply, &max_diff, &psnr);
|
||||||
if (min_psnr > 0.) {
|
if (min_psnr > 0.) {
|
||||||
if (psnr < min_psnr) {
|
if (psnr < min_psnr) {
|
||||||
fprintf(stderr, "Frame #%d, psnr = %.2lf (min_psnr = %f)\n", i, psnr,
|
fprintf(stderr, "Frame #%d, psnr = %.2lf (min_psnr = %f)\n", i,
|
||||||
min_psnr);
|
psnr, min_psnr);
|
||||||
ok = 0;
|
ok = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -197,17 +199,15 @@ static void Help(void) {
|
|||||||
printf(" -min_psnr <float> ... minimum per-frame PSNR\n");
|
printf(" -min_psnr <float> ... minimum per-frame PSNR\n");
|
||||||
printf(" -raw_comparison ..... if this flag is not used, RGB is\n");
|
printf(" -raw_comparison ..... if this flag is not used, RGB is\n");
|
||||||
printf(" premultiplied before comparison\n");
|
printf(" premultiplied before comparison\n");
|
||||||
printf(
|
printf(" -max_diff <int> ..... maximum allowed difference per channel\n"
|
||||||
" -max_diff <int> ..... maximum allowed difference per channel\n"
|
|
||||||
" between corresponding pixels in subsequent\n"
|
" between corresponding pixels in subsequent\n"
|
||||||
" frames\n");
|
" frames\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");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.;
|
||||||
@@ -252,8 +252,9 @@ int main(int argc, const char* argv[]) {
|
|||||||
GetAnimatedImageVersions(&dec_version, &demux_version);
|
GetAnimatedImageVersions(&dec_version, &demux_version);
|
||||||
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
|
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
|
||||||
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
||||||
(dec_version >> 0) & 0xff, (demux_version >> 16) & 0xff,
|
(dec_version >> 0) & 0xff,
|
||||||
(demux_version >> 8) & 0xff, (demux_version >> 0) & 0xff);
|
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
|
||||||
|
(demux_version >> 0) & 0xff);
|
||||||
FREE_WARGV_AND_RETURN(0);
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else {
|
} else {
|
||||||
if (!got_input1) {
|
if (!got_input1) {
|
||||||
@@ -268,17 +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) {
|
||||||
@@ -291,18 +293,18 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CompareAnimatedImagePair(&images[0], &images[1], premultiply,
|
if (!CompareAnimatedImagePair(&images[0], &images[1],
|
||||||
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]);
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -29,8 +27,7 @@ static void Help(void) {
|
|||||||
printf("Usage: anim_dump [options] files...\n");
|
printf("Usage: anim_dump [options] files...\n");
|
||||||
printf("\nOptions:\n");
|
printf("\nOptions:\n");
|
||||||
printf(" -folder <string> .... dump folder (default: '.')\n");
|
printf(" -folder <string> .... dump folder (default: '.')\n");
|
||||||
printf(
|
printf(" -prefix <string> .... prefix for dumped frames "
|
||||||
" -prefix <string> .... prefix for dumped frames "
|
|
||||||
"(default: 'dump_')\n");
|
"(default: 'dump_')\n");
|
||||||
printf(" -tiff ............... save frames as TIFF\n");
|
printf(" -tiff ............... save frames as TIFF\n");
|
||||||
printf(" -pam ................ save frames as PAM\n");
|
printf(" -pam ................ save frames as PAM\n");
|
||||||
@@ -38,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(".");
|
||||||
@@ -51,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) {
|
||||||
@@ -77,22 +73,23 @@ 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);
|
||||||
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
|
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
|
||||||
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
||||||
(dec_version >> 0) & 0xff, (demux_version >> 16) & 0xff,
|
(dec_version >> 0) & 0xff,
|
||||||
(demux_version >> 8) & 0xff, (demux_version >> 0) & 0xff);
|
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
|
||||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
(demux_version >> 0) & 0xff);
|
||||||
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else {
|
} else {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
AnimatedImage image;
|
AnimatedImage image;
|
||||||
const W_CHAR* const file = GET_WARGV(argv, c);
|
const W_CHAR* const file = GET_WARGV(argv, c);
|
||||||
memset(&image, 0, sizeof(image));
|
memset(&image, 0, sizeof(image));
|
||||||
WPRINTF("Decoding file: %s as %s/%sxxxx.%s\n", file, dump_folder, prefix,
|
WPRINTF("Decoding file: %s as %s/%sxxxx.%s\n",
|
||||||
suffix);
|
file, dump_folder, prefix, suffix);
|
||||||
if (!ReadAnimatedImage((const char*)file, &image, 0, NULL)) {
|
if (!ReadAnimatedImage((const char*)file, &image, 0, NULL)) {
|
||||||
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n", file);
|
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n", file);
|
||||||
error = 1;
|
error = 1;
|
||||||
@@ -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;
|
||||||
@@ -113,8 +106,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
buffer.u.RGBA.rgba = image.frames[i].rgba;
|
buffer.u.RGBA.rgba = image.frames[i].rgba;
|
||||||
buffer.u.RGBA.stride = buffer.width * sizeof(uint32_t);
|
buffer.u.RGBA.stride = buffer.width * sizeof(uint32_t);
|
||||||
buffer.u.RGBA.size = buffer.u.RGBA.stride * buffer.height;
|
buffer.u.RGBA.size = buffer.u.RGBA.stride * buffer.height;
|
||||||
WSNPRINTF(out_file, sizeof(out_file), "%s/%s%.4d.%s", dump_folder,
|
WSNPRINTF(out_file, sizeof(out_file), "%s/%s%.4d.%s",
|
||||||
prefix, i, suffix);
|
dump_folder, prefix, i, suffix);
|
||||||
if (!WebPSaveImage(&buffer, format, (const char*)out_file)) {
|
if (!WebPSaveImage(&buffer, format, (const char*)out_file)) {
|
||||||
WFPRINTF(stderr, "Error while saving image '%s'\n", out_file);
|
WFPRINTF(stderr, "Error while saving image '%s'\n", out_file);
|
||||||
error = 1;
|
error = 1;
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -41,8 +38,8 @@ static const int kNumChannels = 4;
|
|||||||
|
|
||||||
#if defined(WEBP_HAVE_GIF)
|
#if defined(WEBP_HAVE_GIF)
|
||||||
// Returns true if the frame covers the full canvas.
|
// Returns true if the frame covers the full canvas.
|
||||||
static int IsFullFrame(int width, int height, int canvas_width,
|
static int IsFullFrame(int width, int height,
|
||||||
int canvas_height) {
|
int canvas_width, int canvas_height) {
|
||||||
return (width == canvas_width && height == canvas_height);
|
return (width == canvas_width && height == canvas_height);
|
||||||
}
|
}
|
||||||
#endif // WEBP_HAVE_GIF
|
#endif // WEBP_HAVE_GIF
|
||||||
@@ -95,8 +92,8 @@ void ClearAnimatedImage(AnimatedImage* const image) {
|
|||||||
|
|
||||||
#if defined(WEBP_HAVE_GIF)
|
#if defined(WEBP_HAVE_GIF)
|
||||||
// Clear the canvas to transparent.
|
// Clear the canvas to transparent.
|
||||||
static void ZeroFillCanvas(uint8_t* rgba, uint32_t canvas_width,
|
static void ZeroFillCanvas(uint8_t* rgba,
|
||||||
uint32_t canvas_height) {
|
uint32_t canvas_width, uint32_t canvas_height) {
|
||||||
memset(rgba, 0, canvas_width * kNumChannels * canvas_height);
|
memset(rgba, 0, canvas_width * kNumChannels * canvas_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,16 +110,16 @@ static void ZeroFillFrameRect(uint8_t* rgba, int rgba_stride, int x_offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy width * height pixels from 'src' to 'dst'.
|
// Copy width * height pixels from 'src' to 'dst'.
|
||||||
static void CopyCanvas(const uint8_t* src, uint8_t* dst, uint32_t width,
|
static void CopyCanvas(const uint8_t* src, uint8_t* dst,
|
||||||
uint32_t height) {
|
uint32_t width, uint32_t height) {
|
||||||
assert(src != NULL && dst != NULL);
|
assert(src != NULL && dst != NULL);
|
||||||
memcpy(dst, src, width * kNumChannels * height);
|
memcpy(dst, src, width * kNumChannels * height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy pixels in the given rectangle from 'src' to 'dst' honoring the 'stride'.
|
// Copy pixels in the given rectangle from 'src' to 'dst' honoring the 'stride'.
|
||||||
static void CopyFrameRectangle(const uint8_t* src, uint8_t* dst, int stride,
|
static void CopyFrameRectangle(const uint8_t* src, uint8_t* dst, int stride,
|
||||||
int x_offset, int y_offset, int width,
|
int x_offset, int y_offset,
|
||||||
int height) {
|
int width, int height) {
|
||||||
int j;
|
int j;
|
||||||
const int width_in_bytes = width * kNumChannels;
|
const int width_in_bytes = width * kNumChannels;
|
||||||
const size_t offset = y_offset * stride + x_offset * kNumChannels;
|
const size_t offset = y_offset * stride + x_offset * kNumChannels;
|
||||||
@@ -138,8 +135,8 @@ static void CopyFrameRectangle(const uint8_t* src, uint8_t* dst, int stride,
|
|||||||
#endif // WEBP_HAVE_GIF
|
#endif // WEBP_HAVE_GIF
|
||||||
|
|
||||||
// Canonicalize all transparent pixels to transparent black to aid comparison.
|
// Canonicalize all transparent pixels to transparent black to aid comparison.
|
||||||
static void CleanupTransparentPixels(uint32_t* rgba, uint32_t width,
|
static void CleanupTransparentPixels(uint32_t* rgba,
|
||||||
uint32_t height) {
|
uint32_t width, uint32_t height) {
|
||||||
const uint32_t* const rgba_end = rgba + width * height;
|
const uint32_t* const rgba_end = rgba + width * height;
|
||||||
while (rgba < rgba_end) {
|
while (rgba < rgba_end) {
|
||||||
const uint8_t alpha = (*rgba >> 24) & 0xff;
|
const uint8_t alpha = (*rgba >> 24) & 0xff;
|
||||||
@@ -152,8 +149,8 @@ static void CleanupTransparentPixels(uint32_t* rgba, uint32_t width,
|
|||||||
|
|
||||||
// Dump frame to a PAM file. Returns true on success.
|
// Dump frame to a PAM file. Returns true on success.
|
||||||
static int DumpFrame(const char filename[], const char dump_folder[],
|
static int DumpFrame(const char filename[], const char dump_folder[],
|
||||||
uint32_t frame_num, const uint8_t rgba[], int canvas_width,
|
uint32_t frame_num, const uint8_t rgba[],
|
||||||
int canvas_height) {
|
int canvas_width, int canvas_height) {
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
size_t max_len;
|
size_t max_len;
|
||||||
int y;
|
int y;
|
||||||
@@ -166,8 +163,8 @@ static int DumpFrame(const char filename[], const char dump_folder[],
|
|||||||
|
|
||||||
base_name = WSTRRCHR(filename, '/');
|
base_name = WSTRRCHR(filename, '/');
|
||||||
base_name = (base_name == NULL) ? (const W_CHAR*)filename : base_name + 1;
|
base_name = (base_name == NULL) ? (const W_CHAR*)filename : base_name + 1;
|
||||||
max_len = WSTRLEN(dump_folder) + 1 + WSTRLEN(base_name) + strlen("_frame_") +
|
max_len = WSTRLEN(dump_folder) + 1 + WSTRLEN(base_name)
|
||||||
strlen(".pam") + 8;
|
+ strlen("_frame_") + strlen(".pam") + 8;
|
||||||
file_name = (W_CHAR*)WebPMalloc(max_len * sizeof(*file_name));
|
file_name = (W_CHAR*)WebPMalloc(max_len * sizeof(*file_name));
|
||||||
if (file_name == NULL) goto End;
|
if (file_name == NULL) goto End;
|
||||||
|
|
||||||
@@ -183,8 +180,7 @@ static int DumpFrame(const char filename[], const char dump_folder[],
|
|||||||
ok = 0;
|
ok = 0;
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
if (fprintf(f,
|
if (fprintf(f, "P7\nWIDTH %d\nHEIGHT %d\n"
|
||||||
"P7\nWIDTH %d\nHEIGHT %d\n"
|
|
||||||
"DEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n",
|
"DEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n",
|
||||||
canvas_width, canvas_height) < 0) {
|
canvas_width, canvas_height) < 0) {
|
||||||
WFPRINTF(stderr, "Write error for file %s\n", file_name);
|
WFPRINTF(stderr, "Write error for file %s\n", file_name);
|
||||||
@@ -245,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)) {
|
||||||
@@ -267,8 +263,8 @@ static int ReadAnimatedWebP(const char filename[],
|
|||||||
image->canvas_width * kNumChannels * image->canvas_height);
|
image->canvas_width * kNumChannels * image->canvas_height);
|
||||||
|
|
||||||
// Needed only because we may want to compare with GIF later.
|
// Needed only because we may want to compare with GIF later.
|
||||||
CleanupTransparentPixels((uint32_t*)curr_rgba, image->canvas_width,
|
CleanupTransparentPixels((uint32_t*)curr_rgba,
|
||||||
image->canvas_height);
|
image->canvas_width, image->canvas_height);
|
||||||
|
|
||||||
if (dump_frames && dump_ok) {
|
if (dump_frames && dump_ok) {
|
||||||
dump_ok = DumpFrame(filename, dump_folder, frame_index, curr_rgba,
|
dump_ok = DumpFrame(filename, dump_folder, frame_index, curr_rgba,
|
||||||
@@ -305,7 +301,8 @@ static int IsGIF(const WebPData* const data) {
|
|||||||
// GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
|
// GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
|
||||||
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR)
|
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR)
|
||||||
# define LOCAL_GIF_VERSION ((GIFLIB_MAJOR << 8) | GIFLIB_MINOR)
|
# define LOCAL_GIF_VERSION ((GIFLIB_MAJOR << 8) | GIFLIB_MINOR)
|
||||||
#define LOCAL_GIF_PREREQ(maj, min) (LOCAL_GIF_VERSION >= (((maj) << 8) | (min)))
|
# define LOCAL_GIF_PREREQ(maj, min) \
|
||||||
|
(LOCAL_GIF_VERSION >= (((maj) << 8) | (min)))
|
||||||
#else
|
#else
|
||||||
# define LOCAL_GIF_VERSION 0
|
# define LOCAL_GIF_VERSION 0
|
||||||
# define LOCAL_GIF_PREREQ(maj, min) 0
|
# define LOCAL_GIF_PREREQ(maj, min) 0
|
||||||
@@ -357,8 +354,8 @@ static int DGifSavedExtensionToGCB(GifFileType* GifFile, int ImageIndex,
|
|||||||
for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) {
|
for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) {
|
||||||
ExtensionBlock* ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
|
ExtensionBlock* ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
|
||||||
if (ep->Function == GRAPHICS_EXT_FUNC_CODE) {
|
if (ep->Function == GRAPHICS_EXT_FUNC_CODE) {
|
||||||
return DGifExtensionToGCB(ep->ByteCount, (const GifByteType*)ep->Bytes,
|
return DGifExtensionToGCB(
|
||||||
gcb);
|
ep->ByteCount, (const GifByteType*)ep->Bytes, gcb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return GIF_ERROR;
|
return GIF_ERROR;
|
||||||
@@ -377,12 +374,12 @@ static int DGifSavedExtensionToGCB(GifFileType* GifFile, int ImageIndex,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int IsKeyFrameGIF(const GifImageDesc* prev_desc, int prev_dispose,
|
static int IsKeyFrameGIF(const GifImageDesc* prev_desc, int prev_dispose,
|
||||||
const DecodedFrame* const prev_frame, int canvas_width,
|
const DecodedFrame* const prev_frame,
|
||||||
int canvas_height) {
|
int canvas_width, int canvas_height) {
|
||||||
if (prev_frame == NULL) return 1;
|
if (prev_frame == NULL) return 1;
|
||||||
if (prev_dispose == DISPOSE_BACKGROUND) {
|
if (prev_dispose == DISPOSE_BACKGROUND) {
|
||||||
if (IsFullFrame(prev_desc->Width, prev_desc->Height, canvas_width,
|
if (IsFullFrame(prev_desc->Width, prev_desc->Height,
|
||||||
canvas_height)) {
|
canvas_width, canvas_height)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (prev_frame->is_key_frame) return 1;
|
if (prev_frame->is_key_frame) return 1;
|
||||||
@@ -403,12 +400,14 @@ static uint32_t GetBackgroundColorGIF(GifFileType* gif) {
|
|||||||
if (transparent_index != NO_TRANSPARENT_COLOR &&
|
if (transparent_index != NO_TRANSPARENT_COLOR &&
|
||||||
gif->SBackGroundColor == transparent_index) {
|
gif->SBackGroundColor == transparent_index) {
|
||||||
return 0x00000000; // Special case: transparent black.
|
return 0x00000000; // Special case: transparent black.
|
||||||
} else if (color_map == NULL || color_map->Colors == NULL ||
|
} else if (color_map == NULL || color_map->Colors == NULL
|
||||||
gif->SBackGroundColor >= color_map->ColorCount) {
|
|| gif->SBackGroundColor >= color_map->ColorCount) {
|
||||||
return 0xffffffff; // Invalid: assume white.
|
return 0xffffffff; // Invalid: assume white.
|
||||||
} else {
|
} else {
|
||||||
const GifColorType color = color_map->Colors[gif->SBackGroundColor];
|
const GifColorType color = color_map->Colors[gif->SBackGroundColor];
|
||||||
return (0xffu << 24) | (color.Red << 16) | (color.Green << 8) |
|
return (0xffu << 24) |
|
||||||
|
(color.Red << 16) |
|
||||||
|
(color.Green << 8) |
|
||||||
(color.Blue << 0);
|
(color.Blue << 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -433,10 +432,11 @@ static uint32_t GetLoopCountGIF(const GifFileType* const gif) {
|
|||||||
(eb1->ByteCount == 11) &&
|
(eb1->ByteCount == 11) &&
|
||||||
(!memcmp(signature, "NETSCAPE2.0", 11) ||
|
(!memcmp(signature, "NETSCAPE2.0", 11) ||
|
||||||
!memcmp(signature, "ANIMEXTS1.0", 11));
|
!memcmp(signature, "ANIMEXTS1.0", 11));
|
||||||
if (signature_is_ok && eb2->Function == CONTINUE_EXT_FUNC_CODE &&
|
if (signature_is_ok &&
|
||||||
eb2->ByteCount >= 3 && eb2->Bytes[0] == 1) {
|
eb2->Function == CONTINUE_EXT_FUNC_CODE && eb2->ByteCount >= 3 &&
|
||||||
const uint32_t extra_loop =
|
eb2->Bytes[0] == 1) {
|
||||||
((uint32_t)(eb2->Bytes[2]) << 8) + ((uint32_t)(eb2->Bytes[1]) << 0);
|
const uint32_t extra_loop = ((uint32_t)(eb2->Bytes[2]) << 8) +
|
||||||
|
((uint32_t)(eb2->Bytes[1]) << 0);
|
||||||
return (extra_loop > 0) ? extra_loop + 1 : 0;
|
return (extra_loop > 0) ? extra_loop + 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -532,8 +532,8 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
|||||||
image->canvas_height = (uint32_t)gif->SHeight;
|
image->canvas_height = (uint32_t)gif->SHeight;
|
||||||
if (image->canvas_width > MAX_CANVAS_SIZE ||
|
if (image->canvas_width > MAX_CANVAS_SIZE ||
|
||||||
image->canvas_height > MAX_CANVAS_SIZE) {
|
image->canvas_height > MAX_CANVAS_SIZE) {
|
||||||
fprintf(stderr, "Invalid canvas dimension: %d x %d\n", image->canvas_width,
|
fprintf(stderr, "Invalid canvas dimension: %d x %d\n",
|
||||||
image->canvas_height);
|
image->canvas_width, image->canvas_height);
|
||||||
DGifCloseFile(gif, NULL);
|
DGifCloseFile(gif, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -558,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;
|
||||||
@@ -608,9 +605,11 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
|||||||
CopyCanvas(prev_rgba, curr_rgba, canvas_width, canvas_height);
|
CopyCanvas(prev_rgba, curr_rgba, canvas_width, canvas_height);
|
||||||
|
|
||||||
// Dispose previous frame rectangle.
|
// Dispose previous frame rectangle.
|
||||||
prev_frame_disposed = (prev_gcb.DisposalMode == DISPOSE_BACKGROUND ||
|
prev_frame_disposed =
|
||||||
|
(prev_gcb.DisposalMode == DISPOSE_BACKGROUND ||
|
||||||
prev_gcb.DisposalMode == DISPOSE_PREVIOUS);
|
prev_gcb.DisposalMode == DISPOSE_PREVIOUS);
|
||||||
curr_frame_opaque = (curr_gcb.TransparentColor == NO_TRANSPARENT_COLOR);
|
curr_frame_opaque =
|
||||||
|
(curr_gcb.TransparentColor == NO_TRANSPARENT_COLOR);
|
||||||
prev_frame_completely_covered =
|
prev_frame_completely_covered =
|
||||||
curr_frame_opaque &&
|
curr_frame_opaque &&
|
||||||
CoversFrameGIF(&curr_gif_image->ImageDesc, prev_desc);
|
CoversFrameGIF(&curr_gif_image->ImageDesc, prev_desc);
|
||||||
@@ -638,9 +637,9 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
|||||||
uint8_t* const src_frame_rgba =
|
uint8_t* const src_frame_rgba =
|
||||||
image->frames[src_frame_num].rgba;
|
image->frames[src_frame_num].rgba;
|
||||||
CopyFrameRectangle(src_frame_rgba, curr_rgba,
|
CopyFrameRectangle(src_frame_rgba, curr_rgba,
|
||||||
canvas_width_in_bytes, prev_desc->Left,
|
canvas_width_in_bytes,
|
||||||
prev_desc->Top, prev_desc->Width,
|
prev_desc->Left, prev_desc->Top,
|
||||||
prev_desc->Height);
|
prev_desc->Width, prev_desc->Height);
|
||||||
} else {
|
} else {
|
||||||
// Source canvas doesn't exist. So clear previous frame
|
// Source canvas doesn't exist. So clear previous frame
|
||||||
// rectangle to background.
|
// rectangle to background.
|
||||||
@@ -665,8 +664,8 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dump_frames) {
|
if (dump_frames) {
|
||||||
if (!DumpFrame(filename, dump_folder, i, curr_rgba, canvas_width,
|
if (!DumpFrame(filename, dump_folder, i, curr_rgba,
|
||||||
canvas_height)) {
|
canvas_width, canvas_height)) {
|
||||||
DGifCloseFile(gif, NULL);
|
DGifCloseFile(gif, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -690,8 +689,7 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
|||||||
(void)image;
|
(void)image;
|
||||||
(void)dump_frames;
|
(void)dump_frames;
|
||||||
(void)dump_folder;
|
(void)dump_folder;
|
||||||
fprintf(stderr,
|
fprintf(stderr, "GIF support not compiled. Please install the libgif-dev "
|
||||||
"GIF support not compiled. Please install the libgif-dev "
|
|
||||||
"package before building.\n");
|
"package before building.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -714,8 +712,8 @@ int ReadAnimatedImage(const char filename[], AnimatedImage* const image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IsWebP(&webp_data)) {
|
if (IsWebP(&webp_data)) {
|
||||||
ok =
|
ok = ReadAnimatedWebP(filename, &webp_data, image, dump_frames,
|
||||||
ReadAnimatedWebP(filename, &webp_data, image, dump_frames, dump_folder);
|
dump_folder);
|
||||||
} else if (IsGIF(&webp_data)) {
|
} else if (IsGIF(&webp_data)) {
|
||||||
ok = ReadAnimatedGIF(filename, image, dump_frames, dump_folder);
|
ok = ReadAnimatedGIF(filename, image, dump_frames, dump_folder);
|
||||||
} else {
|
} else {
|
||||||
@@ -759,7 +757,8 @@ void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
|
|||||||
// premultiply R/G/B channels with alpha value
|
// premultiply R/G/B channels with alpha value
|
||||||
for (k = 0; k < kAlphaChannel; ++k) {
|
for (k = 0; k < kAlphaChannel; ++k) {
|
||||||
Accumulate(rgba1[offset + k] * alpha1 / 255.,
|
Accumulate(rgba1[offset + k] * alpha1 / 255.,
|
||||||
rgba2[offset + k] * alpha2 / 255., &f_max_diff, &sse);
|
rgba2[offset + k] * alpha2 / 255.,
|
||||||
|
&f_max_diff, &sse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -769,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,10 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum { ANIM_GIF, ANIM_WEBP } AnimatedFileFormat;
|
typedef enum {
|
||||||
|
ANIM_GIF,
|
||||||
|
ANIM_WEBP
|
||||||
|
} AnimatedFileFormat;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t* rgba; // Decoded and reconstructed full frame.
|
uint8_t* rgba; // Decoded and reconstructed full frame.
|
||||||
|
|||||||
288
examples/cwebp.c
288
examples/cwebp.c
@@ -27,10 +27,7 @@
|
|||||||
#include "../imageio/webpdec.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
|
||||||
@@ -66,12 +63,12 @@ static int ReadYUV(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
pic->use_argb = 0;
|
pic->use_argb = 0;
|
||||||
if (!WebPPictureAlloc(pic)) return 0;
|
if (!WebPPictureAlloc(pic)) return 0;
|
||||||
ImgIoUtilCopyPlane(data, pic->width, pic->y, pic->y_stride, pic->width,
|
ImgIoUtilCopyPlane(data, pic->width, pic->y, pic->y_stride,
|
||||||
pic->height);
|
pic->width, pic->height);
|
||||||
ImgIoUtilCopyPlane(data + y_plane_size, uv_width, pic->u, pic->uv_stride,
|
ImgIoUtilCopyPlane(data + y_plane_size, uv_width,
|
||||||
uv_width, uv_height);
|
pic->u, pic->uv_stride, uv_width, uv_height);
|
||||||
ImgIoUtilCopyPlane(data + y_plane_size + uv_plane_size, uv_width, pic->v,
|
ImgIoUtilCopyPlane(data + y_plane_size + uv_plane_size, uv_width,
|
||||||
pic->uv_stride, uv_width, uv_height);
|
pic->v, pic->uv_stride, uv_width, uv_height);
|
||||||
return use_argb ? WebPPictureYUVAToARGB(pic) : 1;
|
return use_argb ? WebPPictureYUVAToARGB(pic) : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,8 +165,8 @@ static void PrintValues(const int values[4]) {
|
|||||||
|
|
||||||
static void PrintFullLosslessInfo(const WebPAuxStats* const stats,
|
static void PrintFullLosslessInfo(const WebPAuxStats* const stats,
|
||||||
const char* const description) {
|
const char* const description) {
|
||||||
fprintf(stderr, "Lossless-%s compressed size: %d bytes\n", description,
|
fprintf(stderr, "Lossless-%s compressed size: %d bytes\n",
|
||||||
stats->lossless_size);
|
description, stats->lossless_size);
|
||||||
fprintf(stderr, " * Header size: %d bytes, image data size: %d\n",
|
fprintf(stderr, " * Header size: %d bytes, image data size: %d\n",
|
||||||
stats->lossless_hdr_size, stats->lossless_data_size);
|
stats->lossless_hdr_size, stats->lossless_data_size);
|
||||||
if (stats->lossless_features) {
|
if (stats->lossless_features) {
|
||||||
@@ -180,14 +177,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);
|
||||||
}
|
}
|
||||||
@@ -209,7 +200,8 @@ static void PrintExtraInfoLossless(const WebPPicture* const pic,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
|
static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
|
||||||
int full_details, const char* const file_name) {
|
int full_details,
|
||||||
|
const char* const file_name) {
|
||||||
const WebPAuxStats* const stats = pic->stats;
|
const WebPAuxStats* const stats = pic->stats;
|
||||||
if (short_output) {
|
if (short_output) {
|
||||||
fprintf(stderr, "%7d %2.2f\n", stats->coded_size, stats->PSNR[3]);
|
fprintf(stderr, "%7d %2.2f\n", stats->coded_size, stats->PSNR[3]);
|
||||||
@@ -219,24 +211,24 @@ static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
|
|||||||
const int num_skip = stats->block_count[2];
|
const int num_skip = stats->block_count[2];
|
||||||
const int total = num_i4 + num_i16;
|
const int total = num_i4 + num_i16;
|
||||||
WFPRINTF(stderr, "File: %s\n", (const W_CHAR*)file_name);
|
WFPRINTF(stderr, "File: %s\n", (const W_CHAR*)file_name);
|
||||||
fprintf(stderr, "Dimension: %d x %d%s\n", pic->width, pic->height,
|
fprintf(stderr, "Dimension: %d x %d%s\n",
|
||||||
|
pic->width, pic->height,
|
||||||
stats->alpha_data_size ? " (with alpha)" : "");
|
stats->alpha_data_size ? " (with alpha)" : "");
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Output: "
|
||||||
"Output: "
|
|
||||||
"%d bytes Y-U-V-All-PSNR %2.2f %2.2f %2.2f %2.2f dB\n"
|
"%d bytes Y-U-V-All-PSNR %2.2f %2.2f %2.2f %2.2f dB\n"
|
||||||
" (%.2f bpp)\n",
|
" (%.2f bpp)\n",
|
||||||
stats->coded_size, stats->PSNR[0], stats->PSNR[1], stats->PSNR[2],
|
stats->coded_size,
|
||||||
stats->PSNR[3], 8.f * stats->coded_size / pic->width / pic->height);
|
stats->PSNR[0], stats->PSNR[1], stats->PSNR[2], stats->PSNR[3],
|
||||||
|
8.f * stats->coded_size / pic->width / pic->height);
|
||||||
if (total > 0) {
|
if (total > 0) {
|
||||||
int totals[4] = { 0, 0, 0, 0 };
|
int totals[4] = { 0, 0, 0, 0 };
|
||||||
fprintf(stderr,
|
fprintf(stderr, "block count: intra4: %6d (%.2f%%)\n"
|
||||||
"block count: intra4: %6d (%.2f%%)\n"
|
|
||||||
" intra16: %6d (%.2f%%)\n"
|
" intra16: %6d (%.2f%%)\n"
|
||||||
" skipped: %6d (%.2f%%)\n",
|
" skipped: %6d (%.2f%%)\n",
|
||||||
num_i4, 100.f * num_i4 / total, num_i16, 100.f * num_i16 / total,
|
num_i4, 100.f * num_i4 / total,
|
||||||
|
num_i16, 100.f * num_i16 / total,
|
||||||
num_skip, 100.f * num_skip / total);
|
num_skip, 100.f * num_skip / total);
|
||||||
fprintf(stderr,
|
fprintf(stderr, "bytes used: header: %6d (%.1f%%)\n"
|
||||||
"bytes used: header: %6d (%.1f%%)\n"
|
|
||||||
" mode-partition: %6d (%.1f%%)\n",
|
" mode-partition: %6d (%.1f%%)\n",
|
||||||
stats->header_bytes[0],
|
stats->header_bytes[0],
|
||||||
100.f * stats->header_bytes[0] / stats->coded_size,
|
100.f * stats->header_bytes[0] / stats->coded_size,
|
||||||
@@ -246,8 +238,7 @@ static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
|
|||||||
fprintf(stderr, " transparency: %6d (%.1f dB)\n",
|
fprintf(stderr, " transparency: %6d (%.1f dB)\n",
|
||||||
stats->alpha_data_size, stats->PSNR[4]);
|
stats->alpha_data_size, stats->PSNR[4]);
|
||||||
}
|
}
|
||||||
fprintf(stderr,
|
fprintf(stderr, " Residuals bytes "
|
||||||
" Residuals bytes "
|
|
||||||
"|segment 1|segment 2|segment 3"
|
"|segment 1|segment 2|segment 3"
|
||||||
"|segment 4| total\n");
|
"|segment 4| total\n");
|
||||||
if (full_details) {
|
if (full_details) {
|
||||||
@@ -314,7 +305,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 +319,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -411,9 +398,9 @@ static int WriteMetadataChunk(FILE* const out, const char fourcc[4],
|
|||||||
|
|
||||||
// Sets 'flag' in 'vp8x_flags' and updates 'metadata_size' with the size of the
|
// Sets 'flag' in 'vp8x_flags' and updates 'metadata_size' with the size of the
|
||||||
// chunk if there is metadata and 'keep' is true.
|
// chunk if there is metadata and 'keep' is true.
|
||||||
static int UpdateFlagsAndSize(const MetadataPayload* const payload, int keep,
|
static int UpdateFlagsAndSize(const MetadataPayload* const payload,
|
||||||
int flag, uint32_t* vp8x_flags,
|
int keep, int flag,
|
||||||
uint64_t* metadata_size) {
|
uint32_t* vp8x_flags, uint64_t* metadata_size) {
|
||||||
if (keep && payload->bytes != NULL && payload->size > 0) {
|
if (keep && payload->bytes != NULL && payload->size > 0) {
|
||||||
*vp8x_flags |= flag;
|
*vp8x_flags |= flag;
|
||||||
*metadata_size += kChunkHeaderSize + payload->size + (payload->size & 1);
|
*metadata_size += kChunkHeaderSize + payload->size + (payload->size & 1);
|
||||||
@@ -442,14 +429,14 @@ static int WriteWebPWithMetadata(FILE* const out,
|
|||||||
const size_t kMinSize = kRiffHeaderSize + kChunkHeaderSize;
|
const size_t kMinSize = kRiffHeaderSize + kChunkHeaderSize;
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
uint64_t metadata_size = 0;
|
uint64_t metadata_size = 0;
|
||||||
const int write_exif =
|
const int write_exif = UpdateFlagsAndSize(&metadata->exif,
|
||||||
UpdateFlagsAndSize(&metadata->exif, !!(keep_metadata & METADATA_EXIF),
|
!!(keep_metadata & METADATA_EXIF),
|
||||||
kEXIFFlag, &flags, &metadata_size);
|
kEXIFFlag, &flags, &metadata_size);
|
||||||
const int write_iccp =
|
const int write_iccp = UpdateFlagsAndSize(&metadata->iccp,
|
||||||
UpdateFlagsAndSize(&metadata->iccp, !!(keep_metadata & METADATA_ICC),
|
!!(keep_metadata & METADATA_ICC),
|
||||||
kICCPFlag, &flags, &metadata_size);
|
kICCPFlag, &flags, &metadata_size);
|
||||||
const int write_xmp =
|
const int write_xmp = UpdateFlagsAndSize(&metadata->xmp,
|
||||||
UpdateFlagsAndSize(&metadata->xmp, !!(keep_metadata & METADATA_XMP),
|
!!(keep_metadata & METADATA_XMP),
|
||||||
kXMPFlag, &flags, &metadata_size);
|
kXMPFlag, &flags, &metadata_size);
|
||||||
uint8_t* webp = memory_writer->mem;
|
uint8_t* webp = memory_writer->mem;
|
||||||
size_t webp_size = memory_writer->size;
|
size_t webp_size = memory_writer->size;
|
||||||
@@ -458,8 +445,7 @@ static int WriteWebPWithMetadata(FILE* const out,
|
|||||||
|
|
||||||
if (webp_size < kMinSize) return 0;
|
if (webp_size < kMinSize) return 0;
|
||||||
if (webp_size - kChunkHeaderSize + metadata_size > kMaxChunkPayload) {
|
if (webp_size - kChunkHeaderSize + metadata_size > kMaxChunkPayload) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Error! Addition of metadata would exceed "
|
||||||
"Error! Addition of metadata would exceed "
|
|
||||||
"container size limit.\n");
|
"container size limit.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -467,9 +453,9 @@ static int WriteWebPWithMetadata(FILE* const out,
|
|||||||
if (metadata_size > 0) {
|
if (metadata_size > 0) {
|
||||||
const int kVP8XChunkSize = 18;
|
const int kVP8XChunkSize = 18;
|
||||||
const int has_vp8x = !memcmp(webp + kRiffHeaderSize, "VP8X", kTagSize);
|
const int has_vp8x = !memcmp(webp + kRiffHeaderSize, "VP8X", kTagSize);
|
||||||
const uint32_t riff_size =
|
const uint32_t riff_size = (uint32_t)(webp_size - kChunkHeaderSize +
|
||||||
(uint32_t)(webp_size - kChunkHeaderSize +
|
(has_vp8x ? 0 : kVP8XChunkSize) +
|
||||||
(has_vp8x ? 0 : kVP8XChunkSize) + metadata_size);
|
metadata_size);
|
||||||
// RIFF
|
// RIFF
|
||||||
int ok = (fwrite(webp, kTagSize, 1, out) == 1);
|
int ok = (fwrite(webp, kTagSize, 1, out) == 1);
|
||||||
// RIFF size (file header size is not recorded)
|
// RIFF size (file header size is not recorded)
|
||||||
@@ -518,39 +504,11 @@ 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) {
|
||||||
fprintf(stderr, "[%s]: %3d %% \r", (char*)picture->user_data, percent);
|
fprintf(stderr, "[%s]: %3d %% \r",
|
||||||
|
(char*)picture->user_data, percent);
|
||||||
return 1; // all ok
|
return 1; // all ok
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -567,8 +525,7 @@ static void HelpShort(void) {
|
|||||||
static void HelpLong(void) {
|
static void HelpLong(void) {
|
||||||
printf("Usage:\n");
|
printf("Usage:\n");
|
||||||
printf(" cwebp [-preset <...>] [options] in_file [-o out_file]\n\n");
|
printf(" cwebp [-preset <...>] [options] in_file [-o out_file]\n\n");
|
||||||
printf(
|
printf("If input size (-s) for an image is not specified, it is\n"
|
||||||
"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");
|
printf("Note: Animated PNG and WebP files are not supported.\n");
|
||||||
#ifdef HAVE_WINCODEC_H
|
#ifdef HAVE_WINCODEC_H
|
||||||
@@ -577,59 +534,44 @@ static void HelpLong(void) {
|
|||||||
printf("\nOptions:\n");
|
printf("\nOptions:\n");
|
||||||
printf(" -h / -help ............. short help\n");
|
printf(" -h / -help ............. short help\n");
|
||||||
printf(" -H / -longhelp ......... long help\n");
|
printf(" -H / -longhelp ......... long help\n");
|
||||||
printf(
|
printf(" -q <float> ............. quality factor (0:small..100:big), "
|
||||||
" -q <float> ............. quality factor (0:small..100:big), "
|
|
||||||
"default=75\n");
|
"default=75\n");
|
||||||
printf(
|
printf(" -alpha_q <int> ......... transparency-compression quality (0..100),"
|
||||||
" -alpha_q <int> ......... transparency-compression quality (0..100),"
|
|
||||||
"\n default=100\n");
|
"\n default=100\n");
|
||||||
printf(" -preset <string> ....... preset setting, one of:\n");
|
printf(" -preset <string> ....... preset setting, one of:\n");
|
||||||
printf(" default, photo, picture,\n");
|
printf(" default, photo, picture,\n");
|
||||||
printf(" drawing, icon, text\n");
|
printf(" drawing, icon, text\n");
|
||||||
printf(" -preset must come first, as it overwrites other parameters\n");
|
printf(" -preset must come first, as it overwrites other parameters\n");
|
||||||
printf(
|
printf(" -z <int> ............... activates lossless preset with given\n"
|
||||||
" -z <int> ............... activates lossless preset with given\n"
|
|
||||||
" level in [0:fast, ..., 9:slowest]\n");
|
" level in [0:fast, ..., 9:slowest]\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(
|
printf(" -m <int> ............... compression method (0=fast, 6=slowest), "
|
||||||
" -m <int> ............... compression method (0=fast, 6=slowest), "
|
|
||||||
"default=4\n");
|
"default=4\n");
|
||||||
printf(
|
printf(" -segments <int> ........ number of segments to use (1..4), "
|
||||||
" -segments <int> ........ number of segments to use (1..4), "
|
|
||||||
"default=4\n");
|
"default=4\n");
|
||||||
printf(" -size <int> ............ target size (in bytes)\n");
|
printf(" -size <int> ............ target size (in bytes)\n");
|
||||||
printf(" -psnr <float> .......... target PSNR (in dB. typically: 42)\n");
|
printf(" -psnr <float> .......... target PSNR (in dB. typically: 42)\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" -s <int> <int> ......... input size (width x height) for YUV\n");
|
printf(" -s <int> <int> ......... input size (width x height) for YUV\n");
|
||||||
printf(
|
printf(" -sns <int> ............. spatial noise shaping (0:off, 100:max), "
|
||||||
" -sns <int> ............. spatial noise shaping (0:off, 100:max), "
|
|
||||||
"default=50\n");
|
"default=50\n");
|
||||||
printf(
|
printf(" -f <int> ............... filter strength (0=off..100), "
|
||||||
" -f <int> ............... filter strength (0=off..100), "
|
|
||||||
"default=60\n");
|
"default=60\n");
|
||||||
printf(
|
printf(" -sharpness <int> ....... "
|
||||||
" -sharpness <int> ....... "
|
|
||||||
"filter sharpness (0:most .. 7:least sharp), default=0\n");
|
"filter sharpness (0:most .. 7:least sharp), default=0\n");
|
||||||
printf(
|
printf(" -strong ................ use strong filter instead "
|
||||||
" -strong ................ use strong filter instead "
|
|
||||||
"of simple (default)\n");
|
"of simple (default)\n");
|
||||||
printf(" -nostrong .............. use simple filter instead of strong\n");
|
printf(" -nostrong .............. use simple filter instead of strong\n");
|
||||||
printf(
|
printf(" -sharp_yuv ............. use sharper (and slower) RGB->YUV "
|
||||||
" -sharp_yuv ............. use sharper (and slower) RGB->YUV "
|
|
||||||
"conversion\n");
|
"conversion\n");
|
||||||
printf(" -partition_limit <int> . limit quality to fit the 512k limit on\n");
|
printf(" -partition_limit <int> . limit quality to fit the 512k limit on\n");
|
||||||
printf(
|
printf(" "
|
||||||
" "
|
|
||||||
"the first partition (0=no degradation ... 100=full)\n");
|
"the first partition (0=no degradation ... 100=full)\n");
|
||||||
printf(" -pass <int> ............ analysis pass number (1..10)\n");
|
printf(" -pass <int> ............ analysis pass number (1..10)\n");
|
||||||
printf(
|
printf(" -qrange <min> <max> .... specifies the permissible quality range\n"
|
||||||
" -qrange <min> <max> .... specifies the permissible quality range\n"
|
|
||||||
" (default: 0 100)\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,24 +579,21 @@ static void HelpLong(void) {
|
|||||||
printf(" -print_ssim ............ prints averaged SSIM distortion\n");
|
printf(" -print_ssim ............ prints averaged SSIM distortion\n");
|
||||||
printf(" -print_lsim ............ prints local-similarity distortion\n");
|
printf(" -print_lsim ............ prints local-similarity distortion\n");
|
||||||
printf(" -d <file.pgm> .......... dump the compressed output (PGM file)\n");
|
printf(" -d <file.pgm> .......... dump the compressed output (PGM file)\n");
|
||||||
printf(
|
printf(" -alpha_method <int> .... transparency-compression method (0..1), "
|
||||||
" -alpha_method <int> .... transparency-compression method (0..1), "
|
|
||||||
"default=1\n");
|
"default=1\n");
|
||||||
printf(" -alpha_filter <string> . predictive filtering for alpha plane,\n");
|
printf(" -alpha_filter <string> . predictive filtering for alpha plane,\n");
|
||||||
printf(" one of: none, fast (default) or best\n");
|
printf(" one of: none, fast (default) or best\n");
|
||||||
printf(
|
printf(" -exact ................. preserve RGB values in transparent area, "
|
||||||
" -exact ................. preserve RGB values in transparent area, "
|
|
||||||
"default=off\n");
|
"default=off\n");
|
||||||
printf(
|
printf(" -blend_alpha <hex> ..... blend colors against background color\n"
|
||||||
" -blend_alpha <hex> ..... blend colors against background color\n"
|
|
||||||
" expressed as RGB values written in\n"
|
" expressed as RGB values written in\n"
|
||||||
" hexadecimal, e.g. 0xc0e0d0 for red=0xc0\n"
|
" hexadecimal, e.g. 0xc0e0d0 for red=0xc0\n"
|
||||||
" green=0xe0 and blue=0xd0\n");
|
" green=0xe0 and blue=0xd0\n");
|
||||||
printf(" -noalpha ............... discard any transparency information\n");
|
printf(" -noalpha ............... discard any transparency information\n");
|
||||||
printf(" -lossless .............. encode image losslessly, default=off\n");
|
printf(" -lossless .............. encode image losslessly, default=off\n");
|
||||||
printf(
|
printf(" -near_lossless <int> ... use near-lossless image\n"
|
||||||
" -near_lossless <int> ... use near-lossless image preprocessing\n"
|
" preprocessing (0..100=off), "
|
||||||
" (0..100=off), default=100\n");
|
"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");
|
||||||
|
|
||||||
@@ -662,8 +601,7 @@ static void HelpLong(void) {
|
|||||||
printf(" -metadata <string> ..... comma separated list of metadata to\n");
|
printf(" -metadata <string> ..... comma separated list of metadata to\n");
|
||||||
printf(" ");
|
printf(" ");
|
||||||
printf("copy from the input to the output if present.\n");
|
printf("copy from the input to the output if present.\n");
|
||||||
printf(
|
printf(" "
|
||||||
" "
|
|
||||||
"Valid values: all, none (default), exif, icc, xmp\n");
|
"Valid values: all, none (default), exif, icc, xmp\n");
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -673,8 +611,7 @@ static void HelpLong(void) {
|
|||||||
#ifndef WEBP_DLL
|
#ifndef WEBP_DLL
|
||||||
printf(" -noasm ................. disable all assembly optimizations\n");
|
printf(" -noasm ................. disable all assembly optimizations\n");
|
||||||
#endif
|
#endif
|
||||||
printf(
|
printf(" -v ..................... verbose, e.g. print encoding/decoding "
|
||||||
" -v ..................... verbose, e.g. print encoding/decoding "
|
|
||||||
"times\n");
|
"times\n");
|
||||||
printf(" -progress .............. report encoding progress\n");
|
printf(" -progress .............. report encoding progress\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -683,7 +620,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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -705,13 +641,13 @@ static const char* const kErrorMessages[VP8_ENC_ERROR_LAST] = {
|
|||||||
"PARTITION_OVERFLOW: Partition is too big to fit 16M",
|
"PARTITION_OVERFLOW: Partition is too big to fit 16M",
|
||||||
"BAD_WRITE: Picture writer returned an I/O error",
|
"BAD_WRITE: Picture writer returned an I/O error",
|
||||||
"FILE_TOO_BIG: File would be too big to fit in 4G",
|
"FILE_TOO_BIG: File would be too big to fit in 4G",
|
||||||
"USER_ABORT: encoding abort requested by user"};
|
"USER_ABORT: encoding abort requested by user"
|
||||||
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// 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;
|
||||||
@@ -722,7 +658,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;
|
||||||
@@ -742,25 +677,26 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
MetadataInit(&metadata);
|
MetadataInit(&metadata);
|
||||||
WebPMemoryWriterInit(&memory_writer);
|
WebPMemoryWriterInit(&memory_writer);
|
||||||
if (!WebPPictureInit(&picture) || !WebPPictureInit(&original_picture) ||
|
if (!WebPPictureInit(&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 + 1 < argc) {
|
||||||
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 + 1 < argc) {
|
||||||
@@ -782,7 +718,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
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 ||
|
||||||
picture.height > WEBP_MAX_DIMENSION || picture.height < 0) {
|
picture.height > WEBP_MAX_DIMENSION || picture.height < 0) {
|
||||||
fprintf(stderr, "Specified dimension (%d x %d) is out of range.\n",
|
fprintf(stderr,
|
||||||
|
"Specified dimension (%d x %d) is out of range.\n",
|
||||||
picture.width, picture.height);
|
picture.width, picture.height);
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
@@ -888,30 +825,15 @@ int main(int argc, const char* argv[]) {
|
|||||||
} else if (!strcmp(argv[c], "-resize") && c + 2 < argc) {
|
} else if (!strcmp(argv[c], "-resize") && c + 2 < argc) {
|
||||||
resize_w = ExUtilGetInt(argv[++c], 0, &parse_error);
|
resize_w = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
resize_h = ExUtilGetInt(argv[++c], 0, &parse_error);
|
resize_h = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} 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 >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
||||||
version & 0xff);
|
FREE_WARGV_AND_RETURN(0);
|
||||||
printf("libsharpyuv: %d.%d.%d\n", (sharpyuv_version >> 24) & 0xff,
|
|
||||||
(sharpyuv_version >> 16) & 0xffff, sharpyuv_version & 0xff);
|
|
||||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
|
||||||
} else if (!strcmp(argv[c], "-progress")) {
|
} else if (!strcmp(argv[c], "-progress")) {
|
||||||
show_progress = 1;
|
show_progress = 1;
|
||||||
} else if (!strcmp(argv[c], "-quiet")) {
|
} else if (!strcmp(argv[c], "-quiet")) {
|
||||||
@@ -944,11 +866,11 @@ int main(int argc, const char* argv[]) {
|
|||||||
const char* option;
|
const char* option;
|
||||||
int flag;
|
int flag;
|
||||||
} kTokens[] = {
|
} kTokens[] = {
|
||||||
{"all", METADATA_ALL}, //
|
{ "all", METADATA_ALL },
|
||||||
{"none", 0}, //
|
{ "none", 0 },
|
||||||
{"exif", METADATA_EXIF}, //
|
{ "exif", METADATA_EXIF },
|
||||||
{"icc", METADATA_ICC}, //
|
{ "icc", METADATA_ICC },
|
||||||
{"xmp", METADATA_XMP}, //
|
{ "xmp", METADATA_XMP },
|
||||||
};
|
};
|
||||||
const size_t kNumTokens = sizeof(kTokens) / sizeof(kTokens[0]);
|
const size_t kNumTokens = sizeof(kTokens) / sizeof(kTokens[0]);
|
||||||
const char* start = argv[++c];
|
const char* start = argv[++c];
|
||||||
@@ -973,15 +895,14 @@ 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;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_WINCODEC_H
|
#ifdef HAVE_WINCODEC_H
|
||||||
if (keep_metadata != 0 && keep_metadata != METADATA_ICC) {
|
if (keep_metadata != 0 && keep_metadata != METADATA_ICC) {
|
||||||
// TODO(jzern): remove when -metadata is supported on all platforms.
|
// TODO(jzern): remove when -metadata is supported on all platforms.
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Warning: only ICC profile extraction is currently"
|
||||||
"Warning: only ICC profile extraction is currently"
|
|
||||||
" supported on this platform!\n");
|
" supported on this platform!\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -993,14 +914,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]);
|
||||||
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) {
|
||||||
@@ -1020,13 +941,11 @@ int main(int argc, const char* argv[]) {
|
|||||||
// warning for such options.
|
// warning for such options.
|
||||||
if (!quiet && config.lossless == 1) {
|
if (!quiet && config.lossless == 1) {
|
||||||
if (config.target_size > 0 || config.target_PSNR > 0) {
|
if (config.target_size > 0 || config.target_PSNR > 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Encoding for specified size or PSNR is not supported"
|
||||||
"Encoding for specified size or PSNR is not supported"
|
|
||||||
" for lossless encoding. Ignoring such option(s)!\n");
|
" for lossless encoding. Ignoring such option(s)!\n");
|
||||||
}
|
}
|
||||||
if (config.partition_limit > 0) {
|
if (config.partition_limit > 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Partition limit option is not required for lossless"
|
||||||
"Partition limit option is not required for lossless"
|
|
||||||
" encoding. Ignoring this option!\n");
|
" encoding. Ignoring this option!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1044,8 +963,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
// Read the input. We need to decide if we prefer ARGB or YUVA
|
// Read the input. We need to decide if we prefer ARGB or YUVA
|
||||||
// samples, depending on the expected compression mode (this saves
|
// samples, depending on the expected compression mode (this saves
|
||||||
// some conversion steps).
|
// some conversion steps).
|
||||||
picture.use_argb =
|
picture.use_argb = (config.lossless || config.use_sharp_yuv ||
|
||||||
(config.lossless || config.use_sharp_yuv || config.preprocessing > 0 ||
|
config.preprocessing > 0 ||
|
||||||
crop || (resize_w | resize_h) > 0);
|
crop || (resize_w | resize_h) > 0);
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
StopwatchReset(&stop_watch);
|
StopwatchReset(&stop_watch);
|
||||||
@@ -1122,7 +1041,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) {
|
||||||
@@ -1194,8 +1112,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
if (!WebPEncode(&config, &picture)) {
|
if (!WebPEncode(&config, &picture)) {
|
||||||
fprintf(stderr, "Error! Cannot encode picture as WebP\n");
|
fprintf(stderr, "Error! Cannot encode picture as WebP\n");
|
||||||
fprintf(stderr, "Error code: %d (%s)\n", picture.error_code,
|
fprintf(stderr, "Error code: %d (%s)\n",
|
||||||
kErrorMessages[picture.error_code]);
|
picture.error_code, kErrorMessages[picture.error_code]);
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
@@ -1221,9 +1139,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
picture.use_argb = 1;
|
picture.use_argb = 1;
|
||||||
if (!ReadWebP(
|
if (!ReadWebP(memory_writer.mem, memory_writer.size, &picture,
|
||||||
memory_writer.mem, memory_writer.size, &picture,
|
/*keep_alpha=*/WebPPictureHasTransparency(&picture),
|
||||||
/*keep_alpha=*/WebPPictureHasTransparency(&original_picture),
|
|
||||||
/*metadata=*/NULL)) {
|
/*metadata=*/NULL)) {
|
||||||
fprintf(stderr, "Error! Cannot decode encoded WebP bitstream\n");
|
fprintf(stderr, "Error! Cannot decode encoded WebP bitstream\n");
|
||||||
fprintf(stderr, "Error code: %d (%s)\n", picture.error_code,
|
fprintf(stderr, "Error code: %d (%s)\n", picture.error_code,
|
||||||
@@ -1238,8 +1155,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
// Write the YUV planes to a PGM file. Only available for lossy.
|
// 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,
|
fprintf(stderr, "Warning: can't dump file (-d option) "
|
||||||
"Warning: can't dump file (-d option) "
|
|
||||||
"in lossless mode.\n");
|
"in lossless mode.\n");
|
||||||
} else if (!DumpPicture(&picture, dump_file)) {
|
} else if (!DumpPicture(&picture, dump_file)) {
|
||||||
WFPRINTF(stderr, "Warning, couldn't dump picture %s\n",
|
WFPRINTF(stderr, "Warning, couldn't dump picture %s\n",
|
||||||
@@ -1288,15 +1204,15 @@ int main(int argc, const char* argv[]) {
|
|||||||
if (print_distortion >= 0) { // print distortion
|
if (print_distortion >= 0) { // print distortion
|
||||||
static const char* distortion_names[] = { "PSNR", "SSIM", "LSIM" };
|
static const char* distortion_names[] = { "PSNR", "SSIM", "LSIM" };
|
||||||
float values[5];
|
float values[5];
|
||||||
if (!WebPPictureDistortion(&picture, &original_picture, print_distortion,
|
if (!WebPPictureDistortion(&picture, &original_picture,
|
||||||
values)) {
|
print_distortion, values)) {
|
||||||
fprintf(stderr, "Error while computing the distortion.\n");
|
fprintf(stderr, "Error while computing the distortion.\n");
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
if (!short_output) {
|
if (!short_output) {
|
||||||
fprintf(stderr, "%s: ", distortion_names[print_distortion]);
|
fprintf(stderr, "%s: ", distortion_names[print_distortion]);
|
||||||
fprintf(stderr, "B:%.2f G:%.2f R:%.2f A:%.2f Total:%.2f\n", values[0],
|
fprintf(stderr, "B:%.2f G:%.2f R:%.2f A:%.2f Total:%.2f\n",
|
||||||
values[1], values[2], values[3], values[4]);
|
values[0], values[1], values[2], values[3], values[4]);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "%7d %.4f\n", picture.stats->coded_size, values[4]);
|
fprintf(stderr, "%7d %.4f\n", picture.stats->coded_size, values[4]);
|
||||||
}
|
}
|
||||||
@@ -1305,7 +1221,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);
|
||||||
|
|||||||
146
examples/dwebp.c
146
examples/dwebp.c
@@ -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;
|
||||||
@@ -42,6 +40,7 @@ extern void* VP8GetCPUInfo; // opaque forward declaration.
|
|||||||
#endif
|
#endif
|
||||||
#endif // WEBP_DLL
|
#endif // WEBP_DLL
|
||||||
|
|
||||||
|
|
||||||
static int SaveOutput(const WebPDecBuffer* const buffer,
|
static int SaveOutput(const WebPDecBuffer* const buffer,
|
||||||
WebPOutputFileFormat format, const char* const out_file) {
|
WebPOutputFileFormat format, const char* const out_file) {
|
||||||
const int use_stdout = (out_file != NULL) && !WSTRCMP(out_file, "-");
|
const int use_stdout = (out_file != NULL) && !WSTRCMP(out_file, "-");
|
||||||
@@ -76,8 +75,7 @@ static int SaveOutput(const WebPDecBuffer* const buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void Help(void) {
|
static void Help(void) {
|
||||||
printf(
|
printf("Usage: dwebp in_file [options] [-o out_file]\n\n"
|
||||||
"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"
|
"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"
|
||||||
@@ -98,7 +96,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"
|
||||||
@@ -111,7 +109,9 @@ static void Help(void) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* const kFormatType[] = {"unspecified", "lossy", "lossless"};
|
static const char* const kFormatType[] = {
|
||||||
|
"unspecified", "lossy", "lossless"
|
||||||
|
};
|
||||||
|
|
||||||
static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
|
static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
|
||||||
WebPOutputFileFormat format,
|
WebPOutputFileFormat format,
|
||||||
@@ -128,9 +128,9 @@ static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
|
|||||||
h = config->options.crop_height;
|
h = config->options.crop_height;
|
||||||
}
|
}
|
||||||
if (format >= RGB && format <= rgbA_4444) {
|
if (format >= RGB && format <= rgbA_4444) {
|
||||||
const int bpp =
|
const int bpp = (format == RGB || format == BGR) ? 3
|
||||||
(format == RGB || format == BGR) ? 3
|
: (format == RGBA_4444 || format == rgbA_4444 ||
|
||||||
: (format == RGBA_4444 || format == rgbA_4444 || format == RGB_565) ? 2
|
format == RGB_565) ? 2
|
||||||
: 4;
|
: 4;
|
||||||
uint32_t stride = bpp * w + 7; // <- just for exercising
|
uint32_t stride = bpp * w + 7; // <- just for exercising
|
||||||
external_buffer = (uint8_t*)WebPMalloc(stride * h);
|
external_buffer = (uint8_t*)WebPMalloc(stride * h);
|
||||||
@@ -143,8 +143,8 @@ static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
|
|||||||
uint8_t* tmp;
|
uint8_t* tmp;
|
||||||
uint32_t stride = w + 3;
|
uint32_t stride = w + 3;
|
||||||
uint32_t uv_stride = (w + 1) / 2 + 13;
|
uint32_t uv_stride = (w + 1) / 2 + 13;
|
||||||
uint32_t total_size =
|
uint32_t total_size = stride * h * (has_alpha ? 2 : 1)
|
||||||
stride * h * (has_alpha ? 2 : 1) + 2 * uv_stride * (h + 1) / 2;
|
+ 2 * uv_stride * (h + 1) / 2;
|
||||||
assert(format >= YUV && format <= YUVA);
|
assert(format >= YUV && format <= YUVA);
|
||||||
external_buffer = (uint8_t*)WebPMalloc(total_size);
|
external_buffer = (uint8_t*)WebPMalloc(total_size);
|
||||||
if (external_buffer == NULL) return NULL;
|
if (external_buffer == NULL) return NULL;
|
||||||
@@ -177,7 +177,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;
|
||||||
@@ -198,14 +197,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")) {
|
||||||
@@ -226,42 +225,29 @@ int main(int argc, const char* argv[]) {
|
|||||||
quiet = 1;
|
quiet = 1;
|
||||||
} else if (!strcmp(argv[c], "-version")) {
|
} else if (!strcmp(argv[c], "-version")) {
|
||||||
const int version = WebPGetDecoderVersion();
|
const int version = WebPGetDecoderVersion();
|
||||||
printf("%d.%d.%d\n", (version >> 16) & 0xff, (version >> 8) & 0xff,
|
printf("%d.%d.%d\n",
|
||||||
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")) {
|
||||||
format = RAW_YUV;
|
format = RAW_YUV;
|
||||||
} else if (!strcmp(argv[c], "-pixel_format") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-pixel_format") && c < argc - 1) {
|
||||||
const char* const fmt = argv[++c];
|
const char* const fmt = argv[++c];
|
||||||
if (!strcmp(fmt, "RGB")) {
|
if (!strcmp(fmt, "RGB")) format = RGB;
|
||||||
format = RGB;
|
else if (!strcmp(fmt, "RGBA")) format = RGBA;
|
||||||
} else if (!strcmp(fmt, "RGBA")) {
|
else if (!strcmp(fmt, "BGR")) format = BGR;
|
||||||
format = RGBA;
|
else if (!strcmp(fmt, "BGRA")) format = BGRA;
|
||||||
} else if (!strcmp(fmt, "BGR")) {
|
else if (!strcmp(fmt, "ARGB")) format = ARGB;
|
||||||
format = BGR;
|
else if (!strcmp(fmt, "RGBA_4444")) format = RGBA_4444;
|
||||||
} else if (!strcmp(fmt, "BGRA")) {
|
else if (!strcmp(fmt, "RGB_565")) format = RGB_565;
|
||||||
format = BGRA;
|
else if (!strcmp(fmt, "rgbA")) format = rgbA;
|
||||||
} else if (!strcmp(fmt, "ARGB")) {
|
else if (!strcmp(fmt, "bgrA")) format = bgrA;
|
||||||
format = ARGB;
|
else if (!strcmp(fmt, "Argb")) format = Argb;
|
||||||
} else if (!strcmp(fmt, "RGBA_4444")) {
|
else if (!strcmp(fmt, "rgbA_4444")) format = rgbA_4444;
|
||||||
format = RGBA_4444;
|
else if (!strcmp(fmt, "YUV")) format = YUV;
|
||||||
} else if (!strcmp(fmt, "RGB_565")) {
|
else if (!strcmp(fmt, "YUVA")) format = YUVA;
|
||||||
format = RGB_565;
|
else {
|
||||||
} else if (!strcmp(fmt, "rgbA")) {
|
|
||||||
format = rgbA;
|
|
||||||
} else if (!strcmp(fmt, "bgrA")) {
|
|
||||||
format = bgrA;
|
|
||||||
} else if (!strcmp(fmt, "Argb")) {
|
|
||||||
format = Argb;
|
|
||||||
} else if (!strcmp(fmt, "rgbA_4444")) {
|
|
||||||
format = rgbA_4444;
|
|
||||||
} else if (!strcmp(fmt, "YUV")) {
|
|
||||||
format = YUV;
|
|
||||||
} else if (!strcmp(fmt, "YUVA")) {
|
|
||||||
format = YUVA;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Can't parse pixel_format %s\n", fmt);
|
fprintf(stderr, "Can't parse pixel_format %s\n", fmt);
|
||||||
parse_error = 1;
|
parse_error = 1;
|
||||||
}
|
}
|
||||||
@@ -307,21 +293,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;
|
||||||
@@ -330,7 +316,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) {
|
||||||
@@ -361,52 +347,25 @@ int main(int argc, const char* argv[]) {
|
|||||||
output_buffer->colorspace = MODE_YUVA;
|
output_buffer->colorspace = MODE_YUVA;
|
||||||
break;
|
break;
|
||||||
// forced modes:
|
// forced modes:
|
||||||
case RGB:
|
case RGB: output_buffer->colorspace = MODE_RGB; break;
|
||||||
output_buffer->colorspace = MODE_RGB;
|
case RGBA: output_buffer->colorspace = MODE_RGBA; break;
|
||||||
break;
|
case BGR: output_buffer->colorspace = MODE_BGR; break;
|
||||||
case RGBA:
|
case BGRA: output_buffer->colorspace = MODE_BGRA; break;
|
||||||
output_buffer->colorspace = MODE_RGBA;
|
case ARGB: output_buffer->colorspace = MODE_ARGB; break;
|
||||||
break;
|
case RGBA_4444: output_buffer->colorspace = MODE_RGBA_4444; break;
|
||||||
case BGR:
|
case RGB_565: output_buffer->colorspace = MODE_RGB_565; break;
|
||||||
output_buffer->colorspace = MODE_BGR;
|
case rgbA: output_buffer->colorspace = MODE_rgbA; break;
|
||||||
break;
|
case bgrA: output_buffer->colorspace = MODE_bgrA; break;
|
||||||
case BGRA:
|
case Argb: output_buffer->colorspace = MODE_Argb; break;
|
||||||
output_buffer->colorspace = MODE_BGRA;
|
case rgbA_4444: output_buffer->colorspace = MODE_rgbA_4444; break;
|
||||||
break;
|
case YUV: output_buffer->colorspace = MODE_YUV; break;
|
||||||
case ARGB:
|
case YUVA: output_buffer->colorspace = MODE_YUVA; break;
|
||||||
output_buffer->colorspace = MODE_ARGB;
|
default: goto Exit;
|
||||||
break;
|
|
||||||
case RGBA_4444:
|
|
||||||
output_buffer->colorspace = MODE_RGBA_4444;
|
|
||||||
break;
|
|
||||||
case RGB_565:
|
|
||||||
output_buffer->colorspace = MODE_RGB_565;
|
|
||||||
break;
|
|
||||||
case rgbA:
|
|
||||||
output_buffer->colorspace = MODE_rgbA;
|
|
||||||
break;
|
|
||||||
case bgrA:
|
|
||||||
output_buffer->colorspace = MODE_bgrA;
|
|
||||||
break;
|
|
||||||
case Argb:
|
|
||||||
output_buffer->colorspace = MODE_Argb;
|
|
||||||
break;
|
|
||||||
case rgbA_4444:
|
|
||||||
output_buffer->colorspace = MODE_rgbA_4444;
|
|
||||||
break;
|
|
||||||
case YUV:
|
|
||||||
output_buffer->colorspace = MODE_YUV;
|
|
||||||
break;
|
|
||||||
case YUVA:
|
|
||||||
output_buffer->colorspace = MODE_YUVA;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto Exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_external_memory > 0 && format >= RGB) {
|
if (use_external_memory > 0 && format >= RGB) {
|
||||||
external_buffer =
|
external_buffer = AllocateExternalBuffer(&config, format,
|
||||||
AllocateExternalBuffer(&config, format, use_external_memory);
|
use_external_memory);
|
||||||
if (external_buffer == NULL) goto Exit;
|
if (external_buffer == NULL) goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,8 +407,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
output_buffer->width, output_buffer->height,
|
output_buffer->width, output_buffer->height,
|
||||||
bitstream->has_alpha ? " (with alpha)" : "",
|
bitstream->has_alpha ? " (with alpha)" : "",
|
||||||
kFormatType[bitstream->format]);
|
kFormatType[bitstream->format]);
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Nothing written; "
|
||||||
"Nothing written; "
|
|
||||||
"use -o flag to save the result as e.g. PNG.\n");
|
"use -o flag to save the result as e.g. PNG.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -457,7 +415,7 @@ Exit:
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -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,28 +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); cur != NULL;
|
for (cur = strtok((char*)args->argv_data_.bytes, sep);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
#ifndef WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
#ifndef WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
||||||
#define WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
#define WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
||||||
|
|
||||||
#include "webp/mux_types.h"
|
|
||||||
#include "webp/types.h"
|
#include "webp/types.h"
|
||||||
|
#include "webp/mux_types.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -28,15 +28,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <gif_lib.h>
|
#include <gif_lib.h>
|
||||||
|
#include "webp/encode.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 "./gifdec.h"
|
#include "./gifdec.h"
|
||||||
#include "./unicode.h"
|
#include "./unicode.h"
|
||||||
#include "./unicode_gif.h"
|
#include "./unicode_gif.h"
|
||||||
#include "sharpyuv/sharpyuv.h"
|
|
||||||
#include "webp/encode.h"
|
|
||||||
#include "webp/mux.h"
|
|
||||||
|
|
||||||
#if !defined(STDIN_FILENO)
|
#if !defined(STDIN_FILENO)
|
||||||
#define STDIN_FILENO 0
|
#define STDIN_FILENO 0
|
||||||
@@ -48,7 +46,8 @@ static int transparent_index = GIF_INDEX_INVALID; // Opaque by default.
|
|||||||
|
|
||||||
static const char* const kErrorMessages[-WEBP_MUX_NOT_ENOUGH_DATA + 1] = {
|
static const char* const kErrorMessages[-WEBP_MUX_NOT_ENOUGH_DATA + 1] = {
|
||||||
"WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", "WEBP_MUX_BAD_DATA",
|
"WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", "WEBP_MUX_BAD_DATA",
|
||||||
"WEBP_MUX_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA"};
|
"WEBP_MUX_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA"
|
||||||
|
};
|
||||||
|
|
||||||
static const char* ErrorString(WebPMuxError err) {
|
static const char* ErrorString(WebPMuxError err) {
|
||||||
assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA);
|
assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA);
|
||||||
@@ -69,22 +68,11 @@ static void Help(void) {
|
|||||||
printf("Options:\n");
|
printf("Options:\n");
|
||||||
printf(" -h / -help ............. this help\n");
|
printf(" -h / -help ............. this help\n");
|
||||||
printf(" -lossy ................. encode image using lossy compression\n");
|
printf(" -lossy ................. encode image using lossy compression\n");
|
||||||
printf(
|
printf(" -mixed ................. for each frame in the image, pick lossy\n"
|
||||||
" -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(
|
printf(" -m <int> ............... compression method (0=fast, 6=slowest)\n");
|
||||||
" -m <int> ............... compression method (0=fast, 6=slowest), "
|
printf(" -min_size .............. minimize output size (default:off)\n"
|
||||||
"default=4\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"
|
||||||
" options\n");
|
" options\n");
|
||||||
@@ -108,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;
|
||||||
@@ -153,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.
|
||||||
|
|
||||||
@@ -163,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")) {
|
||||||
@@ -178,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) {
|
||||||
@@ -233,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;
|
||||||
}
|
}
|
||||||
@@ -242,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;
|
||||||
@@ -262,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,8 +304,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
printf("Fixed canvas screen dimension to: %d x %d\n", gif->SWidth,
|
printf("Fixed canvas screen dimension to: %d x %d\n",
|
||||||
gif->SHeight);
|
gif->SWidth, gif->SHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Allocate current buffer.
|
// Allocate current buffer.
|
||||||
@@ -334,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,
|
||||||
@@ -560,10 +537,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
err = WebPMuxAssemble(mux, &webp_data);
|
err = WebPMuxAssemble(mux, &webp_data);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "ERROR (%s): Could not assemble when re-muxing to add "
|
||||||
"ERROR (%s): Could not assemble when re-muxing to add "
|
"loop count/metadata.\n", ErrorString(err));
|
||||||
"loop count/metadata.\n",
|
|
||||||
ErrorString(err));
|
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -576,7 +551,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
if (!WSTRCMP(out_file, "-")) {
|
if (!WSTRCMP(out_file, "-")) {
|
||||||
fprintf(stderr, "Saved %d bytes to STDIO\n", (int)webp_data.size);
|
fprintf(stderr, "Saved %d bytes to STDIO\n",
|
||||||
|
(int)webp_data.size);
|
||||||
} else {
|
} else {
|
||||||
WFPRINTF(stderr, "Saved output file (%d bytes): %s\n",
|
WFPRINTF(stderr, "Saved output file (%d bytes): %s\n",
|
||||||
(int)webp_data.size, out_file);
|
(int)webp_data.size, out_file);
|
||||||
@@ -584,10 +560,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Nothing written; use -o flag to save the result "
|
||||||
"Nothing written; use -o flag to save the result "
|
"(%d bytes).\n", (int)webp_data.size);
|
||||||
"(%d bytes).\n",
|
|
||||||
(int)webp_data.size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,7 +590,7 @@ End:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
|
FREE_WARGV_AND_RETURN(!ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // !WEBP_HAVE_GIF
|
#else // !WEBP_HAVE_GIF
|
||||||
@@ -624,7 +598,7 @@ End:
|
|||||||
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
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
#include "webp/mux_types.h"
|
#include "webp/mux_types.h"
|
||||||
#include "webp/types.h"
|
|
||||||
|
|
||||||
#define GIF_TRANSPARENT_COLOR 0x00000000u
|
#define GIF_TRANSPARENT_COLOR 0x00000000u
|
||||||
#define GIF_WHITE_COLOR 0xffffffffu
|
#define GIF_WHITE_COLOR 0xffffffffu
|
||||||
@@ -32,8 +31,9 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
extern void WebPCopyPlane(const uint8_t* src, int src_stride, uint8_t* dst,
|
extern void WebPCopyPlane(const uint8_t* src, int src_stride,
|
||||||
int dst_stride, int width, int height);
|
uint8_t* dst, int dst_stride,
|
||||||
|
int width, int height);
|
||||||
extern void WebPCopyPixels(const WebPPicture* const src,
|
extern void WebPCopyPixels(const WebPPicture* const src,
|
||||||
WebPPicture* const dst);
|
WebPPicture* const dst);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -46,16 +46,18 @@ void GIFGetBackgroundColor(const ColorMapObject* const color_map,
|
|||||||
if (transparent_index != GIF_INDEX_INVALID &&
|
if (transparent_index != GIF_INDEX_INVALID &&
|
||||||
bgcolor_index == transparent_index) {
|
bgcolor_index == transparent_index) {
|
||||||
*bgcolor = GIF_TRANSPARENT_COLOR; // Special case.
|
*bgcolor = GIF_TRANSPARENT_COLOR; // Special case.
|
||||||
} else if (color_map == NULL || color_map->Colors == NULL ||
|
} else if (color_map == NULL || color_map->Colors == NULL
|
||||||
bgcolor_index >= color_map->ColorCount) {
|
|| bgcolor_index >= color_map->ColorCount) {
|
||||||
*bgcolor = GIF_WHITE_COLOR;
|
*bgcolor = GIF_WHITE_COLOR;
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"GIF decode warning: invalid background color index. Assuming "
|
"GIF decode warning: invalid background color index. Assuming "
|
||||||
"white background.\n");
|
"white background.\n");
|
||||||
} else {
|
} else {
|
||||||
const GifColorType color = color_map->Colors[bgcolor_index];
|
const GifColorType color = color_map->Colors[bgcolor_index];
|
||||||
*bgcolor = (0xffu << 24) | (color.Red << 16) | (color.Green << 8) |
|
*bgcolor = (0xffu << 24)
|
||||||
(color.Blue << 0);
|
| (color.Red << 16)
|
||||||
|
| (color.Green << 8)
|
||||||
|
| (color.Blue << 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,8 +116,9 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
|
|||||||
const GifImageDesc* const image_desc = &gif->Image;
|
const GifImageDesc* const image_desc = &gif->Image;
|
||||||
uint32_t* dst = NULL;
|
uint32_t* dst = NULL;
|
||||||
uint8_t* tmp = NULL;
|
uint8_t* tmp = NULL;
|
||||||
const GIFFrameRect rect = {image_desc->Left, image_desc->Top,
|
const GIFFrameRect rect = {
|
||||||
image_desc->Width, image_desc->Height};
|
image_desc->Left, image_desc->Top, image_desc->Width, image_desc->Height
|
||||||
|
};
|
||||||
const uint64_t memory_needed = 4 * rect.width * (uint64_t)rect.height;
|
const uint64_t memory_needed = 4 * rect.width * (uint64_t)rect.height;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
*gif_rect = rect;
|
*gif_rect = rect;
|
||||||
@@ -126,8 +129,8 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use a view for the sub-picture:
|
// Use a view for the sub-picture:
|
||||||
if (!WebPPictureView(picture, rect.x_offset, rect.y_offset, rect.width,
|
if (!WebPPictureView(picture, rect.x_offset, rect.y_offset,
|
||||||
rect.height, &sub_image)) {
|
rect.width, rect.height, &sub_image)) {
|
||||||
fprintf(stderr, "Sub-image %dx%d at position %d,%d is invalid!\n",
|
fprintf(stderr, "Sub-image %dx%d at position %d,%d is invalid!\n",
|
||||||
rect.width, rect.height, rect.x_offset, rect.y_offset);
|
rect.width, rect.height, rect.x_offset, rect.y_offset);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -216,7 +219,8 @@ int GIFReadMetadata(GifFileType* const gif, GifByteType** const buf,
|
|||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memcpy((void*)(tmp + metadata->size), subblock.bytes, subblock.size);
|
memcpy((void*)(tmp + metadata->size),
|
||||||
|
subblock.bytes, subblock.size);
|
||||||
metadata->bytes = tmp;
|
metadata->bytes = tmp;
|
||||||
metadata->size += subblock.size;
|
metadata->size += subblock.size;
|
||||||
}
|
}
|
||||||
@@ -230,8 +234,8 @@ int GIFReadMetadata(GifFileType* const gif, GifByteType** const buf,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ClearRectangle(WebPPicture* const picture, int left, int top,
|
static void ClearRectangle(WebPPicture* const picture,
|
||||||
int width, int height) {
|
int left, int top, int width, int height) {
|
||||||
int i, j;
|
int i, j;
|
||||||
const size_t stride = picture->argb_stride;
|
const size_t stride = picture->argb_stride;
|
||||||
uint32_t* dst = picture->argb + top * stride + left;
|
uint32_t* dst = picture->argb + top * stride + left;
|
||||||
@@ -242,8 +246,8 @@ static void ClearRectangle(WebPPicture* const picture, int left, int top,
|
|||||||
|
|
||||||
void GIFClearPic(WebPPicture* const pic, const GIFFrameRect* const rect) {
|
void GIFClearPic(WebPPicture* const pic, const GIFFrameRect* const rect) {
|
||||||
if (rect != NULL) {
|
if (rect != NULL) {
|
||||||
ClearRectangle(pic, rect->x_offset, rect->y_offset, rect->width,
|
ClearRectangle(pic, rect->x_offset, rect->y_offset,
|
||||||
rect->height);
|
rect->width, rect->height);
|
||||||
} else {
|
} else {
|
||||||
ClearRectangle(pic, 0, 0, pic->width, pic->height);
|
ClearRectangle(pic, 0, 0, pic->width, pic->height);
|
||||||
}
|
}
|
||||||
@@ -261,14 +265,15 @@ void GIFDisposeFrame(GIFDisposeMethod dispose, const GIFFrameRect* const rect,
|
|||||||
GIFClearPic(curr_canvas, rect);
|
GIFClearPic(curr_canvas, rect);
|
||||||
} else if (dispose == GIF_DISPOSE_RESTORE_PREVIOUS) {
|
} else if (dispose == GIF_DISPOSE_RESTORE_PREVIOUS) {
|
||||||
const size_t src_stride = prev_canvas->argb_stride;
|
const size_t src_stride = prev_canvas->argb_stride;
|
||||||
const uint32_t* const src =
|
const uint32_t* const src = prev_canvas->argb + rect->x_offset
|
||||||
prev_canvas->argb + rect->x_offset + rect->y_offset * src_stride;
|
+ rect->y_offset * src_stride;
|
||||||
const size_t dst_stride = curr_canvas->argb_stride;
|
const size_t dst_stride = curr_canvas->argb_stride;
|
||||||
uint32_t* const dst =
|
uint32_t* const dst = curr_canvas->argb + rect->x_offset
|
||||||
curr_canvas->argb + rect->x_offset + rect->y_offset * dst_stride;
|
+ rect->y_offset * dst_stride;
|
||||||
assert(prev_canvas != NULL);
|
assert(prev_canvas != NULL);
|
||||||
WebPCopyPlane((uint8_t*)src, (int)(4 * src_stride), (uint8_t*)dst,
|
WebPCopyPlane((uint8_t*)src, (int)(4 * src_stride),
|
||||||
(int)(4 * dst_stride), 4 * rect->width, rect->height);
|
(uint8_t*)dst, (int)(4 * dst_stride),
|
||||||
|
4 * rect->width, rect->height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,8 +299,8 @@ void GIFDisplayError(const GifFileType* const gif, int gif_error) {
|
|||||||
#if LOCAL_GIF_PREREQ(4,2)
|
#if LOCAL_GIF_PREREQ(4,2)
|
||||||
#if LOCAL_GIF_PREREQ(5,0)
|
#if LOCAL_GIF_PREREQ(5,0)
|
||||||
// Static string actually, hence the const char* cast.
|
// Static string actually, hence the const char* cast.
|
||||||
const char* error_str =
|
const char* error_str = (const char*)GifErrorString(
|
||||||
(const char*)GifErrorString((gif == NULL) ? gif_error : gif->Error);
|
(gif == NULL) ? gif_error : gif->Error);
|
||||||
#else
|
#else
|
||||||
const char* error_str = (const char*)GifErrorString();
|
const char* error_str = (const char*)GifErrorString();
|
||||||
(void)gif;
|
(void)gif;
|
||||||
@@ -312,9 +317,8 @@ 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,
|
fprintf(stderr, "GIF support not compiled. Please install the libgif-dev "
|
||||||
"GIF support not compiled. Please install the libgif-dev "
|
|
||||||
"package before building.\n");
|
"package before building.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -31,7 +30,8 @@ extern "C" {
|
|||||||
// GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
|
// GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
|
||||||
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR)
|
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR)
|
||||||
# define LOCAL_GIF_VERSION ((GIFLIB_MAJOR << 8) | GIFLIB_MINOR)
|
# define LOCAL_GIF_VERSION ((GIFLIB_MAJOR << 8) | GIFLIB_MINOR)
|
||||||
#define LOCAL_GIF_PREREQ(maj, min) (LOCAL_GIF_VERSION >= (((maj) << 8) | (min)))
|
# define LOCAL_GIF_PREREQ(maj, min) \
|
||||||
|
(LOCAL_GIF_VERSION >= (((maj) << 8) | (min)))
|
||||||
#else
|
#else
|
||||||
# define LOCAL_GIF_VERSION 0
|
# define LOCAL_GIF_VERSION 0
|
||||||
# define LOCAL_GIF_PREREQ(maj, min) 0
|
# define LOCAL_GIF_PREREQ(maj, min) 0
|
||||||
|
|||||||
@@ -28,36 +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(
|
printf(" -loop <int> .......... loop count (default: 0, = infinite loop)\n");
|
||||||
" -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(
|
printf(" -kmin <int> .......... minimum number of frame between key-frames\n"
|
||||||
" -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");
|
||||||
@@ -65,30 +54,18 @@ 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(
|
printf(" -m <int> ............. method to use\n");
|
||||||
" -m <int> ............. compression method (0=fast, 6=slowest), "
|
|
||||||
"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(
|
printf("example: img2webp -loop 2 in0.png -lossy in1.jpg\n"
|
||||||
"example: img2webp -loop 2 in0.png -lossy in1.jpg\n"
|
|
||||||
" -d 80 in2.tiff -o out.webp\n");
|
" -d 80 in2.tiff -o out.webp\n");
|
||||||
printf(
|
printf("\nNote: if a single file name is passed as the argument, the "
|
||||||
"\nNote: if a single file name is passed as the argument, the "
|
|
||||||
"arguments will be\n");
|
"arguments will be\n");
|
||||||
printf(
|
printf("tokenized from this file. The file name must not start with "
|
||||||
"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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -146,7 +123,6 @@ End:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// 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;
|
||||||
@@ -162,20 +138,20 @@ 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) || !WebPConfigInit(&config) ||
|
if (!WebPAnimEncoderOptionsInit(&anim_config) ||
|
||||||
|
!WebPConfigInit(&config) ||
|
||||||
!WebPPictureInit(&pic)) {
|
!WebPPictureInit(&pic)) {
|
||||||
fprintf(stderr, "Library version mismatch!\n");
|
fprintf(stderr, "Library version mismatch!\n");
|
||||||
ok = 0;
|
ok = 0;
|
||||||
@@ -207,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;
|
||||||
@@ -240,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,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]);
|
||||||
@@ -290,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) {
|
||||||
@@ -306,8 +267,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
if (ok) {
|
if (ok) {
|
||||||
ok = (width == pic.width && height == pic.height);
|
ok = (width == pic.width && height == pic.height);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Frame #%d dimension mismatched! "
|
||||||
"Frame #%d dimension mismatched! "
|
|
||||||
"Got %d x %d. Was expecting %d x %d.\n",
|
"Got %d x %d. Was expecting %d x %d.\n",
|
||||||
pic_num, pic.width, pic.height, width, height);
|
pic_num, pic.width, pic.height, width, height);
|
||||||
}
|
}
|
||||||
@@ -323,22 +283,13 @@ int main(int argc, const char* argv[]) {
|
|||||||
if (!ok) goto End;
|
if (!ok) goto End;
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
WFPRINTF(stderr, "Added frame #%3d at time %4d (file: %s)\n", pic_num,
|
WFPRINTF(stderr, "Added frame #%3d at time %4d (file: %s)\n",
|
||||||
timestamp_ms, GET_WARGV_SHIFTED(argv, c));
|
pic_num, timestamp_ms, GET_WARGV_SHIFTED(argv, c));
|
||||||
}
|
}
|
||||||
timestamp_ms += duration;
|
timestamp_ms += duration;
|
||||||
++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);
|
||||||
@@ -364,10 +315,10 @@ End:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
fprintf(stderr, "[%d frames, %u bytes].\n", pic_num,
|
fprintf(stderr, "[%d frames, %u bytes].\n",
|
||||||
(unsigned int)webp_data.size);
|
pic_num, (unsigned int)webp_data.size);
|
||||||
}
|
}
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,12 +28,16 @@ static WEBP_INLINE void StopwatchReset(Stopwatch* watch) {
|
|||||||
static WEBP_INLINE double StopwatchReadAndReset(Stopwatch* watch) {
|
static WEBP_INLINE double StopwatchReadAndReset(Stopwatch* watch) {
|
||||||
const LARGE_INTEGER old_value = *watch;
|
const LARGE_INTEGER old_value = *watch;
|
||||||
LARGE_INTEGER freq;
|
LARGE_INTEGER freq;
|
||||||
if (!QueryPerformanceCounter(watch)) return 0.0;
|
if (!QueryPerformanceCounter(watch))
|
||||||
if (!QueryPerformanceFrequency(&freq)) return 0.0;
|
return 0.0;
|
||||||
if (freq.QuadPart == 0) return 0.0;
|
if (!QueryPerformanceFrequency(&freq))
|
||||||
|
return 0.0;
|
||||||
|
if (freq.QuadPart == 0)
|
||||||
|
return 0.0;
|
||||||
return (watch->QuadPart - old_value.QuadPart) / (double)freq.QuadPart;
|
return (watch->QuadPart - old_value.QuadPart) / (double)freq.QuadPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#else /* !_WIN32 */
|
#else /* !_WIN32 */
|
||||||
#include <string.h> // memcpy
|
#include <string.h> // memcpy
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|||||||
@@ -16,19 +16,13 @@
|
|||||||
#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>
|
||||||
|
|
||||||
// shellapi.h must be included after windows.h.
|
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
|
||||||
// Create a wchar_t array containing Unicode parameters.
|
// Create a wchar_t array containing Unicode parameters.
|
||||||
@@ -50,7 +44,7 @@
|
|||||||
#define GET_WARGV_OR_NULL() wargv
|
#define GET_WARGV_OR_NULL() wargv
|
||||||
|
|
||||||
// Release resources. LocalFree() is needed after CommandLineToArgvW().
|
// Release resources. LocalFree() is needed after CommandLineToArgvW().
|
||||||
#define FREE_WARGV() LOCAL_FREE((W_CHAR**)wargv)
|
#define FREE_WARGV() LOCAL_FREE((W_CHAR** const)wargv)
|
||||||
#define LOCAL_FREE(WARGV) \
|
#define LOCAL_FREE(WARGV) \
|
||||||
do { \
|
do { \
|
||||||
if ((WARGV) != NULL) LocalFree(WARGV); \
|
if ((WARGV) != NULL) LocalFree(WARGV); \
|
||||||
@@ -61,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))
|
||||||
@@ -79,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.
|
||||||
|
|
||||||
@@ -99,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)
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
#include <gif_lib.h>
|
#include <gif_lib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "./gifdec.h"
|
#include "./gifdec.h"
|
||||||
|
|
||||||
#if !defined(STDIN_FILENO)
|
#if !defined(STDIN_FILENO)
|
||||||
@@ -46,7 +45,7 @@ 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;
|
||||||
@@ -58,7 +57,6 @@ static GifFileType* DGifOpenFileUnicode(const W_CHAR* file_name, int* error) {
|
|||||||
#else
|
#else
|
||||||
return DGifOpenFileHandle(file_handle);
|
return DGifOpenFileHandle(file_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -38,11 +37,12 @@
|
|||||||
#include <qcms.h>
|
#include <qcms.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "webp/decode.h"
|
||||||
|
#include "webp/demux.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/demux.h"
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
@@ -134,8 +134,9 @@ static int ApplyColorProfile(const WebPData* const profile,
|
|||||||
}
|
}
|
||||||
|
|
||||||
qcms_profile_precache_output_transform(output_profile);
|
qcms_profile_precache_output_transform(output_profile);
|
||||||
transform = qcms_transform_create(input_profile, input_type, output_profile,
|
transform = qcms_transform_create(input_profile, input_type,
|
||||||
output_type, intent);
|
output_profile, output_type,
|
||||||
|
intent);
|
||||||
if (transform == NULL) {
|
if (transform == NULL) {
|
||||||
fprintf(stderr, "Error creating color transform!\n");
|
fprintf(stderr, "Error creating color transform!\n");
|
||||||
goto Error;
|
goto Error;
|
||||||
@@ -170,8 +171,8 @@ static int Decode(void) { // Fills kParams.curr_frame
|
|||||||
|
|
||||||
ClearPreviousPic();
|
ClearPreviousPic();
|
||||||
output_buffer->colorspace = MODE_RGBA;
|
output_buffer->colorspace = MODE_RGBA;
|
||||||
ok = (WebPDecode(curr->fragment.bytes, curr->fragment.size, config) ==
|
ok = (WebPDecode(curr->fragment.bytes, curr->fragment.size,
|
||||||
VP8_STATUS_OK);
|
config) == VP8_STATUS_OK);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
fprintf(stderr, "Decoding of frame #%d failed!\n", curr->frame_num);
|
fprintf(stderr, "Decoding of frame #%d failed!\n", curr->frame_num);
|
||||||
} else {
|
} else {
|
||||||
@@ -291,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;
|
||||||
}
|
}
|
||||||
@@ -339,7 +327,8 @@ static void DrawBackground(void) {
|
|||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glColor4f(GetColorf(kParams.bg_color, 16), // BGRA from spec
|
glColor4f(GetColorf(kParams.bg_color, 16), // BGRA from spec
|
||||||
GetColorf(kParams.bg_color, 8), GetColorf(kParams.bg_color, 0),
|
GetColorf(kParams.bg_color, 8),
|
||||||
|
GetColorf(kParams.bg_color, 0),
|
||||||
GetColorf(kParams.bg_color, 24));
|
GetColorf(kParams.bg_color, 24));
|
||||||
glRecti(-1, -1, +1, +1);
|
glRecti(-1, -1, +1, +1);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
@@ -399,22 +388,23 @@ static void HandleDisplay(void) {
|
|||||||
|
|
||||||
*prev = *curr;
|
*prev = *curr;
|
||||||
|
|
||||||
glDrawPixels(pic->width, pic->height, GL_RGBA, GL_UNSIGNED_BYTE,
|
glDrawPixels(pic->width, pic->height,
|
||||||
|
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
(GLvoid*)pic->u.RGBA.rgba);
|
(GLvoid*)pic->u.RGBA.rgba);
|
||||||
if (kParams.print_info) {
|
if (kParams.print_info) {
|
||||||
char tmp[32];
|
char tmp[32];
|
||||||
|
|
||||||
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);
|
||||||
glRasterPos2f(-0.95f, 0.80f);
|
glRasterPos2f(-0.95f, 0.80f);
|
||||||
PrintString(tmp);
|
PrintString(tmp);
|
||||||
if (curr->x_offset != 0 || curr->y_offset != 0) {
|
if (curr->x_offset != 0 || curr->y_offset != 0) {
|
||||||
snprintf(tmp, sizeof(tmp), " (offset:%d,%d)", curr->x_offset,
|
snprintf(tmp, sizeof(tmp), " (offset:%d,%d)",
|
||||||
curr->y_offset);
|
curr->x_offset, curr->y_offset);
|
||||||
glRasterPos2f(-0.95f, 0.70f);
|
glRasterPos2f(-0.95f, 0.70f);
|
||||||
PrintString(tmp);
|
PrintString(tmp);
|
||||||
}
|
}
|
||||||
@@ -427,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)
|
||||||
@@ -453,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);
|
||||||
@@ -494,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;
|
||||||
|
|
||||||
@@ -502,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;
|
||||||
@@ -514,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")) {
|
||||||
@@ -537,38 +523,34 @@ int main(int argc, char* argv[]) {
|
|||||||
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
||||||
dec_version & 0xff, (dmux_version >> 16) & 0xff,
|
dec_version & 0xff, (dmux_version >> 16) & 0xff,
|
||||||
(dmux_version >> 8) & 0xff, dmux_version & 0xff);
|
(dmux_version >> 8) & 0xff, dmux_version & 0xff);
|
||||||
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, &kParams.data.bytes,
|
if (!ImgIoUtilReadFile(kParams.file_name,
|
||||||
&kParams.data.size)) {
|
&kParams.data.bytes, &kParams.data.size)) {
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,8 +581,7 @@ int main(int argc, char* argv[]) {
|
|||||||
if (!WebPDemuxGetChunk(kParams.dmux, "ICCP", 1, &kParams.iccp)) goto Error;
|
if (!WebPDemuxGetChunk(kParams.dmux, "ICCP", 1, &kParams.iccp)) goto Error;
|
||||||
printf("VP8X: Found color profile\n");
|
printf("VP8X: Found color profile\n");
|
||||||
#else
|
#else
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Warning: color profile present, but qcms is unavailable!\n"
|
||||||
"Warning: color profile present, but qcms is unavailable!\n"
|
|
||||||
"Build libqcms from Mozilla or Chromium and define WEBP_HAVE_QCMS "
|
"Build libqcms from Mozilla or Chromium and define WEBP_HAVE_QCMS "
|
||||||
"before building.\n");
|
"before building.\n");
|
||||||
#endif
|
#endif
|
||||||
@@ -611,15 +592,15 @@ int main(int argc, char* argv[]) {
|
|||||||
kParams.has_animation = (curr->num_frames > 1);
|
kParams.has_animation = (curr->num_frames > 1);
|
||||||
kParams.loop_count = (int)WebPDemuxGetI(kParams.dmux, WEBP_FF_LOOP_COUNT);
|
kParams.loop_count = (int)WebPDemuxGetI(kParams.dmux, WEBP_FF_LOOP_COUNT);
|
||||||
kParams.bg_color = WebPDemuxGetI(kParams.dmux, WEBP_FF_BACKGROUND_COLOR);
|
kParams.bg_color = WebPDemuxGetI(kParams.dmux, WEBP_FF_BACKGROUND_COLOR);
|
||||||
printf("VP8X: Found %d images in file (loop count = %d)\n", curr->num_frames,
|
printf("VP8X: Found %d images in file (loop count = %d)\n",
|
||||||
kParams.loop_count);
|
curr->num_frames, kParams.loop_count);
|
||||||
|
|
||||||
// Decode first frame
|
// Decode first frame
|
||||||
if (!Decode()) goto Error;
|
if (!Decode()) goto Error;
|
||||||
|
|
||||||
// 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__)
|
||||||
@@ -633,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
|
||||||
@@ -652,7 +633,7 @@ Error:
|
|||||||
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
|
||||||
|
|||||||
@@ -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,26 +31,38 @@
|
|||||||
|
|
||||||
#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; \
|
++webp_info->num_warnings_; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static const char* const kFormats[3] = {"Unknown", "Lossy", "Lossless"};
|
static const char* const kFormats[3] = {
|
||||||
|
"Unknown",
|
||||||
|
"Lossy",
|
||||||
|
"Lossless"
|
||||||
|
};
|
||||||
|
|
||||||
static const char* const kLosslessTransforms[4] = {
|
static const char* const kLosslessTransforms[4] = {
|
||||||
"Predictor", "Cross Color", "Subtract Green", "Color Indexing"};
|
"Predictor",
|
||||||
|
"Cross Color",
|
||||||
|
"Subtract Green",
|
||||||
|
"Color Indexing"
|
||||||
|
};
|
||||||
|
|
||||||
static const char* const kAlphaFilterMethods[4] = {"None", "Horizontal",
|
static const char* const kAlphaFilterMethods[4] = {
|
||||||
"Vertical", "Gradient"};
|
"None",
|
||||||
|
"Horizontal",
|
||||||
|
"Vertical",
|
||||||
|
"Gradient"
|
||||||
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WEBP_INFO_OK = 0,
|
WEBP_INFO_OK = 0,
|
||||||
@@ -80,52 +89,52 @@ 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 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', ' ' },
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -175,23 +184,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) { mem->start += size; }
|
static void Skip(MemBuffer* const mem, size_t 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);
|
||||||
@@ -252,8 +263,7 @@ static WebPInfoStatus ParseLossySegmentHeader(const WebPInfo* const webp_info,
|
|||||||
int update_map, update_data;
|
int update_map, update_data;
|
||||||
GET_BITS(update_map, 1);
|
GET_BITS(update_map, 1);
|
||||||
GET_BITS(update_data, 1);
|
GET_BITS(update_data, 1);
|
||||||
printf(
|
printf(" Update map: %d\n"
|
||||||
" Update map: %d\n"
|
|
||||||
" Update data: %d\n",
|
" Update data: %d\n",
|
||||||
update_map, update_data);
|
update_map, update_data);
|
||||||
if (update_data) {
|
if (update_data) {
|
||||||
@@ -285,8 +295,8 @@ static WebPInfoStatus ParseLossySegmentHeader(const WebPInfo* const webp_info,
|
|||||||
GET_BITS(bit, 1);
|
GET_BITS(bit, 1);
|
||||||
if (bit) GET_BITS(prob_segment[i], 8);
|
if (bit) GET_BITS(prob_segment[i], 8);
|
||||||
}
|
}
|
||||||
printf(" Prob segment: %d %d %d\n", prob_segment[0], prob_segment[1],
|
printf(" Prob segment: %d %d %d\n",
|
||||||
prob_segment[2]);
|
prob_segment[0], prob_segment[1], prob_segment[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return WEBP_INFO_OK;
|
return WEBP_INFO_OK;
|
||||||
@@ -323,8 +333,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;
|
||||||
@@ -336,7 +346,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;
|
||||||
@@ -347,19 +357,18 @@ 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: Yes\n"
|
" Display: %s\n"
|
||||||
" Part. 0 length: %d\n",
|
" Part. 0 length: %d\n",
|
||||||
key_frame ? "Yes" : "No", profile, partition0_length);
|
key_frame ? "Yes" : "No", profile,
|
||||||
|
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.");
|
||||||
return WEBP_INFO_BITSTREAM_ERROR;
|
return WEBP_INFO_BITSTREAM_ERROR;
|
||||||
}
|
}
|
||||||
printf(
|
printf(" Width: %d\n"
|
||||||
" Width: %d\n"
|
|
||||||
" X scale: %d\n"
|
" X scale: %d\n"
|
||||||
" Height: %d\n"
|
" Height: %d\n"
|
||||||
" Y scale: %d\n",
|
" Y scale: %d\n",
|
||||||
@@ -487,8 +496,7 @@ static WebPInfoStatus ParseLosslessTransform(WebPInfo* const webp_info,
|
|||||||
n_colors += 1;
|
n_colors += 1;
|
||||||
printf(" No. of colors: %d\n", n_colors);
|
printf(" No. of colors: %d\n", n_colors);
|
||||||
break;
|
break;
|
||||||
default:
|
default: break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return WEBP_INFO_OK;
|
return WEBP_INFO_OK;
|
||||||
@@ -496,8 +504,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;
|
||||||
@@ -532,8 +540,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;
|
||||||
@@ -545,8 +553,8 @@ static WebPInfoStatus ParseAlphaHeader(const ChunkData* const chunk_data,
|
|||||||
const int pre_processing = (data[0] >> 4) & 0x03;
|
const int pre_processing = (data[0] >> 4) & 0x03;
|
||||||
const int reserved_bits = (data[0] >> 6) & 0x03;
|
const int reserved_bits = (data[0] >> 6) & 0x03;
|
||||||
printf(" Compression: %d\n", compression_method);
|
printf(" Compression: %d\n", compression_method);
|
||||||
printf(" Filter: %s (%d)\n", kAlphaFilterMethods[filter],
|
printf(" Filter: %s (%d)\n",
|
||||||
filter);
|
kAlphaFilterMethods[filter], filter);
|
||||||
printf(" Pre-processing: %d\n", pre_processing);
|
printf(" Pre-processing: %d\n", pre_processing);
|
||||||
if (compression_method > ALPHA_LOSSLESS_COMPRESSION) {
|
if (compression_method > ALPHA_LOSSLESS_COMPRESSION) {
|
||||||
LOG_ERROR("Invalid Alpha compression method.");
|
LOG_ERROR("Invalid Alpha compression method.");
|
||||||
@@ -598,14 +606,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;
|
||||||
}
|
}
|
||||||
@@ -621,7 +629,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);
|
||||||
@@ -636,13 +644,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;
|
||||||
@@ -661,39 +669,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", webp_info->canvas_width,
|
printf(" Canvas size %d x %d\n",
|
||||||
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.");
|
||||||
}
|
}
|
||||||
@@ -702,25 +710,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 >> 16) & 0xff,
|
(webp_info->bgcolor_ >> 24) & 0xff,
|
||||||
(webp_info->bgcolor >> 8) & 0xff, webp_info->bgcolor & 0xff);
|
(webp_info->bgcolor_ >> 16) & 0xff,
|
||||||
printf(" Loop count : %d\n", webp_info->loop_count);
|
(webp_info->bgcolor_ >> 8) & 0xff,
|
||||||
|
webp_info->bgcolor_ & 0xff);
|
||||||
|
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;
|
||||||
@@ -728,17 +738,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;
|
||||||
}
|
}
|
||||||
@@ -750,10 +760,9 @@ 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(
|
printf(" Offset_X: %d\n Offset_Y: %d\n Width: %d\n Height: %d\n"
|
||||||
" 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);
|
||||||
}
|
}
|
||||||
@@ -765,92 +774,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(
|
printf(" Width: %d\n Height: %d\n Alpha: %d\n Animation: %d\n"
|
||||||
" 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 && webp_info->chunk_counts[CHUNK_ALPHA]) {
|
if (chunk_data->id_ == CHUNK_VP8L &&
|
||||||
|
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);
|
||||||
@@ -861,42 +870,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(
|
LOG_ERROR("ALPHA sub-chunk detected after VP8 sub-chunk "
|
||||||
"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;
|
||||||
}
|
}
|
||||||
@@ -906,40 +914,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];
|
printf("Chunk %c%c%c%c at offset %6d, length %6d\n",
|
||||||
#ifdef WORDS_BIGENDIAN
|
tag[0], tag[1], tag[2], tag[3], (int)chunk_data->offset_,
|
||||||
fourcc = (fourcc >> 24) | ((fourcc >> 8) & 0xff00) |
|
(int)chunk_data->size_);
|
||||||
((fourcc << 8) & 0xff0000) | (fourcc << 24);
|
|
||||||
#endif
|
|
||||||
memcpy(tag, &fourcc, sizeof(tag));
|
|
||||||
printf("Chunk %c%c%c%c at offset %6d, length %6d\n", tag[0], tag[1],
|
|
||||||
tag[2], tag[3], (int)chunk_data->offset, (int)chunk_data->size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (id) {
|
switch (id) {
|
||||||
@@ -964,21 +967,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;
|
||||||
@@ -988,55 +991,55 @@ static WebPInfoStatus ProcessChunk(const ChunkData* const chunk_data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static WebPInfoStatus Validate(WebPInfo* const webp_info) {
|
static WebPInfoStatus Validate(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;
|
||||||
}
|
}
|
||||||
@@ -1047,17 +1050,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(
|
printf("Chunk type : VP8 VP8L VP8X ALPH ANIM ANMF(VP8 /VP8L/ALPH) ICCP "
|
||||||
"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 ", webp_info->anmf_subchunk_counts[0],
|
printf("%4d %4d %4d ",
|
||||||
webp_info->anmf_subchunk_counts[1],
|
webp_info->anmf_subchunk_counts_[0],
|
||||||
webp_info->anmf_subchunk_counts[2]);
|
webp_info->anmf_subchunk_counts_[1],
|
||||||
|
webp_info->anmf_subchunk_counts_[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -1080,28 +1083,27 @@ 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) {
|
if (webp_info->num_warnings_ > 0) {
|
||||||
printf("There were %d warning(s).\n", webp_info->num_warnings);
|
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 Help(void) {
|
||||||
printf(
|
printf("Usage: webpinfo [options] in_files\n"
|
||||||
"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"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
@@ -1112,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;
|
||||||
@@ -1123,7 +1124,7 @@ 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(WEBP_INFO_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse command-line input.
|
// Parse command-line input.
|
||||||
@@ -1131,7 +1132,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
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")) {
|
!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
|
||||||
Help();
|
Help();
|
||||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
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")) {
|
||||||
@@ -1142,9 +1143,9 @@ int main(int argc, const char* argv[]) {
|
|||||||
parse_bitstream = 1;
|
parse_bitstream = 1;
|
||||||
} else if (!strcmp(argv[c], "-version")) {
|
} else if (!strcmp(argv[c], "-version")) {
|
||||||
const int version = WebPGetDecoderVersion();
|
const int version = WebPGetDecoderVersion();
|
||||||
printf("WebP Decoder version: %d.%d.%d\n", (version >> 16) & 0xff,
|
printf("WebP Decoder version: %d.%d.%d\n",
|
||||||
(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;
|
||||||
}
|
}
|
||||||
@@ -1152,7 +1153,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
if (c == argc) {
|
if (c == argc) {
|
||||||
Help();
|
Help();
|
||||||
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.
|
||||||
@@ -1160,10 +1161,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)) {
|
||||||
@@ -1171,10 +1172,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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,14 +59,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 +86,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 {
|
||||||
@@ -106,21 +103,24 @@ typedef enum {
|
|||||||
LAST_FEATURE
|
LAST_FEATURE
|
||||||
} FeatureType;
|
} FeatureType;
|
||||||
|
|
||||||
static const char* const kFourccList[LAST_FEATURE] = {NULL, "EXIF", "XMP ",
|
static const char* const kFourccList[LAST_FEATURE] = {
|
||||||
"ICCP", "ANMF"};
|
NULL, "EXIF", "XMP ", "ICCP", "ANMF"
|
||||||
|
};
|
||||||
|
|
||||||
static const char* const kDescriptions[LAST_FEATURE] = {
|
static const char* const kDescriptions[LAST_FEATURE] = {
|
||||||
NULL, "EXIF metadata", "XMP metadata", "ICC profile", "Animation frame"};
|
NULL, "EXIF metadata", "XMP metadata", "ICC profile",
|
||||||
|
"Animation frame"
|
||||||
|
};
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -131,8 +131,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +141,8 @@ static int CountOccurrences(const CommandLineArguments* const args,
|
|||||||
|
|
||||||
static const char* const kErrorMessages[-WEBP_MUX_NOT_ENOUGH_DATA + 1] = {
|
static const char* const kErrorMessages[-WEBP_MUX_NOT_ENOUGH_DATA + 1] = {
|
||||||
"WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", "WEBP_MUX_BAD_DATA",
|
"WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", "WEBP_MUX_BAD_DATA",
|
||||||
"WEBP_MUX_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA"};
|
"WEBP_MUX_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA"
|
||||||
|
};
|
||||||
|
|
||||||
static const char* ErrorString(WebPMuxError err) {
|
static const char* ErrorString(WebPMuxError err) {
|
||||||
assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA);
|
assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA);
|
||||||
@@ -149,20 +150,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 { \
|
||||||
@@ -218,8 +215,8 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
|
|||||||
WebPMuxAnimParams params;
|
WebPMuxAnimParams params;
|
||||||
err = WebPMuxGetAnimationParams(mux, ¶ms);
|
err = WebPMuxGetAnimationParams(mux, ¶ms);
|
||||||
assert(err == WEBP_MUX_OK);
|
assert(err == WEBP_MUX_OK);
|
||||||
printf("Background color : 0x%.8X Loop Count : %d\n", params.bgcolor,
|
printf("Background color : 0x%.8X Loop Count : %d\n",
|
||||||
params.loop_count);
|
params.bgcolor, params.loop_count);
|
||||||
|
|
||||||
err = WebPMuxNumChunks(mux, id, &nFrames);
|
err = WebPMuxNumChunks(mux, id, &nFrames);
|
||||||
assert(err == WEBP_MUX_OK);
|
assert(err == WEBP_MUX_OK);
|
||||||
@@ -251,9 +248,9 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
|
|||||||
printf("%8d %10s %5s ", frame.duration, dispose, blend);
|
printf("%8d %10s %5s ", frame.duration, dispose, blend);
|
||||||
}
|
}
|
||||||
printf("%10d %11s\n", (int)frame.bitstream.size,
|
printf("%10d %11s\n", (int)frame.bitstream.size,
|
||||||
(features.format == 1) ? "lossy"
|
(features.format == 1) ? "lossy" :
|
||||||
: (features.format == 2) ? "lossless"
|
(features.format == 2) ? "lossless" :
|
||||||
: "undefined");
|
"undefined");
|
||||||
}
|
}
|
||||||
WebPDataClear(&frame.bitstream);
|
WebPDataClear(&frame.bitstream);
|
||||||
RETURN_IF_ERROR3("Failed to retrieve %s#%d\n", type_str, i);
|
RETURN_IF_ERROR3("Failed to retrieve %s#%d\n", type_str, i);
|
||||||
@@ -301,8 +298,7 @@ static void PrintHelp(void) {
|
|||||||
printf(" webpmux -duration DURATION_OPTIONS [-duration ...]\n");
|
printf(" webpmux -duration DURATION_OPTIONS [-duration ...]\n");
|
||||||
printf(" INPUT -o OUTPUT\n");
|
printf(" INPUT -o OUTPUT\n");
|
||||||
printf(" webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT\n");
|
printf(" webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT\n");
|
||||||
printf(
|
printf(" webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]"
|
||||||
" webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]"
|
|
||||||
"\n");
|
"\n");
|
||||||
printf(" [-bgcolor BACKGROUND_COLOR] -o OUTPUT\n");
|
printf(" [-bgcolor BACKGROUND_COLOR] -o OUTPUT\n");
|
||||||
printf(" webpmux -info INPUT\n");
|
printf(" webpmux -info INPUT\n");
|
||||||
@@ -333,7 +329,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");
|
||||||
@@ -352,13 +348,12 @@ 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");
|
||||||
printf(" 'mi' is the dispose method for this frame (0 or 1),\n");
|
printf(" 'mi' is the dispose method for this frame (0 or 1),\n");
|
||||||
printf(
|
printf(" 'bi' is the blending method for this frame (+b or -b)"
|
||||||
" 'bi' is the blending method for this frame (+b or -b)"
|
|
||||||
"\n");
|
"\n");
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -370,11 +365,9 @@ static void PrintHelp(void) {
|
|||||||
printf("BACKGROUND_COLOR:\n");
|
printf("BACKGROUND_COLOR:\n");
|
||||||
printf(" Background color of the canvas.\n");
|
printf(" Background color of the canvas.\n");
|
||||||
printf(" A,R,G,B\n");
|
printf(" A,R,G,B\n");
|
||||||
printf(
|
printf(" where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 "
|
||||||
" where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 "
|
|
||||||
"specifying\n");
|
"specifying\n");
|
||||||
printf(
|
printf(" the Alpha, Red, Green and Blue component values "
|
||||||
" the Alpha, Red, Green and Blue component values "
|
|
||||||
"respectively\n");
|
"respectively\n");
|
||||||
printf(" [Default: 255,255,255,255]\n");
|
printf(" [Default: 255,255,255,255]\n");
|
||||||
|
|
||||||
@@ -382,21 +375,17 @@ static void PrintHelp(void) {
|
|||||||
|
|
||||||
printf("\nNote: The nature of EXIF, XMP and ICC data is not checked");
|
printf("\nNote: The nature of EXIF, XMP and ICC data is not checked");
|
||||||
printf(" and is assumed to be\nvalid.\n");
|
printf(" and is assumed to be\nvalid.\n");
|
||||||
printf(
|
printf("\nNote: if a single file name is passed as the argument, the "
|
||||||
"\nNote: if a single file name is passed as the argument, the "
|
|
||||||
"arguments will be\n");
|
"arguments will be\n");
|
||||||
printf(
|
printf("tokenized from this file. The file name must not start with "
|
||||||
"tokenized from this file. The file name must not start with "
|
|
||||||
"the character '-'.\n");
|
"the character '-'.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WarnAboutOddOffset(const WebPMuxFrameInfo* const info) {
|
static void WarnAboutOddOffset(const WebPMuxFrameInfo* const info) {
|
||||||
if ((info->x_offset | info->y_offset) & 1) {
|
if ((info->x_offset | info->y_offset) & 1) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Warning: odd offsets will be snapped to even values"
|
||||||
"Warning: odd offsets will be snapped to even values"
|
" (%d, %d) -> (%d, %d)\n", info->x_offset, info->y_offset,
|
||||||
" (%d, %d) -> (%d, %d)\n",
|
info->x_offset & ~1, info->y_offset & ~1);
|
||||||
info->x_offset, info->y_offset, info->x_offset & ~1,
|
|
||||||
info->y_offset & ~1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,8 +413,8 @@ static int WriteData(const char* filename, const WebPData* const webpdata) {
|
|||||||
if (fwrite(webpdata->bytes, webpdata->size, 1, fout) != 1) {
|
if (fwrite(webpdata->bytes, webpdata->size, 1, fout) != 1) {
|
||||||
WFPRINTF(stderr, "Error writing file %s!\n", (const W_CHAR*)filename);
|
WFPRINTF(stderr, "Error writing file %s!\n", (const W_CHAR*)filename);
|
||||||
} else {
|
} else {
|
||||||
WFPRINTF(stderr, "Saved file %s (%d bytes)\n", (const W_CHAR*)filename,
|
WFPRINTF(stderr, "Saved file %s (%d bytes)\n",
|
||||||
(int)webpdata->size);
|
(const W_CHAR*)filename, (int)webpdata->size);
|
||||||
ok = 1;
|
ok = 1;
|
||||||
}
|
}
|
||||||
if (fout != stdout) fclose(fout);
|
if (fout != stdout) fclose(fout);
|
||||||
@@ -458,8 +447,8 @@ static WebPMux* DuplicateMuxHeader(const WebPMux* const mux) {
|
|||||||
if (err == WEBP_MUX_OK) {
|
if (err == WEBP_MUX_OK) {
|
||||||
err = WebPMuxSetAnimationParams(new_mux, &p);
|
err = WebPMuxSetAnimationParams(new_mux, &p);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO2("Error (%s) handling animation params.\n", ErrorString(err),
|
ERROR_GOTO2("Error (%s) handling animation params.\n",
|
||||||
End);
|
ErrorString(err), End);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* it might not be an animation. Just keep moving. */
|
/* it might not be an animation. Just keep moving. */
|
||||||
@@ -471,8 +460,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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -515,7 +503,8 @@ static int ParseFrameArgs(const char* args, WebPMuxFrameInfo* const info) {
|
|||||||
|
|
||||||
if (blend_method != 'b') return 0;
|
if (blend_method != 'b') return 0;
|
||||||
if (plus_minus != '-' && plus_minus != '+') return 0;
|
if (plus_minus != '-' && plus_minus != '+') return 0;
|
||||||
info->blend_method = (plus_minus == '+') ? WEBP_MUX_BLEND : WEBP_MUX_NO_BLEND;
|
info->blend_method =
|
||||||
|
(plus_minus == '+') ? WEBP_MUX_BLEND : WEBP_MUX_NO_BLEND;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,8 +521,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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -587,10 +576,8 @@ static int ValidateCommandLine(const CommandLineArguments* const cmd_args,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((num_frame_args == 0) && (num_loop_args + num_bgcolor_args > 0)) {
|
if ((num_frame_args == 0) && (num_loop_args + num_bgcolor_args > 0)) {
|
||||||
ERROR_GOTO1(
|
ERROR_GOTO1("ERROR: Loop count and background color are relevant only in "
|
||||||
"ERROR: Loop count and background color are relevant only in "
|
"case of animation.\n", ErrValidate);
|
||||||
"case of animation.\n",
|
|
||||||
ErrValidate);
|
|
||||||
}
|
}
|
||||||
if (num_durations_args > 0 && num_frame_args != 0) {
|
if (num_durations_args > 0 && num_frame_args != 0) {
|
||||||
ERROR_GOTO1("ERROR: Can not combine -duration and -frame commands.\n",
|
ERROR_GOTO1("ERROR: Can not combine -duration and -frame commands.\n",
|
||||||
@@ -612,31 +599,25 @@ ErrValidate:
|
|||||||
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.
|
||||||
@@ -644,116 +625,117 @@ 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")) {
|
||||||
PrintHelp();
|
PrintHelp();
|
||||||
DeleteConfig(config);
|
DeleteConfig(config);
|
||||||
LOCAL_FREE((W_CHAR**)unicode_argv);
|
LOCAL_FREE((W_CHAR** const)unicode_argv);
|
||||||
exit(0);
|
exit(0);
|
||||||
} else if (!strcmp(argv[i], "-version")) {
|
} else if (!strcmp(argv[i], "-version")) {
|
||||||
const int version = WebPGetMuxVersion();
|
const int version = WebPGetMuxVersion();
|
||||||
printf("%d.%d.%d\n", (version >> 16) & 0xff, (version >> 8) & 0xff,
|
printf("%d.%d.%d\n",
|
||||||
version & 0xff);
|
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
||||||
DeleteConfig(config);
|
DeleteConfig(config);
|
||||||
LOCAL_FREE((W_CHAR**)unicode_argv);
|
LOCAL_FREE((W_CHAR** const)unicode_argv);
|
||||||
exit(0);
|
exit(0);
|
||||||
} 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);
|
||||||
@@ -764,66 +746,50 @@ 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
|
(!strcmp(argv[i], "exif")) ? FEATURE_EXIF : FEATURE_XMP;
|
||||||
: 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);
|
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
|
||||||
arg->filename = wargv[i + 1];
|
arg->filename_ = wargv[i + 1];
|
||||||
++feature_arg_index;
|
++feature_arg_index;
|
||||||
i += 2;
|
i += 2;
|
||||||
} else {
|
} 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;
|
++i;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(argv[i], "frame") &&
|
} else if (!strcmp(argv[i], "frame") &&
|
||||||
(config->action_type == ACTION_GET)) {
|
(config->action_type_ == ACTION_GET)) {
|
||||||
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
|
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
|
||||||
config->type = FEATURE_ANMF;
|
config->type_ = FEATURE_ANMF;
|
||||||
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], "loop") &&
|
} else if (!strcmp(argv[i], "loop") &&
|
||||||
(config->action_type == ACTION_SET)) {
|
(config->action_type_ == ACTION_SET)) {
|
||||||
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
|
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
|
||||||
config->type = FEATURE_LOOP;
|
config->type_ = FEATURE_LOOP;
|
||||||
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], "bgcolor") &&
|
} else if (!strcmp(argv[i], "bgcolor") &&
|
||||||
(config->action_type == ACTION_SET)) {
|
(config->action_type_ == ACTION_SET)) {
|
||||||
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
|
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
|
||||||
config->type = FEATURE_BGCOLOR;
|
config->type_ = FEATURE_BGCOLOR;
|
||||||
arg->params = argv[i + 1];
|
arg->params_ = argv[i + 1];
|
||||||
++feature_arg_index;
|
++feature_arg_index;
|
||||||
i += 2;
|
i += 2;
|
||||||
} else {
|
} else { // Assume input file.
|
||||||
is_input = 1;
|
if (config->input_ == NULL) {
|
||||||
}
|
config->input_ = wargv[i];
|
||||||
}
|
|
||||||
|
|
||||||
if (is_input) {
|
|
||||||
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);
|
||||||
@@ -846,21 +812,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -876,17 +842,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -918,7 +884,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);
|
||||||
}
|
}
|
||||||
@@ -927,8 +893,8 @@ static int GetFrame(const WebPMux* mux, const Config* config) {
|
|||||||
err = WebPMuxGetFrame(mux, num, &info);
|
err = WebPMuxGetFrame(mux, num, &info);
|
||||||
if (err == WEBP_MUX_OK && info.id != id) err = WEBP_MUX_NOT_FOUND;
|
if (err == WEBP_MUX_OK && info.id != id) err = WEBP_MUX_NOT_FOUND;
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO3("ERROR (%s): Could not get frame %d.\n", ErrorString(err), num,
|
ERROR_GOTO3("ERROR (%s): Could not get frame %d.\n",
|
||||||
ErrGet);
|
ErrorString(err), num, ErrGet);
|
||||||
}
|
}
|
||||||
|
|
||||||
mux_single = WebPMuxNew();
|
mux_single = WebPMuxNew();
|
||||||
@@ -943,7 +909,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);
|
||||||
@@ -958,11 +924,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;
|
||||||
@@ -970,12 +936,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", ErrorString(err),
|
ERROR_GOTO3("ERROR (%s): Could not get the %s.\n",
|
||||||
kDescriptions[config->type], Err2);
|
ErrorString(err), kDescriptions[config->type_], Err2);
|
||||||
}
|
}
|
||||||
ok = WriteData(config->output, &chunk);
|
ok = WriteData(config->output_, &chunk);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -985,7 +951,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 };
|
||||||
@@ -994,11 +960,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);
|
||||||
@@ -1009,15 +975,13 @@ 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
|
||||||
// WebPMuxSetAnimationParams() method called later.
|
// WebPMuxSetAnimationParams() method called later.
|
||||||
ERROR_GOTO1(
|
ERROR_GOTO1("ERROR: Loop count must be in the range 0 to "
|
||||||
"ERROR: Loop count must be in the range 0 to "
|
"65535.\n", Err2);
|
||||||
"65535.\n",
|
|
||||||
Err2);
|
|
||||||
}
|
}
|
||||||
ok = !parse_error;
|
ok = !parse_error;
|
||||||
if (!ok) goto Err2;
|
if (!ok) goto Err2;
|
||||||
@@ -1027,10 +991,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",
|
||||||
@@ -1039,10 +1003,8 @@ static int Process(const Config* config) {
|
|||||||
err = WebPMuxPushFrame(mux, &frame, 1);
|
err = WebPMuxPushFrame(mux, &frame, 1);
|
||||||
WebPDataClear(&frame.bitstream);
|
WebPDataClear(&frame.bitstream);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO3(
|
ERROR_GOTO3("ERROR (%s): Could not add a frame at index %d."
|
||||||
"ERROR (%s): Could not add a frame at index %d."
|
"\n", ErrorString(err), i, Err2);
|
||||||
"\n",
|
|
||||||
ErrorString(err), i, Err2);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1063,15 +1025,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);
|
WebPDataClear(&chunk);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO3("ERROR (%s): Could not set the %s.\n", ErrorString(err),
|
ERROR_GOTO3("ERROR (%s): Could not set the %s.\n",
|
||||||
kDescriptions[config->type], Err2);
|
ErrorString(err), kDescriptions[config->type_], Err2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1079,12 +1041,12 @@ static int Process(const Config* config) {
|
|||||||
WebPMuxAnimParams params = { 0xFFFFFFFF, 0 };
|
WebPMuxAnimParams params = { 0xFFFFFFFF, 0 };
|
||||||
int parse_error = 0;
|
int parse_error = 0;
|
||||||
const int loop_count =
|
const int loop_count =
|
||||||
ExUtilGetInt(config->args[0].params, 10, &parse_error);
|
ExUtilGetInt(config->args_[0].params_, 10, &parse_error);
|
||||||
if (loop_count < 0 || loop_count > 65535 || 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",
|
ERROR_GOTO1("ERROR: Loop count must be in the range 0 to 65535.\n",
|
||||||
Err2);
|
Err2);
|
||||||
}
|
}
|
||||||
ok = CreateMux(config->input, &mux);
|
ok = CreateMux(config->input_, &mux);
|
||||||
if (!ok) goto Err2;
|
if (!ok) goto Err2;
|
||||||
ok = (WebPMuxGetAnimationParams(mux, ¶ms) == WEBP_MUX_OK);
|
ok = (WebPMuxGetAnimationParams(mux, ¶ms) == WEBP_MUX_OK);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@@ -1103,11 +1065,12 @@ static int Process(const Config* config) {
|
|||||||
case FEATURE_BGCOLOR: {
|
case FEATURE_BGCOLOR: {
|
||||||
WebPMuxAnimParams params = { 0xFFFFFFFF, 0 };
|
WebPMuxAnimParams params = { 0xFFFFFFFF, 0 };
|
||||||
uint32_t bgcolor;
|
uint32_t bgcolor;
|
||||||
ok = ParseBgcolorArgs(config->args[0].params, &bgcolor);
|
ok = ParseBgcolorArgs(config->args_[0].params_, &bgcolor);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
ERROR_GOTO1("ERROR: Could not parse the background color.\n", Err2);
|
ERROR_GOTO1("ERROR: Could not parse the background color.\n",
|
||||||
|
Err2);
|
||||||
}
|
}
|
||||||
ok = CreateMux(config->input, &mux);
|
ok = CreateMux(config->input_, &mux);
|
||||||
if (!ok) goto Err2;
|
if (!ok) goto Err2;
|
||||||
ok = (WebPMuxGetAnimationParams(mux, ¶ms) == WEBP_MUX_OK);
|
ok = (WebPMuxGetAnimationParams(mux, ¶ms) == WEBP_MUX_OK);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@@ -1128,12 +1091,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);
|
||||||
@@ -1141,10 +1104,9 @@ static int Process(const Config* config) {
|
|||||||
ERROR_GOTO1("ERROR: can not parse the number of frames.\n", Err2);
|
ERROR_GOTO1("ERROR: can not parse the number of frames.\n", Err2);
|
||||||
}
|
}
|
||||||
if (num_frames == 0) {
|
if (num_frames == 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Doesn't look like the source is animated. "
|
||||||
"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;
|
||||||
@@ -1156,12 +1118,12 @@ 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 =
|
const int nb_args = ExUtilGetInts(config->args_[i].params_,
|
||||||
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;
|
||||||
duration = args[0];
|
duration = args[0];
|
||||||
@@ -1204,7 +1166,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;
|
||||||
|
|
||||||
@@ -1216,24 +1178,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", ErrorString(err),
|
ERROR_GOTO3("ERROR (%s): Could not strip the %s.\n",
|
||||||
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;
|
||||||
@@ -1252,7 +1214,6 @@ Err2:
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// 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;
|
||||||
@@ -1266,7 +1227,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
171
extras/extras.c
171
extras/extras.c
@@ -11,22 +11,15 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#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 2
|
||||||
#define XTRA_REV_VERSION 0
|
#define XTRA_REV_VERSION 1
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -49,10 +46,10 @@ WEBP_EXTERN int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic);
|
|||||||
// MAX_PALETTE_SIZE. 'pic' must have been initialized. Its content, if any,
|
// MAX_PALETTE_SIZE. 'pic' must have been initialized. Its content, if any,
|
||||||
// will be discarded. Returns 'false' in case of error, or if indexed[] contains
|
// will be discarded. Returns 'false' in case of error, or if indexed[] contains
|
||||||
// invalid indices.
|
// invalid indices.
|
||||||
WEBP_EXTERN int WebPImportColorMappedARGB(const uint8_t* indexed,
|
WEBP_EXTERN int
|
||||||
int indexed_stride,
|
WebPImportColorMappedARGB(const uint8_t* indexed, int indexed_stride,
|
||||||
const uint32_t palette[],
|
const uint32_t palette[], int palette_size,
|
||||||
int palette_size, WebPPicture* pic);
|
WebPPicture* pic);
|
||||||
|
|
||||||
// Convert the ARGB content of 'pic' from associated to unassociated.
|
// Convert the ARGB content of 'pic' from associated to unassociated.
|
||||||
// 'pic' can be for instance the result of calling of some WebPPictureImportXXX
|
// 'pic' can be for instance the result of calling of some WebPPictureImportXXX
|
||||||
@@ -73,40 +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
|
||||||
|
|||||||
@@ -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) {
|
||||||
@@ -57,8 +56,8 @@ End:
|
|||||||
return ok ? data_size : 0;
|
return ok ? data_size : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RescalePlane(uint8_t* plane, int width, int height, int x_stride,
|
static void RescalePlane(uint8_t* plane, int width, int height,
|
||||||
int y_stride, int max) {
|
int x_stride, int y_stride, int max) {
|
||||||
const uint32_t factor = (max > 0) ? (255u << 16) / max : 0;
|
const uint32_t factor = (max > 0) ? (255u << 16) / max : 0;
|
||||||
int x, y;
|
int x, y;
|
||||||
for (y = 0; y < height; ++y) {
|
for (y = 0; y < height; ++y) {
|
||||||
@@ -71,9 +70,9 @@ static void RescalePlane(uint8_t* plane, int width, int height, int x_stride,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return the max absolute difference.
|
// Return the max absolute difference.
|
||||||
static int DiffScaleChannel(uint8_t* src1, int stride1, const uint8_t* src2,
|
static int DiffScaleChannel(uint8_t* src1, int stride1,
|
||||||
int stride2, int x_stride, int w, int h,
|
const uint8_t* src2, int stride2,
|
||||||
int do_scaling) {
|
int x_stride, int w, int h, int do_scaling) {
|
||||||
int x, y;
|
int x, y;
|
||||||
int max = 0;
|
int max = 0;
|
||||||
for (y = 0; y < h; ++y) {
|
for (y = 0; y < h; ++y) {
|
||||||
@@ -133,8 +132,8 @@ static WEBP_INLINE double SSIMCalculation(const DistoStats* const stats) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static double SSIMGetClipped(const uint8_t* src1, int stride1,
|
static double SSIMGetClipped(const uint8_t* src1, int stride1,
|
||||||
const uint8_t* src2, int stride2, int xo, int yo,
|
const uint8_t* src2, int stride2,
|
||||||
int W, int H) {
|
int xo, int yo, int W, int H) {
|
||||||
DistoStats stats = { 0, 0, 0, 0, 0, 0 };
|
DistoStats stats = { 0, 0, 0, 0, 0, 0 };
|
||||||
const int ymin = (yo - SSIM_KERNEL < 0) ? 0 : yo - SSIM_KERNEL;
|
const int ymin = (yo - SSIM_KERNEL < 0) ? 0 : yo - SSIM_KERNEL;
|
||||||
const int ymax = (yo + SSIM_KERNEL > H - 1) ? H - 1 : yo + SSIM_KERNEL;
|
const int ymax = (yo + SSIM_KERNEL > H - 1) ? H - 1 : yo + SSIM_KERNEL;
|
||||||
@@ -145,8 +144,8 @@ static double SSIMGetClipped(const uint8_t* src1, int stride1,
|
|||||||
src2 += ymin * stride2;
|
src2 += ymin * stride2;
|
||||||
for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) {
|
for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) {
|
||||||
for (x = xmin; x <= xmax; ++x) {
|
for (x = xmin; x <= xmax; ++x) {
|
||||||
const uint32_t w =
|
const uint32_t w = kWeight[SSIM_KERNEL + x - xo]
|
||||||
kWeight[SSIM_KERNEL + x - xo] * kWeight[SSIM_KERNEL + y - yo];
|
* kWeight[SSIM_KERNEL + y - yo];
|
||||||
const uint32_t s1 = src1[x];
|
const uint32_t s1 = src1[x];
|
||||||
const uint32_t s2 = src2[x];
|
const uint32_t s2 = src2[x];
|
||||||
stats.w += w;
|
stats.w += w;
|
||||||
@@ -161,9 +160,9 @@ static double SSIMGetClipped(const uint8_t* src1, int stride1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute SSIM-score map. Return -1 in case of error, max diff otherwise.
|
// Compute SSIM-score map. Return -1 in case of error, max diff otherwise.
|
||||||
static int SSIMScaleChannel(uint8_t* src1, int stride1, const uint8_t* src2,
|
static int SSIMScaleChannel(uint8_t* src1, int stride1,
|
||||||
int stride2, int x_stride, int w, int h,
|
const uint8_t* src2, int stride2,
|
||||||
int do_scaling) {
|
int x_stride, int w, int h, int do_scaling) {
|
||||||
int x, y;
|
int x, y;
|
||||||
int max = 0;
|
int max = 0;
|
||||||
uint8_t* const plane1 = (uint8_t*)malloc(2 * w * h * sizeof(*plane1));
|
uint8_t* const plane1 = (uint8_t*)malloc(2 * w * h * sizeof(*plane1));
|
||||||
@@ -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]);
|
||||||
@@ -297,7 +294,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
fprintf(stderr, "Error while computing the distortion.\n");
|
fprintf(stderr, "Error while computing the distortion.\n");
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
printf("%u %.2f %.2f %.2f %.2f %.2f [ %.2f bpp ]\n", (unsigned int)size1,
|
printf("%u %.2f %.2f %.2f %.2f %.2f [ %.2f bpp ]\n",
|
||||||
|
(unsigned int)size1,
|
||||||
disto[4], disto[0], disto[1], disto[2], disto[3],
|
disto[4], disto[0], disto[1], disto[2], disto[3],
|
||||||
8.f * size1 / pic1.width / pic1.height);
|
8.f * size1 / pic1.width / pic1.height);
|
||||||
|
|
||||||
@@ -305,8 +303,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
uint8_t* data = NULL;
|
uint8_t* data = NULL;
|
||||||
size_t data_size = 0;
|
size_t data_size = 0;
|
||||||
if (pic1.use_argb != pic2.use_argb) {
|
if (pic1.use_argb != pic2.use_argb) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Pictures are not in the same argb format. "
|
||||||
"Pictures are not in the same argb format. "
|
|
||||||
"Can't save the difference map.\n");
|
"Can't save the difference map.\n");
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
@@ -314,16 +311,13 @@ int main(int argc, const char* argv[]) {
|
|||||||
int n;
|
int n;
|
||||||
fprintf(stderr, "max differences per channel: ");
|
fprintf(stderr, "max differences per channel: ");
|
||||||
for (n = 0; n < 3; ++n) { // skip the alpha channel
|
for (n = 0; n < 3; ++n) { // skip the alpha channel
|
||||||
const int range =
|
const int range = (type == 1) ?
|
||||||
(type == 1)
|
SSIMScaleChannel((uint8_t*)pic1.argb + n, pic1.argb_stride * 4,
|
||||||
? SSIMScaleChannel(
|
(const uint8_t*)pic2.argb + n, pic2.argb_stride * 4,
|
||||||
(uint8_t*)pic1.argb + n, pic1.argb_stride * 4,
|
4, pic1.width, pic1.height, scale) :
|
||||||
(const uint8_t*)pic2.argb + n, pic2.argb_stride * 4, 4,
|
DiffScaleChannel((uint8_t*)pic1.argb + n, pic1.argb_stride * 4,
|
||||||
pic1.width, pic1.height, scale)
|
(const uint8_t*)pic2.argb + n, pic2.argb_stride * 4,
|
||||||
: DiffScaleChannel(
|
4, pic1.width, pic1.height, scale);
|
||||||
(uint8_t*)pic1.argb + n, pic1.argb_stride * 4,
|
|
||||||
(const uint8_t*)pic2.argb + n, pic2.argb_stride * 4, 4,
|
|
||||||
pic1.width, pic1.height, scale);
|
|
||||||
if (range < 0) fprintf(stderr, "\nError computing diff map\n");
|
if (range < 0) fprintf(stderr, "\nError computing diff map\n");
|
||||||
fprintf(stderr, "[%d]", range);
|
fprintf(stderr, "[%d]", range);
|
||||||
}
|
}
|
||||||
@@ -334,27 +328,25 @@ int main(int argc, const char* argv[]) {
|
|||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
#if !defined(WEBP_REDUCE_CSP)
|
#if !defined(WEBP_REDUCE_CSP)
|
||||||
data_size =
|
data_size = WebPEncodeLosslessBGRA((const uint8_t*)pic1.argb,
|
||||||
WebPEncodeLosslessBGRA((const uint8_t*)pic1.argb, pic1.width,
|
pic1.width, pic1.height,
|
||||||
pic1.height, pic1.argb_stride * 4, &data);
|
pic1.argb_stride * 4,
|
||||||
|
&data);
|
||||||
if (data_size == 0) {
|
if (data_size == 0) {
|
||||||
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
|
||||||
(void)data;
|
(void)data;
|
||||||
(void)data_size;
|
(void)data_size;
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Cannot save the difference map. Please recompile "
|
||||||
"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);
|
||||||
|
|||||||
@@ -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
@@ -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_
|
|
||||||
@@ -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"
|
||||||
@@ -23,15 +22,15 @@
|
|||||||
|
|
||||||
#if defined(WEBP_HAVE_SDL)
|
#if defined(WEBP_HAVE_SDL)
|
||||||
|
|
||||||
#include "../examples/unicode.h"
|
|
||||||
#include "imageio/imageio_util.h"
|
|
||||||
#include "webp/decode.h"
|
|
||||||
#include "webp_to_sdl.h"
|
#include "webp_to_sdl.h"
|
||||||
|
#include "webp/decode.h"
|
||||||
|
#include "imageio/imageio_util.h"
|
||||||
|
#include "../examples/unicode.h"
|
||||||
|
|
||||||
#if defined(WEBP_HAVE_JUST_SDL_H)
|
#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) {
|
||||||
@@ -41,39 +40,28 @@ static void ProcessEvents(void) {
|
|||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case SDL_KEYUP:
|
case SDL_KEYUP:
|
||||||
switch (event.key.keysym.sym) {
|
switch (event.key.keysym.sym) {
|
||||||
case SDLK_q:
|
case SDLK_q: done = 1; break;
|
||||||
done = 1;
|
default: break;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default: break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
@@ -87,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);
|
||||||
@@ -99,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
|
||||||
|
|||||||
@@ -11,12 +11,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "../examples/unicode.h"
|
|
||||||
#include "extras/extras.h"
|
#include "extras/extras.h"
|
||||||
#include "imageio/imageio_util.h"
|
#include "imageio/imageio_util.h"
|
||||||
#include "src/webp/types.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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,77 +17,91 @@
|
|||||||
|
|
||||||
#if defined(WEBP_HAVE_SDL)
|
#if defined(WEBP_HAVE_SDL)
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "src/webp/decode.h"
|
|
||||||
#include "webp_to_sdl.h"
|
#include "webp_to_sdl.h"
|
||||||
|
|
||||||
|
#include <stdio.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 =
|
output->colorspace = MODE_BGRA;
|
||||||
WebPDecodeBGRA((const uint8_t*)data, (size_t)data_size, &width, &height);
|
|
||||||
#else
|
#else
|
||||||
output =
|
output->colorspace = MODE_RGBA;
|
||||||
WebPDecodeRGBA((const uint8_t*)data, (size_t)data_size, &width, &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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -11,30 +11,6 @@
|
|||||||
|
|
||||||
#include "./image_dec.h"
|
#include "./image_dec.h"
|
||||||
|
|
||||||
#include <stddef.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];
|
||||||
}
|
}
|
||||||
@@ -63,8 +39,8 @@ WebPInputFileFormat WebPGuessImageType(const uint8_t* const data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int FailReader(const uint8_t* const data, size_t data_size,
|
static int FailReader(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic, int keep_alpha,
|
struct WebPPicture* const pic,
|
||||||
struct Metadata* const metadata) {
|
int keep_alpha, struct Metadata* const metadata) {
|
||||||
(void)data;
|
(void)data;
|
||||||
(void)data_size;
|
(void)data_size;
|
||||||
(void)pic;
|
(void)pic;
|
||||||
@@ -75,18 +51,12 @@ static int FailReader(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
WebPImageReader WebPGetImageReader(WebPInputFileFormat format) {
|
WebPImageReader WebPGetImageReader(WebPInputFileFormat format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case WEBP_PNG_FORMAT:
|
case WEBP_PNG_FORMAT: return ReadPNG;
|
||||||
return ReadPNG;
|
case WEBP_JPEG_FORMAT: return ReadJPEG;
|
||||||
case WEBP_JPEG_FORMAT:
|
case WEBP_TIFF_FORMAT: return ReadTIFF;
|
||||||
return ReadJPEG;
|
case WEBP_WEBP_FORMAT: return ReadWebP;
|
||||||
case WEBP_TIFF_FORMAT:
|
case WEBP_PNM_FORMAT: return ReadPNM;
|
||||||
return ReadTIFF;
|
default: return FailReader;
|
||||||
case WEBP_WEBP_FORMAT:
|
|
||||||
return ReadWebP;
|
|
||||||
case WEBP_PNM_FORMAT:
|
|
||||||
return ReadPNM;
|
|
||||||
default:
|
|
||||||
return FailReader;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,16 +14,14 @@
|
|||||||
#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
|
||||||
#include "webp/config.h"
|
#include "webp/config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "./jpegdec.h"
|
|
||||||
#include "./metadata.h"
|
#include "./metadata.h"
|
||||||
|
#include "./jpegdec.h"
|
||||||
#include "./pngdec.h"
|
#include "./pngdec.h"
|
||||||
#include "./pnmdec.h"
|
#include "./pnmdec.h"
|
||||||
#include "./tiffdec.h"
|
#include "./tiffdec.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,
|
||||||
@@ -53,8 +48,8 @@ WebPInputFileFormat WebPGuessImageType(const uint8_t* const data,
|
|||||||
|
|
||||||
// Signature for common image-reading functions (ReadPNG, ReadJPEG, ...)
|
// Signature for common image-reading functions (ReadPNG, ReadJPEG, ...)
|
||||||
typedef int (*WebPImageReader)(const uint8_t* const data, size_t data_size,
|
typedef int (*WebPImageReader)(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic, int keep_alpha,
|
struct WebPPicture* const pic,
|
||||||
struct Metadata* const metadata);
|
int keep_alpha, struct Metadata* const metadata);
|
||||||
|
|
||||||
// Return the reader associated to a given file format.
|
// Return the reader associated to a given file format.
|
||||||
WebPImageReader WebPGetImageReader(WebPInputFileFormat format);
|
WebPImageReader WebPGetImageReader(WebPInputFileFormat format);
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -26,20 +25,17 @@
|
|||||||
#endif
|
#endif
|
||||||
#define CINTERFACE
|
#define CINTERFACE
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
#define _WIN32_IE \
|
#define _WIN32_IE 0x500 // Workaround bug in shlwapi.h when compiling C++
|
||||||
0x500 // Workaround bug in shlwapi.h when compiling C++
|
|
||||||
// code with COBJMACROS.
|
// code with COBJMACROS.
|
||||||
#include <ole2.h> // CreateStreamOnHGlobal()
|
#include <ole2.h> // CreateStreamOnHGlobal()
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <wincodec.h>
|
|
||||||
#include <windows.h>
|
#include <windows.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
|
||||||
@@ -60,8 +56,8 @@
|
|||||||
#define MAKE_REFGUID(x) &(x)
|
#define MAKE_REFGUID(x) &(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static HRESULT CreateOutputStream(const char* out_file_name, int write_to_mem,
|
static HRESULT CreateOutputStream(const char* out_file_name,
|
||||||
IStream** stream) {
|
int write_to_mem, IStream** stream) {
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
if (write_to_mem) {
|
if (write_to_mem) {
|
||||||
// Output to a memory buffer. This is freed when 'stream' is released.
|
// Output to a memory buffer. This is freed when 'stream' is released.
|
||||||
@@ -78,22 +74,24 @@ static HRESULT CreateOutputStream(const char* out_file_name, int write_to_mem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WriteUsingWIC(const char* out_file_name, int use_stdout,
|
static HRESULT WriteUsingWIC(const char* out_file_name, int use_stdout,
|
||||||
REFGUID container_guid, uint8_t* rgb, int stride,
|
REFGUID container_guid,
|
||||||
|
uint8_t* rgb, int stride,
|
||||||
uint32_t width, uint32_t height, int has_alpha) {
|
uint32_t width, uint32_t height, int has_alpha) {
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
IWICImagingFactory* factory = NULL;
|
IWICImagingFactory* factory = NULL;
|
||||||
IWICBitmapFrameEncode* frame = NULL;
|
IWICBitmapFrameEncode* frame = NULL;
|
||||||
IWICBitmapEncoder* encoder = NULL;
|
IWICBitmapEncoder* encoder = NULL;
|
||||||
IStream* stream = NULL;
|
IStream* stream = NULL;
|
||||||
WICPixelFormatGUID pixel_format =
|
WICPixelFormatGUID pixel_format = has_alpha ? GUID_WICPixelFormat32bppBGRA
|
||||||
has_alpha ? GUID_WICPixelFormat32bppBGRA : GUID_WICPixelFormat24bppBGR;
|
: GUID_WICPixelFormat24bppBGR;
|
||||||
|
|
||||||
if (out_file_name == NULL || rgb == NULL) return E_INVALIDARG;
|
if (out_file_name == NULL || rgb == NULL) return E_INVALIDARG;
|
||||||
|
|
||||||
IFS(CoInitialize(NULL));
|
IFS(CoInitialize(NULL));
|
||||||
IFS(CoCreateInstance(
|
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
|
||||||
MAKE_REFGUID(CLSID_WICImagingFactory), NULL, CLSCTX_INPROC_SERVER,
|
CLSCTX_INPROC_SERVER,
|
||||||
MAKE_REFGUID(IID_IWICImagingFactory), (LPVOID*)&factory));
|
MAKE_REFGUID(IID_IWICImagingFactory),
|
||||||
|
(LPVOID*)&factory));
|
||||||
if (hr == REGDB_E_CLASSNOTREG) {
|
if (hr == REGDB_E_CLASSNOTREG) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Couldn't access Windows Imaging Component (are you running "
|
"Couldn't access Windows Imaging Component (are you running "
|
||||||
@@ -103,13 +101,14 @@ static HRESULT WriteUsingWIC(const char* out_file_name, int use_stdout,
|
|||||||
IFS(CreateOutputStream(out_file_name, use_stdout, &stream));
|
IFS(CreateOutputStream(out_file_name, use_stdout, &stream));
|
||||||
IFS(IWICImagingFactory_CreateEncoder(factory, container_guid, NULL,
|
IFS(IWICImagingFactory_CreateEncoder(factory, container_guid, NULL,
|
||||||
&encoder));
|
&encoder));
|
||||||
IFS(IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache));
|
IFS(IWICBitmapEncoder_Initialize(encoder, stream,
|
||||||
|
WICBitmapEncoderNoCache));
|
||||||
IFS(IWICBitmapEncoder_CreateNewFrame(encoder, &frame, NULL));
|
IFS(IWICBitmapEncoder_CreateNewFrame(encoder, &frame, NULL));
|
||||||
IFS(IWICBitmapFrameEncode_Initialize(frame, NULL));
|
IFS(IWICBitmapFrameEncode_Initialize(frame, NULL));
|
||||||
IFS(IWICBitmapFrameEncode_SetSize(frame, width, height));
|
IFS(IWICBitmapFrameEncode_SetSize(frame, width, height));
|
||||||
IFS(IWICBitmapFrameEncode_SetPixelFormat(frame, &pixel_format));
|
IFS(IWICBitmapFrameEncode_SetPixelFormat(frame, &pixel_format));
|
||||||
IFS(IWICBitmapFrameEncode_WritePixels(frame, height, stride, height * stride,
|
IFS(IWICBitmapFrameEncode_WritePixels(frame, height, stride,
|
||||||
rgb));
|
height * stride, rgb));
|
||||||
IFS(IWICBitmapFrameEncode_Commit(frame));
|
IFS(IWICBitmapFrameEncode_Commit(frame));
|
||||||
IFS(IWICBitmapEncoder_Commit(encoder));
|
IFS(IWICBitmapEncoder_Commit(encoder));
|
||||||
|
|
||||||
@@ -151,8 +150,8 @@ int WebPWritePNG(const char* out_file_name, int use_stdout,
|
|||||||
const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
|
const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
|
||||||
|
|
||||||
return SUCCEEDED(WriteUsingWIC(out_file_name, use_stdout,
|
return SUCCEEDED(WriteUsingWIC(out_file_name, use_stdout,
|
||||||
MAKE_REFGUID(GUID_ContainerFormatPng), rgb,
|
MAKE_REFGUID(GUID_ContainerFormatPng),
|
||||||
stride, width, height, has_alpha));
|
rgb, stride, width, height, has_alpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H
|
#elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H
|
||||||
@@ -167,8 +166,8 @@ int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
|
|||||||
|
|
||||||
if (out_file == NULL || buffer == NULL) return 0;
|
if (out_file == NULL || buffer == NULL) return 0;
|
||||||
|
|
||||||
png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, PNGErrorFunction,
|
png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
||||||
NULL);
|
NULL, PNGErrorFunction, NULL);
|
||||||
if (png == NULL) {
|
if (png == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -208,8 +207,7 @@ int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
|
|||||||
int WebPWritePNG(FILE* fout, const WebPDecBuffer* const buffer) {
|
int WebPWritePNG(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||||
if (fout == NULL || buffer == NULL) return 0;
|
if (fout == NULL || buffer == NULL) return 0;
|
||||||
|
|
||||||
fprintf(stderr,
|
fprintf(stderr, "PNG support not compiled. Please install the libpng "
|
||||||
"PNG support not compiled. Please install the libpng "
|
|
||||||
"development package before building.\n");
|
"development package before building.\n");
|
||||||
fprintf(stderr, "You can run with -ppm flag to decode in PPM format.\n");
|
fprintf(stderr, "You can run with -ppm flag to decode in PPM format.\n");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -234,10 +232,8 @@ static int WritePPMPAM(FILE* fout, const WebPDecBuffer* const buffer,
|
|||||||
if (row == NULL) return 0;
|
if (row == NULL) return 0;
|
||||||
|
|
||||||
if (alpha) {
|
if (alpha) {
|
||||||
fprintf(fout,
|
fprintf(fout, "P7\nWIDTH %u\nHEIGHT %u\nDEPTH 4\nMAXVAL 255\n"
|
||||||
"P7\nWIDTH %u\nHEIGHT %u\nDEPTH 4\nMAXVAL 255\n"
|
"TUPLTYPE RGB_ALPHA\nENDHDR\n", width, height);
|
||||||
"TUPLTYPE RGB_ALPHA\nENDHDR\n",
|
|
||||||
width, height);
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(fout, "P6\n%u %u\n255\n", width, height);
|
fprintf(fout, "P6\n%u %u\n255\n", width, height);
|
||||||
}
|
}
|
||||||
@@ -264,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) {
|
||||||
@@ -290,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;
|
||||||
@@ -303,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 (placeholder)
|
||||||
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
|
||||||
@@ -373,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
|
||||||
@@ -389,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
|
||||||
@@ -405,24 +380,24 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
|
|||||||
0x00, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 10: Width (TBD)
|
0x00, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 10: Width (TBD)
|
||||||
0x01, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 22: Height (TBD)
|
0x01, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 22: Height (TBD)
|
||||||
0x02, 0x01, 3, 0, bytes_per_px, 0, 0, 0, // 34: BitsPerSample: 8888
|
0x02, 0x01, 3, 0, bytes_per_px, 0, 0, 0, // 34: BitsPerSample: 8888
|
||||||
EXTRA_DATA_OFFSET + 0, 0, 0, 0, 0x03, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0,
|
EXTRA_DATA_OFFSET + 0, 0, 0, 0,
|
||||||
0, // 46: Compression: none
|
0x03, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 46: Compression: none
|
||||||
0x06, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 58: Photometric: RGB
|
0x06, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 58: Photometric: RGB
|
||||||
0x11, 0x01, 4, 0, 1, 0, 0, 0, // 70: Strips offset:
|
0x11, 0x01, 4, 0, 1, 0, 0, 0, // 70: Strips offset:
|
||||||
TIFF_HEADER_SIZE, 0, 0, 0, // data follows header
|
TIFF_HEADER_SIZE, 0, 0, 0, // data follows header
|
||||||
0x12, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 82: Orientation: topleft
|
0x12, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 82: Orientation: topleft
|
||||||
0x15, 0x01, 3, 0, 1, 0, 0, 0, // 94: SamplesPerPixels
|
0x15, 0x01, 3, 0, 1, 0, 0, 0, // 94: SamplesPerPixels
|
||||||
bytes_per_px, 0, 0, 0, 0x16, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0,
|
bytes_per_px, 0, 0, 0,
|
||||||
0, // 106: Rows per strip (TBD)
|
0x16, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 106: Rows per strip (TBD)
|
||||||
0x17, 0x01, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 118: StripByteCount (TBD)
|
0x17, 0x01, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 118: StripByteCount (TBD)
|
||||||
0x1a, 0x01, 5, 0, 1, 0, 0, 0, // 130: X-resolution
|
0x1a, 0x01, 5, 0, 1, 0, 0, 0, // 130: X-resolution
|
||||||
EXTRA_DATA_OFFSET + 8, 0, 0, 0, 0x1b, 0x01, 5, 0, 1, 0, 0,
|
EXTRA_DATA_OFFSET + 8, 0, 0, 0,
|
||||||
0, // 142: Y-resolution
|
0x1b, 0x01, 5, 0, 1, 0, 0, 0, // 142: Y-resolution
|
||||||
EXTRA_DATA_OFFSET + 8, 0, 0, 0, 0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0,
|
EXTRA_DATA_OFFSET + 8, 0, 0, 0,
|
||||||
0, // 154: PlanarConfiguration
|
0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 154: PlanarConfiguration
|
||||||
0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch)
|
0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch)
|
||||||
0x52, 0x01, 3, 0, 1, 0, 0, 0, assoc_alpha, 0, 0,
|
0x52, 0x01, 3, 0, 1, 0, 0, 0,
|
||||||
0, // 178: ExtraSamples: rgbA/RGBA
|
assoc_alpha, 0, 0, 0, // 178: ExtraSamples: rgbA/RGBA
|
||||||
0, 0, 0, 0, // 190: IFD terminator
|
0, 0, 0, 0, // 190: IFD terminator
|
||||||
// EXTRA_DATA_OFFSET:
|
// EXTRA_DATA_OFFSET:
|
||||||
8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample
|
8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample
|
||||||
@@ -430,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);
|
||||||
@@ -518,8 +480,8 @@ int WebPWritePGM(FILE* fout, const WebPDecBuffer* const buffer) {
|
|||||||
|
|
||||||
if (src_y == NULL || src_u == NULL || src_v == NULL) return 0;
|
if (src_y == NULL || src_u == NULL || src_v == NULL) return 0;
|
||||||
|
|
||||||
fprintf(fout, "P5\n%d %d\n255\n", (width + 1) & ~1,
|
fprintf(fout, "P5\n%d %d\n255\n",
|
||||||
height + uv_height + a_height);
|
(width + 1) & ~1, height + uv_height + a_height);
|
||||||
for (y = 0; ok && y < height; ++y) {
|
for (y = 0; ok && y < height; ++y) {
|
||||||
ok &= (fwrite(src_y, width, 1, fout) == 1);
|
ok &= (fwrite(src_y, width, 1, fout) == 1);
|
||||||
if (width & 1) fputc(0, fout); // padding byte
|
if (width & 1) fputc(0, fout); // padding byte
|
||||||
@@ -610,7 +572,8 @@ int WebPSaveImage(const WebPDecBuffer* const buffer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format == PNG || format == RGBA || format == BGRA || format == ARGB ||
|
if (format == PNG ||
|
||||||
|
format == RGBA || format == BGRA || format == ARGB ||
|
||||||
format == rgbA || format == bgrA || format == Argb) {
|
format == rgbA || format == bgrA || format == Argb) {
|
||||||
#ifdef HAVE_WINCODEC_H
|
#ifdef HAVE_WINCODEC_H
|
||||||
ok &= WebPWritePNG(out_file_name, use_stdout, buffer);
|
ok &= WebPWritePNG(out_file_name, use_stdout, buffer);
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
#include "webp/config.h"
|
#include "webp/config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "webp/decode.h"
|
|
||||||
#include "webp/types.h"
|
#include "webp/types.h"
|
||||||
|
#include "webp/decode.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -38,19 +38,10 @@ typedef enum {
|
|||||||
RAW_YUV,
|
RAW_YUV,
|
||||||
ALPHA_PLANE_ONLY, // this is for experimenting only
|
ALPHA_PLANE_ONLY, // this is for experimenting only
|
||||||
// forced colorspace output (for testing, mostly)
|
// forced colorspace output (for testing, mostly)
|
||||||
RGB,
|
RGB, RGBA, BGR, BGRA, ARGB,
|
||||||
RGBA,
|
RGBA_4444, RGB_565,
|
||||||
BGR,
|
rgbA, bgrA, Argb, rgbA_4444,
|
||||||
BGRA,
|
YUV, YUVA
|
||||||
ARGB,
|
|
||||||
RGBA_4444,
|
|
||||||
RGB_565,
|
|
||||||
rgbA,
|
|
||||||
bgrA,
|
|
||||||
Argb,
|
|
||||||
rgbA_4444,
|
|
||||||
YUV,
|
|
||||||
YUVA
|
|
||||||
} WebPOutputFileFormat;
|
} WebPOutputFileFormat;
|
||||||
|
|
||||||
// General all-purpose call.
|
// General all-purpose call.
|
||||||
@@ -88,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);
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,9 @@
|
|||||||
#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 "../examples/unicode.h"
|
#include "../examples/unicode.h"
|
||||||
#include "webp/types.h"
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// File I/O
|
// File I/O
|
||||||
@@ -71,8 +68,8 @@ Error:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImgIoUtilReadFile(const char* const file_name, const uint8_t** data,
|
int ImgIoUtilReadFile(const char* const file_name,
|
||||||
size_t* data_size) {
|
const uint8_t** data, size_t* data_size) {
|
||||||
int ok;
|
int ok;
|
||||||
uint8_t* file_data;
|
uint8_t* file_data;
|
||||||
size_t file_size;
|
size_t file_size;
|
||||||
@@ -92,11 +89,6 @@ int ImgIoUtilReadFile(const char* const file_name, const uint8_t** data,
|
|||||||
}
|
}
|
||||||
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*)WebPMalloc(file_size + 1);
|
||||||
@@ -123,8 +115,8 @@ int ImgIoUtilReadFile(const char* const file_name, const uint8_t** data,
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
int ImgIoUtilWriteFile(const char* const file_name, const uint8_t* data,
|
int ImgIoUtilWriteFile(const char* const file_name,
|
||||||
size_t data_size) {
|
const uint8_t* data, size_t data_size) {
|
||||||
int ok;
|
int ok;
|
||||||
FILE* out;
|
FILE* out;
|
||||||
const int to_stdout = (file_name == NULL) || !WSTRCMP(file_name, "-");
|
const int to_stdout = (file_name == NULL) || !WSTRCMP(file_name, "-");
|
||||||
@@ -145,8 +137,8 @@ int ImgIoUtilWriteFile(const char* const file_name, const uint8_t* data,
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride, uint8_t* dst,
|
void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
|
||||||
int dst_stride, int width, int height) {
|
uint8_t* dst, int dst_stride, int width, int height) {
|
||||||
while (height-- > 0) {
|
while (height-- > 0) {
|
||||||
memcpy(dst, src, width * sizeof(*dst));
|
memcpy(dst, src, width * sizeof(*dst));
|
||||||
src += src_stride;
|
src += src_stride;
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -36,22 +35,22 @@ FILE* ImgIoUtilSetBinaryMode(FILE* file);
|
|||||||
// to be used as a C-string.
|
// to be used as a C-string.
|
||||||
// If 'file_name' is NULL or equal to "-", input is read from stdin by calling
|
// If 'file_name' is NULL or equal to "-", input is read from stdin by calling
|
||||||
// the function ImgIoUtilReadFromStdin().
|
// the function ImgIoUtilReadFromStdin().
|
||||||
int ImgIoUtilReadFile(const char* const file_name, const uint8_t** data,
|
int ImgIoUtilReadFile(const char* const file_name,
|
||||||
size_t* data_size);
|
const uint8_t** data, size_t* data_size);
|
||||||
|
|
||||||
// Same as ImgIoUtilReadFile(), but reads until EOF from stdin instead.
|
// Same as ImgIoUtilReadFile(), but reads until EOF from stdin instead.
|
||||||
int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size);
|
int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size);
|
||||||
|
|
||||||
// Write a data segment into a file named 'file_name'. Returns true if ok.
|
// Write a data segment into a file named 'file_name'. Returns true if ok.
|
||||||
// If 'file_name' is NULL or equal to "-", output is written to stdout.
|
// If 'file_name' is NULL or equal to "-", output is written to stdout.
|
||||||
int ImgIoUtilWriteFile(const char* const file_name, const uint8_t* data,
|
int ImgIoUtilWriteFile(const char* const file_name,
|
||||||
size_t data_size);
|
const uint8_t* data, size_t data_size);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Copy width x height pixels from 'src' to 'dst' honoring the strides.
|
// Copy width x height pixels from 'src' to 'dst' honoring the strides.
|
||||||
void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride, uint8_t* dst,
|
void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
|
||||||
int dst_stride, int width, int height);
|
uint8_t* dst, int dst_stride, int width, int height);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -18,16 +18,15 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef WEBP_HAVE_JPEG
|
#ifdef WEBP_HAVE_JPEG
|
||||||
#include <jerror.h>
|
|
||||||
#include <jpeglib.h>
|
#include <jpeglib.h>
|
||||||
|
#include <jerror.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.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"
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Metadata processing
|
// Metadata processing
|
||||||
@@ -74,7 +73,8 @@ static int StoreICCP(j_decompress_ptr dinfo, MetadataPayload* const iccp) {
|
|||||||
|
|
||||||
memset(iccp_segments, 0, sizeof(iccp_segments));
|
memset(iccp_segments, 0, sizeof(iccp_segments));
|
||||||
for (marker = dinfo->marker_list; marker != NULL; marker = marker->next) {
|
for (marker = dinfo->marker_list; marker != NULL; marker = marker->next) {
|
||||||
if (marker->marker == JPEG_APP2 && marker->data_length > kICCPSkipLength &&
|
if (marker->marker == JPEG_APP2 &&
|
||||||
|
marker->data_length > kICCPSkipLength &&
|
||||||
!memcmp(marker->data, kICCPSignature, kICCPSignatureLength)) {
|
!memcmp(marker->data, kICCPSignature, kICCPSignatureLength)) {
|
||||||
// ICC_PROFILE\0<seq><count>; 'seq' starts at 1.
|
// ICC_PROFILE\0<seq><count>; 'seq' starts at 1.
|
||||||
const int seq = marker->data[kICCPSignatureLength];
|
const int seq = marker->data[kICCPSignatureLength];
|
||||||
@@ -83,8 +83,7 @@ static int StoreICCP(j_decompress_ptr dinfo, MetadataPayload* const iccp) {
|
|||||||
ICCPSegment* segment;
|
ICCPSegment* segment;
|
||||||
|
|
||||||
if (segment_size == 0 || count == 0 || seq == 0) {
|
if (segment_size == 0 || count == 0 || seq == 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "[ICCP] size (%d) / count (%d) / sequence number (%d)"
|
||||||
"[ICCP] size (%d) / count (%d) / sequence number (%d)"
|
|
||||||
" cannot be 0!\n",
|
" cannot be 0!\n",
|
||||||
(int)segment_size, seq, count);
|
(int)segment_size, seq, count);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -138,8 +137,8 @@ static int StoreICCP(j_decompress_ptr dinfo, MetadataPayload* const iccp) {
|
|||||||
int i;
|
int i;
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
for (i = 0; i < seq_max; ++i) {
|
for (i = 0; i < seq_max; ++i) {
|
||||||
memcpy(iccp->bytes + offset, iccp_segments[i].data,
|
memcpy(iccp->bytes + offset,
|
||||||
iccp_segments[i].data_length);
|
iccp_segments[i].data, iccp_segments[i].data_length);
|
||||||
offset += iccp_segments[i].data_length;
|
offset += iccp_segments[i].data_length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,8 +178,8 @@ static int ExtractMetadataFromJPEG(j_decompress_ptr dinfo,
|
|||||||
kJPEGMetadataMap[i].storage_offset);
|
kJPEGMetadataMap[i].storage_offset);
|
||||||
|
|
||||||
if (payload->bytes == NULL) {
|
if (payload->bytes == NULL) {
|
||||||
const char* marker_data =
|
const char* marker_data = (const char*)marker->data +
|
||||||
(const char*)marker->data + kJPEGMetadataMap[i].signature_length;
|
kJPEGMetadataMap[i].signature_length;
|
||||||
const size_t marker_data_length =
|
const size_t marker_data_length =
|
||||||
marker->data_length - kJPEGMetadataMap[i].signature_length;
|
marker->data_length - kJPEGMetadataMap[i].signature_length;
|
||||||
if (!MetadataCopy(marker_data, marker_data_length, payload)) return 0;
|
if (!MetadataCopy(marker_data, marker_data_length, payload)) return 0;
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +239,9 @@ static void ContextSkip(j_decompress_ptr cinfo, long jump_size) {
|
|||||||
ctx->pub.next_input_byte += jump;
|
ctx->pub.next_input_byte += jump;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ContextTerm(j_decompress_ptr cinfo) { (void)cinfo; }
|
static void ContextTerm(j_decompress_ptr cinfo) {
|
||||||
|
(void)cinfo;
|
||||||
|
}
|
||||||
|
|
||||||
static void ContextSetup(volatile struct jpeg_decompress_struct* const cinfo,
|
static void ContextSetup(volatile struct jpeg_decompress_struct* const cinfo,
|
||||||
JPEGReadContext* const ctx) {
|
JPEGReadContext* const ctx) {
|
||||||
@@ -265,7 +256,8 @@ static void ContextSetup(volatile struct jpeg_decompress_struct* const cinfo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ReadJPEG(const uint8_t* const data, size_t data_size,
|
int ReadJPEG(const uint8_t* const data, size_t data_size,
|
||||||
WebPPicture* const pic, int keep_alpha, Metadata* const metadata) {
|
WebPPicture* const pic, int keep_alpha,
|
||||||
|
Metadata* const metadata) {
|
||||||
volatile int ok = 0;
|
volatile int ok = 0;
|
||||||
int width, height;
|
int width, height;
|
||||||
int64_t stride;
|
int64_t stride;
|
||||||
@@ -344,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);
|
||||||
@@ -363,8 +351,7 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
|
|||||||
(void)pic;
|
(void)pic;
|
||||||
(void)keep_alpha;
|
(void)keep_alpha;
|
||||||
(void)metadata;
|
(void)metadata;
|
||||||
fprintf(stderr,
|
fprintf(stderr, "JPEG support not compiled. Please install the libjpeg "
|
||||||
"JPEG support not compiled. Please install the libjpeg "
|
|
||||||
"development package before building.\n");
|
"development package before building.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -26,13 +26,13 @@
|
|||||||
#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) (LOCAL_PNG_VERSION >= (((maj) << 8) | (min)))
|
#define LOCAL_PNG_PREREQ(maj, min) \
|
||||||
|
(LOCAL_PNG_VERSION >= (((maj) << 8) | (min)))
|
||||||
|
|
||||||
static void PNGAPI error_function(png_structp png, png_const_charp error) {
|
static void PNGAPI error_function(png_structp png, png_const_charp error) {
|
||||||
if (error != NULL) fprintf(stderr, "libpng error: %s\n", error);
|
if (error != NULL) fprintf(stderr, "libpng error: %s\n", error);
|
||||||
@@ -111,8 +111,7 @@ static int ProcessRawProfile(const char* profile, size_t profile_len,
|
|||||||
}
|
}
|
||||||
++src;
|
++src;
|
||||||
// skip the profile name and extract the length.
|
// skip the profile name and extract the length.
|
||||||
while (*src != '\0' && *src++ != '\n') {
|
while (*src != '\0' && *src++ != '\n') {}
|
||||||
}
|
|
||||||
expected_length = (int)strtol(src, &end, 10);
|
expected_length = (int)strtol(src, &end, 10);
|
||||||
if (*end != '\n') {
|
if (*end != '\n') {
|
||||||
fprintf(stderr, "Malformed raw profile, expected '\\n' got '\\x%.2X'\n",
|
fprintf(stderr, "Malformed raw profile, expected '\\n' got '\\x%.2X'\n",
|
||||||
@@ -134,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 },
|
||||||
@@ -151,7 +148,8 @@ static const struct {
|
|||||||
// preference to the head.
|
// preference to the head.
|
||||||
// Returns true on success. The caller must use MetadataFree() on 'metadata' in
|
// Returns true on success. The caller must use MetadataFree() on 'metadata' in
|
||||||
// all cases.
|
// all cases.
|
||||||
static int ExtractMetadataFromPNG(png_structp png, png_infop const head_info,
|
static int ExtractMetadataFromPNG(png_structp png,
|
||||||
|
png_infop const head_info,
|
||||||
png_infop const end_info,
|
png_infop const end_info,
|
||||||
Metadata* const metadata) {
|
Metadata* const metadata) {
|
||||||
int p;
|
int p;
|
||||||
@@ -161,20 +159,6 @@ static int ExtractMetadataFromPNG(png_structp png, png_infop const head_info,
|
|||||||
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;
|
||||||
@@ -208,7 +192,6 @@ static int ExtractMetadataFromPNG(png_structp png, png_infop const head_info,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef PNG_iCCP_SUPPORTED
|
|
||||||
// Look for an ICC profile.
|
// Look for an ICC profile.
|
||||||
{
|
{
|
||||||
png_charp name;
|
png_charp name;
|
||||||
@@ -220,12 +203,11 @@ static int ExtractMetadataFromPNG(png_structp png, png_infop const head_info,
|
|||||||
#endif
|
#endif
|
||||||
png_uint_32 len;
|
png_uint_32 len;
|
||||||
|
|
||||||
if (png_get_iCCP(png, info, &name, &comp_type, &profile, &len) ==
|
if (png_get_iCCP(png, info,
|
||||||
PNG_INFO_iCCP) {
|
&name, &comp_type, &profile, &len) == PNG_INFO_iCCP) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -246,14 +228,14 @@ static void ReadFunc(png_structp png_ptr, png_bytep data, png_size_t length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ReadPNG(const uint8_t* const data, size_t data_size,
|
int ReadPNG(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic, int keep_alpha,
|
struct WebPPicture* const pic,
|
||||||
struct Metadata* const metadata) {
|
int keep_alpha, struct Metadata* const metadata) {
|
||||||
volatile png_structp png = NULL;
|
volatile png_structp png = NULL;
|
||||||
volatile png_infop info = NULL;
|
volatile png_infop info = NULL;
|
||||||
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;
|
||||||
@@ -266,8 +248,8 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
context.data = data;
|
context.data = data;
|
||||||
context.data_size = data_size;
|
context.data_size = data_size;
|
||||||
|
|
||||||
png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, NULL,
|
png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL,
|
||||||
MallocFunc, FreeFunc);
|
NULL, MallocFunc, FreeFunc);
|
||||||
if (png == NULL) goto End;
|
if (png == NULL) goto End;
|
||||||
|
|
||||||
png_set_error_fn(png, 0, error_function, NULL);
|
png_set_error_fn(png, 0, error_function, NULL);
|
||||||
@@ -293,9 +275,9 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
png_set_read_fn(png, &context, ReadFunc);
|
png_set_read_fn(png, &context, ReadFunc);
|
||||||
png_read_info(png, info);
|
png_read_info(png, info);
|
||||||
if (!png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type,
|
if (!png_get_IHDR(png, info,
|
||||||
&interlaced, NULL, NULL))
|
&width, &height, &bit_depth, &color_type, &interlaced,
|
||||||
goto Error;
|
NULL, NULL)) goto Error;
|
||||||
|
|
||||||
png_set_strip_16(png);
|
png_set_strip_16(png);
|
||||||
png_set_packing(png);
|
png_set_packing(png);
|
||||||
@@ -311,6 +293,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.
|
||||||
@@ -325,16 +310,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;
|
||||||
@@ -359,7 +341,7 @@ 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) {
|
||||||
@@ -368,23 +350,22 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
End:
|
End:
|
||||||
if (png != NULL) {
|
if (png != NULL) {
|
||||||
png_destroy_read_struct((png_structpp)&png, (png_infopp)&info,
|
png_destroy_read_struct((png_structpp)&png,
|
||||||
(png_infopp)&end_info);
|
(png_infopp)&info, (png_infopp)&end_info);
|
||||||
}
|
}
|
||||||
free(rgb);
|
free(rgb);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
#else // !WEBP_HAVE_PNG
|
#else // !WEBP_HAVE_PNG
|
||||||
int ReadPNG(const uint8_t* const data, size_t data_size,
|
int ReadPNG(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic, int keep_alpha,
|
struct WebPPicture* const pic,
|
||||||
struct Metadata* const metadata) {
|
int keep_alpha, struct Metadata* const metadata) {
|
||||||
(void)data;
|
(void)data;
|
||||||
(void)data_size;
|
(void)data_size;
|
||||||
(void)pic;
|
(void)pic;
|
||||||
(void)keep_alpha;
|
(void)keep_alpha;
|
||||||
(void)metadata;
|
(void)metadata;
|
||||||
fprintf(stderr,
|
fprintf(stderr, "PNG support not compiled. Please install the libpng "
|
||||||
"PNG support not compiled. Please install the libpng "
|
|
||||||
"development package before building.\n");
|
"development package before building.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -29,8 +27,8 @@ struct WebPPicture;
|
|||||||
// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV.
|
// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV.
|
||||||
// Returns true on success.
|
// Returns true on success.
|
||||||
int ReadPNG(const uint8_t* const data, size_t data_size,
|
int ReadPNG(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic, int keep_alpha,
|
struct WebPPicture* const pic,
|
||||||
struct Metadata* const metadata);
|
int keep_alpha, struct Metadata* const metadata);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -116,9 +111,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] = ' ';
|
||||||
@@ -173,8 +167,9 @@ static size_t ReadHeader(PNMInfo* const info) {
|
|||||||
info->depth = (info->type == 5) ? 1 : 3;
|
info->depth = (info->type == 5) ? 1 : 3;
|
||||||
}
|
}
|
||||||
// perform some basic numerical validation
|
// perform some basic numerical validation
|
||||||
if (info->width <= 0 || info->height <= 0 || info->type <= 0 ||
|
if (info->width <= 0 || info->height <= 0 ||
|
||||||
info->type >= 9 || info->depth <= 0 || info->depth > 4 ||
|
info->type <= 0 || info->type >= 9 ||
|
||||||
|
info->depth <= 0 || info->depth > 4 ||
|
||||||
info->max_value <= 0 || info->max_value >= 65536) {
|
info->max_value <= 0 || info->max_value >= 65536) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -182,8 +177,9 @@ static size_t ReadHeader(PNMInfo* const info) {
|
|||||||
return off;
|
return off;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadPNM(const uint8_t* const data, size_t data_size, WebPPicture* const pic,
|
int ReadPNM(const uint8_t* const data, size_t data_size,
|
||||||
int keep_alpha, struct Metadata* const metadata) {
|
WebPPicture* const pic, int keep_alpha,
|
||||||
|
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, sample_size, depth;
|
||||||
@@ -207,8 +203,8 @@ int ReadPNM(const uint8_t* const data, size_t data_size, WebPPicture* const pic,
|
|||||||
// Some basic validations.
|
// Some basic validations.
|
||||||
if (pic == NULL) goto End;
|
if (pic == NULL) goto End;
|
||||||
if (info.width > WEBP_MAX_DIMENSION || info.height > WEBP_MAX_DIMENSION) {
|
if (info.width > WEBP_MAX_DIMENSION || info.height > WEBP_MAX_DIMENSION) {
|
||||||
fprintf(stderr, "Invalid %dx%d dimension for PNM\n", info.width,
|
fprintf(stderr, "Invalid %dx%d dimension for PNM\n",
|
||||||
info.height);
|
info.width, info.height);
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,8 +252,8 @@ int ReadPNM(const uint8_t* const data, size_t data_size, WebPPicture* const pic,
|
|||||||
const uint32_t round = info.max_value / 2;
|
const uint32_t round = info.max_value / 2;
|
||||||
int k = 0;
|
int k = 0;
|
||||||
for (i = 0; i < info.width * info.depth; ++i) {
|
for (i = 0; i < info.width * info.depth; ++i) {
|
||||||
uint32_t v =
|
uint32_t v = (sample_size == 2) ? 256u * in[2 * i + 0] + in[2 * i + 1]
|
||||||
(sample_size == 2) ? 256u * in[2 * i + 0] + in[2 * i + 1] : in[i];
|
: in[i];
|
||||||
if (info.max_value != 255) v = (v * 255u + round) / info.max_value;
|
if (info.max_value != 255) v = (v * 255u + round) / info.max_value;
|
||||||
if (v > 255u) v = 255u;
|
if (v > 255u) v = 255u;
|
||||||
if (info.depth > 2) {
|
if (info.depth > 2) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -128,7 +127,9 @@ static uint32_t Unmult(uint8_t x, uint32_t mult) {
|
|||||||
return (v > 255u) ? 255u : v;
|
return (v > 255u) ? 255u : v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE uint32_t GetScale(uint32_t a) { return (255u << MFIX) / a; }
|
static WEBP_INLINE uint32_t GetScale(uint32_t a) {
|
||||||
|
return (255u << MFIX) / a;
|
||||||
|
}
|
||||||
|
|
||||||
#undef MFIX
|
#undef MFIX
|
||||||
#undef HALF
|
#undef HALF
|
||||||
@@ -151,7 +152,8 @@ static void MultARGBRow(uint8_t* ptr, int width) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ReadTIFF(const uint8_t* const data, size_t data_size,
|
int ReadTIFF(const uint8_t* const data, size_t data_size,
|
||||||
WebPPicture* const pic, int keep_alpha, Metadata* const metadata) {
|
WebPPicture* const pic, int keep_alpha,
|
||||||
|
Metadata* const metadata) {
|
||||||
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;
|
||||||
@@ -168,7 +170,8 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tif = TIFFClientOpen("Memory", "r", &my_data, MyRead, MyRead, MySeek, MyClose,
|
tif = TIFFClientOpen("Memory", "r", &my_data,
|
||||||
|
MyRead, MyRead, MySeek, MyClose,
|
||||||
MySize, MyMapFile, MyUnmapFile);
|
MySize, MyMapFile, MyUnmapFile);
|
||||||
if (tif == NULL) {
|
if (tif == NULL) {
|
||||||
fprintf(stderr, "Error! Cannot parse TIFF file\n");
|
fprintf(stderr, "Error! Cannot parse TIFF file\n");
|
||||||
@@ -177,8 +180,7 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
dircount = TIFFNumberOfDirectories(tif);
|
dircount = TIFFNumberOfDirectories(tif);
|
||||||
if (dircount > 1) {
|
if (dircount > 1) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Warning: multi-directory TIFF files are not supported.\n"
|
||||||
"Warning: multi-directory TIFF files are not supported.\n"
|
|
||||||
"Only the first will be used, %d will be ignored.\n",
|
"Only the first will be used, %d will be ignored.\n",
|
||||||
dircount - 1);
|
dircount - 1);
|
||||||
}
|
}
|
||||||
@@ -186,9 +188,7 @@ 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))) {
|
||||||
@@ -212,7 +212,7 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height)) {
|
TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height)) {
|
||||||
if ((tile_width > 32 && tile_width / 2 > image_width) ||
|
if ((tile_width > 32 && tile_width / 2 > image_width) ||
|
||||||
(tile_height > 32 && tile_height / 2 > image_height) ||
|
(tile_height > 32 && tile_height / 2 > image_height) ||
|
||||||
!ImgIoUtilCheckSizeArgumentsOverflow(
|
ImgIoUtilCheckSizeArgumentsOverflow(
|
||||||
(uint64_t)tile_width * sizeof(*raster), tile_height)) {
|
(uint64_t)tile_width * sizeof(*raster), tile_height)) {
|
||||||
fprintf(stderr, "Error! TIFF tile dimension (%d x %d) is too large.\n",
|
fprintf(stderr, "Error! TIFF tile dimension (%d x %d) is too large.\n",
|
||||||
tile_width, tile_height);
|
tile_width, tile_height);
|
||||||
@@ -250,8 +250,7 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
tmp += stride;
|
tmp += stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ok =
|
ok = keep_alpha
|
||||||
keep_alpha
|
|
||||||
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, (int)stride)
|
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, (int)stride)
|
||||||
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, (int)stride);
|
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, (int)stride);
|
||||||
}
|
}
|
||||||
@@ -283,8 +282,7 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
(void)pic;
|
(void)pic;
|
||||||
(void)keep_alpha;
|
(void)keep_alpha;
|
||||||
(void)metadata;
|
(void)metadata;
|
||||||
fprintf(stderr,
|
fprintf(stderr, "TIFF support not compiled. Please install the libtiff "
|
||||||
"TIFF support not compiled. Please install the libtiff "
|
|
||||||
"development package before building.\n");
|
"development package before building.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -13,32 +13,26 @@
|
|||||||
#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
|
||||||
|
|
||||||
static const char* const kStatusMessages[VP8_STATUS_NOT_ENOUGH_DATA + 1] = {
|
static const char* const kStatusMessages[VP8_STATUS_NOT_ENOUGH_DATA + 1] = {
|
||||||
"OK",
|
"OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR",
|
||||||
"OUT_OF_MEMORY",
|
"UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA"
|
||||||
"INVALID_PARAM",
|
};
|
||||||
"BITSTREAM_ERROR",
|
|
||||||
"UNSUPPORTED_FEATURE",
|
|
||||||
"SUSPENDED",
|
|
||||||
"USER_ABORT",
|
|
||||||
"NOT_ENOUGH_DATA"};
|
|
||||||
|
|
||||||
static void PrintAnimationWarning(const WebPDecoderConfig* const config) {
|
static void PrintAnimationWarning(const WebPDecoderConfig* const config) {
|
||||||
if (config->input.has_animation) {
|
if (config->input.has_animation) {
|
||||||
@@ -58,7 +52,8 @@ void PrintWebPError(const char* const in_file, int status) {
|
|||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int LoadWebP(const char* const in_file, const uint8_t** data, size_t* data_size,
|
int LoadWebP(const char* const in_file,
|
||||||
|
const uint8_t** data, size_t* data_size,
|
||||||
WebPBitstreamFeatures* bitstream) {
|
WebPBitstreamFeatures* bitstream) {
|
||||||
VP8StatusCode status;
|
VP8StatusCode status;
|
||||||
WebPBitstreamFeatures local_features;
|
WebPBitstreamFeatures local_features;
|
||||||
@@ -88,7 +83,8 @@ VP8StatusCode DecodeWebP(const uint8_t* const data, size_t data_size,
|
|||||||
return WebPDecode(data, data_size, config);
|
return WebPDecode(data, data_size, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
VP8StatusCode DecodeWebPIncremental(const uint8_t* const data, size_t data_size,
|
VP8StatusCode DecodeWebPIncremental(
|
||||||
|
const uint8_t* const data, size_t data_size,
|
||||||
WebPDecoderConfig* const config) {
|
WebPDecoderConfig* const config) {
|
||||||
VP8StatusCode status = VP8_STATUS_OK;
|
VP8StatusCode status = VP8_STATUS_OK;
|
||||||
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
|
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
|
||||||
@@ -146,7 +142,8 @@ static int ExtractMetadata(const uint8_t* const data, size_t data_size,
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
int ReadWebP(const uint8_t* const data, size_t data_size,
|
int ReadWebP(const uint8_t* const data, size_t data_size,
|
||||||
WebPPicture* const pic, int keep_alpha, Metadata* const metadata) {
|
WebPPicture* const pic,
|
||||||
|
int keep_alpha, Metadata* const metadata) {
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
VP8StatusCode status = VP8_STATUS_OK;
|
VP8StatusCode status = VP8_STATUS_OK;
|
||||||
WebPDecoderConfig config;
|
WebPDecoderConfig config;
|
||||||
@@ -196,8 +193,7 @@ int ReadWebP(const uint8_t* const data, size_t data_size,
|
|||||||
#endif
|
#endif
|
||||||
output_buffer->u.RGBA.rgba = (uint8_t*)pic->argb;
|
output_buffer->u.RGBA.rgba = (uint8_t*)pic->argb;
|
||||||
output_buffer->u.RGBA.stride = pic->argb_stride * sizeof(uint32_t);
|
output_buffer->u.RGBA.stride = pic->argb_stride * sizeof(uint32_t);
|
||||||
output_buffer->u.RGBA.size =
|
output_buffer->u.RGBA.size = output_buffer->u.RGBA.stride * pic->height;
|
||||||
(size_t)output_buffer->u.RGBA.stride * pic->height;
|
|
||||||
} else {
|
} else {
|
||||||
output_buffer->colorspace = has_alpha ? MODE_YUVA : MODE_YUV;
|
output_buffer->colorspace = has_alpha ? MODE_YUVA : MODE_YUV;
|
||||||
output_buffer->u.YUVA.y = pic->y;
|
output_buffer->u.YUVA.y = pic->y;
|
||||||
@@ -208,12 +204,10 @@ int ReadWebP(const uint8_t* const data, size_t data_size,
|
|||||||
output_buffer->u.YUVA.u_stride = pic->uv_stride;
|
output_buffer->u.YUVA.u_stride = pic->uv_stride;
|
||||||
output_buffer->u.YUVA.v_stride = pic->uv_stride;
|
output_buffer->u.YUVA.v_stride = pic->uv_stride;
|
||||||
output_buffer->u.YUVA.a_stride = has_alpha ? pic->a_stride : 0;
|
output_buffer->u.YUVA.a_stride = has_alpha ? pic->a_stride : 0;
|
||||||
output_buffer->u.YUVA.y_size = (size_t)pic->height * pic->y_stride;
|
output_buffer->u.YUVA.y_size = pic->height * pic->y_stride;
|
||||||
output_buffer->u.YUVA.u_size =
|
output_buffer->u.YUVA.u_size = (pic->height + 1) / 2 * pic->uv_stride;
|
||||||
(size_t)(pic->height + 1) / 2 * pic->uv_stride;
|
output_buffer->u.YUVA.v_size = (pic->height + 1) / 2 * pic->uv_stride;
|
||||||
output_buffer->u.YUVA.v_size =
|
output_buffer->u.YUVA.a_size = pic->height * pic->a_stride;
|
||||||
(size_t)(pic->height + 1) / 2 * pic->uv_stride;
|
|
||||||
output_buffer->u.YUVA.a_size = (size_t)pic->height * pic->a_stride;
|
|
||||||
}
|
}
|
||||||
output_buffer->is_external_memory = 1;
|
output_buffer->is_external_memory = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -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" {
|
||||||
@@ -35,7 +32,8 @@ void PrintWebPError(const char* const in_file, int status);
|
|||||||
// Reads a WebP from 'in_file', returning the contents and size in 'data' and
|
// Reads a WebP from 'in_file', returning the contents and size in 'data' and
|
||||||
// 'data_size'. If not NULL, 'bitstream' is populated using WebPGetFeatures().
|
// 'data_size'. If not NULL, 'bitstream' is populated using WebPGetFeatures().
|
||||||
// Returns true on success.
|
// Returns true on success.
|
||||||
int LoadWebP(const char* const in_file, const uint8_t** data, size_t* data_size,
|
int LoadWebP(const char* const in_file,
|
||||||
|
const uint8_t** data, size_t* data_size,
|
||||||
WebPBitstreamFeatures* bitstream);
|
WebPBitstreamFeatures* bitstream);
|
||||||
|
|
||||||
// Decodes the WebP contained in 'data'.
|
// Decodes the WebP contained in 'data'.
|
||||||
@@ -47,7 +45,8 @@ VP8StatusCode DecodeWebP(const uint8_t* const data, size_t data_size,
|
|||||||
WebPDecoderConfig* const config);
|
WebPDecoderConfig* const config);
|
||||||
|
|
||||||
// Same as DecodeWebP(), but using the incremental decoder.
|
// Same as DecodeWebP(), but using the incremental decoder.
|
||||||
VP8StatusCode DecodeWebPIncremental(const uint8_t* const data, size_t data_size,
|
VP8StatusCode DecodeWebPIncremental(
|
||||||
|
const uint8_t* const data, size_t data_size,
|
||||||
WebPDecoderConfig* const config);
|
WebPDecoderConfig* const config);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -58,8 +57,8 @@ VP8StatusCode DecodeWebPIncremental(const uint8_t* const data, size_t data_size,
|
|||||||
// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV.
|
// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV.
|
||||||
// Returns true on success.
|
// Returns true on success.
|
||||||
int ReadWebP(const uint8_t* const data, size_t data_size,
|
int ReadWebP(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic, int keep_alpha,
|
struct WebPPicture* const pic,
|
||||||
struct Metadata* const metadata);
|
int keep_alpha, struct Metadata* const metadata);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@@ -25,14 +25,13 @@
|
|||||||
#endif
|
#endif
|
||||||
#define CINTERFACE
|
#define CINTERFACE
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
#define _WIN32_IE \
|
#define _WIN32_IE 0x500 // Workaround bug in shlwapi.h when compiling C++
|
||||||
0x500 // Workaround bug in shlwapi.h when compiling C++
|
|
||||||
// code with COBJMACROS.
|
// code with COBJMACROS.
|
||||||
#include <ole2.h> // CreateStreamOnHGlobal()
|
#include <ole2.h> // CreateStreamOnHGlobal()
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <wincodec.h>
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <wincodec.h>
|
||||||
|
|
||||||
#include "../examples/unicode.h"
|
#include "../examples/unicode.h"
|
||||||
#include "./imageio_util.h"
|
#include "./imageio_util.h"
|
||||||
@@ -49,7 +48,8 @@
|
|||||||
|
|
||||||
// modified version of DEFINE_GUID from guiddef.h.
|
// modified version of DEFINE_GUID from guiddef.h.
|
||||||
#define WEBP_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
#define WEBP_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||||
static const GUID name = {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}}
|
static const GUID name = \
|
||||||
|
{ l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define MAKE_REFGUID(x) (x)
|
#define MAKE_REFGUID(x) (x)
|
||||||
@@ -66,17 +66,23 @@ typedef struct WICFormatImporter {
|
|||||||
// From Microsoft SDK 7.0a -- wincodec.h
|
// From Microsoft SDK 7.0a -- wincodec.h
|
||||||
// Create local copies for compatibility when building against earlier
|
// Create local copies for compatibility when building against earlier
|
||||||
// versions of the SDK.
|
// versions of the SDK.
|
||||||
WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppBGR_, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1,
|
WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppBGR_,
|
||||||
0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0c);
|
0x6fddc324, 0x4e03, 0x4bfe,
|
||||||
WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppRGB_, 0x6fddc324, 0x4e03, 0x4bfe, 0xb1,
|
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0c);
|
||||||
0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0d);
|
WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppRGB_,
|
||||||
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppBGRA_, 0x6fddc324, 0x4e03, 0x4bfe,
|
0x6fddc324, 0x4e03, 0x4bfe,
|
||||||
|
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0d);
|
||||||
|
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppBGRA_,
|
||||||
|
0x6fddc324, 0x4e03, 0x4bfe,
|
||||||
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0f);
|
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0f);
|
||||||
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppRGBA_, 0xf5c7ad2d, 0x6a8d, 0x43dd,
|
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppRGBA_,
|
||||||
|
0xf5c7ad2d, 0x6a8d, 0x43dd,
|
||||||
0xa7, 0xa8, 0xa2, 0x99, 0x35, 0x26, 0x1a, 0xe9);
|
0xa7, 0xa8, 0xa2, 0x99, 0x35, 0x26, 0x1a, 0xe9);
|
||||||
WEBP_DEFINE_GUID(GUID_WICPixelFormat64bppBGRA_, 0x1562ff7c, 0xd352, 0x46f9,
|
WEBP_DEFINE_GUID(GUID_WICPixelFormat64bppBGRA_,
|
||||||
|
0x1562ff7c, 0xd352, 0x46f9,
|
||||||
0x97, 0x9e, 0x42, 0x97, 0x6b, 0x79, 0x22, 0x46);
|
0x97, 0x9e, 0x42, 0x97, 0x6b, 0x79, 0x22, 0x46);
|
||||||
WEBP_DEFINE_GUID(GUID_WICPixelFormat64bppRGBA_, 0x6fddc324, 0x4e03, 0x4bfe,
|
WEBP_DEFINE_GUID(GUID_WICPixelFormat64bppRGBA_,
|
||||||
|
0x6fddc324, 0x4e03, 0x4bfe,
|
||||||
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x16);
|
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x16);
|
||||||
|
|
||||||
static HRESULT OpenInputStream(const char* filename, IStream** stream) {
|
static HRESULT OpenInputStream(const char* filename, IStream** stream) {
|
||||||
@@ -141,7 +147,8 @@ static HRESULT ExtractICCP(IWICImagingFactory* const factory,
|
|||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
UINT num_color_contexts;
|
UINT num_color_contexts;
|
||||||
IFS(IWICBitmapFrameDecode_GetColorContexts(frame, count, color_contexts,
|
IFS(IWICBitmapFrameDecode_GetColorContexts(frame,
|
||||||
|
count, color_contexts,
|
||||||
&num_color_contexts));
|
&num_color_contexts));
|
||||||
assert(FAILED(hr) || num_color_contexts <= count);
|
assert(FAILED(hr) || num_color_contexts <= count);
|
||||||
for (i = 0; SUCCEEDED(hr) && i < num_color_contexts; ++i) {
|
for (i = 0; SUCCEEDED(hr) && i < num_color_contexts; ++i) {
|
||||||
@@ -149,8 +156,8 @@ static HRESULT ExtractICCP(IWICImagingFactory* const factory,
|
|||||||
IFS(IWICColorContext_GetType(color_contexts[i], &type));
|
IFS(IWICColorContext_GetType(color_contexts[i], &type));
|
||||||
if (SUCCEEDED(hr) && type == WICColorContextProfile) {
|
if (SUCCEEDED(hr) && type == WICColorContextProfile) {
|
||||||
UINT size;
|
UINT size;
|
||||||
IFS(IWICColorContext_GetProfileBytes(color_contexts[i], 0, NULL,
|
IFS(IWICColorContext_GetProfileBytes(color_contexts[i],
|
||||||
&size));
|
0, NULL, &size));
|
||||||
if (SUCCEEDED(hr) && size > 0) {
|
if (SUCCEEDED(hr) && size > 0) {
|
||||||
iccp->bytes = (uint8_t*)malloc(size);
|
iccp->bytes = (uint8_t*)malloc(size);
|
||||||
if (iccp->bytes == NULL) {
|
if (iccp->bytes == NULL) {
|
||||||
@@ -158,8 +165,9 @@ static HRESULT ExtractICCP(IWICImagingFactory* const factory,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
iccp->size = size;
|
iccp->size = size;
|
||||||
IFS(IWICColorContext_GetProfileBytes(
|
IFS(IWICColorContext_GetProfileBytes(color_contexts[i],
|
||||||
color_contexts[i], (UINT)iccp->size, iccp->bytes, &size));
|
(UINT)iccp->size, iccp->bytes,
|
||||||
|
&size));
|
||||||
if (SUCCEEDED(hr) && size != iccp->size) {
|
if (SUCCEEDED(hr) && size != iccp->size) {
|
||||||
fprintf(stderr, "Warning! ICC profile size (%u) != expected (%u)\n",
|
fprintf(stderr, "Warning! ICC profile size (%u) != expected (%u)\n",
|
||||||
size, (uint32_t)iccp->size);
|
size, (uint32_t)iccp->size);
|
||||||
@@ -201,7 +209,8 @@ static int HasPalette(GUID pixel_format) {
|
|||||||
|
|
||||||
static int HasAlpha(IWICImagingFactory* const factory,
|
static int HasAlpha(IWICImagingFactory* const factory,
|
||||||
IWICBitmapDecoder* const decoder,
|
IWICBitmapDecoder* const decoder,
|
||||||
IWICBitmapFrameDecode* const frame, GUID pixel_format) {
|
IWICBitmapFrameDecode* const frame,
|
||||||
|
GUID pixel_format) {
|
||||||
int has_alpha;
|
int has_alpha;
|
||||||
if (HasPalette(pixel_format)) {
|
if (HasPalette(pixel_format)) {
|
||||||
IWICPalette* frame_palette = NULL;
|
IWICPalette* frame_palette = NULL;
|
||||||
@@ -236,8 +245,9 @@ static int HasAlpha(IWICImagingFactory* const factory,
|
|||||||
return has_alpha;
|
return has_alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadPictureWithWIC(const char* const filename, WebPPicture* const pic,
|
int ReadPictureWithWIC(const char* const filename,
|
||||||
int keep_alpha, Metadata* const metadata) {
|
WebPPicture* const pic, int keep_alpha,
|
||||||
|
Metadata* const metadata) {
|
||||||
// From Microsoft SDK 6.0a -- ks.h
|
// From Microsoft SDK 6.0a -- ks.h
|
||||||
// Define a local copy to avoid link errors under mingw.
|
// Define a local copy to avoid link errors under mingw.
|
||||||
WEBP_DEFINE_GUID(GUID_NULL_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
WEBP_DEFINE_GUID(GUID_NULL_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
@@ -264,20 +274,26 @@ int ReadPictureWithWIC(const char* const filename, WebPPicture* const pic,
|
|||||||
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
|
// From Windows Kits\10\Include\10.0.19041.0\um\wincodec.h
|
||||||
WEBP_DEFINE_GUID(GUID_ContainerFormatWebp_, 0xe094b0e2, 0x67f2, 0x45b3, 0xb0,
|
WEBP_DEFINE_GUID(GUID_ContainerFormatWebp_,
|
||||||
0xea, 0x11, 0x53, 0x37, 0xca, 0x7c, 0xf3);
|
0xe094b0e2, 0x67f2, 0x45b3,
|
||||||
|
0xb0, 0xea, 0x11, 0x53, 0x37, 0xca, 0x7c, 0xf3);
|
||||||
static const GUID* kAlphaContainers[] = {
|
static const GUID* kAlphaContainers[] = {
|
||||||
&GUID_ContainerFormatBmp, &GUID_ContainerFormatPng,
|
&GUID_ContainerFormatBmp,
|
||||||
&GUID_ContainerFormatTiff, &GUID_ContainerFormatWebp_, NULL};
|
&GUID_ContainerFormatPng,
|
||||||
|
&GUID_ContainerFormatTiff,
|
||||||
|
&GUID_ContainerFormatWebp_,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
int has_alpha = 0;
|
int has_alpha = 0;
|
||||||
int64_t stride;
|
int64_t stride;
|
||||||
|
|
||||||
if (filename == NULL || pic == NULL) return 0;
|
if (filename == NULL || pic == NULL) return 0;
|
||||||
|
|
||||||
IFS(CoInitialize(NULL));
|
IFS(CoInitialize(NULL));
|
||||||
IFS(CoCreateInstance(
|
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
|
||||||
MAKE_REFGUID(CLSID_WICImagingFactory), NULL, CLSCTX_INPROC_SERVER,
|
CLSCTX_INPROC_SERVER,
|
||||||
MAKE_REFGUID(IID_IWICImagingFactory), (LPVOID*)&factory));
|
MAKE_REFGUID(IID_IWICImagingFactory),
|
||||||
|
(LPVOID*)&factory));
|
||||||
if (hr == REGDB_E_CLASSNOTREG) {
|
if (hr == REGDB_E_CLASSNOTREG) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Couldn't access Windows Imaging Component (are you running "
|
"Couldn't access Windows Imaging Component (are you running "
|
||||||
@@ -287,7 +303,8 @@ int ReadPictureWithWIC(const char* const filename, WebPPicture* const pic,
|
|||||||
// Prepare for image decoding.
|
// Prepare for image decoding.
|
||||||
IFS(OpenInputStream(filename, &stream));
|
IFS(OpenInputStream(filename, &stream));
|
||||||
IFS(IWICImagingFactory_CreateDecoderFromStream(
|
IFS(IWICImagingFactory_CreateDecoderFromStream(
|
||||||
factory, stream, NULL, WICDecodeMetadataCacheOnDemand, &decoder));
|
factory, stream, NULL,
|
||||||
|
WICDecodeMetadataCacheOnDemand, &decoder));
|
||||||
IFS(IWICBitmapDecoder_GetFrameCount(decoder, &frame_count));
|
IFS(IWICBitmapDecoder_GetFrameCount(decoder, &frame_count));
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
if (frame_count == 0) {
|
if (frame_count == 0) {
|
||||||
@@ -321,15 +338,18 @@ int ReadPictureWithWIC(const char* const filename, WebPPicture* const pic,
|
|||||||
hr == S_OK && importer->import != NULL; ++importer) {
|
hr == S_OK && importer->import != NULL; ++importer) {
|
||||||
BOOL can_convert;
|
BOOL can_convert;
|
||||||
const HRESULT cchr = IWICFormatConverter_CanConvert(
|
const HRESULT cchr = IWICFormatConverter_CanConvert(
|
||||||
converter, MAKE_REFGUID(src_pixel_format),
|
converter,
|
||||||
MAKE_REFGUID(*importer->pixel_format), &can_convert);
|
MAKE_REFGUID(src_pixel_format),
|
||||||
|
MAKE_REFGUID(*importer->pixel_format),
|
||||||
|
&can_convert);
|
||||||
if (SUCCEEDED(cchr) && can_convert) break;
|
if (SUCCEEDED(cchr) && can_convert) break;
|
||||||
}
|
}
|
||||||
if (importer->import == NULL) hr = E_FAIL;
|
if (importer->import == NULL) hr = E_FAIL;
|
||||||
|
|
||||||
IFS(IWICFormatConverter_Initialize(
|
IFS(IWICFormatConverter_Initialize(converter, (IWICBitmapSource*)frame,
|
||||||
converter, (IWICBitmapSource*)frame, importer->pixel_format,
|
importer->pixel_format,
|
||||||
WICBitmapDitherTypeNone, NULL, 0.0, WICBitmapPaletteTypeCustom));
|
WICBitmapDitherTypeNone,
|
||||||
|
NULL, 0.0, WICBitmapPaletteTypeCustom));
|
||||||
|
|
||||||
// Decode.
|
// Decode.
|
||||||
IFS(IWICFormatConverter_GetSize(converter, &width, &height));
|
IFS(IWICFormatConverter_GetSize(converter, &width, &height));
|
||||||
@@ -341,10 +361,11 @@ int ReadPictureWithWIC(const char* const filename, WebPPicture* const pic,
|
|||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
rgb = (BYTE*)malloc((size_t)stride * height);
|
rgb = (BYTE*)malloc((size_t)stride * height);
|
||||||
if (rgb == NULL) hr = E_OUTOFMEMORY;
|
if (rgb == NULL)
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
IFS(IWICFormatConverter_CopyPixels(converter, NULL, (UINT)stride,
|
IFS(IWICFormatConverter_CopyPixels(converter, NULL,
|
||||||
(UINT)stride * height, rgb));
|
(UINT)stride, (UINT)stride * height, rgb));
|
||||||
|
|
||||||
// WebP conversion.
|
// WebP conversion.
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
@@ -381,8 +402,7 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
(void)pic;
|
(void)pic;
|
||||||
(void)keep_alpha;
|
(void)keep_alpha;
|
||||||
(void)metadata;
|
(void)metadata;
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Windows Imaging Component (WIC) support not compiled. "
|
||||||
"Windows Imaging Component (WIC) support not compiled. "
|
|
||||||
"Visual Studio and mingw-w64 builds support WIC. Make sure "
|
"Visual Studio and mingw-w64 builds support WIC. Make sure "
|
||||||
"wincodec.h detection is working correctly if using autoconf "
|
"wincodec.h detection is working correctly if using autoconf "
|
||||||
"and HAVE_WINCODEC_H is defined before building.\n");
|
"and HAVE_WINCODEC_H is defined before building.\n");
|
||||||
|
|||||||
@@ -85,10 +85,10 @@ scan_build make -j4
|
|||||||
|
|
||||||
index="$(find "${OUTPUT_DIR}" -name index.html)"
|
index="$(find "${OUTPUT_DIR}" -name index.html)"
|
||||||
if [[ -f "${index}" ]]; then
|
if [[ -f "${index}" ]]; then
|
||||||
mv "$(dirname "${index}")/"* "${OUTPUT_DIR}"
|
mv "$(dirname "${index}")/"* .
|
||||||
else
|
else
|
||||||
# make a empty report to wipe out any old bug reports.
|
# make a empty report to wipe out any old bug reports.
|
||||||
cat << EOT > "${OUTPUT_DIR}/index.html"
|
cat << EOT > index.html
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
No bugs reported.
|
No bugs reported.
|
||||||
|
|||||||
36
iosbuild.sh
36
iosbuild.sh
@@ -9,7 +9,7 @@
|
|||||||
# (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
|
||||||
|
|
||||||
@@ -31,8 +31,8 @@ readonly OLDPATH=${PATH}
|
|||||||
|
|
||||||
# Add iPhoneOS-V6 to the list of platforms below if you need armv6 support.
|
# Add iPhoneOS-V6 to the list of platforms below if you need armv6 support.
|
||||||
# Note that iPhoneOS-V6 support is not available with the iOS6 SDK.
|
# Note that iPhoneOS-V6 support is not available with the iOS6 SDK.
|
||||||
PLATFORMS="iPhoneSimulator64"
|
PLATFORMS="iPhoneSimulator iPhoneSimulator64"
|
||||||
PLATFORMS+=" iPhoneOS-arm64"
|
PLATFORMS+=" iPhoneOS-V7 iPhoneOS-V7s iPhoneOS-V7-arm64"
|
||||||
readonly PLATFORMS
|
readonly PLATFORMS
|
||||||
readonly SRCDIR=$(dirname $0)
|
readonly SRCDIR=$(dirname $0)
|
||||||
readonly TOPDIR=$(pwd)
|
readonly TOPDIR=$(pwd)
|
||||||
@@ -41,7 +41,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,7 +52,7 @@ 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%%.*} -le 6 ]]; then
|
||||||
echo "You need iOS SDK version 6.0 or above"
|
echo "You need iOS SDK version 6.0 or above"
|
||||||
@@ -64,8 +63,7 @@ echo "Xcode Version: ${XCODE}"
|
|||||||
echo "iOS SDK Version: ${SDK}"
|
echo "iOS SDK Version: ${SDK}"
|
||||||
|
|
||||||
if [[ -e "${BUILDDIR}" || -e "${TARGETDIR}" || -e "${DECTARGETDIR}" \
|
if [[ -e "${BUILDDIR}" || -e "${TARGETDIR}" || -e "${DECTARGETDIR}" \
|
||||||
|| -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" \
|
|| -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" ]]; then
|
||||||
|| -e "${SHARPYUVTARGETDIR}" ]]; then
|
|
||||||
cat << EOF
|
cat << EOF
|
||||||
WARNING: The following directories will be deleted:
|
WARNING: The following directories will be deleted:
|
||||||
WARNING: ${BUILDDIR}
|
WARNING: ${BUILDDIR}
|
||||||
@@ -73,16 +71,14 @@ WARNING: ${TARGETDIR}
|
|||||||
WARNING: ${DECTARGETDIR}
|
WARNING: ${DECTARGETDIR}
|
||||||
WARNING: ${MUXTARGETDIR}
|
WARNING: ${MUXTARGETDIR}
|
||||||
WARNING: ${DEMUXTARGETDIR}
|
WARNING: ${DEMUXTARGETDIR}
|
||||||
WARNING: ${SHARPYUVTARGETDIR}
|
|
||||||
WARNING: The build will continue in 5 seconds...
|
WARNING: The build will continue in 5 seconds...
|
||||||
EOF
|
EOF
|
||||||
sleep 5
|
sleep 5
|
||||||
fi
|
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
|
||||||
@@ -90,7 +86,7 @@ if [[ ! -e ${SRCDIR}/configure ]]; then
|
|||||||
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
|
EOF
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -98,7 +94,7 @@ fi
|
|||||||
|
|
||||||
for PLATFORM in ${PLATFORMS}; do
|
for PLATFORM in ${PLATFORMS}; do
|
||||||
ARCH2=""
|
ARCH2=""
|
||||||
if [[ "${PLATFORM}" == "iPhoneOS-arm64" ]]; then
|
if [[ "${PLATFORM}" == "iPhoneOS-V7-arm64" ]]; then
|
||||||
PLATFORM="iPhoneOS"
|
PLATFORM="iPhoneOS"
|
||||||
ARCH="aarch64"
|
ARCH="aarch64"
|
||||||
ARCH2="arm64"
|
ARCH2="arm64"
|
||||||
@@ -137,17 +133,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
|
||||||
@@ -170,9 +167,4 @@ 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"
|
echo "SUCCESS"
|
||||||
|
|||||||
@@ -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 \
|
||||||
@@ -276,7 +266,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 +280,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 +296,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 +304,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 +326,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 +334,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 +341,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 +386,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 +403,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 +411,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 +424,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 +438,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 +448,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 +468,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 +489,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/*~ \
|
||||||
|
|||||||
59
man/cwebp.1
59
man/cwebp.1
@@ -1,5 +1,5 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH CWEBP 1 "April 10, 2025"
|
.TH CWEBP 1 "November 19, 2020"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
cwebp \- compress an image file to a WebP file
|
cwebp \- compress an image file to a WebP file
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -90,25 +90,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,9 +133,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
|
.TP
|
||||||
.BI \-qrange " int int
|
.BI \-qrange " int int
|
||||||
Specifies the permissible interval for the quality factor. This is particularly
|
Specifies the permissible interval for the quality factor. This is particularly
|
||||||
@@ -188,8 +176,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 +200,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 +209,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 +222,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 +293,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 +318,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.
|
||||||
|
|||||||
23
man/dwebp.1
23
man/dwebp.1
@@ -1,5 +1,5 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH DWEBP 1 "July 18, 2024"
|
.TH DWEBP 1 "November 19, 2020"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
dwebp \- decompress a WebP file to an image file
|
dwebp \- decompress a WebP file to an image file
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -108,12 +108,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 +133,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
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH GIF2WEBP 1 "November 4, 2024"
|
.TH GIF2WEBP 1 "May 1, 2020"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
gif2webp \- Convert a GIF image to WebP
|
gif2webp \- Convert a GIF image to WebP
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH IMG2WEBP 1 "November 26, 2024"
|
.TH IMG2WEBP 1 "May 1, 2020"
|
||||||
.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
|
||||||
@@ -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.
|
||||||
|
|||||||
23
man/vwebp.1
23
man/vwebp.1
@@ -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.
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH WEBPMUX 1 "July 18, 2024"
|
.TH WEBPMUX 1 "November 3, 2021"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
webpmux \- create animated WebP files from non\-animated WebP images, extract
|
webpmux \- create animated WebP files from non\-animated WebP images, extract
|
||||||
frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
|
frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
|
||||||
@@ -186,12 +186,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 +262,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.
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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@
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
#define APSTUDIO_READONLY_SYMBOLS
|
|
||||||
#include "winres.h"
|
|
||||||
#undef APSTUDIO_READONLY_SYMBOLS
|
|
||||||
|
|
||||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
|
||||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
|
||||||
FILEVERSION 0,0,4,2
|
|
||||||
PRODUCTVERSION 0,0,4,2
|
|
||||||
FILEFLAGSMASK 0x3fL
|
|
||||||
#ifdef _DEBUG
|
|
||||||
FILEFLAGS 0x1L
|
|
||||||
#else
|
|
||||||
FILEFLAGS 0x0L
|
|
||||||
#endif
|
|
||||||
FILEOS 0x40004L
|
|
||||||
FILETYPE 0x2L
|
|
||||||
FILESUBTYPE 0x0L
|
|
||||||
BEGIN
|
|
||||||
BLOCK "StringFileInfo"
|
|
||||||
BEGIN
|
|
||||||
BLOCK "040904b0"
|
|
||||||
BEGIN
|
|
||||||
VALUE "CompanyName", "Google, Inc."
|
|
||||||
VALUE "FileDescription", "libsharpyuv DLL"
|
|
||||||
VALUE "FileVersion", "0.4.2"
|
|
||||||
VALUE "InternalName", "libsharpyuv.dll"
|
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2025"
|
|
||||||
VALUE "OriginalFilename", "libsharpyuv.dll"
|
|
||||||
VALUE "ProductName", "SharpYuv Library"
|
|
||||||
VALUE "ProductVersion", "0.4.2"
|
|
||||||
END
|
|
||||||
END
|
|
||||||
BLOCK "VarFileInfo"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Translation", 0x409, 1200
|
|
||||||
END
|
|
||||||
END
|
|
||||||
|
|
||||||
#endif // English (United States) resources
|
|
||||||
@@ -1,565 +0,0 @@
|
|||||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by a BSD-style license
|
|
||||||
// that can be found in the COPYING file in the root of the source
|
|
||||||
// tree. An additional intellectual property rights grant can be found
|
|
||||||
// in the file PATENTS. All contributing project authors may
|
|
||||||
// be found in the AUTHORS file in the root of the source tree.
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Sharp RGB to YUV conversion.
|
|
||||||
//
|
|
||||||
// Author: Skal (pascal.massimino@gmail.com)
|
|
||||||
|
|
||||||
#include "sharpyuv/sharpyuv.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "sharpyuv/sharpyuv_cpu.h"
|
|
||||||
#include "sharpyuv/sharpyuv_dsp.h"
|
|
||||||
#include "sharpyuv/sharpyuv_gamma.h"
|
|
||||||
#include "src/webp/types.h"
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int SharpYuvGetVersion(void) { return SHARPYUV_VERSION; }
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Sharp RGB->YUV conversion
|
|
||||||
|
|
||||||
static const int kNumIterations = 4;
|
|
||||||
|
|
||||||
#define YUV_FIX 16 // fixed-point precision for RGB->YUV
|
|
||||||
static const int kYuvHalf = 1 << (YUV_FIX - 1);
|
|
||||||
|
|
||||||
// Max bit depth so that intermediate calculations fit in 16 bits.
|
|
||||||
static const int kMaxBitDepth = 14;
|
|
||||||
|
|
||||||
// Returns the precision shift to use based on the input rgb_bit_depth.
|
|
||||||
static int GetPrecisionShift(int rgb_bit_depth) {
|
|
||||||
// Try to add 2 bits of precision if it fits in kMaxBitDepth. Otherwise remove
|
|
||||||
// bits if needed.
|
|
||||||
return ((rgb_bit_depth + 2) <= kMaxBitDepth) ? 2
|
|
||||||
: (kMaxBitDepth - rgb_bit_depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef int16_t fixed_t; // signed type with extra precision for UV
|
|
||||||
typedef uint16_t fixed_y_t; // unsigned type with extra precision for W
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static uint8_t clip_8b(fixed_t v) {
|
|
||||||
return (!(v & ~0xff)) ? (uint8_t)v : (v < 0) ? 0u : 255u;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t clip(fixed_t v, int max) {
|
|
||||||
return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static fixed_y_t clip_bit_depth(int y, int bit_depth) {
|
|
||||||
const int max = (1 << bit_depth) - 1;
|
|
||||||
return (!(y & ~max)) ? (fixed_y_t)y : (y < 0) ? 0 : max;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static int RGBToGray(int64_t r, int64_t g, int64_t b) {
|
|
||||||
const int64_t luma = 13933 * r + 46871 * g + 4732 * b + kYuvHalf;
|
|
||||||
return (int)(luma >> YUV_FIX);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ScaleDown(uint16_t a, uint16_t b, uint16_t c, uint16_t d,
|
|
||||||
int bit_depth,
|
|
||||||
SharpYuvTransferFunctionType transfer_type) {
|
|
||||||
const uint32_t A = SharpYuvGammaToLinear(a, bit_depth, transfer_type);
|
|
||||||
const uint32_t B = SharpYuvGammaToLinear(b, bit_depth, transfer_type);
|
|
||||||
const uint32_t C = SharpYuvGammaToLinear(c, bit_depth, transfer_type);
|
|
||||||
const uint32_t D = SharpYuvGammaToLinear(d, bit_depth, transfer_type);
|
|
||||||
return SharpYuvLinearToGamma((A + B + C + D + 2) >> 2, bit_depth,
|
|
||||||
transfer_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int w,
|
|
||||||
int bit_depth,
|
|
||||||
SharpYuvTransferFunctionType transfer_type) {
|
|
||||||
int i = 0;
|
|
||||||
do {
|
|
||||||
const uint32_t R =
|
|
||||||
SharpYuvGammaToLinear(src[0 * w + i], bit_depth, transfer_type);
|
|
||||||
const uint32_t G =
|
|
||||||
SharpYuvGammaToLinear(src[1 * w + i], bit_depth, transfer_type);
|
|
||||||
const uint32_t B =
|
|
||||||
SharpYuvGammaToLinear(src[2 * w + i], bit_depth, transfer_type);
|
|
||||||
const uint32_t Y = RGBToGray(R, G, B);
|
|
||||||
dst[i] = (fixed_y_t)SharpYuvLinearToGamma(Y, bit_depth, transfer_type);
|
|
||||||
} while (++i < w);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void UpdateChroma(const fixed_y_t* src1, const fixed_y_t* src2,
|
|
||||||
fixed_t* dst, int uv_w, int bit_depth,
|
|
||||||
SharpYuvTransferFunctionType transfer_type) {
|
|
||||||
int i = 0;
|
|
||||||
do {
|
|
||||||
const int r =
|
|
||||||
ScaleDown(src1[0 * uv_w + 0], src1[0 * uv_w + 1], src2[0 * uv_w + 0],
|
|
||||||
src2[0 * uv_w + 1], bit_depth, transfer_type);
|
|
||||||
const int g =
|
|
||||||
ScaleDown(src1[2 * uv_w + 0], src1[2 * uv_w + 1], src2[2 * uv_w + 0],
|
|
||||||
src2[2 * uv_w + 1], bit_depth, transfer_type);
|
|
||||||
const int b =
|
|
||||||
ScaleDown(src1[4 * uv_w + 0], src1[4 * uv_w + 1], src2[4 * uv_w + 0],
|
|
||||||
src2[4 * uv_w + 1], bit_depth, transfer_type);
|
|
||||||
const int W = RGBToGray(r, g, b);
|
|
||||||
dst[0 * uv_w] = (fixed_t)(r - W);
|
|
||||||
dst[1 * uv_w] = (fixed_t)(g - W);
|
|
||||||
dst[2 * uv_w] = (fixed_t)(b - W);
|
|
||||||
dst += 1;
|
|
||||||
src1 += 2;
|
|
||||||
src2 += 2;
|
|
||||||
} while (++i < uv_w);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StoreGray(const fixed_y_t* rgb, fixed_y_t* y, int w) {
|
|
||||||
int i = 0;
|
|
||||||
assert(w > 0);
|
|
||||||
do {
|
|
||||||
y[i] = RGBToGray(rgb[0 * w + i], rgb[1 * w + i], rgb[2 * w + i]);
|
|
||||||
} while (++i < w);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static WEBP_INLINE fixed_y_t Filter2(int A, int B, int W0, int bit_depth) {
|
|
||||||
const int v0 = (A * 3 + B + 2) >> 2;
|
|
||||||
return clip_bit_depth(v0 + W0, bit_depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static WEBP_INLINE int Shift(int v, int shift) {
|
|
||||||
return (shift >= 0) ? (v << shift) : (v >> -shift);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ImportOneRow(const uint8_t* const r_ptr, const uint8_t* const g_ptr,
|
|
||||||
const uint8_t* const b_ptr, int rgb_step,
|
|
||||||
int rgb_bit_depth, int pic_width,
|
|
||||||
fixed_y_t* const dst) {
|
|
||||||
// Convert the rgb_step from a number of bytes to a number of uint8_t or
|
|
||||||
// uint16_t values depending the bit depth.
|
|
||||||
const int step = (rgb_bit_depth > 8) ? rgb_step / 2 : rgb_step;
|
|
||||||
int i = 0;
|
|
||||||
const int w = (pic_width + 1) & ~1;
|
|
||||||
do {
|
|
||||||
const int off = i * step;
|
|
||||||
const int shift = GetPrecisionShift(rgb_bit_depth);
|
|
||||||
if (rgb_bit_depth == 8) {
|
|
||||||
dst[i + 0 * w] = Shift(r_ptr[off], shift);
|
|
||||||
dst[i + 1 * w] = Shift(g_ptr[off], shift);
|
|
||||||
dst[i + 2 * w] = Shift(b_ptr[off], shift);
|
|
||||||
} else {
|
|
||||||
dst[i + 0 * w] = Shift(((uint16_t*)r_ptr)[off], shift);
|
|
||||||
dst[i + 1 * w] = Shift(((uint16_t*)g_ptr)[off], shift);
|
|
||||||
dst[i + 2 * w] = Shift(((uint16_t*)b_ptr)[off], shift);
|
|
||||||
}
|
|
||||||
} while (++i < pic_width);
|
|
||||||
if (pic_width & 1) { // replicate rightmost pixel
|
|
||||||
dst[pic_width + 0 * w] = dst[pic_width + 0 * w - 1];
|
|
||||||
dst[pic_width + 1 * w] = dst[pic_width + 1 * w - 1];
|
|
||||||
dst[pic_width + 2 * w] = dst[pic_width + 2 * w - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void InterpolateTwoRows(const fixed_y_t* const best_y,
|
|
||||||
const fixed_t* prev_uv, const fixed_t* cur_uv,
|
|
||||||
const fixed_t* next_uv, int w, fixed_y_t* out1,
|
|
||||||
fixed_y_t* out2, int bit_depth) {
|
|
||||||
const int uv_w = w >> 1;
|
|
||||||
const int len = (w - 1) >> 1; // length to filter
|
|
||||||
int k = 3;
|
|
||||||
while (k-- > 0) { // process each R/G/B segments in turn
|
|
||||||
// special boundary case for i==0
|
|
||||||
out1[0] = Filter2(cur_uv[0], prev_uv[0], best_y[0], bit_depth);
|
|
||||||
out2[0] = Filter2(cur_uv[0], next_uv[0], best_y[w], bit_depth);
|
|
||||||
|
|
||||||
SharpYuvFilterRow(cur_uv, prev_uv, len, best_y + 0 + 1, out1 + 1,
|
|
||||||
bit_depth);
|
|
||||||
SharpYuvFilterRow(cur_uv, next_uv, len, best_y + w + 1, out2 + 1,
|
|
||||||
bit_depth);
|
|
||||||
|
|
||||||
// special boundary case for i == w - 1 when w is even
|
|
||||||
if (!(w & 1)) {
|
|
||||||
out1[w - 1] = Filter2(cur_uv[uv_w - 1], prev_uv[uv_w - 1],
|
|
||||||
best_y[w - 1 + 0], bit_depth);
|
|
||||||
out2[w - 1] = Filter2(cur_uv[uv_w - 1], next_uv[uv_w - 1],
|
|
||||||
best_y[w - 1 + w], bit_depth);
|
|
||||||
}
|
|
||||||
out1 += w;
|
|
||||||
out2 += w;
|
|
||||||
prev_uv += uv_w;
|
|
||||||
cur_uv += uv_w;
|
|
||||||
next_uv += uv_w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static WEBP_INLINE int RGBToYUVComponent(int r, int g, int b,
|
|
||||||
const int coeffs[4], int sfix) {
|
|
||||||
const int srounder = 1 << (YUV_FIX + sfix - 1);
|
|
||||||
const int luma =
|
|
||||||
coeffs[0] * r + coeffs[1] * g + coeffs[2] * b + coeffs[3] + srounder;
|
|
||||||
return (luma >> (YUV_FIX + sfix));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv,
|
|
||||||
uint8_t* y_ptr, int y_stride, uint8_t* u_ptr,
|
|
||||||
int u_stride, uint8_t* v_ptr, int v_stride,
|
|
||||||
int rgb_bit_depth, int yuv_bit_depth, int width,
|
|
||||||
int height,
|
|
||||||
const SharpYuvConversionMatrix* yuv_matrix) {
|
|
||||||
int i, j;
|
|
||||||
const fixed_t* const best_uv_base = best_uv;
|
|
||||||
const int w = (width + 1) & ~1;
|
|
||||||
const int h = (height + 1) & ~1;
|
|
||||||
const int uv_w = w >> 1;
|
|
||||||
const int uv_h = h >> 1;
|
|
||||||
const int sfix = GetPrecisionShift(rgb_bit_depth);
|
|
||||||
const int yuv_max = (1 << yuv_bit_depth) - 1;
|
|
||||||
|
|
||||||
best_uv = best_uv_base;
|
|
||||||
j = 0;
|
|
||||||
do {
|
|
||||||
i = 0;
|
|
||||||
do {
|
|
||||||
const int off = (i >> 1);
|
|
||||||
const int W = best_y[i];
|
|
||||||
const int r = best_uv[off + 0 * uv_w] + W;
|
|
||||||
const int g = best_uv[off + 1 * uv_w] + W;
|
|
||||||
const int b = best_uv[off + 2 * uv_w] + W;
|
|
||||||
const int y = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_y, sfix);
|
|
||||||
if (yuv_bit_depth <= 8) {
|
|
||||||
y_ptr[i] = clip_8b(y);
|
|
||||||
} else {
|
|
||||||
((uint16_t*)y_ptr)[i] = clip(y, yuv_max);
|
|
||||||
}
|
|
||||||
} while (++i < width);
|
|
||||||
best_y += w;
|
|
||||||
best_uv += (j & 1) * 3 * uv_w;
|
|
||||||
y_ptr += y_stride;
|
|
||||||
} while (++j < height);
|
|
||||||
|
|
||||||
best_uv = best_uv_base;
|
|
||||||
j = 0;
|
|
||||||
do {
|
|
||||||
i = 0;
|
|
||||||
do {
|
|
||||||
// Note r, g and b values here are off by W, but a constant offset on all
|
|
||||||
// 3 components doesn't change the value of u and v with a YCbCr matrix.
|
|
||||||
const int r = best_uv[i + 0 * uv_w];
|
|
||||||
const int g = best_uv[i + 1 * uv_w];
|
|
||||||
const int b = best_uv[i + 2 * uv_w];
|
|
||||||
const int u = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_u, sfix);
|
|
||||||
const int v = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_v, sfix);
|
|
||||||
if (yuv_bit_depth <= 8) {
|
|
||||||
u_ptr[i] = clip_8b(u);
|
|
||||||
v_ptr[i] = clip_8b(v);
|
|
||||||
} else {
|
|
||||||
((uint16_t*)u_ptr)[i] = clip(u, yuv_max);
|
|
||||||
((uint16_t*)v_ptr)[i] = clip(v, yuv_max);
|
|
||||||
}
|
|
||||||
} while (++i < uv_w);
|
|
||||||
best_uv += 3 * uv_w;
|
|
||||||
u_ptr += u_stride;
|
|
||||||
v_ptr += v_stride;
|
|
||||||
} while (++j < uv_h);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Main function
|
|
||||||
|
|
||||||
static void* SafeMalloc(uint64_t nmemb, size_t size) {
|
|
||||||
const uint64_t total_size = nmemb * (uint64_t)size;
|
|
||||||
if (total_size != (size_t)total_size) return NULL;
|
|
||||||
return malloc((size_t)total_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
|
|
||||||
const uint8_t* b_ptr, int rgb_step, int rgb_stride,
|
|
||||||
int rgb_bit_depth, uint8_t* y_ptr, int y_stride,
|
|
||||||
uint8_t* u_ptr, int u_stride, uint8_t* v_ptr,
|
|
||||||
int v_stride, int yuv_bit_depth, int width,
|
|
||||||
int height,
|
|
||||||
const SharpYuvConversionMatrix* yuv_matrix,
|
|
||||||
SharpYuvTransferFunctionType transfer_type) {
|
|
||||||
// we expand the right/bottom border if needed
|
|
||||||
const int w = (width + 1) & ~1;
|
|
||||||
const int h = (height + 1) & ~1;
|
|
||||||
const int uv_w = w >> 1;
|
|
||||||
const int uv_h = h >> 1;
|
|
||||||
const int y_bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth);
|
|
||||||
uint64_t prev_diff_y_sum = ~0;
|
|
||||||
int j, iter;
|
|
||||||
|
|
||||||
const uint64_t tmp_buffer_size = (uint64_t)w * 3 * 2;
|
|
||||||
const uint64_t best_y_base_size = (uint64_t)w * h;
|
|
||||||
const uint64_t target_y_base_size = (uint64_t)w * h;
|
|
||||||
const uint64_t best_rgb_y_size = (uint64_t)w * 2;
|
|
||||||
const uint64_t best_uv_base_size = (uint64_t)uv_w * 3 * uv_h;
|
|
||||||
const uint64_t target_uv_base_size = (uint64_t)uv_w * 3 * uv_h;
|
|
||||||
const uint64_t best_rgb_uv_size = (uint64_t)uv_w * 3;
|
|
||||||
fixed_y_t* const tmp_buffer = (fixed_y_t*)SafeMalloc(
|
|
||||||
(tmp_buffer_size + best_y_base_size + target_y_base_size +
|
|
||||||
best_rgb_y_size) +
|
|
||||||
(best_uv_base_size + target_uv_base_size + best_rgb_uv_size),
|
|
||||||
sizeof(*tmp_buffer));
|
|
||||||
fixed_y_t *best_y_base, *target_y_base, *best_rgb_y;
|
|
||||||
fixed_t *best_uv_base, *target_uv_base, *best_rgb_uv;
|
|
||||||
fixed_y_t *best_y, *target_y;
|
|
||||||
fixed_t *best_uv, *target_uv;
|
|
||||||
const uint64_t diff_y_threshold = (uint64_t)(3.0 * w * h);
|
|
||||||
int ok;
|
|
||||||
assert(w > 0);
|
|
||||||
assert(h > 0);
|
|
||||||
assert(sizeof(fixed_y_t) == sizeof(fixed_t));
|
|
||||||
|
|
||||||
if (tmp_buffer == NULL) {
|
|
||||||
ok = 0;
|
|
||||||
goto End;
|
|
||||||
}
|
|
||||||
best_y_base = tmp_buffer + tmp_buffer_size;
|
|
||||||
target_y_base = best_y_base + best_y_base_size;
|
|
||||||
best_rgb_y = target_y_base + target_y_base_size;
|
|
||||||
best_uv_base = (fixed_t*)(best_rgb_y + best_rgb_y_size);
|
|
||||||
target_uv_base = best_uv_base + best_uv_base_size;
|
|
||||||
best_rgb_uv = target_uv_base + target_uv_base_size;
|
|
||||||
best_y = best_y_base;
|
|
||||||
target_y = target_y_base;
|
|
||||||
best_uv = best_uv_base;
|
|
||||||
target_uv = target_uv_base;
|
|
||||||
|
|
||||||
// Import RGB samples to W/RGB representation.
|
|
||||||
for (j = 0; j < height; j += 2) {
|
|
||||||
const int is_last_row = (j == height - 1);
|
|
||||||
fixed_y_t* const src1 = tmp_buffer + 0 * w;
|
|
||||||
fixed_y_t* const src2 = tmp_buffer + 3 * w;
|
|
||||||
|
|
||||||
// prepare two rows of input
|
|
||||||
ImportOneRow(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth, width, src1);
|
|
||||||
if (!is_last_row) {
|
|
||||||
ImportOneRow(r_ptr + rgb_stride, g_ptr + rgb_stride, b_ptr + rgb_stride,
|
|
||||||
rgb_step, rgb_bit_depth, width, src2);
|
|
||||||
} else {
|
|
||||||
memcpy(src2, src1, 3 * w * sizeof(*src2));
|
|
||||||
}
|
|
||||||
StoreGray(src1, best_y + 0, w);
|
|
||||||
StoreGray(src2, best_y + w, w);
|
|
||||||
|
|
||||||
UpdateW(src1, target_y, w, y_bit_depth, transfer_type);
|
|
||||||
UpdateW(src2, target_y + w, w, y_bit_depth, transfer_type);
|
|
||||||
UpdateChroma(src1, src2, target_uv, uv_w, y_bit_depth, transfer_type);
|
|
||||||
memcpy(best_uv, target_uv, 3 * uv_w * sizeof(*best_uv));
|
|
||||||
best_y += 2 * w;
|
|
||||||
best_uv += 3 * uv_w;
|
|
||||||
target_y += 2 * w;
|
|
||||||
target_uv += 3 * uv_w;
|
|
||||||
r_ptr += 2 * rgb_stride;
|
|
||||||
g_ptr += 2 * rgb_stride;
|
|
||||||
b_ptr += 2 * rgb_stride;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate and resolve clipping conflicts.
|
|
||||||
for (iter = 0; iter < kNumIterations; ++iter) {
|
|
||||||
const fixed_t* cur_uv = best_uv_base;
|
|
||||||
const fixed_t* prev_uv = best_uv_base;
|
|
||||||
uint64_t diff_y_sum = 0;
|
|
||||||
|
|
||||||
best_y = best_y_base;
|
|
||||||
best_uv = best_uv_base;
|
|
||||||
target_y = target_y_base;
|
|
||||||
target_uv = target_uv_base;
|
|
||||||
j = 0;
|
|
||||||
do {
|
|
||||||
fixed_y_t* const src1 = tmp_buffer + 0 * w;
|
|
||||||
fixed_y_t* const src2 = tmp_buffer + 3 * w;
|
|
||||||
{
|
|
||||||
const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0);
|
|
||||||
InterpolateTwoRows(best_y, prev_uv, cur_uv, next_uv, w, src1, src2,
|
|
||||||
y_bit_depth);
|
|
||||||
prev_uv = cur_uv;
|
|
||||||
cur_uv = next_uv;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateW(src1, best_rgb_y + 0 * w, w, y_bit_depth, transfer_type);
|
|
||||||
UpdateW(src2, best_rgb_y + 1 * w, w, y_bit_depth, transfer_type);
|
|
||||||
UpdateChroma(src1, src2, best_rgb_uv, uv_w, y_bit_depth, transfer_type);
|
|
||||||
|
|
||||||
// update two rows of Y and one row of RGB
|
|
||||||
diff_y_sum +=
|
|
||||||
SharpYuvUpdateY(target_y, best_rgb_y, best_y, 2 * w, y_bit_depth);
|
|
||||||
SharpYuvUpdateRGB(target_uv, best_rgb_uv, best_uv, 3 * uv_w);
|
|
||||||
|
|
||||||
best_y += 2 * w;
|
|
||||||
best_uv += 3 * uv_w;
|
|
||||||
target_y += 2 * w;
|
|
||||||
target_uv += 3 * uv_w;
|
|
||||||
j += 2;
|
|
||||||
} while (j < h);
|
|
||||||
// test exit condition
|
|
||||||
if (iter > 0) {
|
|
||||||
if (diff_y_sum < diff_y_threshold) break;
|
|
||||||
if (diff_y_sum > prev_diff_y_sum) break;
|
|
||||||
}
|
|
||||||
prev_diff_y_sum = diff_y_sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
// final reconstruction
|
|
||||||
ok = ConvertWRGBToYUV(best_y_base, best_uv_base, y_ptr, y_stride, u_ptr,
|
|
||||||
u_stride, v_ptr, v_stride, rgb_bit_depth, yuv_bit_depth,
|
|
||||||
width, height, yuv_matrix);
|
|
||||||
|
|
||||||
End:
|
|
||||||
free(tmp_buffer);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(WEBP_USE_THREAD) && !defined(_WIN32)
|
|
||||||
#include <pthread.h> // NOLINT
|
|
||||||
|
|
||||||
#define LOCK_ACCESS \
|
|
||||||
static pthread_mutex_t sharpyuv_lock = PTHREAD_MUTEX_INITIALIZER; \
|
|
||||||
if (pthread_mutex_lock(&sharpyuv_lock)) return
|
|
||||||
#define UNLOCK_ACCESS_AND_RETURN \
|
|
||||||
do { \
|
|
||||||
(void)pthread_mutex_unlock(&sharpyuv_lock); \
|
|
||||||
return; \
|
|
||||||
} while (0)
|
|
||||||
#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32))
|
|
||||||
#define LOCK_ACCESS \
|
|
||||||
do { \
|
|
||||||
} while (0)
|
|
||||||
#define UNLOCK_ACCESS_AND_RETURN return
|
|
||||||
#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32)
|
|
||||||
|
|
||||||
// Hidden exported init function.
|
|
||||||
// By default SharpYuvConvert calls it with SharpYuvGetCPUInfo. If needed,
|
|
||||||
// users can declare it as extern and call it with an alternate VP8CPUInfo
|
|
||||||
// function.
|
|
||||||
extern VP8CPUInfo SharpYuvGetCPUInfo;
|
|
||||||
SHARPYUV_EXTERN void SharpYuvInit(VP8CPUInfo cpu_info_func);
|
|
||||||
void SharpYuvInit(VP8CPUInfo cpu_info_func) {
|
|
||||||
static volatile VP8CPUInfo sharpyuv_last_cpuinfo_used =
|
|
||||||
(VP8CPUInfo)&sharpyuv_last_cpuinfo_used;
|
|
||||||
LOCK_ACCESS;
|
|
||||||
// Only update SharpYuvGetCPUInfo when called from external code to avoid a
|
|
||||||
// race on reading the value in SharpYuvConvert().
|
|
||||||
if (cpu_info_func != (VP8CPUInfo)&SharpYuvGetCPUInfo) {
|
|
||||||
SharpYuvGetCPUInfo = cpu_info_func;
|
|
||||||
}
|
|
||||||
if (sharpyuv_last_cpuinfo_used == SharpYuvGetCPUInfo) {
|
|
||||||
UNLOCK_ACCESS_AND_RETURN;
|
|
||||||
}
|
|
||||||
|
|
||||||
SharpYuvInitDsp();
|
|
||||||
SharpYuvInitGammaTables();
|
|
||||||
|
|
||||||
sharpyuv_last_cpuinfo_used = SharpYuvGetCPUInfo;
|
|
||||||
UNLOCK_ACCESS_AND_RETURN;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SharpYuvConvert(const void* r_ptr, const void* g_ptr, const void* b_ptr,
|
|
||||||
int rgb_step, int rgb_stride, int rgb_bit_depth,
|
|
||||||
void* y_ptr, int y_stride, void* u_ptr, int u_stride,
|
|
||||||
void* v_ptr, int v_stride, int yuv_bit_depth, int width,
|
|
||||||
int height, const SharpYuvConversionMatrix* yuv_matrix) {
|
|
||||||
SharpYuvOptions options;
|
|
||||||
options.yuv_matrix = yuv_matrix;
|
|
||||||
options.transfer_type = kSharpYuvTransferFunctionSrgb;
|
|
||||||
return SharpYuvConvertWithOptions(
|
|
||||||
r_ptr, g_ptr, b_ptr, rgb_step, rgb_stride, rgb_bit_depth, y_ptr, y_stride,
|
|
||||||
u_ptr, u_stride, v_ptr, v_stride, yuv_bit_depth, width, height, &options);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SharpYuvOptionsInitInternal(const SharpYuvConversionMatrix* yuv_matrix,
|
|
||||||
SharpYuvOptions* options, int version) {
|
|
||||||
const int major = (version >> 24);
|
|
||||||
const int minor = (version >> 16) & 0xff;
|
|
||||||
if (options == NULL || yuv_matrix == NULL ||
|
|
||||||
(major == SHARPYUV_VERSION_MAJOR && major == 0 &&
|
|
||||||
minor != SHARPYUV_VERSION_MINOR) ||
|
|
||||||
(major != SHARPYUV_VERSION_MAJOR)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
options->yuv_matrix = yuv_matrix;
|
|
||||||
options->transfer_type = kSharpYuvTransferFunctionSrgb;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SharpYuvConvertWithOptions(const void* r_ptr, const void* g_ptr,
|
|
||||||
const void* b_ptr, int rgb_step, int rgb_stride,
|
|
||||||
int rgb_bit_depth, void* y_ptr, int y_stride,
|
|
||||||
void* u_ptr, int u_stride, void* v_ptr,
|
|
||||||
int v_stride, int yuv_bit_depth, int width,
|
|
||||||
int height, const SharpYuvOptions* options) {
|
|
||||||
const SharpYuvConversionMatrix* yuv_matrix = options->yuv_matrix;
|
|
||||||
SharpYuvTransferFunctionType transfer_type = options->transfer_type;
|
|
||||||
SharpYuvConversionMatrix scaled_matrix;
|
|
||||||
const int rgb_max = (1 << rgb_bit_depth) - 1;
|
|
||||||
const int rgb_round = 1 << (rgb_bit_depth - 1);
|
|
||||||
const int yuv_max = (1 << yuv_bit_depth) - 1;
|
|
||||||
const int sfix = GetPrecisionShift(rgb_bit_depth);
|
|
||||||
|
|
||||||
if (width < 1 || height < 1 || width == INT_MAX || height == INT_MAX ||
|
|
||||||
r_ptr == NULL || g_ptr == NULL || b_ptr == NULL || y_ptr == NULL ||
|
|
||||||
u_ptr == NULL || v_ptr == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (rgb_bit_depth != 8 && rgb_bit_depth != 10 && rgb_bit_depth != 12 &&
|
|
||||||
rgb_bit_depth != 16) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (yuv_bit_depth != 8 && yuv_bit_depth != 10 && yuv_bit_depth != 12) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (rgb_bit_depth > 8 && (rgb_step % 2 != 0 || rgb_stride % 2 != 0)) {
|
|
||||||
// Step/stride should be even for uint16_t buffers.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (yuv_bit_depth > 8 &&
|
|
||||||
(y_stride % 2 != 0 || u_stride % 2 != 0 || v_stride % 2 != 0)) {
|
|
||||||
// Stride should be even for uint16_t buffers.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// The address of the function pointer is used to avoid a read race.
|
|
||||||
SharpYuvInit((VP8CPUInfo)&SharpYuvGetCPUInfo);
|
|
||||||
|
|
||||||
// Add scaling factor to go from rgb_bit_depth to yuv_bit_depth, to the
|
|
||||||
// rgb->yuv conversion matrix.
|
|
||||||
if (rgb_bit_depth == yuv_bit_depth) {
|
|
||||||
memcpy(&scaled_matrix, yuv_matrix, sizeof(scaled_matrix));
|
|
||||||
} else {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < 3; ++i) {
|
|
||||||
scaled_matrix.rgb_to_y[i] =
|
|
||||||
(yuv_matrix->rgb_to_y[i] * yuv_max + rgb_round) / rgb_max;
|
|
||||||
scaled_matrix.rgb_to_u[i] =
|
|
||||||
(yuv_matrix->rgb_to_u[i] * yuv_max + rgb_round) / rgb_max;
|
|
||||||
scaled_matrix.rgb_to_v[i] =
|
|
||||||
(yuv_matrix->rgb_to_v[i] * yuv_max + rgb_round) / rgb_max;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Also incorporate precision change scaling.
|
|
||||||
scaled_matrix.rgb_to_y[3] = Shift(yuv_matrix->rgb_to_y[3], sfix);
|
|
||||||
scaled_matrix.rgb_to_u[3] = Shift(yuv_matrix->rgb_to_u[3], sfix);
|
|
||||||
scaled_matrix.rgb_to_v[3] = Shift(yuv_matrix->rgb_to_v[3], sfix);
|
|
||||||
|
|
||||||
return DoSharpArgbToYuv(
|
|
||||||
(const uint8_t*)r_ptr, (const uint8_t*)g_ptr, (const uint8_t*)b_ptr,
|
|
||||||
rgb_step, rgb_stride, rgb_bit_depth, (uint8_t*)y_ptr, y_stride,
|
|
||||||
(uint8_t*)u_ptr, u_stride, (uint8_t*)v_ptr, v_stride, yuv_bit_depth,
|
|
||||||
width, height, &scaled_matrix, transfer_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
@@ -1,181 +0,0 @@
|
|||||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by a BSD-style license
|
|
||||||
// that can be found in the COPYING file in the root of the source
|
|
||||||
// tree. An additional intellectual property rights grant can be found
|
|
||||||
// in the file PATENTS. All contributing project authors may
|
|
||||||
// be found in the AUTHORS file in the root of the source tree.
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Sharp RGB to YUV conversion.
|
|
||||||
|
|
||||||
#ifndef WEBP_SHARPYUV_SHARPYUV_H_
|
|
||||||
#define WEBP_SHARPYUV_SHARPYUV_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SHARPYUV_EXTERN
|
|
||||||
#ifdef WEBP_EXTERN
|
|
||||||
#define SHARPYUV_EXTERN WEBP_EXTERN
|
|
||||||
#else
|
|
||||||
// This explicitly marks library functions and allows for changing the
|
|
||||||
// signature for e.g., Windows DLL builds.
|
|
||||||
#if defined(_WIN32) && defined(WEBP_DLL)
|
|
||||||
#define SHARPYUV_EXTERN __declspec(dllexport)
|
|
||||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
|
||||||
#define SHARPYUV_EXTERN extern __attribute__((visibility("default")))
|
|
||||||
#else
|
|
||||||
#define SHARPYUV_EXTERN extern
|
|
||||||
#endif /* defined(_WIN32) && defined(WEBP_DLL) */
|
|
||||||
#endif /* WEBP_EXTERN */
|
|
||||||
#endif /* SHARPYUV_EXTERN */
|
|
||||||
|
|
||||||
#ifndef SHARPYUV_INLINE
|
|
||||||
#ifdef WEBP_INLINE
|
|
||||||
#define SHARPYUV_INLINE WEBP_INLINE
|
|
||||||
#else
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \
|
|
||||||
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
|
|
||||||
#define SHARPYUV_INLINE inline
|
|
||||||
#else
|
|
||||||
#define SHARPYUV_INLINE
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define SHARPYUV_INLINE __forceinline
|
|
||||||
#endif /* _MSC_VER */
|
|
||||||
#endif /* WEBP_INLINE */
|
|
||||||
#endif /* SHARPYUV_INLINE */
|
|
||||||
|
|
||||||
// SharpYUV API version following the convention from semver.org
|
|
||||||
#define SHARPYUV_VERSION_MAJOR 0
|
|
||||||
#define SHARPYUV_VERSION_MINOR 4
|
|
||||||
#define SHARPYUV_VERSION_PATCH 2
|
|
||||||
// Version as a uint32_t. The major number is the high 8 bits.
|
|
||||||
// The minor number is the middle 8 bits. The patch number is the low 16 bits.
|
|
||||||
#define SHARPYUV_MAKE_VERSION(MAJOR, MINOR, PATCH) \
|
|
||||||
(((MAJOR) << 24) | ((MINOR) << 16) | (PATCH))
|
|
||||||
#define SHARPYUV_VERSION \
|
|
||||||
SHARPYUV_MAKE_VERSION(SHARPYUV_VERSION_MAJOR, SHARPYUV_VERSION_MINOR, \
|
|
||||||
SHARPYUV_VERSION_PATCH)
|
|
||||||
|
|
||||||
// Returns the library's version number, packed in hexadecimal. See
|
|
||||||
// SHARPYUV_VERSION.
|
|
||||||
SHARPYUV_EXTERN int SharpYuvGetVersion(void);
|
|
||||||
|
|
||||||
// RGB to YUV conversion matrix, in 16 bit fixed point.
|
|
||||||
// y_ = rgb_to_y[0] * r + rgb_to_y[1] * g + rgb_to_y[2] * b + rgb_to_y[3]
|
|
||||||
// u_ = rgb_to_u[0] * r + rgb_to_u[1] * g + rgb_to_u[2] * b + rgb_to_u[3]
|
|
||||||
// v_ = rgb_to_v[0] * r + rgb_to_v[1] * g + rgb_to_v[2] * b + rgb_to_v[3]
|
|
||||||
// Then the values are divided by 1<<16 and rounded.
|
|
||||||
// y = (y_ + (1 << 15)) >> 16
|
|
||||||
// u = (u_ + (1 << 15)) >> 16
|
|
||||||
// v = (v_ + (1 << 15)) >> 16
|
|
||||||
//
|
|
||||||
// Typically, the offset values rgb_to_y[3], rgb_to_u[3] and rgb_to_v[3] depend
|
|
||||||
// on the input's bit depth, e.g., rgb_to_u[3] = 1 << (rgb_bit_depth - 1 + 16).
|
|
||||||
// See also sharpyuv_csp.h to get a predefined matrix or generate a matrix.
|
|
||||||
typedef struct {
|
|
||||||
int rgb_to_y[4];
|
|
||||||
int rgb_to_u[4];
|
|
||||||
int rgb_to_v[4];
|
|
||||||
} SharpYuvConversionMatrix;
|
|
||||||
|
|
||||||
typedef struct SharpYuvOptions SharpYuvOptions;
|
|
||||||
|
|
||||||
// Enums for transfer functions, as defined in H.273,
|
|
||||||
// https://www.itu.int/rec/T-REC-H.273-202107-I/en
|
|
||||||
typedef enum SharpYuvTransferFunctionType {
|
|
||||||
// 0 is reserved
|
|
||||||
kSharpYuvTransferFunctionBt709 = 1,
|
|
||||||
// 2 is unspecified
|
|
||||||
// 3 is reserved
|
|
||||||
kSharpYuvTransferFunctionBt470M = 4,
|
|
||||||
kSharpYuvTransferFunctionBt470Bg = 5,
|
|
||||||
kSharpYuvTransferFunctionBt601 = 6,
|
|
||||||
kSharpYuvTransferFunctionSmpte240 = 7,
|
|
||||||
kSharpYuvTransferFunctionLinear = 8,
|
|
||||||
kSharpYuvTransferFunctionLog100 = 9,
|
|
||||||
kSharpYuvTransferFunctionLog100_Sqrt10 = 10,
|
|
||||||
kSharpYuvTransferFunctionIec61966 = 11,
|
|
||||||
kSharpYuvTransferFunctionBt1361 = 12,
|
|
||||||
kSharpYuvTransferFunctionSrgb = 13,
|
|
||||||
kSharpYuvTransferFunctionBt2020_10Bit = 14,
|
|
||||||
kSharpYuvTransferFunctionBt2020_12Bit = 15,
|
|
||||||
kSharpYuvTransferFunctionSmpte2084 = 16, // PQ
|
|
||||||
kSharpYuvTransferFunctionSmpte428 = 17,
|
|
||||||
kSharpYuvTransferFunctionHlg = 18,
|
|
||||||
kSharpYuvTransferFunctionNum
|
|
||||||
} SharpYuvTransferFunctionType;
|
|
||||||
|
|
||||||
// Converts RGB to YUV420 using a downsampling algorithm that minimizes
|
|
||||||
// artefacts caused by chroma subsampling.
|
|
||||||
// This is slower than standard downsampling (averaging of 4 UV values).
|
|
||||||
// Assumes that the image will be upsampled using a bilinear filter. If nearest
|
|
||||||
// neighbor is used instead, the upsampled image might look worse than with
|
|
||||||
// standard downsampling.
|
|
||||||
// r_ptr, g_ptr, b_ptr: pointers to the source r, g and b channels. Should point
|
|
||||||
// to uint8_t buffers if rgb_bit_depth is 8, or uint16_t buffers otherwise.
|
|
||||||
// rgb_step: distance in bytes between two horizontally adjacent pixels on the
|
|
||||||
// r, g and b channels. If rgb_bit_depth is > 8, it should be a
|
|
||||||
// multiple of 2.
|
|
||||||
// rgb_stride: distance in bytes between two vertically adjacent pixels on the
|
|
||||||
// r, g, and b channels. If rgb_bit_depth is > 8, it should be a
|
|
||||||
// multiple of 2.
|
|
||||||
// rgb_bit_depth: number of bits for each r/g/b value. One of: 8, 10, 12, 16.
|
|
||||||
// Note: 16 bit input is truncated to 14 bits before conversion to yuv.
|
|
||||||
// yuv_bit_depth: number of bits for each y/u/v value. One of: 8, 10, 12.
|
|
||||||
// y_ptr, u_ptr, v_ptr: pointers to the destination y, u and v channels. Should
|
|
||||||
// point to uint8_t buffers if yuv_bit_depth is 8, or uint16_t buffers
|
|
||||||
// otherwise.
|
|
||||||
// y_stride, u_stride, v_stride: distance in bytes between two vertically
|
|
||||||
// adjacent pixels on the y, u and v channels. If yuv_bit_depth > 8, they
|
|
||||||
// should be multiples of 2.
|
|
||||||
// width, height: width and height of the image in pixels
|
|
||||||
// yuv_matrix: RGB to YUV conversion matrix. The matrix values typically
|
|
||||||
// depend on the input's rgb_bit_depth.
|
|
||||||
// This function calls SharpYuvConvertWithOptions with a default transfer
|
|
||||||
// function of kSharpYuvTransferFunctionSrgb.
|
|
||||||
SHARPYUV_EXTERN int SharpYuvConvert(const void* r_ptr, const void* g_ptr,
|
|
||||||
const void* b_ptr, int rgb_step,
|
|
||||||
int rgb_stride, int rgb_bit_depth,
|
|
||||||
void* y_ptr, int y_stride, void* u_ptr,
|
|
||||||
int u_stride, void* v_ptr, int v_stride,
|
|
||||||
int yuv_bit_depth, int width, int height,
|
|
||||||
const SharpYuvConversionMatrix* yuv_matrix);
|
|
||||||
|
|
||||||
struct SharpYuvOptions {
|
|
||||||
// This matrix cannot be NULL and can be initialized by
|
|
||||||
// SharpYuvComputeConversionMatrix.
|
|
||||||
const SharpYuvConversionMatrix* yuv_matrix;
|
|
||||||
SharpYuvTransferFunctionType transfer_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Internal, version-checked, entry point
|
|
||||||
SHARPYUV_EXTERN int SharpYuvOptionsInitInternal(const SharpYuvConversionMatrix*,
|
|
||||||
SharpYuvOptions*, int);
|
|
||||||
|
|
||||||
// Should always be called, to initialize a fresh SharpYuvOptions
|
|
||||||
// structure before modification. SharpYuvOptionsInit() must have succeeded
|
|
||||||
// before using the 'options' object.
|
|
||||||
static SHARPYUV_INLINE int SharpYuvOptionsInit(
|
|
||||||
const SharpYuvConversionMatrix* yuv_matrix, SharpYuvOptions* options) {
|
|
||||||
return SharpYuvOptionsInitInternal(yuv_matrix, options, SHARPYUV_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHARPYUV_EXTERN int SharpYuvConvertWithOptions(
|
|
||||||
const void* r_ptr, const void* g_ptr, const void* b_ptr, int rgb_step,
|
|
||||||
int rgb_stride, int rgb_bit_depth, void* y_ptr, int y_stride, void* u_ptr,
|
|
||||||
int u_stride, void* v_ptr, int v_stride, int yuv_bit_depth, int width,
|
|
||||||
int height, const SharpYuvOptions* options);
|
|
||||||
|
|
||||||
// TODO(b/194336375): Add YUV444 to YUV420 conversion. Maybe also add 422
|
|
||||||
// support (it's rarely used in practice, especially for images).
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} // extern "C"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // WEBP_SHARPYUV_SHARPYUV_H_
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by a BSD-style license
|
|
||||||
// that can be found in the COPYING file in the root of the source
|
|
||||||
// tree. An additional intellectual property rights grant can be found
|
|
||||||
// in the file PATENTS. All contributing project authors may
|
|
||||||
// be found in the AUTHORS file in the root of the source tree.
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
#include "sharpyuv/sharpyuv_cpu.h"
|
|
||||||
|
|
||||||
// Include src/dsp/cpu.c to create SharpYuvGetCPUInfo from VP8GetCPUInfo. The
|
|
||||||
// function pointer is renamed in sharpyuv_cpu.h.
|
|
||||||
#include "src/dsp/cpu.c"
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by a BSD-style license
|
|
||||||
// that can be found in the COPYING file in the root of the source
|
|
||||||
// tree. An additional intellectual property rights grant can be found
|
|
||||||
// in the file PATENTS. All contributing project authors may
|
|
||||||
// be found in the AUTHORS file in the root of the source tree.
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
#ifndef WEBP_SHARPYUV_SHARPYUV_CPU_H_
|
|
||||||
#define WEBP_SHARPYUV_SHARPYUV_CPU_H_
|
|
||||||
|
|
||||||
#include "sharpyuv/sharpyuv.h"
|
|
||||||
|
|
||||||
// Avoid exporting SharpYuvGetCPUInfo in shared object / DLL builds.
|
|
||||||
// SharpYuvInit() replaces the use of the function pointer.
|
|
||||||
#undef WEBP_EXTERN
|
|
||||||
#define WEBP_EXTERN extern
|
|
||||||
#define VP8GetCPUInfo SharpYuvGetCPUInfo
|
|
||||||
#include "src/dsp/cpu.h"
|
|
||||||
|
|
||||||
#endif // WEBP_SHARPYUV_SHARPYUV_CPU_H_
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by a BSD-style license
|
|
||||||
// that can be found in the COPYING file in the root of the source
|
|
||||||
// tree. An additional intellectual property rights grant can be found
|
|
||||||
// in the file PATENTS. All contributing project authors may
|
|
||||||
// be found in the AUTHORS file in the root of the source tree.
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Colorspace utilities.
|
|
||||||
|
|
||||||
#include "sharpyuv/sharpyuv_csp.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "sharpyuv/sharpyuv.h"
|
|
||||||
|
|
||||||
static int ToFixed16(float f) { return (int)floor(f * (1 << 16) + 0.5f); }
|
|
||||||
|
|
||||||
void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space,
|
|
||||||
SharpYuvConversionMatrix* matrix) {
|
|
||||||
const float kr = yuv_color_space->kr;
|
|
||||||
const float kb = yuv_color_space->kb;
|
|
||||||
const float kg = 1.0f - kr - kb;
|
|
||||||
const float cb = 0.5f / (1.0f - kb);
|
|
||||||
const float cr = 0.5f / (1.0f - kr);
|
|
||||||
|
|
||||||
const int shift = yuv_color_space->bit_depth - 8;
|
|
||||||
|
|
||||||
const float denom = (float)((1 << yuv_color_space->bit_depth) - 1);
|
|
||||||
float scale_y = 1.0f;
|
|
||||||
float add_y = 0.0f;
|
|
||||||
float scale_u = cb;
|
|
||||||
float scale_v = cr;
|
|
||||||
float add_uv = (float)(128 << shift);
|
|
||||||
assert(yuv_color_space->bit_depth >= 8);
|
|
||||||
|
|
||||||
if (yuv_color_space->range == kSharpYuvRangeLimited) {
|
|
||||||
scale_y *= (219 << shift) / denom;
|
|
||||||
scale_u *= (224 << shift) / denom;
|
|
||||||
scale_v *= (224 << shift) / denom;
|
|
||||||
add_y = (float)(16 << shift);
|
|
||||||
}
|
|
||||||
|
|
||||||
matrix->rgb_to_y[0] = ToFixed16(kr * scale_y);
|
|
||||||
matrix->rgb_to_y[1] = ToFixed16(kg * scale_y);
|
|
||||||
matrix->rgb_to_y[2] = ToFixed16(kb * scale_y);
|
|
||||||
matrix->rgb_to_y[3] = ToFixed16(add_y);
|
|
||||||
|
|
||||||
matrix->rgb_to_u[0] = ToFixed16(-kr * scale_u);
|
|
||||||
matrix->rgb_to_u[1] = ToFixed16(-kg * scale_u);
|
|
||||||
matrix->rgb_to_u[2] = ToFixed16((1 - kb) * scale_u);
|
|
||||||
matrix->rgb_to_u[3] = ToFixed16(add_uv);
|
|
||||||
|
|
||||||
matrix->rgb_to_v[0] = ToFixed16((1 - kr) * scale_v);
|
|
||||||
matrix->rgb_to_v[1] = ToFixed16(-kg * scale_v);
|
|
||||||
matrix->rgb_to_v[2] = ToFixed16(-kb * scale_v);
|
|
||||||
matrix->rgb_to_v[3] = ToFixed16(add_uv);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Matrices are in YUV_FIX fixed point precision.
|
|
||||||
// WebP's matrix, similar but not identical to kRec601LimitedMatrix
|
|
||||||
// Derived using the following formulas:
|
|
||||||
// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16
|
|
||||||
// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128
|
|
||||||
// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128
|
|
||||||
static const SharpYuvConversionMatrix kWebpMatrix = {
|
|
||||||
{16839, 33059, 6420, 16 << 16},
|
|
||||||
{-9719, -19081, 28800, 128 << 16},
|
|
||||||
{28800, -24116, -4684, 128 << 16},
|
|
||||||
};
|
|
||||||
// Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeLimited
|
|
||||||
static const SharpYuvConversionMatrix kRec601LimitedMatrix = {
|
|
||||||
{16829, 33039, 6416, 16 << 16},
|
|
||||||
{-9714, -19071, 28784, 128 << 16},
|
|
||||||
{28784, -24103, -4681, 128 << 16},
|
|
||||||
};
|
|
||||||
// Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeFull
|
|
||||||
static const SharpYuvConversionMatrix kRec601FullMatrix = {
|
|
||||||
{19595, 38470, 7471, 0},
|
|
||||||
{-11058, -21710, 32768, 128 << 16},
|
|
||||||
{32768, -27439, -5329, 128 << 16},
|
|
||||||
};
|
|
||||||
// Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeLimited
|
|
||||||
static const SharpYuvConversionMatrix kRec709LimitedMatrix = {
|
|
||||||
{11966, 40254, 4064, 16 << 16},
|
|
||||||
{-6596, -22189, 28784, 128 << 16},
|
|
||||||
{28784, -26145, -2639, 128 << 16},
|
|
||||||
};
|
|
||||||
// Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeFull
|
|
||||||
static const SharpYuvConversionMatrix kRec709FullMatrix = {
|
|
||||||
{13933, 46871, 4732, 0},
|
|
||||||
{-7509, -25259, 32768, 128 << 16},
|
|
||||||
{32768, -29763, -3005, 128 << 16},
|
|
||||||
};
|
|
||||||
|
|
||||||
const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix(
|
|
||||||
SharpYuvMatrixType matrix_type) {
|
|
||||||
switch (matrix_type) {
|
|
||||||
case kSharpYuvMatrixWebp:
|
|
||||||
return &kWebpMatrix;
|
|
||||||
case kSharpYuvMatrixRec601Limited:
|
|
||||||
return &kRec601LimitedMatrix;
|
|
||||||
case kSharpYuvMatrixRec601Full:
|
|
||||||
return &kRec601FullMatrix;
|
|
||||||
case kSharpYuvMatrixRec709Limited:
|
|
||||||
return &kRec709LimitedMatrix;
|
|
||||||
case kSharpYuvMatrixRec709Full:
|
|
||||||
return &kRec709FullMatrix;
|
|
||||||
case kSharpYuvMatrixNum:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// Use of this source code is governed by a BSD-style license
|
|
||||||
// that can be found in the COPYING file in the root of the source
|
|
||||||
// tree. An additional intellectual property rights grant can be found
|
|
||||||
// in the file PATENTS. All contributing project authors may
|
|
||||||
// be found in the AUTHORS file in the root of the source tree.
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Colorspace utilities.
|
|
||||||
|
|
||||||
#ifndef WEBP_SHARPYUV_SHARPYUV_CSP_H_
|
|
||||||
#define WEBP_SHARPYUV_SHARPYUV_CSP_H_
|
|
||||||
|
|
||||||
#include "sharpyuv/sharpyuv.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Range of YUV values.
|
|
||||||
typedef enum {
|
|
||||||
kSharpYuvRangeFull, // YUV values between [0;255] (for 8 bit)
|
|
||||||
kSharpYuvRangeLimited // Y in [16;235], YUV in [16;240] (for 8 bit)
|
|
||||||
} SharpYuvRange;
|
|
||||||
|
|
||||||
// Constants that define a YUV color space.
|
|
||||||
typedef struct {
|
|
||||||
// Kr and Kb are defined such that:
|
|
||||||
// Y = Kr * r + Kg * g + Kb * b where Kg = 1 - Kr - Kb.
|
|
||||||
float kr;
|
|
||||||
float kb;
|
|
||||||
int bit_depth; // 8, 10 or 12
|
|
||||||
SharpYuvRange range;
|
|
||||||
} SharpYuvColorSpace;
|
|
||||||
|
|
||||||
// Fills in 'matrix' for the given YUVColorSpace.
|
|
||||||
SHARPYUV_EXTERN void SharpYuvComputeConversionMatrix(
|
|
||||||
const SharpYuvColorSpace* yuv_color_space,
|
|
||||||
SharpYuvConversionMatrix* matrix);
|
|
||||||
|
|
||||||
// Enums for precomputed conversion matrices.
|
|
||||||
typedef enum {
|
|
||||||
// WebP's matrix, similar but not identical to kSharpYuvMatrixRec601Limited
|
|
||||||
kSharpYuvMatrixWebp = 0,
|
|
||||||
// Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeLimited
|
|
||||||
kSharpYuvMatrixRec601Limited,
|
|
||||||
// Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeFull
|
|
||||||
kSharpYuvMatrixRec601Full,
|
|
||||||
// Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeLimited
|
|
||||||
kSharpYuvMatrixRec709Limited,
|
|
||||||
// Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeFull
|
|
||||||
kSharpYuvMatrixRec709Full,
|
|
||||||
kSharpYuvMatrixNum
|
|
||||||
} SharpYuvMatrixType;
|
|
||||||
|
|
||||||
// Returns a pointer to a matrix for one of the predefined colorspaces.
|
|
||||||
SHARPYUV_EXTERN const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix(
|
|
||||||
SharpYuvMatrixType matrix_type);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} // extern "C"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // WEBP_SHARPYUV_SHARPYUV_CSP_H_
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user