diff options
author | James Zern <jzern@google.com> | 2015-03-17 18:54:21 -0700 |
---|---|---|
committer | James Zern <jzern@google.com> | 2015-03-25 11:17:23 -0700 |
commit | 9e80ee991168a0a6c2a906dd2c17c5e17df4566e (patch) | |
tree | 48b5b5c2dc881c16a703c09de1287f398e357ed3 | |
parent | d4402ea027d98455680d2494152812b477240260 (diff) | |
download | webp-marshmallow-dr-release.tar.gz |
external/webp: update to v0.4.3android-cts-6.0_r9android-cts-6.0_r8android-cts-6.0_r7android-cts-6.0_r6android-cts-6.0_r5android-cts-6.0_r4android-cts-6.0_r32android-cts-6.0_r31android-cts-6.0_r30android-cts-6.0_r3android-cts-6.0_r29android-cts-6.0_r28android-cts-6.0_r27android-cts-6.0_r26android-cts-6.0_r25android-cts-6.0_r24android-cts-6.0_r23android-cts-6.0_r22android-cts-6.0_r21android-cts-6.0_r20android-cts-6.0_r2android-cts-6.0_r19android-cts-6.0_r18android-cts-6.0_r17android-cts-6.0_r16android-cts-6.0_r15android-cts-6.0_r14android-cts-6.0_r13android-cts-6.0_r12android-cts-6.0_r1android-6.0.1_r9android-6.0.1_r81android-6.0.1_r80android-6.0.1_r8android-6.0.1_r79android-6.0.1_r78android-6.0.1_r77android-6.0.1_r74android-6.0.1_r73android-6.0.1_r72android-6.0.1_r70android-6.0.1_r7android-6.0.1_r69android-6.0.1_r68android-6.0.1_r67android-6.0.1_r66android-6.0.1_r65android-6.0.1_r63android-6.0.1_r62android-6.0.1_r61android-6.0.1_r60android-6.0.1_r59android-6.0.1_r58android-6.0.1_r57android-6.0.1_r56android-6.0.1_r55android-6.0.1_r54android-6.0.1_r53android-6.0.1_r52android-6.0.1_r51android-6.0.1_r50android-6.0.1_r5android-6.0.1_r49android-6.0.1_r48android-6.0.1_r47android-6.0.1_r46android-6.0.1_r45android-6.0.1_r43android-6.0.1_r42android-6.0.1_r41android-6.0.1_r40android-6.0.1_r4android-6.0.1_r33android-6.0.1_r32android-6.0.1_r31android-6.0.1_r30android-6.0.1_r3android-6.0.1_r28android-6.0.1_r27android-6.0.1_r26android-6.0.1_r25android-6.0.1_r24android-6.0.1_r22android-6.0.1_r21android-6.0.1_r20android-6.0.1_r18android-6.0.1_r17android-6.0.1_r16android-6.0.1_r13android-6.0.1_r12android-6.0.1_r11android-6.0.1_r10android-6.0.1_r1android-6.0.0_r7android-6.0.0_r6android-6.0.0_r5android-6.0.0_r41android-6.0.0_r4android-6.0.0_r3android-6.0.0_r26android-6.0.0_r25android-6.0.0_r24android-6.0.0_r23android-6.0.0_r2android-6.0.0_r13android-6.0.0_r12android-6.0.0_r11android-6.0.0_r1marshmallow-releasemarshmallow-mr3-releasemarshmallow-mr2-releasemarshmallow-mr1-releasemarshmallow-mr1-devmarshmallow-dr1.6-releasemarshmallow-dr1.5-releasemarshmallow-dr1.5-devmarshmallow-dr-releasemarshmallow-dr-dragon-releasemarshmallow-dr-devmarshmallow-devmarshmallow-cts-release
+ dropped some dated / unused files: INSTALL, examples/*
- 3/3/15: version 0.4.3
This is a binary compatible release.
* Android / gcc / iOS / MSVS build fixes and improvements
* lossless decode fix (issue #239 -- since 0.4.0)
* documentation / vwebp updates for animation
* multi-threading fix (issue #234)
Change-Id: I7777e5d35f5659488a98fd773bd2a645ac06215d
55 files changed, 1677 insertions, 935 deletions
diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 78ca2c2f..00000000 --- a/AUTHORS +++ /dev/null @@ -1,6 +0,0 @@ -Initial release: -- Pascal Massimino (pascal.massimino@gmail.com) - -Contributors: -- pierre.php@gmail.com (ansi-C port) -- vikaas.arora@gmail.com @@ -10,3 +10,4 @@ - 1/14: Release version 0.4.0-rc1 (change#I22be12d8) - 7/14: Release version 0.4.1-rc1 (change#I5346984d2) - 1/15: Release version 0.4.2 (change#I32a22786f) +- 3/17: Release version 0.4.3 (tag: v0.4.3) diff --git a/INSTALL b/INSTALL deleted file mode 100644 index d3c5b40a..00000000 --- a/INSTALL +++ /dev/null @@ -1,237 +0,0 @@ -Installation Instructions -************************* - -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. - -This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. - -Basic Installation -================== - -Briefly, the shell commands `./configure; make; make install' should -configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for -instructions specific to this package. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. - - Running `configure' might take a while. While running, it prints - some messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - - 6. Often, you can also type `make uninstall' to remove the installed - files again. - -Compilers and Options -===================== - -Some systems require unusual options for compilation or linking that the -`configure' script does not know about. Run `./configure --help' for -details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - -You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - With a non-GNU `make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before -reconfiguring for another architecture. - -Installation Names -================== - -By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - -Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - -There may be some features `configure' cannot figure out automatically, -but needs to determine by the type of machine the package will run on. -Usually, assuming the package is built to be run on the _same_ -architectures, `configure' can figure that out, but if it prints a -message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - -If you want to set default values for `configure' scripts to share, you -can create a site shell script called `config.site' that gives default -values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - -Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). - -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf bug. Until the bug is fixed you can use this workaround: - - CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash - -`configure' Invocation -====================== - -`configure' recognizes the following options to control how it operates. - -`--help' -`-h' - Print a summary of the options to `configure', and exit. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - @@ -1,9 +0,0 @@ -- 9/10: initial release version 0.1 -- 8/12: release version 0.2.0-rc1 (head change#Ia5475247). -- 3/13: Updated WebP with head change#I9e5ae737 -- 8/13: release version 0.3.1 (head change#Idea3464b). -- 8/13: Updated WebP with patches required for Animation - (#I737451d7f, #Ia300385a & #I9566a8e2). -- 1/14: release version 0.4.0-rc1 (change#I22be12d8). -- 7/14: release version 0.4.1-rc1 (change#I5346984d2). -- 1/15: release version 0.4.2 (change#I32a22786f). @@ -1,22 +1,23 @@ Additional IP Rights Grant (Patents) +------------------------------------ -"This implementation" means the copyrightable works distributed by -Google as part of the WebM Project. +"These implementations" means the copyrightable works that implement the WebM +codecs distributed by Google as part of the WebM Project. -Google hereby grants to you a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer, and otherwise run, modify and propagate the contents of this -implementation of VP8, where such license applies only to those patent -claims, both currently owned by Google and acquired in the future, -licensable by Google that are necessarily infringed by this -implementation of VP8. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of VP8 or any code incorporated within this -implementation of VP8 constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of VP8 -shall terminate as of the date such litigation is filed. +Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge, +royalty-free, irrevocable (except as stated in this section) patent license to +make, have made, use, offer to sell, sell, import, transfer, and otherwise +run, modify and propagate the contents of these implementations of WebM, where +such license applies only to those patent claims, both currently owned by +Google and acquired in the future, licensable by Google that are necessarily +infringed by these implementations of WebM. This grant does not include claims +that would be infringed only as a consequence of further modification of these +implementations. If you or your agent or exclusive licensee institute or order +or agree to the institution of patent litigation or any other patent +enforcement activity against any entity (including a cross-claim or +counterclaim in a lawsuit) alleging that any of these implementations of WebM +or any code incorporated within any of these implementations of WebM +constitutes direct or contributory patent infringement, or inducement of +patent infringement, then any patent rights granted to you under this License +for these implementations of WebM shall terminate as of the date such +litigation is filed. @@ -4,7 +4,7 @@ \__\__/\____/\_____/__/ ____ ___ / _/ / \ \ / _ \/ _/ / \_/ / / \ \ __/ \__ - \____/____/\_____/_____/____/v0.4.2 + \____/____/\_____/_____/____/v0.4.3 Description: ============ diff --git a/README.android b/README.android index 81e7ac7d..63ef2bc2 100644 --- a/README.android +++ b/README.android @@ -1,56 +1,21 @@ -URL: http://review.webmproject.org/gitweb?p=libwebp.git -Version: 43/1443/1 +URL: https://gerrit.chromium.org/gerrit/gitweb?p=webm%2Flibwebp.git +Version: v0.4.3 License: Google BSD like Local modifications: - Rewrite Android.mk to remove duplicate definitions and set module name in a consistent way with other external libraries -- Move public headers from src/webp to include/webp, so path to headers +- Copy public headers from src/webp to include/webp, so path to headers may be appended into CFLAGS without risk for other private headers (e.g. bits.h) to leak into -- Sync-patch with libwebp ver 0.1.2 -- Removed Build files necessary for building via autoconf/automake tools +- Removed build files necessary for building via autoconf/automake tools These files are not required to build via Android.mk - - Makefile.am Makefile.vc Makefile.in - - config.h.in configure config.guess config.sub configure.ac - - autogen.sh install-sh missing depcomp ltmain.sh aclocal.m4 -- Added WebP Encoder (ver 0.1.2) as well - - Removed some more unused Makefile.am & Makefile.in - - Added Android.mk to encoder & decoder code levels. -- Synced the WebP Code (Encoder/Decoder) with the head change#Ia53f845b - - Added three color-spaces viz ARGB_8888, RGBA_4444, RGB_565 - supported by Android. -- Fixed the Endian'ness bug for Color-Configs (RGB_565 & ARGB_4444). - The fix is similar to jpeglib handling for JCS_RGB_565 & JCS_RGBA_8888 - color configs. Added the code under "ANDROID_WEBP_RGB" flag. -- Sync-patch with libwebp ver 0.2.0-rc1 (head change#Ia5475247). -- Updated WebP with head change#I3da2063b -- Updated WebP with head change#I9e5ae737 - - 16bit swapping of RGB565 / RGB4444 colorspace. Added compile-time flag - WEBP_SWAP_16BIT_CSP to support byte-swap (required for skia data type for - 16bit values) output for these colorspaces. - - Added ARM/NEON code for decoder/encoder modules. - - Speedup in WebP compression (method 3 and above). - - Added multi-threaded alpha encoding for lossy compression. - - Updated WebP with head change#I9e5ae737 -- Sync-patch with libwebp ver 0.3.1 (head change#Idea3464b). - - Add incremental decoding support for images containing ALPH and ICCP chunks. -- Updated WebP with patches required for Animation - (#I737451d7f, #Ia300385a & #I9566a8e2). -- Fix memleak in WebPIDelete() (change#Id4faef1b). -- Sync-patch with libwebp ver 0.4.0-rc1 (change#I22be12d8). -- Bugfix for incremental decode of lossy-alpha (change#I716ce082) -- Sync-patch with libwebp ver 0.4.1-rc1 (change#I5346984d2). - - NEON assembly optimizations: - - ~25% faster lossy decode / encode (-m 4) - - ~10% faster lossless decode - - ~5-10% faster lossless encode (-m 3/4) - - Arch64 (arm64) & MIPS support/optimizations. -- Sync-patch with libwebp ver 0.4.2 (change#I32a22786f). - - Cherry-picked Alpha-decoding bug. +- Added a local copy of cpu-features.[hc] to src/dsp +- Removed WEBP_ANDROID_NEON check in dsp.h to avoid breaking non-NEON builds + where the flags in Android.mk are not set correctly currently. -The Android.mk file creates WebP Decoder and Encoder static libraries which -can be added to any application by Adding to LOCAL_STATIC_LIBRARIES +The Android.mk file creates WebP decoder and encoder static libraries which +can be added to any application by adding to LOCAL_STATIC_LIBRARIES libwebp-decode libwebp-encode: LOCAL_STATIC_LIBRARIES += libwebp-decode libwebp-encode diff --git a/examples/dwebp.c b/examples/dwebp.c deleted file mode 100644 index c84b0d1d..00000000 --- a/examples/dwebp.c +++ /dev/null @@ -1,527 +0,0 @@ -// Copyright 2010 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. -// ----------------------------------------------------------------------------- -// -// Command-line tool for decoding a WebP image. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef WEBP_HAVE_PNG -#include <png.h> -#endif - -#ifdef HAVE_WINCODEC_H -#ifdef __MINGW32__ -#define INITGUID // Without this GUIDs are declared extern and fail to link -#endif -#define CINTERFACE -#define COBJMACROS -#define _WIN32_IE 0x500 // Workaround bug in shlwapi.h when compiling C++ - // code with COBJMACROS. -#include <shlwapi.h> -#include <windows.h> -#include <wincodec.h> -#endif - -#include "webp/decode.h" -#include "./example_util.h" -#include "./stopwatch.h" - -static int verbose = 0; -#ifndef WEBP_DLL -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -extern void* VP8GetCPUInfo; // opaque forward declaration. - -#if defined(__cplusplus) || defined(c_plusplus) -} // extern "C" -#endif -#endif // WEBP_DLL - -//------------------------------------------------------------------------------ - -// Output types -typedef enum { - PNG = 0, - PAM, - PPM, - PGM, - YUV, - ALPHA_PLANE_ONLY // this is for experimenting only -} OutputFileFormat; - -#ifdef HAVE_WINCODEC_H - -#define IFS(fn) \ - do { \ - if (SUCCEEDED(hr)) { \ - hr = (fn); \ - if (FAILED(hr)) fprintf(stderr, #fn " failed %08lx\n", hr); \ - } \ - } while (0) - -#ifdef __cplusplus -#define MAKE_REFGUID(x) (x) -#else -#define MAKE_REFGUID(x) &(x) -#endif - -static HRESULT CreateOutputStream(const char* out_file_name, IStream** stream) { - HRESULT hr = S_OK; - IFS(SHCreateStreamOnFileA(out_file_name, STGM_WRITE | STGM_CREATE, stream)); - if (FAILED(hr)) { - fprintf(stderr, "Error opening output file %s (%08lx)\n", - out_file_name, hr); - } - return hr; -} - -static HRESULT WriteUsingWIC(const char* out_file_name, REFGUID container_guid, - unsigned char* rgb, int stride, - uint32_t width, uint32_t height, int has_alpha) { - HRESULT hr = S_OK; - IWICImagingFactory* factory = NULL; - IWICBitmapFrameEncode* frame = NULL; - IWICBitmapEncoder* encoder = NULL; - IStream* stream = NULL; - WICPixelFormatGUID pixel_format = has_alpha ? GUID_WICPixelFormat32bppBGRA - : GUID_WICPixelFormat24bppBGR; - - IFS(CoInitialize(NULL)); - IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL, - CLSCTX_INPROC_SERVER, - MAKE_REFGUID(IID_IWICImagingFactory), - (LPVOID*)&factory)); - if (hr == REGDB_E_CLASSNOTREG) { - fprintf(stderr, - "Couldn't access Windows Imaging Component (are you running " - "Windows XP SP3 or newer?). PNG support not available. " - "Use -ppm or -pgm for available PPM and PGM formats.\n"); - } - IFS(CreateOutputStream(out_file_name, &stream)); - IFS(IWICImagingFactory_CreateEncoder(factory, container_guid, NULL, - &encoder)); - IFS(IWICBitmapEncoder_Initialize(encoder, stream, - WICBitmapEncoderNoCache)); - IFS(IWICBitmapEncoder_CreateNewFrame(encoder, &frame, NULL)); - IFS(IWICBitmapFrameEncode_Initialize(frame, NULL)); - IFS(IWICBitmapFrameEncode_SetSize(frame, width, height)); - IFS(IWICBitmapFrameEncode_SetPixelFormat(frame, &pixel_format)); - IFS(IWICBitmapFrameEncode_WritePixels(frame, height, stride, - height * stride, rgb)); - IFS(IWICBitmapFrameEncode_Commit(frame)); - IFS(IWICBitmapEncoder_Commit(encoder)); - - if (frame != NULL) IUnknown_Release(frame); - if (encoder != NULL) IUnknown_Release(encoder); - if (factory != NULL) IUnknown_Release(factory); - if (stream != NULL) IUnknown_Release(stream); - return hr; -} - -static int WritePNG(const char* out_file_name, - const WebPDecBuffer* const buffer) { - const uint32_t width = buffer->width; - const uint32_t height = buffer->height; - unsigned char* const rgb = buffer->u.RGBA.rgba; - const int stride = buffer->u.RGBA.stride; - const int has_alpha = (buffer->colorspace == MODE_BGRA); - - return SUCCEEDED(WriteUsingWIC(out_file_name, - MAKE_REFGUID(GUID_ContainerFormatPng), - rgb, stride, width, height, has_alpha)); -} - -#elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H -static void PNGAPI error_function(png_structp png, png_const_charp dummy) { - (void)dummy; // remove variable-unused warning - longjmp(png_jmpbuf(png), 1); -} - -static int WritePNG(FILE* out_file, const WebPDecBuffer* const buffer) { - const uint32_t width = buffer->width; - const uint32_t height = buffer->height; - unsigned char* const rgb = buffer->u.RGBA.rgba; - const int stride = buffer->u.RGBA.stride; - const int has_alpha = (buffer->colorspace == MODE_RGBA); - png_structp png; - png_infop info; - png_uint_32 y; - - png = png_create_write_struct(PNG_LIBPNG_VER_STRING, - NULL, error_function, NULL); - if (png == NULL) { - return 0; - } - info = png_create_info_struct(png); - if (info == NULL) { - png_destroy_write_struct(&png, NULL); - return 0; - } - if (setjmp(png_jmpbuf(png))) { - png_destroy_write_struct(&png, &info); - return 0; - } - png_init_io(png, out_file); - png_set_IHDR(png, info, width, height, 8, - has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - png_write_info(png, info); - for (y = 0; y < height; ++y) { - png_bytep row = rgb + y * stride; - png_write_rows(png, &row, 1); - } - png_write_end(png, info); - png_destroy_write_struct(&png, &info); - return 1; -} -#else // !HAVE_WINCODEC_H && !WEBP_HAVE_PNG -static int WritePNG(FILE* out_file, const WebPDecBuffer* const buffer) { - (void)out_file; - (void)buffer; - fprintf(stderr, "PNG support not compiled. Please install the libpng " - "development package before building.\n"); - fprintf(stderr, "You can run with -ppm flag to decode in PPM format.\n"); - return 0; -} -#endif - -static int WritePPM(FILE* fout, const WebPDecBuffer* const buffer, int alpha) { - const uint32_t width = buffer->width; - const uint32_t height = buffer->height; - const unsigned char* const rgb = buffer->u.RGBA.rgba; - const int stride = buffer->u.RGBA.stride; - const size_t bytes_per_px = alpha ? 4 : 3; - uint32_t y; - - if (alpha) { - fprintf(fout, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\n" - "TUPLTYPE RGB_ALPHA\nENDHDR\n", width, height); - } else { - fprintf(fout, "P6\n%d %d\n255\n", width, height); - } - for (y = 0; y < height; ++y) { - if (fwrite(rgb + y * stride, width, bytes_per_px, fout) != bytes_per_px) { - return 0; - } - } - return 1; -} - -static int WriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) { - const uint32_t width = buffer->width; - const uint32_t height = buffer->height; - const unsigned char* const a = buffer->u.YUVA.a; - const int a_stride = buffer->u.YUVA.a_stride; - uint32_t y; - assert(a != NULL); - fprintf(fout, "P5\n%d %d\n255\n", width, height); - for (y = 0; y < height; ++y) { - if (fwrite(a + y * a_stride, width, 1, fout) != 1) { - return 0; - } - } - return 1; -} - -// format=PGM: save a grayscale PGM file using the IMC4 layout -// (http://www.fourcc.org/yuv.php#IMC4). This is a very convenient format for -// viewing the samples, esp. for odd dimensions. -// format=YUV: just save the Y/U/V/A planes sequentially without header. -static int WritePGMOrYUV(FILE* fout, const WebPDecBuffer* const buffer, - OutputFileFormat format) { - const int width = buffer->width; - const int height = buffer->height; - const WebPYUVABuffer* const yuv = &buffer->u.YUVA; - int ok = 1; - int y; - const int pad = (format == YUV) ? 0 : 1; - const int uv_width = (width + 1) / 2; - const int uv_height = (height + 1) / 2; - const int out_stride = (width + pad) & ~pad; - const int a_height = yuv->a ? height : 0; - if (format == PGM) { - fprintf(fout, "P5\n%d %d\n255\n", - out_stride, height + uv_height + a_height); - } - for (y = 0; ok && y < height; ++y) { - ok &= (fwrite(yuv->y + y * yuv->y_stride, width, 1, fout) == 1); - if (format == PGM) { - if (width & 1) fputc(0, fout); // padding byte - } - } - if (format == PGM) { // IMC4 layout - for (y = 0; ok && y < uv_height; ++y) { - ok &= (fwrite(yuv->u + y * yuv->u_stride, uv_width, 1, fout) == 1); - ok &= (fwrite(yuv->v + y * yuv->v_stride, uv_width, 1, fout) == 1); - } - } else { - for (y = 0; ok && y < uv_height; ++y) { - ok &= (fwrite(yuv->u + y * yuv->u_stride, uv_width, 1, fout) == 1); - } - for (y = 0; ok && y < uv_height; ++y) { - ok &= (fwrite(yuv->v + y * yuv->v_stride, uv_width, 1, fout) == 1); - } - } - for (y = 0; ok && y < a_height; ++y) { - ok &= (fwrite(yuv->a + y * yuv->a_stride, width, 1, fout) == 1); - if (format == PGM) { - if (width & 1) fputc(0, fout); // padding byte - } - } - return ok; -} - -static void SaveOutput(const WebPDecBuffer* const buffer, - OutputFileFormat format, const char* const out_file) { - FILE* fout = NULL; - int needs_open_file = 1; - int ok = 1; - Stopwatch stop_watch; - - if (verbose) - StopwatchReadAndReset(&stop_watch); - -#ifdef HAVE_WINCODEC_H - needs_open_file = (format != PNG); -#endif - if (needs_open_file) { - fout = fopen(out_file, "wb"); - if (!fout) { - fprintf(stderr, "Error opening output file %s\n", out_file); - return; - } - } - - if (format == PNG) { -#ifdef HAVE_WINCODEC_H - ok &= WritePNG(out_file, buffer); -#else - ok &= WritePNG(fout, buffer); -#endif - } else if (format == PAM) { - ok &= WritePPM(fout, buffer, 1); - } else if (format == PPM) { - ok &= WritePPM(fout, buffer, 0); - } else if (format == PGM || format == YUV) { - ok &= WritePGMOrYUV(fout, buffer, format); - } else if (format == ALPHA_PLANE_ONLY) { - ok &= WriteAlphaPlane(fout, buffer); - } - if (fout) { - fclose(fout); - } - if (ok) { - printf("Saved file %s\n", out_file); - if (verbose) { - const double write_time = StopwatchReadAndReset(&stop_watch); - printf("Time to write output: %.3fs\n", write_time); - } - } else { - fprintf(stderr, "Error writing file %s !!\n", out_file); - } -} - -static void Help(void) { - printf("Usage: dwebp in_file [options] [-o out_file]\n\n" - "Decodes the WebP image file to PNG format [Default]\n" - "Use following options to convert into alternate image formats:\n" - " -pam ......... save the raw RGBA samples as a color PAM\n" - " -ppm ......... save the raw RGB samples as a color PPM\n" - " -pgm ......... save the raw YUV samples as a grayscale PGM\n" - " file with IMC4 layout.\n" - " -yuv ......... save the raw YUV samples in flat layout.\n" - "\n" - " Other options are:\n" - " -version .... print version number and exit.\n" - " -nofancy ..... don't use the fancy YUV420 upscaler.\n" - " -nofilter .... disable in-loop filtering.\n" - " -mt .......... use multi-threading\n" - " -crop <x> <y> <w> <h> ... crop output with the given rectangle\n" - " -scale <w> <h> .......... scale the output (*after* any cropping)\n" - " -alpha ....... only save the alpha plane.\n" - " -h ....... this help message.\n" - " -v ....... verbose (e.g. print encoding/decoding times)\n" -#ifndef WEBP_DLL - " -noasm ....... disable all assembly optimizations.\n" -#endif - ); -} - -static const char* const kStatusMessages[] = { - "OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR", - "UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA" -}; - -int main(int argc, const char *argv[]) { - const char *in_file = NULL; - const char *out_file = NULL; - - WebPDecoderConfig config; - WebPDecBuffer* const output_buffer = &config.output; - WebPBitstreamFeatures* const bitstream = &config.input; - OutputFileFormat format = PNG; - int c; - - if (!WebPInitDecoderConfig(&config)) { - fprintf(stderr, "Library version mismatch!\n"); - return -1; - } - - for (c = 1; c < argc; ++c) { - if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { - Help(); - return 0; - } else if (!strcmp(argv[c], "-o") && c < argc - 1) { - out_file = argv[++c]; - } else if (!strcmp(argv[c], "-alpha")) { - format = ALPHA_PLANE_ONLY; - } else if (!strcmp(argv[c], "-nofancy")) { - config.options.no_fancy_upsampling = 1; - } else if (!strcmp(argv[c], "-nofilter")) { - config.options.bypass_filtering = 1; - } else if (!strcmp(argv[c], "-pam")) { - format = PAM; - } else if (!strcmp(argv[c], "-ppm")) { - format = PPM; - } else if (!strcmp(argv[c], "-version")) { - const int version = WebPGetDecoderVersion(); - printf("%d.%d.%d\n", - (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); - return 0; - } else if (!strcmp(argv[c], "-pgm")) { - format = PGM; - } else if (!strcmp(argv[c], "-yuv")) { - format = YUV; - } else if (!strcmp(argv[c], "-mt")) { - config.options.use_threads = 1; - } else if (!strcmp(argv[c], "-crop") && c < argc - 4) { - config.options.use_cropping = 1; - config.options.crop_left = strtol(argv[++c], NULL, 0); - config.options.crop_top = strtol(argv[++c], NULL, 0); - config.options.crop_width = strtol(argv[++c], NULL, 0); - config.options.crop_height = strtol(argv[++c], NULL, 0); - } else if (!strcmp(argv[c], "-scale") && c < argc - 2) { - config.options.use_scaling = 1; - config.options.scaled_width = strtol(argv[++c], NULL, 0); - config.options.scaled_height = strtol(argv[++c], NULL, 0); - } else if (!strcmp(argv[c], "-v")) { - verbose = 1; -#ifndef WEBP_DLL - } else if (!strcmp(argv[c], "-noasm")) { - VP8GetCPUInfo = NULL; -#endif - } else if (argv[c][0] == '-') { - fprintf(stderr, "Unknown option '%s'\n", argv[c]); - Help(); - return -1; - } else { - in_file = argv[c]; - } - } - - if (in_file == NULL) { - fprintf(stderr, "missing input file!!\n"); - Help(); - return -1; - } - - { - Stopwatch stop_watch; - VP8StatusCode status = VP8_STATUS_OK; - int ok; - size_t data_size = 0; - const uint8_t* data = NULL; - - if (!ExUtilReadFile(in_file, &data, &data_size)) return -1; - - if (verbose) - StopwatchReadAndReset(&stop_watch); - - status = WebPGetFeatures(data, data_size, bitstream); - if (status != VP8_STATUS_OK) { - goto end; - } - - if (bitstream->has_animation) { - fprintf(stderr, - "Error! Decoding of an animated WebP file is not supported.\n" - " Use webpmux to extract the individual frames or\n" - " vwebp to view this image.\n"); - } - - switch (format) { - case PNG: -#ifdef HAVE_WINCODEC_H - output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR; -#else - output_buffer->colorspace = bitstream->has_alpha ? MODE_RGBA : MODE_RGB; -#endif - break; - case PAM: - output_buffer->colorspace = MODE_RGBA; - break; - case PPM: - output_buffer->colorspace = MODE_RGB; // drops alpha for PPM - break; - case PGM: - case YUV: - output_buffer->colorspace = bitstream->has_alpha ? MODE_YUVA : MODE_YUV; - break; - case ALPHA_PLANE_ONLY: - output_buffer->colorspace = MODE_YUVA; - break; - default: - free((void*)data); - return -1; - } - status = WebPDecode(data, data_size, &config); - - if (verbose) { - const double decode_time = StopwatchReadAndReset(&stop_watch); - printf("Time to decode picture: %.3fs\n", decode_time); - } - end: - free((void*)data); - ok = (status == VP8_STATUS_OK); - if (!ok) { - fprintf(stderr, "Decoding of %s failed.\n", in_file); - fprintf(stderr, "Status: %d (%s)\n", status, kStatusMessages[status]); - return -1; - } - } - - if (out_file) { - printf("Decoded %s. Dimensions: %d x %d%s. Now saving...\n", in_file, - output_buffer->width, output_buffer->height, - bitstream->has_alpha ? " (with alpha)" : ""); - SaveOutput(output_buffer, format, out_file); - } else { - printf("File %s can be decoded (dimensions: %d x %d)%s.\n", - in_file, output_buffer->width, output_buffer->height, - bitstream->has_alpha ? " (with alpha)" : ""); - printf("Nothing written; use -o flag to save the result as e.g. PNG.\n"); - } - WebPFreeDecBuffer(output_buffer); - - return 0; -} - -//------------------------------------------------------------------------------ diff --git a/examples/test.webp b/examples/test.webp Binary files differdeleted file mode 100644 index 3e4bca1d..00000000 --- a/examples/test.webp +++ /dev/null diff --git a/examples/test_ref.ppm b/examples/test_ref.ppm deleted file mode 100644 index 97719f01..00000000 --- a/examples/test_ref.ppm +++ /dev/null @@ -1,4 +0,0 @@ -P6 -128 128 -255 -ËáûËáûËáûËáûËáûËáûËáûËáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÐãýÐãýÐãýÐãýÒäþÒäþÒäþÒäþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒäþÒäþÒäþÒäþÓåÿÓåÿÓåÿÓåÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûËáûËáûËáûËáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÏäýÐãýÐãýÐãýÒäþÒäþÒäþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒäþÒäþÒäþÒäþÓåÿÓåÿÓåÿÓåÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûËáûËáûËáûËáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÏäûÏäûÏäûÏäûÐåýÐåýÐåýÐåýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒäþÒäþÒäþÒäþÓåÿÓåÿÓåÿÓåÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûËáûËáûËáûËáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÎåûÎåûÎåûÎåûÏæýÏæýÏæýÏæýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒäþÒäþÒäþÒäþÓåÿÓåÿÓåÿÓåÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûÌâýÌâýÌâýÌâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÎåûÎåùÎåùÎåùÏæúÏæúÏæúÏæýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÓåÿÓåÿÓåÿÓåÿÔæÿÔæÿÔæÿÔæÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÒèùÒèùÒèùÒèùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûÌâýÌâýÌâýÌâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåýÒèûÒèûÒèûÒèûÐæúÐæúÐæúÐæúÐåýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÓåÿÓåÿÓåÿÓåÿÔæÿÔæÿÔæÿÔæÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÒèùÒèùÒèùÒèùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûÌâýÌâýÌâýÌâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåýÐæúÒåøÒåøÒåøÒåøÒåøÒåøÐæúÐåýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÓåÿÓåÿÓåÿÓåÿÔæÿÔæÿÔæÿÔæÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÒèùÒèùÒèùÒèùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûÌâýÌâýÌâýÌâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäÿÐãÿÐãÿÐãÿÏäýÏäýÏäýÐãýÒäþÒåýÒåýÒåýÏáóÏáóÏáóÏáñÔåöÔåöÔåöÔåøÒåúÒåýÒåýÐåýÐåýÐåýÐåýÐåþÓåÿÓåÿÓåÿÓåÿÔæÿÔæÿÔæÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÒèùÒèùÒèùÒèùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒæÿÐåþÒäþÐãýÎáúÒâûÐáúÕåÿÎáýÔæÿÔæÿÓãýÏßøÉÚð·Æ܇–ª‰—©›±»ÎŸª»©³ÅÌÖèÖáòÓáñÖèøÔåö×éûÒåøÒåúÖêÿÐæúÒæþÓæþÓæþÓæþÓæþÔèÿÔèÿÔèÿÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÕëÿÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëý×ëþ×ëþ×ëþ×ëþÖêýÖêýÖêýÖêýÕéûÕéûÕéûÕéûÔèúÔèúÔèúÔèúÓæùÓæùÓæùÓæùÒåøÒåøÒåøÒåøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒäþÒäþÓãý×èÿÕãþÒßúÕäÿÌÛøÈÙò«Åm{•dqˆhtŒlvŒs{…‹y‘‡Ÿ‘—¨¤ªº°¶Æ½ÆÕÎÜêÓäóÕæ÷ÔåöÖèúÓæùÐäùÔêþÓæûÓæûÓæûÓæûÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëý×ëþ×ëþ×ëþ×ëþÖêýÖêýÖêýÖêýÕéûÕéûÕéûÕéûÔèúÔèúÔèúÔèúÓæùÓæùÓæùÓæùÒåøÒåøÒåøÒåøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÌáùÎãûÓåÿÕèÿÒâûÓãýÔâýÙæÿÓáû©·Òlz•\j„mz”hqŒmw‚‹¡†‰ž¥‚–‡‹ž‚”°³Å¸½Ë•›©¿ËÙÓãòÖæö×æøÔåöÖèúÕéûÐä÷ÓæûÓæûÓæûÓæûÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëý×ëþ×ëþ×ëþ×ëþÖêýÖêýÖêýÖêýÕéûÕéûÕéûÕéûÔèúÔèúÔèúÔèúÓæùÓæùÓæùÓæùÒåøÒåøÒåøÒåøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÓèÿÒæÿÐãýÏâûÓãýÕåÿ±¿Úªr€›Wd~\i‚~‹¤˜¢½jq‡Žªz˜„…›œ²‚„š…†›‚…–—š©²´Á¯³¿–Ÿ¬±½ËÆÔäÔâòÙèùÔãôÖèúÕæùÓæûÓæûÓæûÓæûÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëý×ëþ×ëþ×ëþ×ëþÖêýÖêýÖêýÖêýÕéûÕéûÕéûÕéûÔèúÔèúÔèúÔèúÓæùÓæùÓæùÓæùÒåøÒåøÒåøÒåøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÓèÿÉÞ÷ÚìÿÔæÿÈÙòy‰£M[vXfVc}[deo‰ipŒ‡Žªfj‡Œ¬xz—}}˜~{•qo†‘¥—–©‰ˆ˜——¤ž¡ÆÌÚ½ÆÕ˜¢±¯¹ËÖáò×å÷Úèù×æúÖæýÔèýÔèýÔèýÔèýÔèýÔèýÔèýÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþ×íÿ×íÿ×íÿ×íÿ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþÖêýÕéûÔèúÕéûÕéûÕéûÕéûÓæùÓæùÓæùÓæùÓæùÓæùÓæùÓæùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒæÿÒäþÅ×ñfwM]wLZtMZsOXq_f€jq~žrv“rs“ˆ‰©……¤ss‘vs}–ž²›š¬€€šš¥¤¨²·»Ç‹ž‘—¨ˆ‘¡¶ÈÓÝïÚä÷ÛéúÖèúÔèýÔèýÔèýÔèýÔèýÔèýÔèýÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþ×íÿ×íÿ×íÿ×íÿ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþÖêýÕéûÔèúÕéûÕéûÕéûÕéûÓæùÓæùÓæùÓæùÓæùÓæùÓæùÓæùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒæÿÏäý½ÏéXk…IZsL\vP^yN[tbi‚sx‘Ž“¬€‚Ÿ~€‚‚¢©¨Ë¡}}›qq~—œ²œž‚…‘±´¿¤¨²„¨¬º{€Ž‰Ÿ˜ž¯³»Î×ßò×å÷ÖèúÔèýÔèýÔèýÔèýÔèýÔèýÔèýÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþ×íÿ×íÿ×íÿ×íÿ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþÖêýÕéûÔèúÕéûÕéûÕéûÕéûÓæùÓæùÓæùÓæùÓæùÓæùÓæùÓæùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåýÐåýÐåþÐåþÍßù[m‡GWqLZtIWrFQmox“›Ÿ´¡¤¸‘•ªyzss¤¤Â½¹Ù²°Ì‰‹£lm„z{vx‰œž««¯¹ÌÏÚ“›Œš›ž©˜›¨„‘•£ª°ÀÔÚê×âó×æúÔèýÔèýÔèýÔèýÔèýÔèýÔèýÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþ×íÿ×íÿ×íÿ×íÿ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþÖêýÕéûÔèúÕéûÕéûÕéûÕéûÓæùÓæùÓæùÓæùÓæùÓæùÓæùÓæùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÏåÿÏåÿÏæþÏæþÎãúÏåùÖêÿÒåýºÍæk~šJXvLWvLTqFNkQXtlqˆÆÈÚ£¥²áäï··Ä…„–£¢·ÎÍâÝÜïìëû¸¸Å£¢²yy†——£²²»ººÆˆˆ‘•–œž¤·•˜£‚…‘¡¥±¬±¿ÕÞíÖå÷×éûÔèúÓæùÔêþÔêþÔéÿÕéþÖêÿÙêýÙêýÙêýÙêýÙêýÙêýÙêýÖêýÖêýÖêýÖêý×ëþ×ëþ×ëþ×ëþ×íÿ×íý×íý×íý×íý×íý×íý×íý×íý×íý×íý×íý×íý×íý×íý×íýÙíýÙíýÙíýÙíý×ìû×ìû×ìû×ìû×íýÖìûÕëúÔêùÔêùÔêùÔêùÔêùÓéøÓéøÓéøÓéøÒè÷Òè÷Òè÷Òè÷ÐæöÐæöÐæöÐæöÐæöÐæöÐæöÐæöÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÏåÿÏåÿÏæþÐåýÕêÿÐäùÏãø¬ÀÕVi‚IXvN\yHPpLSpHOlei†¨“•¢²²»ÚÛáÒÒÛ‚‘”“£º¹ÉÌÌÙ°°»——£ŒŒ˜yy†··À££¬žžª‹›š¡¯´ªª³»»Åª¸œŸªšžª£©·ÌÚêÒãóÚëûÚíÿÕéûÔêþÔéÿÕéþÙêýÙêýÙêýÙêýÙêýÙêýÙêýÙêýÖêýÖêýÖêýÖêý×ëþ×ëþ×ëþ×ëþ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìú×ïûÖíúÕìùÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÐèôÐèôÐèôÐèôÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÏæþÏæþÐåþÐåýÐäûÐäû½ÍãSc{FVpIWtS^}MUtLSpHOllp“•ˆ‹š¡©Ž‘—‰•jly…‡–wy†“Ÿikxjlysv…ˆ‹šÉÍ×…ˆ“xz‡œ¦¥¯©¨±šš£·²¶À•˜£¦«¶‡Ž˜¦²ÀÈÖæ×è÷×éùÙêýÕéþÕéþÕéþÙêýÙêýÙêýÙêýÙêýÙêýÙêýÙêýÖêýÖêýÖêýÖêý×ëþ×ëþ×ëþ×ëþ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìú×ïûÖíúÕìùÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÐèôÐèôÐèôÐèôÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÏæþÐåýÐåýÒåýÒåý£³ÌTd}IWqIWrQ]{P\zOWwLTqFMjcf„z–il~x{†y}…z~ˆ]_o~€¥¨´kmzikxehw^artwˆŽ~€‡‰˜sv…iit£¢«ÂÂÌ••ž‰—}€‹‘–¡†‹•—ž©ÌÕâÖâðÝëûÜëý×éûÕéûÕéþÙêýÙêýÙêýÙêýÙêýÙêýÙêýÙêýÖêýÖêýÖêýÖêý×ëþ×ëþ×ëþ×ëþ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìú×ïûÖíúÕìùÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÐèôÐèôÐèôÐèôÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÓèÿÎãúÕéÿÈÜóqšIZrJXrIWrO[yJVtPXxT\{FNkV]zv}˜osX\pqv„fkw‚‡“fj{ˆŒ†‘sx„†‹˜y}Žhkei}X]kty‡‡‹œcewbbo†„°°»½½È±´½ÇËÓ·½Ä¡¦·»Æ¶ºÅÀÇÒ×ãïÙæ÷ÙèùÖèúÙìÿÖêýÖêýÖêýÖêý×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþÙìÿÙìÿÙìÿÙìÿ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìúÕìùÕìùÕìùÕìùÔëøÔëøÔëøÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåýÎäøÓæûÄ×ï^o‡HXqM[vDQlP\xNZxIUsLTsMUtHPm]e‚krŽSZsSWoW[pfj{qt†txŒjm]arZ^lmq‚^bv[^sdh}fj{dhyil€ehy~~‹˜–£¢¢©©´¢¥»¿Çª°·±·¾ÁÅËÌÏ׶ºÅÁÈÓÚåóÚèøÛìýÖêýÖêýÖêýÖêýÖêý×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþÙìÿÙìÿÙìÿÙìÿ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìúÕìùÕìùÕìùÕìùÔëøÔëøÔëøÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåýÕéþ²ÆÛTdzEUmM[tAOjWcMXwJSrS[zIQqJSr[c€^f„NWrLSoPTqINhW\sim‚X]tae}V\oX^qU[m]bwW\s]bykq„flV[pTWkqp€•“¡ªª¶˜˜¤ˆŒ”Œ—…‹²¶»·¸»ÌËÏÚÝå½Á̹ÂÏÔâòÛêûÕéûÖêýÕëýÕëýÕëýÖìþÖìþÖìþÖìþ×ëþ×ëþ×ëþ×ëþÙìÿÙìÿÙìÿÙìÿ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìúÕìùÕìùÕìùÕìùÔëøÔëøÔëøÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒåý³ÄÚN^tIZpIWqHVqQ_zJXvLWvNZxEPoLWvQZyV^{W_}U\yOVsQUsTWt{€š\azSWqPUoPUlOTiV[pmr‡TXrOTmmr‡x}‘_d{X\qz}Œœœ¨›––¢z~ˆ†‰”{‰ww€Œ‹‘ÆÅÌÌÌÕ¥ª´°·ÁÅÐÞ×åöÛëúÙêúÖêýÖêýÕëýÖìþÖìþÖìþÖìþ×ëþ×ëþ×ëþ×ëþÙìÿÙìÿÙìÿÙìÿ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìúÕìùÕìùÕìùÕìùÔëøÔëøÔëøÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÒæþÒæþÒæþÒæþÓèÿÓèÿÓèÿÓèÿÒäþÔæÿÕèÿÐãýÐãýÕèÿÕèÿ¨¸ÒZhN[tN[tO]xQ_zM[vLZtL\vJZwBQoP^{Q]{W_W]~W[{UXwQUs\_}hl†TXrLOmIMkDGdDH_EI^‚‡œlq‹TXr~‚š„›TWtaeqv„¦ª´‡‹•~€qp€‡†–Œœ‚€‰‡”¡Ÿ©ÅÅг·Á¡¥°¤©³ÅÌÕÙâìÜêúÞíÿÚëûÖëúÖìû×íý×ðþÙñÿ×íýÙíýÙíýÙíýÙíýÙíýÙíýÙíý×íý×ïû×ïû×ïûÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðúÙðúÙðúÙðú×ïù×ïù×ïù×ïùÖíúÖíúÖíúÖíúÕìùÕìùÕìùÕìùÕìùÔëøÔëøÔëøÓê÷Óê÷ÒéöÒéöÓê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÒæþÒæþÒæþÒæþÓèÿÓèÿÓèÿÓèÿÒäþÖéÿÒäþÓåÿÐãýÐãý}©O_yNZvNVsLWsQ]yLWsN\wN\wHXrIZsHWtSa~S^}[abe†hi‹WXxW[yVZwZ^xTWtPTrOSqNQoBGaINc{€•^c}[_y–›²€…œX\yQVpjo}ˆ—¢¤±°¿wv†‰ˆ›‰†šš–ª‰‡•rp}——£¿¿Ë„‡¢¥»ÁÆÉÐÚÝé÷ÙæøÜëýÝïÿÚïþÙïþÖïýÕíû×íýÙíýÙíýÙíýÙíýÙíýÙíýÙíý×ïû×ïû×ïû×ïûÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðúÙðúÙðúÙðú×ïù×ïù×ïù×ïùÖíúÖíúÖíúÖíúÕìùÕìùÕìùÕìùÕìùÕìùÕìùÔëøÓê÷Óê÷Óê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÒæþÒæþÒæþÒæþÓèÿÓèÿÓèÿÓèÿÔæÿÓãýÖæÿÕåÿÛëÿw‡¡M]wDQlLWsLTqS[xV^{O[wS^zLWsBPkLZtO]xUa}Zbls_copž^bUXv\azW\vGJiHLjMPmFJbIObX^qZ^vy~•Ÿ¥¸w{UZq[_tty‡ty…‡‰–ž…„”‰ˆ˜£¡±¬ªº»»Èvv‚‹ŸŸ«¦ª²©¬´¤¨°¹¾ÈÛæôÛéùÛëúÙêùÛðþÙðýÖïûÕíú×íýÙíýÙíýÙíýÙíýÙíýÙíýÙíý×ïû×ïû×ïû×ïûÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðúÙðúÙðúÙðú×ïù×ïù×ïù×ïùÖíúÖíúÖíúÖíúÕìùÕìùÕìùÕìùÕìùÕìùÕìùÕìùÔëøÓê÷Óê÷Óê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÒæþÒæþÒæþÒæþÓèÿÓèÿÓèÿÔèÿÖæÿÔäþÓãý×èÿ~Ž¨HXrHXrIWrIUqMUrQZwNVsQZwPXvNVsJVrS_yO\vU^y^eVZw^bsv“†ˆ¥y}šUZs]byX]wPTqPTqMQkNSjPViLQdSWo~‚—ž¤·jp‚]bw[_trv‡UZhZ\kkm}€šš¦±¯½À¾Ì©©¶ffsxx…‰‰•Œš–š¢˜œ¤ž£ÆÏÞÝëûÜêúÛëúÙíûÖíúÙðýÚñþÙíýÙíýÙíýÙíýÙíýÙíýÙíýÙíý×ïû×ïû×ïû×ïûÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðúÙðúÙðúÙðú×ïù×ïù×ïù×ïùÖíúÖíúÖíúÖíúÕìùÕìùÕìùÕìùÕìùÕìùÕìùÕìùÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÒæþÒæþÒæþÒæþÒæþÒæþÒæþÓæþÚêÿÏÝøÎÜ÷hvHVqHVqHVqGUpHTpOWtU]zLTqLTqOVsLSpS\wOXqV]wU\v]b{ptŽjoˆkmˆz}—kp‰X]wLPhNSjTWtOSpW\vLPhMQfPUjV[rae}U[mU[mkp…X]r^bv^bvehybdseerŸŸ«©¦³¢Ÿ¬‹‰škm}fixtw„Œ˜˜¢¤±Ÿ¥³ÎÚèÜêøÙéöÞñýÙíùÙðúÕìùÚïþÚïþÚïþÚïþÚïþÚïþÚïþÚïþÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñûÚñûÚñûÚñûÙðúÙðúÙðúÙðú×ïû×ïû×ïû×ïûÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÕìùÔëøÔëøÔëøÔëøÔëøÔëøÓê÷ÒéöÒéöÒéöÒæþÒæþÒæþÒæþÒæþÒæþÒæþÓæþÕåÿÎÜ÷drFToIWrESmFToMXtS^zU]zHPmLSpJQoU\y\c€sw”[_w\ax^czdi€chchdf_bzSWoNSjX]r\ax\azOTmPUlae}QVmHMdLPjINhMQfdj}y~“ejVZojm‚€–‹œŽ‡‡“¨¦°žž¨y{‹…‡˜€‚‘z}Œ}{Œœ‘‘ž¨ª·•›©ÀÉÙÙäòÙæôÚê÷ÜïúÙíùÛòýÚïýÚïþÚïþÚïþÚïþÚïþÚïþÚïþÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñûÚñûÚñûÚñûÙðúÙðúÙðúÙðú×ïû×ïû×ïû×ïûÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÕìùÔëøÔëøÔëøÔëøÔëøÓê÷ÒéöÒéöÒæþÒæþÒæþÒæþÒæþÒæþÒæþÓæþÕãþw‚žHTpMXtO[wLWsNZvT_{P\xLTqIQoLSpOSq\_~il‹„¡mpˆSVkdh}…ˆW[p[^sUZoNShV[r_h~^fzw“qx‘PWqPXockDJdGNjNUqFMiXawt}€ˆœV[rSUmtw‘¦”–¨ª››¤±°·‰‹xz‡‚”„†—‹ž}{Œ”“£œš¨´´Á‘–¤¦°½ËÖâÜëöÝíøÝðù×íöÚïúÚïýÚïþÚïþÚïþÚïþÚïþÚïþÚïþÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñûÚñûÚñûÚñûÙðúÙðúÙðúÙðú×ïû×ïû×ïû×ïûÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÔëøÔëøÔëøÔëøÔëøÔëøÓê÷ÒéöÒæÿÒæþÒæþÒæþÒæþÓæþÓæþÕåþ}‹¥DOkIUqMXtJVrMXtP\xS^zLWvHPpGNkELiNQodh…Œª¦©Ä›ž³[^r{“ilSVkQUjMQfGLaJSf_h{ltˆW_vT[t^eJSiGNhNUqLSoFMjFMiIPjrzV^tLPhOQlxz“˜š°„…š‡†–˜¸·¾•”‚‚„†—„†—xw‰ts„Ÿ››¨´´Á«º—œ¨©°ºÍÙâÛêòÚêôßòûÜòúÚïýÚïþÚïþÚïþÚïþÚïþÚïþÚïýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñûÚñûÚñûÚñûÚñûÙðúÙðúÙðúÙðú×ïù×ïû×ïû×ïûÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÔëøÔëøÔëøÔëøÔëøÔëøÔëøÓê÷ÓèÿÐåþÓåÿÓåÿÒåýÓãûÔäúm{•LWsJSpJSpNVsT\yZbXa~NVvGOqFLoGMmIPlQXrbj~š¢´´ºÍˆ¢fk€im‚\axNSjJOfQVmLPeV[p^cxchFIfMTqHOlFOjNUqZa}FIfQUrMPmTWtej„MQkMQkWZt}šxz“[\rbasfev˜–¤›‹˜ŽŒœŸœ°]\oa_r‹‰šŸŸ¬ÄÄл»Ç¤¤¡¤¯¦·Ë×ÞÝìôÝð÷ÝðùÜïúÜíýÜíýÜíýÜñÿÜñÿÛòÿÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÜóþÜóþÜóþÜóþÜóþÜóþÜóþÜóûÛòúÛòúÚñùÚñùÚñùÚñùÚñùÚñùÙðøÙðúÙðúÙðú×ïù×ïù×ïù×ïù×ïù×ïù×ïù×ïùÖíøÖíøÖíøÖíøÕì÷Õì÷Õì÷Õì÷ÔëöÔëöÔëöÓêôÐãýÖéÿÓæþÔäýÔäý×åÿp~—TazNVsLTsLTsNVvV^~V^~NVvEMlGMpNTwLSpFMi[cypxŒ¦¶«´Ä^cx_d{\axW\sTXpNSjNSj\avioZ^sdi‚FIfGNkIOpGOlSZvfk…^c}}›[_yPTqei†OTmNSlbdª]_x]^t{zzyŒœšªŽŒœ•Ÿ—“¤ž›¯]Zm[Zlkj}›¬³³¿º¹Â¾½Ä¬¬¶¨´±»ÄÐÝäßñøÚêôÝíúÝíúÜïúÜïúÜñýÜñýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÕìôÕìôÕìôÕìôÔëóÔëóÔëóÓêò×éûÒãöÕåû×æýÖäþ„ªIVpW_}PXxMUwMUwPXzU]NVxGOqDLmNTwIOpBIfJQmLTjmv‰¯·Épx‹W\schZ^vMQiSWoOTkPUjaez\btioae}AEbLSpLSpGOlJQkW\sswŒ£¥¾twX[vik†JMjQTopršMOh\]syx‹‰ˆ˜£¡±‹˜˜¨ˆšsp„ro‚a_r^]p‰Œ›¯¯º³²»·¶½ÀÀÉ£ª¯¶¿¿ÌÓÛêòÜì÷ÝíúÝíúÜïúÜïúÜñýÜñýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÕìôÕìôÕìôÕìôÔëóÔëóÔëóÓêòÕåô×è÷Öå÷×äùŒ˜°PZtS\wLTqQZyNVxNVxQZ{OWyHPrFNpIQqQWxW^{LSoMTmHOiS[qz‚–[cwX]wV[tHMf@E\INebf~PUjrx‹iodjzPUjHMfOVrHOlMUrFMiHMdX\qjm‚ei~š€‚›PSkik„wy‘lo‡TWl_av{zŽ¢ŸŽœ¡œ«“ŽŸŒŸ¡rq„ZXkmp¡¡¬–•žº¹ÀËËÔ›ž¦ž¥¯¬·¿ËÖßÛêôÝíúÝíúÜïúÜïúÜñýÜñýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÕìôÕìôÕìôÕìôÔëóÔëóÔëóÓêò•¤¯¯¾È½ËÙz…–S\rV]wQXtV]zS[zT\{PXxLTsFNmIQqOWwT\{W^zQXtJQkELeELeNUoU]sGNhGLePTqNSlUZqMQipt‰[_tz€jq{}„ŽX^oHMdT[wOVsNVvSZwUWrHI_TUkrsˆ€•wxhi~st‰UXmMPeUXmst‰Œœ••¢«¹•“Ÿ¤Ÿ¯ª¥·¨¤¸¢ž²¡Ÿ²qp‚mp››¦¡Ÿ©¬«²´´¾³·¿Ÿ¤¯«²»ª±»ÙäðáïýÜìùáóÿáóÿÜñýÜñýÛòýÛòýÜóþÜóþÜóþÜóþÜóþÜóþÜóþÜóþÝôýÝôýÝôýÝôýÝôýÝôýÝôýÝôýÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÖíöÖíöÖíöÖíöÕìôÕìôÕìôÔëóeqzit~NZeOXhPXlX]tX]w[^{QXvS[xS[xPXvNVsQZwT\yT\yMTmMTmBIcAHbMTmELeBIc@GcIMjOSpOTmjoˆrwŽhldj}MScPWaahrMScV[pT[tQXvOWtT[wVXqVWlijqs…actqs…ŒŽvx‰SVjTWlW[ohj{‘¡¦¦³œš¦›¨¶±À£ž°Ž‹žŒˆœ¢š˜«“¢›š˜¢Œ“¹¹ÂÅÅΦª´¯³¾¦«·¶¿ÌáïýÞïûáóÿáóÿÜñýÜñýÛòýÛòýÜóþÜóþÜóþÜóþÜóþÜóþÜóþÜóþÝôýÝôýÝôýÝôýÝôýÝôýÝôýÝôýÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÖíöÖíöÖíöÖíöÕìôÕìôÕìôÔë󀉔y‚bkxNTdV\oX\qW[p^aySZsU^yU^yQ[vS\wU^yS\wNWpFNdAI_BJa>E^GNhGNj7>Z;B_?Ba?B_BGaX]wINech}‰¢GM]DIWOUeafy_dyJSiMTmWawdl€[]ofevsr‚hfwfevml}š˜«ž¡²qtˆ_cxadx[]o€¦¦³›¨œš¦©¸–‘£}yzw‹{z†…—•—¦œŽ–Œ‹‘©©²ÀÀɲ¶À¸»Æ´·Äœ¢°ÁÏÝÜìùáóÿÞñýÜñýÜñýÛòýÛòýÜóþÜóþÜóþÜóþÜóþÜóþÜóþÜóþÝôýÝôýÝôýÝôýÝôýÝôýÝôýÝôýÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÖíöÖíöÖíöÖíöÕìôÕìôÕìôÔë󅌖t{†pt€lqhlzehyTVh_avZ^sXatU]sPXoQXrT[tNUoELeAHbDH_AF_@GaELh=Da=Da@Gd>A_>A^JNkHMfAF]PUjOTiOUhX^qsyŒejOTiS[qFNdLViT\pX\pZ\m^arihzdcvjiy‹‰š£¢´rsˆy}~“xz‰wy†„„——£‰‡”~{‰‡…“‰‡—‰†…—‹‰š”–£ŒŒ—š˜¢¸·¾»»Å¾¾Ç¿¿Ë½½È¶¶Áª¯º›¦ÓãðáñþÜïúÞñýÜñýÜñýÛòýÜóþÜóþÜóþÜóþÜóþÜóþÜóþÜóþÝôýÝôýÝôýÝôýÝôýÝôýÝôýÝôýÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÖíöÖíöÖíöÖíöÕìôÕìôÕìôÔë󓕘£ˆŒ–‹Ž˜ÆÉÔ±±½šš¥››¨sv‚hjyps…VZmUZqPUoLOlFIhFIhGHhEFeAEc@Db@Dd>Dd>Eb>Eb?FbHOkFMiAHbAHbBIcNVlXatS[m]eydl€U]sLSlJQkLSlTWtHJhOQj]^tcdyxz‰±±¾‡†–mp}~“‘”£ž¡–˜¥‚…‘Žvv‚Œss€‹‹—Žž€……‘““Ÿ©œ›¤¬¶º¹Â¾½Æ¤£¬¹¸Á¾½Æ²¶À—ž©œ¨³ßïùáñûÛíùßòþÝòÿÚïúÞóÿÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÝöúÝöúÝöúÝöúÜôùÜôùÜôùÜôùÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÕïöÕïöÕïöÕïöÔíôÔíôÔíôÓì󖉋›œ¢¢£©³´ºÙÚßÈÉϬ³½¾Ä··À¨ª·[]obc{bdMNmIMkJLkLMlIJjFGi@Dd@Dd>Dd>Eb?Fb>EaGNjDJfBIeAHd?FbFMfDLb@H\IQeckQZpIPjFMfOVrMPoLOmPSm]_x]^spr„……‘~}“~€‘vx‡‡‰–¢¥°£¥²prvx‡Ž……‘ss€ŽŽ›~~‹šªš—¤œ›¤¤£¬ÓÒÛ¤£¬¬¶³²»°°¹±¶À‚Œ–ÒÝéßïùáñþáóÿßôÿÝòþÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÝöúÝöúÝöúÝöúÜôùÜôùÜôùÜôùÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÕïöÕïöÕïöÕïöÔíôÔíôÔíôÓìóÁÂƤ¥©Œ”•˜—˜œÞßãÎÏÓÅÆÉ¿ÀÄ´¶»··Â{zcd}hh†VWyLMoILiJMjHJhEFe@Db@Db>Eb>Eb?Fb>EaELhAHdAHdAHd>Ea@GcELh>E^ELe]e{JSiGOcNVjV^rPUoNSlOQjX\qQShbdvom€{z{}‘mpQTc[]j…ˆ“‹š†ˆ—ŒŽ††“ddqbboyy†ˆˆ•ŒŒ˜œ““Ÿ›¨›š£ž¦²±ºž¦¦¥¯¡Ÿ©š´¹Ä˜Ÿª¬¶ÀâíùáñûÞñýÛðûÝòþÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÝöúÝöúÝöúÝöúÜôùÜôùÜôùÜôùÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÕïöÕïöÕïöÕïöÔíôÔíôÔíôÓìóÉËÍ´¶¸¦¨ª‘“•‹ŒŽ·¸ºÜÝßÚÛݸ¹»²³·ÇÇЪ©¹zxdd€__NOoDFaDFaAD^?A^@Da@Db>Eb>Eb@Gc>EaDJf?Fb=D_@Gc>Ea@GcFMi@GcJQkXawPXoJSfXasPXlGLcQVm\_tQUjSTi\^pts„vt‡‚—ik}UWfikxx{†…‡”‡‰˜‘¡^^kzz‡‚‚‰‰–‡‡”‘‘ž””¡”‘ž£¢«¡Ÿ©±°¹†…Ž£¢«¢¡ªŸŸ©²¶À²½‹‘œÚãíãòýáóýÞóÿáöÿÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÝöúÝöúÝöúÝöúÜôùÜôùÜôùÜôùÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÕïöÕïöÕïöÕïöÔíôÔíôÔíôÓì󩫪¾À¿‘”“ˆ‹‰mpoz}{ËÍÌßâáÖÖÖÒÒÔÁÀÇÀ¾Ë²±Ä–”«de~OOkHLaGJ_HJcFHa@E^=@]:A]=D_>Ea?Fb>Ea;B^>Ea?Fb@GcAHdMTmSZsHPfFNdS[qOWmQZpLTjJOi_d{JNc_cw]_qjl{llyŒy{VXjWZirtlpz€‚•—¦¢¤³””¡ww„}}‰‹‹—††“””¡¡¡““Ÿ›˜¥”“œ›š£ÆÅΣ¢«ž¦ª©²°¯¸ßß黻ǔ˜£ºÄÎÝìôáóýßöþÛòúÞôýÞôýÞôýÞôýßöþßöþßöþßöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞ÷ûÞ÷ûÞ÷ûÞ÷ûÝöúÝöúÝöúÝöúÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ñø×ñø×ñø×ñøÖð÷Öð÷Öð÷Õïö~±²´‰‹‚…deh‘”¯°²ÎÎθ¶·ÓÐÔÜÚÞÒÐ×°ºª©¹wvˆWXmOSdNQeNQeLOd@E\>B\:A]>Ea?Fb>Ea;B^=D_@Gc?Fb>Ea=D]=E[FNdDLbMUkS[qQZpT[tU\vV[rejTWlX\pcewjlyyy…ŽŽ›y{\^plo~y{ˆ‹Ž˜”–£vx‡~€••¢‘‘ž‚‚““Ÿ••¢‰‰–––£˜˜¥Ÿª¡Ÿ©¦¥¯Ÿž¨±°¹£¢«©¨±ª©²±°¹´³½¬°º‹‘›ßëôÛíôÞôýß÷ÿÞôýÞôýÞôýÞôýßöþßöþßöþßöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞ÷ûÞ÷ûÞ÷ûÞ÷ûÝöúÝöúÝöúÝöúÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ñø×ñø×ñø×ñøÖð÷Öð÷Öð÷Õïö¡¢¥”•˜‚„‡{}€dei…†‰˜šššœ›˜šÅÀÁÛÙÜÓÐÔÍÌÐÆÅÌ°°¹eisV[fTXfQUfOSfAF]>B\;B^?Fb>Ea;B^=D_=D_?Fb>Ea=D_;B\BJaEMa@H^MUkIQhJSiNUoV^tdi~{”W[odhysv…z}Œ¢¢¯qp€VXjxzŒrt„vx…€„Ž“•¢fixdfvŽŽ›ww„‡‡”££°¾¾Ë——¤››¨œš¦š˜¢¯·ÁÀÉ¥¤´³½¬¶°¯¸¦£«ÍÉÔ½½Æž£©¶½Þð÷ÞôúÝöúÞôýÞôýÞôýÞôýßöþßöþßöþßöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞ÷ûÞ÷ûÞ÷ûÞ÷ûÝöúÝöúÝöúÝöúÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ñø×ñø×ñø×ñøÖð÷Öð÷Öð÷Õïö°±´°±´¥¦ªŽ“{}€efjmor_^c¯¬°ÕÓÖ—•˜¦¤¨”Œ‹•–œ‰‰“^blV[fSWePTeBF[?D[?B_>Ea;B^=D_=D_>Ea:A];B^=D_>EaFNdAI_;DZJQkHOiBIc;B\AHbV[pafy]arhlzy{‹žjiywy‹bdvjl{}Œfiv~€oq~zz‡˜˜¤ŽŽšœ‡‡“~~‰““Ÿ««¸““žœ›¤¡Ÿ©˜—¡£¢«œ¥ª©²Ÿž¨¶´»¥¢ªÒÐ×ÀÁǯ´»¥°¶Úéðßñ÷ãöýÞôúÞôýÞôýÞôýßöþßöûßöûßöûÞöþÞöþÞöþÞöþÞöþÞ÷ûÞ÷ûÞ÷ûÞ÷ûÞ÷ûÞ÷ûÞ÷ûÝöúÝöúÝöúÝöúÜôùÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ñø×ñø×ñø×ñøÖð÷Öð÷Öð÷Õïö¶´¹¨¦«Ÿž£š˜~}zy~‹‰Žtsxqpt«ª¯ÄÂÉŒ“VU^WV_ljwyy…lpzTWbSVaUWfGJ^GIb@Da>Eb?Fc>Gb=Fa;E];E];E_;E_;E_?Ha?Ha?Ha?Hc@Id>Gb>GbAHdMQiNSh_ctqv„‡‰–Žvt…sr‚zy‰kjzvt…~Žyy†••¢““Ÿ––¢±°¹©¨¯ž¦•”€‰”‘žŽ›¡ž«¢¡ª—–Ÿ‹‰£¢©ÐÏÖª©°¥¤«°¯³±°´ª«¯³¸º²¶»°¶½´»ÂÖáæßïöáóúÝöúÞ÷ûÞ÷ûßøýáùýâøýá÷ûá÷ýá÷ýá÷ýá÷ýâøþâøýâøýâøýáùýáùýßøûÞ÷úÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöúÝöúÝöúÜôùÜôùÜôùÜôùÛóøÛóøÛóøÛóøÚò÷Úò÷Úò÷Úò÷×ñö×ñö×ñö×ñöÖðôÖðôÖðôÕïórqv¥¤©›šžœ›Ÿ{z“‘–„‚‡wvz€†¥¤«º¹Â˜—¡a^k_]jb_mdbpss\_hNQ\\^kNQeGIbDGd>A_?Fc>Fc=Fa;E];E];E_;Da;Da>Gb>G_>Gb>Gb=Fa=Fa?GdELhUZsOTi]ar€…“‚…‘sv‚yxˆkjzom~dcs~Ž‰ˆ˜~~‹}}‰šš¥““œ°¯¶¬«°¨¦›š¡•”¬«´”‘ž”‘ž¥¤–•ž”“š¢¡¨´³¸ÅÄÈÓÒÖ½»À¬°ª«º»¿»¿Å¤¨°ÀÆÍž¤«äï÷âôûÞ÷ûÝöúÜôùâúþÞ÷úß÷øãùþá÷ýá÷ýá÷ýá÷ýâøýâøýâùúâùúáùýáùýßøûÞ÷úÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÜôøÜôøÜôøÜôøÛóøÛóøÛóøÛóøÚò÷Úò÷Úò÷Úò÷×òô×òô×òô×òôÖñóÖñóÖñóÕðò}{€wvzrqvvty€…°¯³¡Ÿ¤”‹‰‰ˆ‰ˆ‘š˜¢„ŽŒ‰–a^lZWe^^j[^iZ]h]_lPTeJNcGLe@Db?Fc>Fc=Fa;E_;E_;E_;Da;Da=Fa=F^=Fa=Fa=Fa=Fa?GdELh\azOTicfx€…“jly\^k{z‹_^oVUebaqqp€~Ž}}‰ss€˜–©¨¯«ª¯¯´œ£¡Ÿ©ÆÅΨ¥²Ž›¬¶‘šž¤¥¤«¡Ÿ¤ÂÁÆëêïÌËÏÆÆȱ±³ÅÆɾ¿Å¯²º½ÀÈ“˜ŸÁÌÔßñøßöûÞôúßöûßöúãùþâúûÞ÷úá÷ýá÷ýá÷ýá÷ýâøýâøýâùúâùúáùýáùýßøûÞ÷úÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÜôøÜôøÜôøÜôøÛóøÛóøÛóøÛóøÚò÷Úò÷Úò÷Úò÷×òô×òô×òô×òôÖñóÖñóÖñóÕðò¿¾Â‰ˆ\[_edi„‚‡±°´¶´¹—–›”“š‹‰„‚Œ[Zc…‚¿½É“žcao]]iVZdkoy_boNQcNQfGLeGJh?Fb>Fc=Fa;E_;E_;E_;Da;E_=F^=F^=Fa=Fa@Id>Gb>FcAHdGLeX]rcfxdiw]_leht~Žbaq\[ksr‚xw‡{z‹‚‚yy†‰‰•••ž£¢©ª©³²¹ž¤”“œª©²¡ž«¤¢¯·¶¿Œ‹”¤£ªª©°¦¥ª©¨¬ÇÆËÁÀŽ½¿¿¿Áº¹¾ÆÇ͹¹Â¾ÁɾÁÉ”ÒáéÞñøä÷þäúÿâøýá÷ûßøùáùýá÷ýá÷ýá÷ýá÷ýâøýâøýâùúâùúáùýáùýßøûÞ÷úÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÜôøÜôøÜôøÜôøÛóøÛóøÛóøÛóøÚò÷Úò÷Úò÷Úò÷×òô×òô×òô×òôÖñóÖñóÖñóÕðò©¨¬´³¸edi~‚¡Ÿ¤—–›¬±¬«°š˜Ÿ–•œž¦~}†WUb¬ª·ÍËÙhesbbmps~Z]ecfq_drMPdINeJOiAHd=Fa=Eb;Da;Da;Da;E_;E_;E];E];E_;E_>Gb;E_AIfJQmJOiW\qZ]olq_boz}‰€ml}ihxrq~}vt…tttt””Ÿ¦¬«²¬«°ª©°š˜Ÿ“‘›ž¦¥£°½ºÇ¦¥¯–•žŒ“š˜Ÿœ›Ÿ¦¥ª¿¾ÂÆÅÉÀ¾ÁÅÂÆ¿¾ÂÔÓÚ²²»»»Å¾ÁÉŸ¤¯…šÉÙáäöýÜïöá÷ûãùþãûýäýÿâøþâøþâøþâøþâøýâøýâùúâùúáùýáùýáùýáùýßøûßøûßøûßøûÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÛó÷Ûó÷Ûó÷Ûó÷ÚòöÚòöÚòöÚòö×òô×òô×òô×òôÖñóÖñóÖñóÕðò»º¿ÂÁÆ¡Ÿ¤Œ‹©¨¬£¢¦–•š”“—¨¦œ›¢ž¦°¯¸‚€[Xe^\j¸¶Ä]]iX\f_ck\_jlq}fj{DH]GLcDJd>Gb=Eb;Da;Da;Da;E_;E_;E];E];E_;E_=Fa;E_?GdGNjPUoQVkSVhlqvx…y{ˆedtedtxw‡xw‡sr‚„‚“‰‰–qq~‰‰•¨¨±ÆÅ̽»À±°·½»ÂŸž¨Ž—“{y†€ˆ˜¤£ª“‘˜”¦¥ª»º¿ËÉÎÈÆÉËÈÌÂÀÅÀ¿Æ»ºÄ¿¿ÈÂÂÌ°´¿}†œ¥ßï÷èùÿáôùá÷ûáùúáùýâøþâøþâøþâøþâøýâøýâùúâùúáùýáùýáùýáùýßøûßøûßøûßøûÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÛó÷Ûó÷Ûó÷Ûó÷ÚòöÚòöÚòöÚòö×òô×òô×òô×òôÖñóÖñóÖñóÕðòÐÏÔ¯²¥¤©¦¥ª—–››šžœ¡‘•‘—ˆ‡Ž–•ž¸·ÀÆÄÐ^\ib_mqo}SS^Z]h[^fadohlx}FL^=AVFMf@Id=Eb=Eb;Da;Da;E_;E];E];E];E_;E_:D^:D^=EbAHdFJdNShMPb]bp„‘ž„‚“‡†–xw‡€yxˆ€šŒtt€ŽŽ—±°·º¹¾¦¥¬¹¸¿¬¶–•ž¥£°š˜—¡š˜¢•”›š˜ŸŽ‘©¨¬»º¿ËÉÎâßãÔÎÓÄÁÆÌÈÐÏÎ×ÎÍÖ»»Å¦ª´£ª´y‚¬¸Áè÷ÿåùþßöúßøùßøûâøþâøþâøþâøþâøýâøýâùúâùúáùýáùýáùýáùýßøûßøûßøûßøûÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÛóôÛóôÛóôÛóôÚòóÚòóÚòóÚòó×òô×òô×òô×òôÖñóÖñóÖñóÕðòÈÇ̪©–•š¯²©¨¬£¢¦³²·¬±£¢¦{z‡†œ›¤¤¢¯ljwVTbVVcNP]Z]hilwbepcfqimyrv‡FL^BJaDJd?Fb>Eb=Da;Da;E_;E];E];E_;E_;E_9B]:D^;Da=D_@Ga?D[FI]ps…ŒŽœž«——¤‚‘‚‘xw‡~Ž€€‡‡”„„vv††¿¾Å²±¶ª©°–•œ‰ˆ‘¡Ÿ©¸·À©¨±»ºÄ¬³¸·¾¡Ÿ¦—–›¬±¾½ÁÄÂÇÍËÎÍËι·»½º¿°¯¶³²»ÁÁËÁÁ˾ÁÌ¢¦²‚‰”Ë×ÞåôûèûÿâøýßøûáùýáùþâøþâøýâøýâøýáùúáùúáùúáùýáùýáùýßøûßøûßøûßøûÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÛóôÛóôÛóôÛóôÚòóÚòóÚòóÚòó×òô×òô×òô×òôÖñóÖñóÖñóÕðòÇÇÉÏÏÒÀÀÂ¥¥¨““•¨¨ª··¹¯¯±›››œœœ‚…rsy˜˜¢hhtNM]NP_SUdacrllxffrllxrt}ŽfizAEZHJcJNkDGd>A_9@];B^@Ga?Fb?Fc>Eb>Eb=D_;B^;B^=D_;B\AF_DHb@B[LOcmpŽ˜›¨‹‹—zz‡Žrr~xx„tt€‹‚‚Œ¶·½¹ºÀ°±·¥¦¬•–œ«¬²³´º±²¸¯´²±¶·¶ºº¹¾Ÿž£¡Ÿ¤½»ÀÇÆËÁÀŲ±¶´³¸º¹¾³²·ÐÏÖÆÅÌÄÂɾ½Æ´´ÀŽ‘œ•œ¥Ýêñè÷ÿåøÿá÷ýáûþáûþâúþãúûäûýãûýâýýâýýâúûâúûâúûâúûáùúáùúáùúáùúßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÛööÛööÛööÛööÚôôÚôôÚôôÚôôÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðÞÞáÈÈ˽½¿³³¶••—““•ÀÀÂÇÇÉ«««¯¯¯º»¾‰‹Ž[^fTVcPSbX[lVXjbdsoo{±±½››¦~~‰hhtkjz^_tHI_HJeMOlFIf?B_9@\;B^>Eb>Eb>Eb>Eb>Ea=D_;B^;B^;B\@Ga>A^@E^QUjNQcUWd…••¡……‡‡“iitffrllx€€Œ‰‰•°°¹´¶»±²¸£¤ª…†Œ¯°¶¦¨²³¹¹¸½²±¶¸·»ÁÀŹ¸½›šž¢¡¥»º¿ÉÈ͹¸½¬«°·¶º´³¸Ù×ÜÄÂÇÈÇÎÀ½Ç¥¤²²»‡Œ–¥¯¹ßëôæ÷ÿäúÿáûþáûûâúûãúûäûýãûýâýýâýýâûùâûùâûùâûùáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÛööÛööÛööÛööÚôôÚôôÚôôÚôôÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðßßâÒÒÔššœŸ££¥““•°³³¶¯¯¯ŸŸŸ—˜›¯°³z~†jlyNP_QTewy‹hjyzz‡””¡ÈÈÔ\\hllyts„y{PQfEG_HJeGJhAEb=D_>Ea>Eb>Eb=Da=Da>Ea>Ea=D_;B^=D]9@Z@Da?D]PTi^bsdfswz…]]immy‰‰•{{‡jjvzz†††‘““ž¢¢«³´º¹ºÀ²³¹–—‘“˜³´º©ª°¸·»²±¶¬±¯²¾½Á¸·»±°´¥¤©¾½ÁÇÆ˺¹¾”“—½»À·¶ºÀ¿ÄÎÍÔÇÆÏ°¯¸½½Æšž©x‰±½Æéøÿä÷þâúþáûûâúûâúûãûýãûýâýýâýýâûùâûùâûùâûùáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÛööÛööÛööÛööÚôôÚôôÚôôÚôôÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðÌÌÎ××Ú³³¶ªª¬°°²¬¬¯ššœ””–¡¡¡¥¥¥£¤¦¤¥©˜œ¤‚…‘WZiTVhpr„\^m~Žffs““ŸZZe‰‰–¡¡¤¦¶twˆEH]FHaLPjGJh?Fb;B^=Da=Da=Da=Da=D_>Ea>Ea=D_>E^:A[;?\@E^NQfcfx…‡”£¦±ŒŒ—€€Œww‚„„{{‡‹œŽŽš˜˜¢´¶»³´º³´º¤¥«‚ˆ¤¥«¡¢¨´³¸³²·±°´·¶ºÌËϽ»À¾½Á¹¸½¿¾Â»º¿ÆÅɘ—œÌËÏÂÁÆìëðáßæÄÂÌÇÆ϶¶¿°³¾y€‹‰“ë÷ÿãôûãùþáûûâúûâúûãûýãûýâýýâýýâûùâûùâûùâûùáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÛööÛööÛööÛööÚôôÚôôÚôôÚôôÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðÄÄÆÌÌÎÏÏÒ¸¸ººº½³³¶ÂÂŬ¬¯˜˜˜“”–—˜œœŸ¨‡‰–LN]IL]qs‚lo~kjzNM]FFSOO\eeq~~‹y{ˆ…‡–_cw>@XOTmFIfAHd>Ea>Eb>Eb>Eb>Eb9@\:A]>Ea>Ea=D]=D];?\HMfHLa\_q„¬°º¯¯º““ž††‘‰‰•ŽŽšˆˆ”——£ˆˆ”¦¥¦¬¯°¶²³¹¸¹¿š›¡Ž”°±·´³¸¹¸½±°´º¹¾ÅÄÈÇÆ˽»À¹¸½ÅÄÈÈÇÌÅÄȤ£¨¨¦«ÖÕÚãâæÝÜãÔÓÜËÉÓÀÀÉÍÐÛ–›¦—¢ÈÎÜë÷ÿãùþãûýâýýâýýâýýâýýãûýãûýãýúâûùáúøáúøáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÜ÷÷Ü÷÷Ü÷÷Ü÷÷ÛööÛööÛööÛööÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðÀÀ··¹ËË;¾À¨¨ª¶¶¸ÈÈËÇÇɲ²²ªªª¬°Ÿ¡¤˜œ¤›ªGIXIL]SUdehw„‚“XWhML\^^k]]ipp{Ž‘œ¯±À“–ªILdINhHLiAHdAHd?Fc>Eb>Eb>Eb:A]:A]=D_>Ea>E^@Ga>A^AF_AEZ]arrt{‰}}ˆˆˆ”……›——£¥¥±ŸŸ«¦¦°ª«±¸¹¿¶·½¯´±²¸†‡ª«±»º¿ÌËÏÂÁÆ«ª¯¹¸½ÍÌÐÄÂǺ¹¾·¶º½»À¾½Á±°´¿¾ÂßÞãÄÂÇÝÜãíìöÂÁËÇÇÐÐÐÜÅÇÔ”Ÿª¯½ëôÿåùþâúûâýýâýýâýýâýýãûýãûýãýúâûùáúøáúøáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÜ÷÷Ü÷÷Ü÷÷Ü÷÷ÛööÛööÛööÛööÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðÁÁĺº½ÅÅǾ¾À“¥¥¨»»¾ÁÁÄÅÅž¾¾³´·°±´¬°¸”–£LN]OQc\^macr…„”ji{TScbboZZejjs¯²ºº½É_ctVZo@E^>A^FMiBIeBIf?Fc>Eb>Eb:A];B^=D_=D_?F_>E^@Da@E^GJ_\_q{~‹z~ˆss††‘……‹‹‹–˜˜¤““ž›¤¤ÍÎÔ»½Â³´º¤¥«Ÿ¡¦¯´ž¤±°´¿¾ÂÏÎÓ¬±±°´ž¢¯²ÂÁÆ¿¾Â³²·¸·»«ª¯º¹¾¿¾ÂÍÌÐ÷öýÙ×áÄÂ̽½ÆÆÆÒ××äšœ©“¢ÉÐÛèùÿâúûâýýßþýßþýâýýãûýäûýãýúâûùáúøáúøáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÜ÷÷Ü÷÷Ü÷÷Ü÷÷ÛööÛööÛööÛööÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðÇÇÉÄÄƽ½¿½½¿¦¦©¹¹»±±³³³³ÁÁ¿ÇÇDz³¶°±´ªª³¡¡NM_IL]UWiik}PObqp‚edt^^kaaljjs·©¬·}Ž{}‘SUmFHcHLiGJhDJfAJe>Gb>Ea:A];B^>Ea=D_?F_9@Z@DaFJd=?WLOc~‚Žwz…ooz‚‚Ž——£‚‚Žˆˆ”––¢……–—•–œ³´º¿ÀÆŒ“¡¢¨½½Æ¦¨¨¦«ÅÄÈÎÍÒ´³¸¬«°·¶ºÀ¿Ä²±¶»º¿ÅÄÈÇÆ˶´¹À¿ÄÎÍÒÜÛßÔÓ××ÖÝãâé¿ÀƬ¬¶ÀÀÌ´´ÁŒœ¡¬áð÷åùûâúûâýýâýýâýýãûýãýúãýúâûùáúøáúøáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÜ÷÷Ü÷÷Ü÷÷Ü÷÷ÛööÛööÛööÛööÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïð‘‘‘ÀÀÀ«««ËË˾¾¾ÁÁÁ¹¹¹½½½ÄÄÁ¿¿¿ÎÎЬ³¯¬¹ŸPMaNMbHF]qo†\[pzyŒ€\\i‚‚Žllv}~„‚‚Œ˜˜¤¬½›²NLeNLhJMjJTlGTkANe=F^=D]:A[;?\=@]?D]?D]?B_?B_AF_?DXfmx~„‹swvvŽŽ—~~‡ww„žž«‡‡“–¥¤«‹‰“£¢«“‘˜œ›¤¯¬¹¡Ÿ©¢¡¥²²´ÏÏÒÀÀÂÆÆȱ±³££¥±±³½½¿ÈÈËÇÇÉÂÂÅÄÄÆÇÇÉÍÍÏÌÌÎñðôöôùÈÇ̬³¿¾ÅÅÄÍ‘œ–š¤¸ÂËæöýäöùëÿÿãýúãþûÞýùâþøäþùãýøâû÷âû÷áúöáúöáúöáúøßù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÝ÷ôÝ÷ôÝ÷ôÝ÷ôÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïxxxÌÌÌÒÒÒ¶¶¶ÌÌÌœœœ‡‡‡°°°¦¦¤¢¢¢¸¸º²±¸°º¢ŸOL_LH^VTkWUlMLahfy˜˜¥ddpœœ¥ss}iho…„‹¥¤±¯½ÉÆÚ‰†XToTTpDMeN[rDPh>G_:A[:A[>A^>A^?D]?D]?B_?B_BFc=AXZ_my~ˆtx‚ppyˆˆ‘‰‰•““Ÿ‹‹—zz‡””ŸŽ—Ÿž¥–•žŒ••”Ž—¶³À»ºÄš˜²²´ÁÁĸ¸º¿¿ÁÇÇɬ¬¯¡¡£»»¾ÆÆȾ¾ÀÁÁÄÀÀÂÅÅÇÌÌÎÇÇÉããåÂÂÅÒÐÕ·¶ºÀ¿Æ¿¾Å«ª³ŽŽ—¢©²áëóåöùéúþåýûáúøâÿúÞý÷ãÿùãýøâû÷âû÷áúöáúöáúöáúößù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÝ÷ôÝ÷ôÝ÷ôÝ÷ôÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïllj––”ÏÏÍ¿¿½¸¸¶~~{……‚¿¿½¡¡žžžœ££¥±°´©¨±«©¶HFTOM]XWjXWjSQb\\ittww‚{{…fhmomt–•œ¯·¾»È½ºË²¯Â[WmVWpBIcQ[vISmBIe=D_>A^?B_>A^?D]?D]?D]?D]?B_BG^MSasx„xz‡zz‡Œ––£{{‡šš£……Ž‚‚Žzx…˜–£œ¥—–Ÿ—–Ÿ–•žª©°ÇÆÍ°¯³³³¶««±±³²²´««¿¿ÁÆÆȳ³¶ÁÁÄÇÇÉÁÁĹ¹»½½¿ÈÈËÈÈ˽½¿ÇÇɸ·»ÁÀŹ¸¿ÉÈϹ¸Á‹‹”Œ›ÆÐÙíúÿèùýåùùåÿýßûöáÿùãÿùãýøâû÷âû÷áúöáúöáúöáúößù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÝ÷ôÝ÷ôÝ÷ôÝ÷ôÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïaa^yywÙÙÖËËÈÈÈÆ……‚wwt¡¡žŸ¡œ´´²ŸŸ¢¦¥¬œ›¤VTaLIVNN[UUbPP\EEPaalMMVMNThiokjož¢½»Â£¢«ÄÁÏ»¹Éws‡QPeFJdMTpNUqHLiEHeAEb>A^=A[?D[?D[?D]?D]?B_DHbBHXqvsv‚qq~wv†——¤……Ž‹Œ‘˜””Ÿqo}Œ‰–¥¤¨¦°›¨›š£–»º¿¸¸º¸¸º»»¾ÄÄÆ»»¾´´·²²´íí𸸺ÅÅÇÂÂÅÅÅǽ½¿´´···¹¹¹»¨¨ªÉÉÌÄÂǺ¹¾±°·¸·¾ÈÇОž¨‚‡‘“š£Üéíâòöæúúãúùãÿùâþøäþùãýøâû÷âû÷áúöáúöáúöáúößù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÝ÷ôÝ÷ôÝ÷ôÝ÷ôÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïVWSopk½¾¹½¾¹Œvwr€}”•‚„²³¯³³±„„„¡¡£Œ‹–•œkjqddmTT]TT]OOXZ[aTU[NOSdeiomrˆ‡Œ¥¤©£¢©ÂÁ˦¤±qo}edtSVk?D]OTmOTmHLiBFc;?\>B\?DX?DX>BZ>B\AEb>B\?EWzsv‚oo{ml}š––Ÿ‚„‰¦““ž›rp}Ž—±°¹°ºž¦Œ‹‘Ž“±±³ÁÁÄÄÄƺº½ÆÆÈÆÆÈÉÉÌÌÌθ¸ºÌÌÎÇÇÉÅÅÇÀÀÂÀÀºº½²²´ºº½èèêÜÛß¿¾Â½»Â¸·¾ÍÌÕÈÈÒ‡‹•y€‰©³¹íúÿä÷÷åýûäþùáý÷åÿúäþùãýøãýøâû÷âû÷âû÷âû÷ßù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÜöóÜöóÜöóÜöóÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïTUPbc^}~y«¬¨¢£žbc^‡ˆ„stpklh‹Œ‡‹‹ˆ€€~€€€‡‡‰°°²°¯³ijm]^bXZ]deiZ[^\]aTUXefjooqwwy¹¹»œ›Ÿ¹¸¿Œ‹”°¯¸††“cewLOdPTiPSkOQlIMj?B_>B\?DX@EZ?D[?D]?B_?D]BH[jo}€‚{{ˆddqxx…œœ¨††‘‘›˜˜¤£¡“xw€Ž—°¯¸±°¹˜—ž†…Œ«ª¯»»¾ÄÄÆÉÉ̾¾ÀÌÌÎÈÈËââäÍÍϸ¸ºËËÍÉÉÌÇÇÉÂÂÅÁÁÄÂÂÅ»»¾ÀÀÂÄÂÇÈÇÌÇÆͨ¦ÒÐÚÅÅΟ£{€‹†”Ôáååøøåùùãýøãÿùåÿúäþùãýøãýøâû÷âû÷âû÷âû÷ßù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÜöóÜöóÜöóÜöóÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïUVOef_lmf©ª£‰‹„WXQ„…~mohde^stpjkfddbaa^eeeŸŸŸŽŽŽijljkm^_b]^aefi„…‡LMOijlrrtkkkžžž‹‹——šjimfel…„}}ˆfivUWiPQfPSkOTmDGd;B\@EZAGZ@E\?D]?B_@E^BH[SWey}‡yy‚mmwww‚……‘Ž……‘šš¥Œ•Ÿž¥Ÿž¨‚‹”“œ³²»š—¤Œ‹”¤£¨»»¾ÅÅÇÕÕ×ÏÏÒÆÆÈÔÔÖÈÈËßßâ»»¾ÍÍÏÇÇÉÈÈËÌÌÎËËÍÆÆÈÂÂÅÎÎÐÇÆˬ«°¶´»«ª±º¹ÂÎÎ×¾ÁÌ{€‹‚‰Ÿ¬±ãóôæúúæþúåÿúåÿúäþùãýøãýøâû÷âû÷âû÷âû÷ßù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÜöóÜöóÜöóÜöóÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïUVQ[\Wfhclmffha^_Xef_cd][\U^_[^_[Z[ViifccaŽŽŒttrceddfe]_^TVUehf{}bcekmlsssiiilll‘‘‘}}}vvxxxz{z‰ˆ€‡ddpVXhTUjTVoINh@E^AGZAGZ@EZ?D[?B_@E^>BWBFWkmz€€‰llvxx„‡‡”jiytt‚‚Ž‰ˆ–•œŸž¨¨¦°zy‚ˆ†“ŽŒš…‚”“—¤¤¦··¹ÄÄÆÎÎÐÎÎÐÐÐÓ××ÚÔÔÖÛÛÝÏÏÒÎÎÐÏÏÒÌÌÎËËÍÍÍÏÅÅÇÈÈËÂÁƾ½Ä´³º·¶½²±ºÒÐÚÒÒÝŒš„‰~ˆŽÞïðêýýêÿþãýøåÿúäþùãýøãýøâû÷âû÷âû÷âû÷ßù÷áø÷áø÷áø÷ß÷öß÷öß÷öß÷öÝôóÝôóÝôóÝôóÝôóÝôóÝôóÜóòÛòñÛòñÛòñÛòñÚñðÚñðÚñðÙðïOOM[[Xiif…†klhefbcd]cd]NOJTTQUUSQQOppmppmXXVddbjjhbb_[[XWWUffdjjjjjjffdhheddbaa^^^\iifxxxqqqttrmmmomr__iPO_LMbGIbAD\AEVLOaNQf?AZAD\?AZ?BWBFZacr††‘}}ˆkkx‰‰–ˆˆ•ddq‹ŽŽ—‡‡˜˜˜¢ªª¶‹‹—˜˜¥˜Œžž¡°°²ÀÀÂËËÍÀÀÂÏÏÒÔÔÖÈÈËÛÛÝÅÅÇÒÒÔÆÆÈÇÇÉÆÆÈÍÍÏÆÆÆËËÍÉÈϾ½Ä¬±¥¤©³²»ÆÄÐÒÐÚ·¶¿‡‹“‘šê÷ùéûùéþúäý÷æÿùåþøäý÷äý÷ãûöãûöãûöãú÷áøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óáöòáöòáöòáöòßôñßôñßôñÞóðÞóðÝòïÝòïÝòïÝòïÜñíÜñíÜñíSSSNNNkkissqqrm]^Zbc\ijeQQOLLIZZWMMJbb_ŽŽŒ^^\ZZWiifbb_\\Z[[Xbb_hheaa^ddbeecVVTddbaa^__]eeceecmmksrojieiii…„ˆ__kTScTVhQUfLP\UZeUXjEH\AEZ?AZ?BWBDXIHXlly††“}}‰‚‚Ž©©´¤¤°„„__kppyˆ””Ÿ••¢””¡¡¡ªª³”žž¡´´···¹ËËÍÉÉÌÅÅÇÎÎÐÇÇÉÛÛÝÍÍÏÓÓÕÄÄÆÉÉÌÓÓÕÝÝßÚÚÚÆÆÈÆÅÌÄÂÉËÉÎœ¡¯·¿½ÉËÇÒÖÕÞœ£•šßíìëþûéþùæÿùæÿùåþøäý÷äý÷ãûöãûöãûöãûöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óáöòáöòáöòáöòßôñßôñßôñÞóðÞóðÝòïÝòïÝòïÝòïÜñíÜñíÜñíJJJMMM]][hhefhcbc^_aZfhcTTQOOM__]TTQUUS‚‚€~~{SSPbc^]^Z[\W\]Xbc^efb^_[efbiifPPN]][eechhemmkjjhddbppmbb____Ž{}‚^^hZZeX\dU[_\biZ^jFI[@DW@DXBF[HI^TSeiivzz‡ww‚–£¤ª²³¹ÅÆ̉‰•bboZZfŽ““žŽŽ—““œ¶¶¿¶´¹œœž¸¸º¸¸ºÂÂÅÒÒÔÂÂÅÐÐÓÔÔÖÔÔÖÓÓÕÐÐÓÇÇÉÆÆÈÈÈË¥¥¨···»»¾ÄÂÇÉÈÍ¿¾ÂÇÆË›š£²±ºÍÉÔ¾½ÆÀÁÇŽ”˜Üêéåøöéþùäý÷æÿùåþøäý÷äý÷ãûöãûöãûöãûöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óáöòáöòáöòáöòßôñßôñßôñÞóðÞóðÞóðÝòïÝòïÝòïÝòïÜñíÜñíAAALLLUUSccabc^Z[V^_Xab]WWUXXVUUSNNLXXVeec““LLI[\WWXTWXTZ[V_a\\]X\]X_a\^^\ZZW]][eeceecmmkjjhZZWffd[]\^a_vxwˆ‰Œklo]^bZ[]X]\]bcX\dDFS@BTDEZLMbTVhLJ[aam~~‰€€‰…†Œ¡¢¥¶·¹ÆÇËÆÆÒ……‘XWhbbo‹‹”„…‹——¡¤¥«ž¢¥¥¨¨¨ªÀÀ¶¶¸»»¾ËËÍÌÌÎÀÀÂÌÌÎÆÆÈÆÆÈÎÎÐÉÉÌŽŽyy{‹‹‹¨¨ªÂÂÅÀ¿Ä¿¾ÂÕÔÛ«ª±“‘›¹¶ÀÏÎ×Ö×Ý•›ŸÍÛÚèúøêÿúèÿúæÿùåþøäý÷äý÷ãûöãûöãûöãûöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óáöòáöòáöòáöòßôñßôñßôñÞóðÞóðÞóðÝòïÝòïÝòïÝòïÜñíÜñíHHHNNNVVTffd]^ZNOJQSL_a\WWU\\ZPPNPPN^^\cca}}zVVTXZU_aZWXQ_aZab[\]VZ[T_a\bb_]][ZZW^^\eeceecddbUUSX[ZX[Z^a_ceddddiiihheTVSTVQ[]Z^_cQQ[IIVEDTML\^]m]]jaaliir‚ˆ}~‰‹¯±°¾¿ÁÉÉÓÎÎÛ‡†–QQ^qqz˜šŸ˜˜¢–~}ÅÅǬ¬¯¿¿ÁËËÍÀÀž¾ÀÍÍÏÆÆȸ¸º½½¿ÎÎÐÍÍÏÓÓÕÎÎÐÌÌί¯±¾¾ÀÉÈ͸·¾½»ÂÐÏÖ“‘˜¹¶ÀÍÌÕÜÝãÍÓ×Õãâéûùæû÷ãûöæÿùåþøäý÷äý÷ãûöãûöãûöãûöäùöäùöäùöäùöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óßôñßôñßôñÞóðßôñßôñÞóðÞóðÝòïÝòïÝòïÝòïOOOGGGQQO]][VWSMNIUVOab]]][__]__][[XVVTaa^aa^]][TUPhibUVObc\bc\]^WWXQ^_[[[X]][VVT]][eecddbddbVXWSWXX]^[\^bdcbbbccalljWXTZ[Vbd_abdTU[JJTFFQJJVWWcaajijp\]c€„z{~}~¥¨¦±²´ÁÁËÐÐÝÍÍÚss€^^j››¤››¤¢¢«š˜¿¿Á³³¶ÅÅdz³¶ÈÈËÂÂÅËËÍÓÓÕÒÒÔªª¬ŸŸ¢¹¹»ËËÍÓÓÕÔÔÖããåééë··¹ÄÂÇËÉв±ºÂÁȯ´¯«¶ÁÀÉÎÏÕÙÞãÛéèèúøæû÷äý÷æÿùåþøäý÷äý÷ãûöãûöãûöãûöäùöäùöäùöäùöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óßôñßôñßôñÞóðßôñßôñÞóðÞóðÝòïÝòïÝòïÝòïZZZPPPQQOOOMPQMNOJWXQ^_[[[X^^\__]\\ZVVTcca^^\ZZW_a\de^XZSde^ab[_aZbc\TUPZZW]][\\Z__]cca__]aa^VXWUZ[PUWNSUcdfiik]]]cab[ZWVWSccaddd\[_WV]TSZSQVTSW]^bvwycdfqrttwvwyx›œ˜šœ©ª°ÉÉÓ××á¾¾É[[hxx…ˆˆ•””‰ˆ½½¿ÝÝߢ¢¤°°²¾¾ÀÌÌÎÂÂÅËËÍÒÒÔ¦¦©––˜½½¿ÆÆÈÕÕ×ÚÚÜææéææéÛÛÛ¿¿ÁÍÌÕ¿¾ÇÍÌÓÈÇΣŸª·¶¿ÀÁÇÝãèáïíèúøèýøåþøæÿùåþøäý÷äý÷ãûöãûöãûöãûöäùöäùöäùöäùöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óßôñßôñßôñÞóðßôñßôñÞóðÞóðÝòïÝòïÝòïÝòïXXXaa^XXVTTQOPLOPLWXQZ[V[\Weec__]bb_[[X__]XXVUVQbc\de^STMXZSde^cd]]^WUVOWXTSSP]][XXV]][XXV[[XTVSNSTGLMEIJ_acaac]]]b_a_^\VVTcca^^^VVXTTVWWZZZ\WWWZ\[fih_ba_bafihqsrŽ‚…‹Œ‘ÅÆÌÖ×ÝÒÓÙ¥¥±vveeq‡‡“‡†Ž“âá囚ž´´·ÅÅÇÍÍÏÈÈËÈÈËÒÒÔÍÍÏææéÒÒÔÍÍÏÌÌÎßßâååèññóäääÇÇÉÆÅÌÐÏÖÈÇÎÄÂǽ¹Á¬³ÅÆÉÎÔÖßëëé÷ôêûøêýùéþùåþøäý÷äý÷ãûöãûöãûöåúöäùöäùöäùöäùöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óßôñßóóßóóÞòòßôñßôñÞóðÞóðÝòïÝññÝññÝññUUS\]X_a\UVQQSNIJFOPL\]XZ[V]^Z^_[]^Z]^ZWXTZ[VXZUab[de^[\UMNG^_XWXQZ[TZ[TVWSWXT_a\XZUab]QSNXZU\\ZNPMVXWGIHXXXeee^^\aa^ccaUUSeecddbZZZSSS___[[[OOO[[[hhhXXVddbjjhyyw‡‡‡€€‚Œ‹¿¾ÅÒÒÔÈÈ˶´¹£¢¦~}„^]fvs€ˆ†“Ÿž¨“‘˜ž¢ÞÞáÒÒÔÌÌÌÇÇÉÅÅÇßßâÉÉÌÖÖÙÐÐÓÒÒÔÙÙÛÞÞÞêêêêêêÕÕÕÅÅÇÈÈË××ÚÀÀÂÀÀ··¹½¾ÀÉÎÏËÒÒÙßÝìöòìøôêýùéþùèýöåúóéþ÷åúóäùòäùôãööä÷÷ä÷ôåøöãöòåøôåøôâôñâôñâôñâôòáóñáóóáòöáòöáòöáóñáóðáóñáóñßòòßñôßñôßñôOPLUVQ]^ZZ[VHIEEFAMNIXZUTUP]^Z^_[WXT^_[XZUTUP]^Z\]V]^WXZSEF?WXQUVOZ[TZ[TXZU]^Z[\WZ[V^_[STOQSN]^ZSSP\\ZPPNVVTZZWQQOWWU\\ZPPNXXViif^^\LLIUUSWWUSSP^^^cca_a\cd_rsowxsttrqqs{z—–›¤¤¦‚‚‚ŸŸŸ¹¹»˜—œ€‰dbp}zˆ‡…‘Œ•–•œ©¨¬ÂÂÅÀÀÀÇÇÉÐÐÓÖÖÙºº½ÏÏÒÛÛÝÈÈËÉÉÌÝÝÝ×××ßßßÖÖÖÄÄÄÍÍÍÌÌÌÅÅÅÁÁÁÇÇÇ°²±ÅÇÆÅÉÈÂÇÆìñðïøôìþúêÿúéþ÷éþ÷åúöèýøåúóâ÷òæù÷åøøãöóâôòæùöãöòâöïåøôâôñâôòáóñßòòáóóáòöáòøáòöáóñáóñáóñáóóßòòßñôßñ÷ßñ÷IJFQSN^_[^_[JLGBD?GHDTUPSTO\]X]^ZVWS^_[XZUTUP]^ZZ[T[\U]^WGHAVWPVWP[\UXZSXZS^_XZ[TXZS\]VNOHOPI^_[]^ZZ[VQSNSTO^_[QSNSTOXZUQSNWXTjkfXZUMNIQSNZ[V[[X__]eec_a\de^fhadeappmlllihl~}rrp€€~¥¥¥‰ˆ£¢©ecpb_lljw´³½´³ºœ¡±±³––˜´´·ÕÕ×ÛÛÝÜÜÞÍÍÏÖÖÙÈÈËÐÐÓÓÓÓÐÐÐÜÜÜÓÓÓÍÍÍÔÔÔÆÆÆÈÈÈÆÆƾ¾¾‹Œ¹»ºÎÓÒÁÆÅ×ÜÛôþúìþøèûôåøôåøôéûùåøöä÷ôæù÷âôòãöóåøôæùöãöòåøôåøôâôñä÷ôãöóâôôâôôáóóáòöáòöáòöáóñáóñáóóáóóßòòßñôßñôßñôHIETUPbc^^_[MNI>?:EFA[\WXZU\]X]^Z\]X]^ZWXTZ[VXZU^_X^_Xbc\STM[\U[\U]^WVWPZ[T]^WZ[TUVO[\UHIBQSL_aZUVQWXTWXTQSN\]XOPLSTO]^ZPQM\]XijeXZUVWSUVQbc^^_[ccaab]fhacd]bc\de^efb___aacqqsmmmhheqqo{{~ÂÁÆ{z„\[d[Zcdcjjimˆ‡Œ¨¨ª••—««ËËÍÇÇÉßßâÔÔÖÕÕ×ÕÕ×ÓÓÕÙÙÙÙÙÙßßßáááÔÔÔÍÍÍÕÕÕÌÌ̹¹¹ÉÉÌœŸ²³¶³¸¹ÐÕÖÌÐÒéððíûùëûúìýûéùúéùýéøÿè÷ÿåôûå÷úä÷÷ä÷÷ãöóä÷ôâôòâôñä÷ôä÷ôãööãööâôôáóóáóóáóóáóóáóóáóóáóóáóóßòòßòòßòòßñôIJFIJFZ[V\]XLMH9:6BD?]^ZVWSUVQXZU\]X[\WZ[V^_[WXTab[\]V]^WXZSNOHTUNXZSXZSZ[Q]^UbcZ\]T\]TTULWXOZ[TSTMXZS]^WLMFZ[T[\U_aZbc\OPI]^Wde^bc\^_XWXQab[]^Z[\W^_[hibde\abX_aZ]^Zbb_VVXjjljjh_a\jkfccahhj¦¥ªÌËÏŽ”•”›zy~~‚ªª¬¥¥¨bbd°¾¾À¤¤¦¾¾ÀÀÀÂÍÍÏÓÓÕÒÒÔÜÜÜåååßßßâââÜÜÜÔÔÔÈÈÈÁÁÁÆÆÈÅÄÈž¢°±´²´ÂÇÉÛßââèêêôøéöúÕâé·ÂÌ—£±—¢´š£¹¡«¾·ÅÓ°À˺ÌÓÍÞäâó÷áóóÝðíä÷ôÝððáóóáóóßòòáóóáóóáóóáóóáóóáóóáóóáóóáóóáóóáóóáóóLMHLMH\]X^_[QSN?@;EFA[\WOPLQSNZ[VVWSZ[VZ[VZ[VUVQ\]V[\U]^W\]VJLEPQJUVOUVOWXO\]TabXZ[QQSITULXZP[\SOPIWXQbc\UVOTUNWXQ[\U[\UNOHde^ab[[\U\]VUVO]^WXZS\]Xcd]Z[Q]^Ucd[]^UZ[T__]ZZZfffbb_Z[V_a\bb____‹‹žž¡¶´¹²±¶‰ˆ~~€œœž¸¸ºkkm‚‚…‘œœž¨¨ª´´·²²´½½¿ÍÍÏÐÐÐÚÚÚßßßéééæææÛÛÛÌÌ̸¸ºÎÍÒ¿¾Â¡¢¥©ª«°²´¹»ÎÓÕáæëÏÖÝÇÎ×´¿Ÿ¥¶¬±Æ¢»„‡¤„‹¦„¥€Ÿ‹›¨—¨²¨¹ÀÆ×ÝÜíñÞðóäöùâó÷ßñôÞññáóóáóóáóñáóñáòöáòöáòöáóóáóóáóóáóñáóñVWSQSN[\WZ[V[\WGHDHIEXZUNOJSTOZ[VXZUZ[VVWSXZUOPLWXQXZSWXQXZSGHAMNGPQJQSLSTJ[\S_aWUVMMNEQSIUVMZ[Q\]VQSLXZSXZSVWPZ[TXZSUVOOPIde^^_XWXQ\]VTUN[\UUVOZ[VZ[T]^U_bU^aTbcZUVOaa^\\\bbb\\ZXZUbc^iif^^^iiikkk´´·¡¡£‡‡‰œœž¥¥¨jjl‡‡‰ÄÄÆ””–††ˆ••—¹¹»¹¹»„‘‘‘ÒÒÒðððÔÔÔÙÙÙåååÙÙÙÆÆÈÂÁÆÎÍÔš›¡¬³°³¹¥©¯»¿ÅÞâèëñóÖÜáÇÌÖ¸½Ëßãø±³ÎŽ„‹¨~‹¢z‰›}ŒŽŸŽž¡¢²¿¾ÎÙÙêñãôúáòöÝððáóóáóñáóñáóñáòöáòøáòöáóóáóóáóñáóñáóðWXTTUP]^Z\]Xab]MNIJLGWXTIJFPQMNOJ[\W[\WPQMZ[VIJFUVOVWPOPIPQMDE@IJFNOJNOJPQJZ[Q^_VSTJOPGOPGNOFXZP[\UNOHUVOVWPIJDSTMWXQUVOPQJ\]V_aZZ[T^_XUVO[\UTUP\]XZ[V_aWcd[WXO\]Tab]^^\]][aa^\]X^_[dealmieecbbbTTQddb———¢¢¢}}}«««›››SSUyy{»»¾……‡ppr€€‚¾¾À˜˜›†††ppp¶¶¶äääíííæææâââÝÝÝÏÏÏÄÂÇÄÂÇÁÂÆŽ“±²¶—˜œ¨©¬ÒÖÙèìïÓ×Ú»¿Ç½Á͸»Ïœž·€‚Ÿ…¢}†ž{ˆ{ˆy†›x…š}‰žˆ•ª•£´¡¯½ËÜãáòøáòöáóóáóñáóðáóðáóóáòöáòöáóóáóóáóñáóñáóñSTOVWSWXTUVQUVQVWSPQMXZUGHDJLGOPLab]LMH[\WPQMIJFQSNMNISTOTTQIIGNNLLLLMMJSTOSTMUVOUVOQSLWXQSTMVWPVWPPQJOPISTMGHAQSLPQJSTMUVMUVM\]V^_XXZUUVQUVQMMJTTQZ[V]^W_aZab[[\UXZU^^\[[X\\Zdeade^ab[lmiffd__]UVQZ[Tjkf}~yool‚‚€iifXXXlll¡¡¡ŒŒŒ•••žžž~~~hhhddb““¸¸¶ÎÎÌååãÕÕÓÖÖÔ¯¯¬ÇÇǺº½ÐÐÓ±±³©©«ŸŸ¢Ÿ¥¦©ÍÎÒæèí¯¯¸©«¸›¯Ž¥†‡Ÿ„†¡ˆ¤”˜Ÿ¤»¤©À“—¯‰Ž¨„t{•…¢¤²ÂÕåðáòøÞòòßôðßôíãøñâôñãóòãóòãóôâòóâòöâòöâòöJLGPQMVWSVWS[\WXZUNOJSTOGHDIJFUVQ_a\LMHWXTNOJEFAQSNLMHNNLUUSLLLLLLGGIJJJOPLPQJTUNTUNSTMMNGZ[T[\UVWPPQJOPISTMNOHLMFSTMOPIUVMUVMXZS]^WVWSTUPOOMHHFPPNXXV]^Zab[cd]^_[XXV]][^^\__]^_[^_XUVO^_[XXVTUPQSLVWNcd]mohbc^xytffd\\Z___qqq‡‡‡†††vvvmmm\\\^^\qrm¦¨£‰‹†×ÙÔ«¬¨ÄÅÀ‹ÌÌÌ···ÎÎÎÐÐÐÛÛÛ½½½ºººªª¬ÝÜãÒÐÚ¾¾É¬«»”–¨‡ˆˆ‰¢‰‹£…‡Ÿ†ˆ¡“«›¶¢¤½–˜±Ž©„ˆŸy‚˜‡•¦£±¿ÕæíÞðóÛðìáöïßôíâôñãóòãóòãóôâòóâòöâñøâñøFGBNOJTUPVWSVWSTUPJLGOPLPQMLMHZ[VTUPJLGVWSVWSNOJOPLMNIMMJSSPPPPGGG@@BGGGIJFQSLMNGUVONOHWXQ]^W^_XVWPPQJOPISTMUVOHIBOPINOHUVMUVMVWN[\UQSLUVQQSNPQMOOMVVTWXTZ[Tef_deaZZW^^\[[Xaa^XZU^_X[\U]^ZPPNJLGUVO\]Tab[bc\TUPefb[[XQQO\\Z__]eeeqqqxxxiiiqqsVVV\\Zffdlljyyw¶¶³{{y——•rrp´´´³³³ÆÆÆÁÁÁÈÈȬ¬¬½½½»»¾âáèÇÅÒÍÌÜ–•¨‘“©€˜{{—„„¢€‚Ÿwy–~€›‘ª£¦»²¶ÉŸ£´–©€ˆœ{†˜‚¡¬»ÆÚëñæùùãøôáöñâôòãóòãóôãóôâòóâòöâòöâòö@@>FFDJJHJJHVVTPPNBB@DE@QSNJLG[\WTUPJLGTUPUVQIJFIJFPQMNNLOOMSSSEEE::=EEEHIEHIEQSNQSNNOJQSNTUPZ[VVWSPQMOPLSTOXZUIJFJLGNOHJLBTULXZP]^WNOHSTOMNIJLGPPNPPNOPLPQJ]^Wbc^XXVVVT\\ZccaPQMVWPWXQWXTJJHGHDVWP]^U^_XXZSPQMcd_bb_]][TTQ\\Z___hhh[[[TTV^^aLLNNNNbb_ddbiif‚‚€eecmmk]][ŸŸŸ³³³ººº¾¾¾………{{{žžžÂÂÅÙ×ÜÆÅÎÆÆÒ°¯¿Ö×ì¿ÀÙ••±††¤wx—xy˜}œ€‚›‹Ž£”—©¢°šŸ•©t‘w“Œ›¥ÏÞæÜíóßñôä÷÷ãóôãóôãóôãóôâòóâòóâòóâòö>>>AAAMMMFFFHHHJJJAAA@@>PQMPQMXZUMNI@A=HIENOJEFAGHDFGBFFDGGENNNAAA99;>>>DDA@@>LLIMMJLLIJJHNNLOOMUUSMMJIIGPPN]][SSPJJHMNISTJWXO^_X^_XPQMEFAHHFIIGLLIPPNVWSSTM^_X]^ZSSPTTQUUS]][UVQUVOZ[TUVQHHFMNIWXQ_aWab[]^WUVQ\]XZZWPPNUVQXXVQQO[[[UUUMMOONSGGIPPPZZZZZZ\\\TTT[[[\\\iii‹‹‹Â–––°°°sss€€€ˆˆˆžžž½½ºÉÉÇÀÁÅ••žÅÇÖÐÒ昚²‡‡¥{}œxy˜xz•}—‚†š˜œšžª¨»¢ª½‹“¦r}ŽsŽ¨·ÆÐÜíôÛìòãó÷äôöãóôäôöãóôâòóâòóâòó666;;;GGG>>>DDDAAA>>>AAAMMJJLGPQMNOJBD?HIELMHDE@DE@EFAEEBDDASSSFFF88:::=;;;@@>??=IIGGGELLIGGEFFDOOMLLIFFDQQOXXVSSPNNLHIELMFSTJ\]V^_XWXTGHDFFDDDAGGEJJHQSNMNG[\U]^ZSSPOOMVVTXXVUVQPQJVWPLMHIIGSTO^_Xfh^fhabc\VWSQSNSSPXXVNOJTUPWWUPPPQQTGGIHGLA@ENNP[[[UUU___WWWSSS]]]ZZZbbbœœœ~~~jjjlllooo‚‚‚‹‹‹±²ÇÈĪ¬«xy¦ª´}Ž‚—xy‘rty{–{~–wz…˜¢šž¬£¨¶¢¨º˜¬rzlwˆr}ŽŒšª²ÀÎãóþâñøãó÷äôøâòóãóôãóôâòñâòñ>>@::=FFHFFHJJMHHJBBE999MMJIJFGHDDE@BD?FGBLMHGHDBD?FGBFFDBB@TTTJJJ88:99;888777>>>BBBLLLEEEGGGGGGJJJFFFGGGQQQQQQUUUOOODDAMNGPQHVWPVWPWXTIJFLLILLINNLLLIMNIHIB^_Xfhc\\ZTTQWWU[[XZ[VUVOWXQOPLHHFTUPbc\ijahibab[XZUFGBJJHXXVOPLXZUUUSNNNSSUPPSQPUDBGJJMUUWPPS^^aJJMHHJPPSbbd^^acceXX[VVX[[]ddf~~€‚‚…¯¯¯–––£¤¦mot˜z~ˆoq~qs‚ps‡{”{”rv‹tx„‡œ‚†›Ž‘¦—œ±‘¦iq…fo‚s~ˆ“¥—¥·ÄÒâÜëóâñøâòöâòóãóôãóòãóòâóð???>>>IIIGGI??A;;>AADAAAEEBHIEEFA?@;?@;BD?LMHMNIDE@IJFIIGDDAQQQNNN:::;;;777666===AAAJJJNNNMMMNNNGGG>>>JJJPPPMMMVVVLLLFFDGHDMNGUVOVWP]^ZOPLQQOQQOJJHEEBHIEFGBUVQbc^VVTJJHOOMZ[VVWSXZUQSNXZULLI]][^_Xde\cd]\]Vab]NOJNNLSSP\]XXZUXXVJJHQQQPPSUTXLJOFEIIHMNMQZZ\PPSMMOOOQ[[][[]]]___bWWZTTViikŽŽooq‚‚…yy{ˆ‰fhkz~„kotfjrilwoq~vx‡rt„fizwx„…›~•„†žˆ‹£…‰¡vz‰‘¤qypyˆ‘ª˜¥ºÅÔÞÛêñßðóßðñâòóãóòãóòãóò480794BEALNM>?A236687FHE@@>FFDFFD>>;GGEAA?FFDHHFDDALLIJJHJJHVVT]][TTQFFD442997;;9@@>DDALLIJJHBB@BEAEGFILJEFHFGINPO@BAGIFDDAIIGUVQ[\WOPLLMH997???GGEBB@FFDEEB]][[[XQQONNLLMHSTONOJWWUSSPMMMIIIUUSef_de\ab[ef_cd_TUPMMJNNLWWU\\Z[[XTUPMMJNNLUUUSSUDEJEFLFGMVW[MNQIJNIJMUVX[[[QQQUUUVVVOOO]]]eeeeeeefi^_bijlabdcdhopshilefjdekqqzssjjwrq‹‰œ˜—¬‡ˆž„„ŸoqŒcfzw}{”s{‘t{˜~‡¢›¬ÌÙßßìïâðïäôöáñòãööáóóAE:AE=EGBDFE9:=013687ILHEEBLLIGGE886663@@>GGEEEB??=MMJPPNQQOaa^bb_XXVTTQ??=@@>;;9DDAFFDLLIJJHAA?JMIEGFGHJFGIDEGIJMJMLFHEFFFGGGVVTXZUQSNTTQ???;;;FFD@@>FFDNNLiif__]SSPSSPMNIOPLOOMJJHQQQFFFDDFBBBVWPab[ab[TUP\]XVVTMMJMMJSSSWWWPPNXZUIJFNNLNNNOOQFGMDDMGHNTU[NOSEFIEFHVWZSSSMMMTTTXXXQQQVVV[[[WWW^_bUVX^_b]^a]^abcebce]^abcfdei{}‚ffpvv‚Œœ«ª½Œ‰¡‰‰¥ij‚advsx†£¦º{€—tx–t{—€ˆ›¤ÛèêäòñãóôäôöÛííä÷÷BF;=@8>@;>@?78:-/1243BEAMMJOOMFFD220220??=EEBGGE@@>IIGJJHLLIUUSbb_ccaaa^OOMEEB997BB@DDALLIJJHBB@DFB>@??@B?@B:;>@ADNPOILHLLLNNNZZW\]XUVQOOMPPP@@@LLIMMJIIGJJHbb___]TTQLLIUVQMNIOOMNNLNNN===::=???PQMXZS[\WGHD\\ZLLIFFFIIIQQQWWWLLIXZUJLGOOMOOOJJMGHL@AGEFLNOSOPTFGIFGIWZXMMMHHHNNNTTTVVVUUUSSSWWWTUWUVX\]_VWZbce]^a]^abcebcfdeibci^^hhhsllyzy‰‹‰žˆ‰¢qrˆikzšœ©¬°Á–š¯qsrwr{‹v€ˆÅÒÔâðïáñôãó÷åö÷ßðñTWMNQI?A=@BA@AD347243?A>NNLIIG??=774>>;;;9==:JJHGGEHHFHHFQQOJJHQQOSSPXXV]][HHF774AA???=IIGMMJGGE:=9;>=@AD=>@;=?;=?EGFDFBGGGOOOOOMXZUWXTJJHJJJ???LLIHHFAA?GGEZZWTTQJJHJJHHIEHIEHHFGGE@@@;;;88:AAA\]XXZUXZUUUSLLI???IIIGGGJJJQQQQQO_a\QSNQQOSSSFFH@AE;=BBDGGHLPQTMNPMONX[ZJJJEEEIIINNNIIITTTTTTVVVOPSNOQTUWVWZXZ\_acXZ\[\^^_cefjfhmQSXeeoddpxx…†…•‘“¨z}Ž_bomq{ž—˜~—txqw…w‰ŸªÜéëäñøâñøãó÷áñò[^TOSJ8:68:9@AD124364>@=LLIJJHAA?::8HHF;;9??=QQOBB@??=QQOSSPNNLOOMOOMNNLZZWEEB::8EEBEEBFFDLLIPPN9;80219:=46801389;>@?@B?FFFQQQSSPNOJXZUSSP>>>BBBOOMLLIGGEFFDOOMHHFBB@BB@EFA?@;AA?DDADDD???::=EEEPPNPQM[[XAA?>>>:::FFHPPSFFFMMMNNLXZUSTOMMJSSSIIL?@D:;?GHLSTVIJMMONNPOUWTOOONNNFFFMMMHHHQQQOOOQQQLMONOQOPSMNPXZ\]^aVWZPQTVWZVW[^_c]^b[\b_afffpmmyz}‰acp[^feiqmp}‰ˆ˜{zoq‚lq{ipw‡“ÅÏÕáëóÞëòßìñéöúTWMLOGDFA;>=@AD679132@B?LLIQQOGGE774MMJEEBAA?NNLEEBAA?PPNLLIWWULLIFFDIIGVVTAA?442??=BB@IIGJJHTTQ>@=79889;/02124>?A?A@GIFGGGEEEHHFQSN[\W^^\LLLLLLLLIIIGJJHEEBIIGIIGAA?GGE@A=DE@HHF@@>BBBHHHEEGBBBJJHMMJZZWBBB@@@NNPGGIMMODDDAAA>>;NOJXZUMMJPPPIIIBDFBDGNOQZ[]LNMLNMJMIQTPVVVQQQEEELLLHHHNNNSSSVVVPQTOPSPQTFGITUW[\^UVXTUWQSUTUW\]_^_cOPTVW[cdhklrdhpSV^W\^efjss}€€vt…oo{eiqekpv~¶½ÄÜãì¸ÁÌâìòâïóMPFMPHNPL=?>=>@78:8:9LNJGGENNLHHF>>;PPNNNL>>;JJHBB@@@>MMJFFDUUSTTQNNLHHFWWU@@>331;;9DDAQQOIIGUUSFHE;>=89;34789;@AD:=;>@=HHH>>>HHF]^Zab]\\ZZZZLLLLLIMMJHHF@@>DDAEEB774IIG@A=;=8FFDBB@DDDJJJNNPGGGGGELLI[[[EEENNPQQT@?DBBE;;;>>>??=QSN^_[LLIJJJIIIGHJHILMNPUWVNPOHJGEGDMOLSSSVVVLLLOOOMMMJJJWWWWWWVWZMNPIJMIJMPQTPQTZ[]WX[LMONOQ[\^_acUVXUVX^_bbceX]_TX[dehdehdcjvt~wtjirbfibhjjpt£©°¿ÆДžÌÖÜÙãæIMBSVNPSN=?>=>@1249;:HJGMMJFFD??=@@>AA?UUS>>;TTQFFDGGEUUSMMJLLIOOMOOMLLI\\ZEEB663>>;FFD[[XFFDNNLBEA8:92364682369;:HJGILHDDDFFDIJFJLG[\WPQMJJH??=GGETTQJJH886>>;MMJ;;9HHFFGB?@;NNLIIGFFFSSSUUU???GGGMMM^^^JJMIILEDHDBG;:?88:>>>==:HIE^_[GGEFFFHHJBDFFGIGHJSUTOQPGIF@B?ILHGGEXXXWWWVVVSSSHHHXXXUUUQTSQSUGHJMNPMNPNOQXZ\\]_QSUPQTVXWX[Z[]\UWV^a_abd^cdPUVacbbdcbaehfmmlsbah^cdejkilrv{‚‚‡“}„Ž»ÂÉÙãæGH?PQJWXTMMM@@B//1BBBBB@JMH:=8362798>@?TVSFHDTVQDE@MNIVWSOPLNOJJLGMNIHIEQQOOOM9:6FGBVWSab]GHDLMHJJJ>>@224224DDDIII??=DDALLIHHFMNINOJVWP^_XSTMHIEJJHMMJDDA442::8886886EEBNNL@@>EEBTTQAA?LLIXXVIIIOOOEEETTVPPSVUZFEIBAH:9>88:???@@>JJH]][AA????JJMABFFGJHIMFGIXZ\MONILJMOLIIGTTQ^^\MMJTTQPPNNNLTTQSUTQTSNPOLNMILJILJQTS\^][\^UVXUVXVWZ^_b[\^[\^]^a\]__ac\]_^_babd^_c^_c_ac^_bijlhioeiq_dp^co€‡Ž•œ£@A8MNGOPLIIIDDF113:::;;9PSNAD?3644768:9NPO@B>OSJNOJLMHOPLLMHPQMFGBLMHAB>UUS[[XGHD?@;HIBZ[THIBJLGFFH327224BBELLLPPPAA???=??=??=HHFNOJPQM\]VUVONOHJLGPPNNNL;;9442663774GGEPPNBB@AA?QQOIIGEEBPPNSSPWWWIIIGGI??AFEI@?D=;B98=779??ADDDZZWaa^LLL@@BJJM9:>?@DDEHFGJOPSGHJGIHJMLJJHOPLZ[VUVQXZUVWSQSNVVTPSQX[ZWZXLNMHJIFHGJMLUWV\]_TUWQSUTUWZ[]WX[STVXZ\[\^XZ\[\^Z[]^_bQSUVWZ\]_bbbcce_afadlX\fX]hsy€}„‹GH?LMFTUPFFFQQT113111;;9MOJAD@/10/02468JML=?;JMHNOJIJFOPLMNIGHD?@;IJFEFAFFDUUSWXTPQMNOHWXQJLEQSNLLL99;,,/;;;UUUUUSNNL@@>@@>>>>EEBGGELMHVWSNOHGHABD?MMJPPNHHF886220997@@>SSPDDA==:NNLJJHFFDPPNTTQWWUJJJNNNHHJ@@B;:??>BIHM@@B??AMMMZZWZZWQQQ;;>GGI:;?;=@?@DBDGMNPHILGIHHJIMMJNNLUUSZZWVVTUUSPPNTTQQTSWZXVXWOQPHJIGIHGIHOQPXZ\QSUNOQVWZXZ\Z[]PQTWX[XZ\VWZXZ\WX[]^aPQTQSU]^a_acWX[TU[[^fSV^LOW_ej_ejLMDQSLNOJ@@@SSU>>@777;;9LNJFHE236347679LMO>@=MOLPPNIIGOOMEEBBB@AA?FFDDDAMMJVVTVWSFGBFG@VWPQSLVWSFFF447;;;777LLITTQHIEEFADDDAAAGGGIIGFFDTUPQSNMNIMMJUUSMMJPPN==:++)997??=TTQDDA>>;LLILLIIIGNNLPPN\\ZIIGUUULLLWWZMMOFEI87;668==?HHHQQO\\ZJJJMMOHHJ89=9:>@AEHIMIJMEFHADB?A@OOOQQQSSSVVVNNNQQQNNNPPPSUTLNMMONSUTNPOILJHJIMONWX[TUWJLNMNPTUWTUWIJMTUWTUWWX[TUWVWZUVXSTVJLNXZ\WX[OTVIMSPTZQU]OSXZ^aW\^VWNUVOMNIDDDOOQTTVHHH::8>@==?>*+-&(+67:@AD@BAEGFFFF>>>FFFFFFMMMPPPPPPMMJAA?QQOWXTHIEIJDNOHTUNPQMJJHGGGTTTFFDIIGVWSSTO>?:888668>>>AAA>>;HHFPPNSSPSSPMMJNNLQQOIIG774442??=VVTOOMEEBFFDUUSMMJIIGMMJXZUXXVWWULLLTTTLLN--0336113>>@HHHUUS\\ZOOOLLN??A67::;?=>AGHLDEGFGI=?>EGFLLLTTVLLNOOQLLNNNPGGIQQQSUTOQPQTSOQPWZXPSQOQPZ\[VWZUVXGHJLMOPQTXZ\FGIHILPQTQSUTUWWX[STVZ[]MNPPQTMQSPUWJNTBFLLOUVZ_TXZTUWWXOLMFHIE???DDFGGI>>>11/79878:)*-*+/237469468:=;DDD======AAADDD@@@@@@DDDEEBUUSVWS?@;@A:FG@VWP[\WQQO[[[SSPEEBNOJQSNOPI894AAA>>@>>@======JJHPPNJJHIIGMMJHHFNNLOOM@@>AA?BB@UUSVVTNNLHHFSSPIIGMMJJJHUVQSTOLLIQQONNNOOO;;>IIL88:;;>QQQOOM[[X\\\BBEDDF?@D?@D;=@>?BDEGDEG9;:;>=EEGPPSJJMGGIGGIJJMFFHLLNJMLMONQTSPSQSUTSUTUWVTVUOPSNOQEFHIJMIJMPQTBDFFGILMOPQTSTVTUWMNPVWZTUWOTUFMMPVXPTZEHNIMSTUXQTSQTSUVMPQJEFABBB??AEEGBBB886243236(),/0634:67:78:=?>FFH::=::=??AAAD::=::=AAATTQVVTWXTMNIJLEFG@NOHOPLTTQ^^\]][GHDMNIQSLEF?9:6IILGFJ??A::=999HHHMMJGGEGGEJJHGGENNLSSPGGE??=;;9OOMWWUTTQGGEIIGJJHNNLFFDQSNLMHMNILLINNLNNNFFF@@@GGIMMOUUUGGEXXVNNNAAD88:78;9:>?@D@AE:;>>?A?A@@BAEEGNNPLLNFFHEEGGGIEEGEEGFHGMONOQPSUTTVUQTSVXWOQPTUWNOQEFHEFHBDFMNPHILNOQHILJLNPQTQSUHILPQTWX[MQSAGIMSUQW\IMSMQTTUWTTQVVTJLEIJDHIE??=BBBQQQIII444-/1236+,0/03-/29:>;=??A@JJM447@@B@@B>>@::=::=>>@@@@UUS[\WGHD?@;BD?OPLWXTPPN\\Z\\ZLMHGHDLMHDE@==:LLNMMOAAD==?777AAAJJHLLIHHFBB@>>;@@>@@>BB@>>>999HHHPPPMMJFFDJJHFFDFFDLLIMNINOJJJHIIGMMJ[[[XXXUUULLNPPSQQQDDAUUSPPP99;44778;=>AIJNIJM9:=?@BDEGBDFBBEEEGFFHBBBBBBEEGFFHAADEGFNPONPOSUTPSQILJVXWVXWUVXOPSJLNJLNEFHJLNFGIFGIFGIHILLMOPQTHILMNPWX[GLM=BEJPSOUWJOQLPQPSQNPMTTQNOJOPLPQMGHDDE@GGEBBE87;:;A01778;013124468:;>>?AEEG779779AADIIL99;336::=HHHZZWUUSEEB>>;FFDLLI[[XPPNZZZ\\\PPNBB@MMJBB@BBBDFEILJ;>=FHG=?>8:9MONFHGLNM@B?9;8=?;?A>;>=78:348=>AGHJHJIILHLNIJMIHJGFHGHJINPOFHGFHGFHGLMO?@B:;>ABEIJMEGF?A>TVSOQP@AD89;/039:>FGIUWV=?>;=?:;>?@D=>AEFHSUTOQNEGD=?>@AD?@BLNMNPOPSQQTSQTSJMLNPOX[ZTUWPQTIJMNOQJLNGHJGHJIJMDFEGIHGIHMONFHGLNMVXWMNPINOHMNMQSLPQHMNINOMQPQTSPPNMMJLMHDE>;=8AA?>>@32911:/06;=@6796879;:9:=:;>>>@224779??A==?224//1668===IIGVVTNNL>>;EEBPPNTTQZZZXXX\\\IIIAAAGGGFFF@@@?A@BEDDFEBED:=;8:9JMLEGFILJ>@?362362:=;89;46923967=@AEDFEEGDGIEFHEEGFDFEJLNNOQDEGABEFGIQSUDEG9:=BDFABEDFE@B?OQNTVUIJMABE2379:>EFHVXWEGF;=?78;:;?>?BIJMTVSTVQJMHBEADEG?@DGHJHJILNMQTSMONHJILNMTVUWX[OPSIJMMNPPQTJLNEFHABEGIHHJINPOLNMJMLSUTTVUMONFJLEIJINOHMNEIJGLMINOLPQIIGQQOTUPFG@9:6??===?329,,6-/4?@D?@B243=?>;=?>?A?@D12667:78;-/2+,0126;=?>>>HHFUUSQQOAA?AA?JJHUUSUUUZZZWWWPPP@@@JJJEEEEEEADB@BAHJIADB9;:9;:HJIEGFMONDFE9;8796=?>9:=46912889??@D=?>;>:?A=BEAFHGILJGHJJLN?@B?@B?@BQSUNOQLMO>?AEFHILJ?A>NPMSUTHIL@AD:;?ABFGHJVXWSUT>?A78;89=469GHJQTPWZUOQMILHEFH>?BJLNHILFGIGHJEFHBDFFGILMONOQIJMGHJEFHJLNJLNHILEFHEGFFHGJMLEGFBEDMONQTSNPOHMNGLMLPQJOPBGHDHIGLMINOQQOUUSUVQGHA=>9BB@AAD98?//8+,2>?BEFH687ADB:;>:;>>?B126:;?:;?237014348:;>???MMJLLIDDA>>;FFDHHFQQOWWWUUUZZZPPPEEEIIINNNGGG@BA8:9=?>:=;7989;:FHGDFEHJIDFE=?;9;8DFE>?A469/0667=>?B>@?=?;FHDFHEFHGFHG>?AFGI?@BBDF;=?EFH;=?9:=78:?@B=?>=?>PSQLNM=>@67:67:ABFDEGJML\^]GHJ>?B89=:;?MNPPSOTVQOQMILHGHJABFHILGHJEFHEFH?@B?@BBDFFGIHILMNPNOQ?@BIJMJLNIJMEFHFHGNPOJMLFHGILJMONVXWLNMEIJDHIHMNGLM?DEAFGDHIFJLSSPWWUWXTPQJ=>9??=DDFA@GEEN12878;347798@BA@AD4687;>&*037=14:-17*-3*-3-/2:::NNLQQOIIG??=AA?GGELLINNNUUUWWWNNNAAAHHHQQQGGGEGF?A@9;:ADB8:99;:DFE@BAEGFBED@B?=?;GIH9:=126-/478>;=@ADB>@=BE@?A>:=;798>?A;=?67978:67989;78:3479:>:;?9:=>?AGHJPQTFGJ46989=?@DEFHEGF\^]LMO=>A12667:FGIQTPX[V^a\JMIHIL;=@?@D>?B?@D?@D;=@:;?@AEHIMGHJ?@BJLN9:=ABELMODEG=>@HJIOQPJMLFHGFHGEGFNPOHJIAFG@EFDHIAFG>BD;@ABGHGLMOOMUUSUVQOPI894886==?>=D88A/0689=6799;:ADB>?A12637=$(-,06(+1*-3(+1*-3014;;;LLINNLHHF@@>==:??=HHFJJJUUUTTTQQQ===GGGMMMIII@BA=?>9;:HJI?A@>@?DFEBEDADBBEDEGDGIFILJ;=?46912834:78;>@?>@=GIEEGDBEDADB>?A9:=12434767989;89;67:78>;=B89=89;DEGNOSDEJ12878;=>AABEDFE[]\PQTBDG9:>FGJMNPSUQWZU]_[PSOLMO?@D;=@:;??@D>?B78;9:>ABFIJNMNPGHJPQT@ADGHJIJMGHJGHJPSQOQPNPOEGFGIHEGFMONMONFJLDHIFJLDHI;@A;@ABGHEIJSSPUUSPQMGHA340997;;>218++4,-378;679364>@?>?A469-17&*2/2:,08%)1%)1*-6239PPPQQOBB@442==:??=;;9==:IIIOOOUUUSSS;;;AAAIIIDDD@BA=?>>@?JMLEGF?A@?A@?A@9;:?A@GIFLNJILJ;=?469128/060149;::=9FHDBEA=?>8:99:=67901334746878:78:46934:89?46967:HIMIJN?@F67=34889=?@BDFESUTPQTDEH>?BGHLIJMOQNSUPZ\WUWTOPS?@D9:@9:@>?E:;A78>89?=>D@AEABEABENOQEFHEFHFGIJLNLMOGIHGIHMONJMLGIHADBFHGHJIBGH?DE@EF=AB9>?;@ABGHBGHNNLQSNOPIFG@:;7::8779,+2%&,,-3469124687>?A;=?014),4#&/&*2"%-"%-#&,*-3348DFELLIFFD??=886DDALLIGGEBBBNNNPPNTTQ;;9IIG@@@>>>9;:@BAGIHPSQOQPEGFDFE?A@=?>BEDLNJQTPGIH9:=126-/467=237:=;=?;@B?=?;9;:78:89=67:01434812634834812622;33=12878;IJNNOSDEJ78>12889==>@ABESTVVWZJLNFGJNOSHILILHJMHQTOTVSMON;=?9:>67=:;A9:@12878>>?EABH>?B?@BHILABE89;?@BJLNIJMFHGJMLLNMQTSNPOADBFHGIJMDHI?DE?DE;@A7;=;@ABGH@EFPQMMNGOPISTMMNIBBB=;@43:)*0()/78;3474689:=78;/06**6%%1$$-%%/()/126236013>@?BED@BA9;:;>=ADBFHGLNMPPPHHFQSNQSNHIELMHHHFBBB78:@ADFHEMOLLNJJMIIJM@AD>?ADFEOQNNPMADB78:34:,,612812689;9;::=;89;78;78>14:14=03;/2=-1;69A26>03;009009/0678;GHJJLO@AG34:1289:@?@D=>AFGJVWZEFHEFH@@BLLNFFFIIGUUSUUSNNLGGGEFH89=34:67=11:88A66?88A?@DEFHHILBDF=>@=>@GHJEFHEFHBDFIJMNOQGHJGHJEFHHIL:;?=>A>?B:;?9:>9:>=>A:;?PQJIJDZ[TMNIDDA===76:218*+1,-3:;?236-/1348128((1))4%%2%%1&&0&(--/2468687?A@:=;798798?A@?A@BEDADB???GGGJLGOPI892>?:???;;>89=ABEFHENPLQTOGIFFGIFGJBDFABEGIHNPMJML=>@239,,634:67=9:>236?@B?@D;=B46;37?,0:+-:02?13@79F14?,08--922;017237:;>QSVFGM67=34:78>EFL=>DBDGNOSGHJ>?A??ALLNHHHFFFSSPWWUPQMEEBNOQ?@D34:239//866?11=>>G?@DDEGGHJ@AD:;>=>@DEGDEG>?A=>@HILNOQMNPFGIABEGHJDEH@AE;=@78;=>A=>A>?B=>AQSLGHAWXQOPLBB@III649107+,2128>?B013+,/126/06%%/&&2$$1%%1))2%&,*+/9:=>@?>@?9;:364243:=;BED>@?>@?GGIGGGNNLLMHAB>IIG;;;==?9:>>?A>@=DFASUP@B?;=?@AE@AD9:=:=;GIFNPO?@B017//834:89?=>A89;>?A89=34:34:26>+/9*,9/1>13@79F14?,0822>//8,-3348?@BOPT@AG23923967=DEJ;=BABFMNQHIL;=?JJMIILFFFHHHVVTTTQMNIHHFX[ZWX\89=67=34:66?11:88A=>A@AEABF:;?78;;=@?@DABF?@B>?AHILNOQMNPFGIABEGHJ?@D9:>67:469BDGEFIBDGDEHLMFQSLTUNNOJMMJ@@@327/-4()/128=>A)*,*+-/03,-3$$-%%1$$1&&2**3#$*&(+;=?BEDEGF679/02679679:;>ABE@ADDDFDDFNNLPPNOOMMMJJJMAAD>?BDEG>@=>@;NPL:=9124014@AD>?A:=;BEALNM=>@-/400967=23934812478:78;67=34:/2:-1;,/;+-:-0=68E26@03;11=11:,-3014FGISTWIJP67=-/467==>D9:@ABFQSVIJM=>@>>@@@BEEEFFFTTQVVTOPLFFDZ\[abdABF237/0612899B67=BDIEFIEFI=>A469:;?;=@@AE?@B=>@DEGHILGHJGHJEFHHILGHL=>A469126>?BBDG@AE?@DSTMIJDQSLVWSEEB@@@98=/-4()/128;=@+,/*+-)*-#$*$$-%%1##0$$0&&0&(-)*-BDFILJ236/03,-1348;=@67:78;34898===?GGGLLLAAA???336-,1+,0236AD@HJFTVQGIF124/03=>@>?AADBEGDBED89;,-3++412846;78;01378:89=89?78>,08(+6-0=02?+-:+-:+/9+/7--9,,6,-3469LMOLMPNOU:;A/0646;89?9:@@AEIJN@AD9:=AAD==?:::AAATTQ[[XLMHLLIZ\[TUWMNP=>A126/06*+19:@;=B;=B>?E46;67==>D?@F>?B;=?;=?BDFEFHIJMIJMHILFGIDEGEFH679124?@BHILHILDEG?@9@A:PQJUVQTTQFFF438(&-()/78>BDG/02)*,)*-#$*%%/##/""/$$0**3()/014GHJTUW89=/03+,0-/2/03014:;?237,+0;:?BBEHHHEEE@@B76:0/34699:=:=9?A=OQMLNJ:;>78;89;;=?>@?=?;>@?78:-/4,,646;46;469,-089;67:128-/4+/7),7,/;,/;*,9*,9*-8*-6--9,,6&(-9:>JLNJLOQSXLMS0172399:@46;BDGDEH>?A;=?HHJ99;888>>>MMJOOMIJFMNIPSOTVUUVXNOQ:;?014/0646;89?67=78>34:01789?;=B:;A9:>468=>@EFHGHJGHJEFHBDFDEGABE9:=89;=>@DEGEFH>?A:;4>?8PQJWXTMMJBBB327%$+*+1?@FJLO347,-0,-1)*0++4((3$$1**666?$%+126BDFSTV:;?-/4,-3+,2239-/4017)*00/698=HHJHHHEEE??A98=/-4:;?;=?8:79;7NPLJMI9:=67:89;@AD@BA9;88:9679/06--746;128126,-078:4699:@ABH+/7),7,/;(*7)+8)+8),7),4))4009+,278;BDFFGJFGM:;A9:@01723934:>?B@AE;=?:;>>>@::=>>>===IIGOOMSTOQSNLNJQTSNPOIJM469-/2126;=B:;A66?33=22;11:77@;;E;=B@AE9:=;=?@AD?@BDEGGHJIJMHJI=?>687798=?>ADBFHGADB>?8:;4IJDTUPIIGHHH:9>&%,+,2DEJQSV78:124237/0622;%%1""/**699B()/78;?@BQSU9:>+,2/06,-3,-39:@89?67=43::9>AADHHHBBB::=76:+*189=78:;>::=8QTOEGD-/1+,0236>?A>@?241364468017--7017,-3014/0223678;78>34:*-6*-8+-:$&3(*7(*7(+6(+3++7))2,-39:>GHJIJNOPVQSX@AG017*+146;;=@?@D89;89;??A==?777;;;FFDOOMTUPPQMLNJSUQLNMGHJ/03-/2+,0;=B??H66?22;33=33=22;33=67=78;4689:=9:=@ADEFHHILIJMDFE4763648:9@BA@BAFHGHJI
\ No newline at end of file diff --git a/include/webp/encode.h b/include/webp/encode.h index 3c263748..b3f05b1f 100644 --- a/include/webp/encode.h +++ b/include/webp/encode.h @@ -419,7 +419,9 @@ WEBP_EXTERN(int) WebPPictureView(const WebPPicture* src, WEBP_EXTERN(int) WebPPictureIsView(const WebPPicture* picture); // Rescale a picture to new dimension width x height. -// Now gamma correction is applied. +// If either 'width' or 'height' (but not both) is 0 the corresponding +// dimension will be calculated preserving the aspect ratio. +// No gamma correction is applied. // Returns false in case of error (invalid parameter or insufficient memory). WEBP_EXTERN(int) WebPPictureRescale(WebPPicture* pic, int width, int height); diff --git a/include/webp/types.h b/include/webp/types.h index 568d1f26..9b036e0c 100644 --- a/include/webp/types.h +++ b/include/webp/types.h @@ -18,10 +18,11 @@ #ifndef _MSC_VER #include <inttypes.h> -#ifdef __STRICT_ANSI__ -#define WEBP_INLINE -#else /* __STRICT_ANSI__ */ +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) #define WEBP_INLINE inline +#else +#define WEBP_INLINE #endif #else typedef signed char int8_t; diff --git a/src/Android.mk b/src/Android.mk index 027a17b4..694e4b73 100644 --- a/src/Android.mk +++ b/src/Android.mk @@ -17,13 +17,27 @@ LOCAL_PATH:= $(call my-dir) ############################################### include $(CLEAR_VARS) LOCAL_SRC_FILES := \ + dsp/alpha_processing.c \ + dsp/alpha_processing_sse2.c \ + dsp/cpu-features.c \ + dsp/cpu.c \ + dsp/enc.c \ + dsp/enc_avx2.c \ + dsp/enc_mips32.c \ + dsp/enc_neon.c \ + dsp/enc_sse2.c \ + dsp/lossless.c \ + dsp/lossless_mips32.c \ + dsp/lossless_neon.c \ + dsp/lossless_sse2.c \ + dsp/yuv.c \ enc/alpha.c \ enc/analysis.c \ enc/backward_references.c \ enc/config.c \ enc/cost.c \ enc/filter.c \ - enc/frame.c\ + enc/frame.c \ enc/histogram.c \ enc/iterator.c \ enc/picture.c \ @@ -33,25 +47,11 @@ LOCAL_SRC_FILES := \ enc/picture_tools.c \ enc/quant.c \ enc/syntax.c \ - enc/tree.c \ enc/token.c \ + enc/tree.c \ enc/vp8l.c \ enc/webpenc.c \ - dsp/alpha_processing.c \ - dsp/alpha_processing_sse2.c \ - dsp/cpu.c \ - dsp/cpu-features.c \ - dsp/enc.c \ - dsp/enc_avx2.c \ - dsp/enc_mips32.c \ - dsp/enc_neon.c \ - dsp/enc_sse2.c \ - dsp/lossless.c \ - dsp/lossless_mips32.c \ - dsp/lossless_neon.c \ - dsp/lossless_sse2.c \ - dsp/yuv.c \ - dsp/yuv_sse2.c \ + utils/bit_reader.c \ utils/bit_writer.c \ utils/color_cache.c \ utils/filters.c \ @@ -89,10 +89,11 @@ LOCAL_SRC_FILES := \ dec/vp8.c \ dec/vp8l.c \ dec/webp.c \ + demux/demux.c \ dsp/alpha_processing.c \ dsp/alpha_processing_sse2.c \ - dsp/cpu.c \ dsp/cpu-features.c \ + dsp/cpu.c \ dsp/dec.c \ dsp/dec_clip_tables.c \ dsp/dec_mips32.c \ @@ -108,7 +109,6 @@ LOCAL_SRC_FILES := \ dsp/yuv.c \ dsp/yuv_mips32.c \ dsp/yuv_sse2.c \ - demux/demux.c \ utils/bit_reader.c \ utils/color_cache.c \ utils/filters.c \ diff --git a/src/dec/alpha.c b/src/dec/alpha.c index 24ca92dc..f23ba7d6 100644 --- a/src/dec/alpha.c +++ b/src/dec/alpha.c @@ -17,7 +17,7 @@ #include "./vp8li.h" #include "../utils/quant_levels_dec.h" #include "../utils/utils.h" -#include "webp/format_constants.h" +#include "../webp/format_constants.h" //------------------------------------------------------------------------------ // ALPHDecoder object. diff --git a/src/dec/decode_vp8.h b/src/dec/decode_vp8.h index 2bf1bdbb..b9337bbe 100644 --- a/src/dec/decode_vp8.h +++ b/src/dec/decode_vp8.h @@ -14,7 +14,7 @@ #ifndef WEBP_WEBP_DECODE_VP8_H_ #define WEBP_WEBP_DECODE_VP8_H_ -#include "webp/decode.h" +#include "../webp/decode.h" #ifdef __cplusplus extern "C" { diff --git a/src/dec/idec.c b/src/dec/idec.c index 5d8bb0c2..e003851e 100644 --- a/src/dec/idec.c +++ b/src/dec/idec.c @@ -357,30 +357,33 @@ static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) { } // Partition #0 -static int CopyParts0Data(WebPIDecoder* const idec) { +static VP8StatusCode CopyParts0Data(WebPIDecoder* const idec) { VP8Decoder* const dec = (VP8Decoder*)idec->dec_; VP8BitReader* const br = &dec->br_; - const size_t psize = br->buf_end_ - br->buf_; + const size_t part_size = br->buf_end_ - br->buf_; MemBuffer* const mem = &idec->mem_; assert(!idec->is_lossless_); assert(mem->part0_buf_ == NULL); - assert(psize > 0); - assert(psize <= mem->part0_size_); // Format limit: no need for runtime check + // the following is a format limitation, no need for runtime check: + assert(part_size <= mem->part0_size_); + if (part_size == 0) { // can't have zero-size partition #0 + return VP8_STATUS_BITSTREAM_ERROR; + } if (mem->mode_ == MEM_MODE_APPEND) { // We copy and grab ownership of the partition #0 data. - uint8_t* const part0_buf = (uint8_t*)WebPSafeMalloc(1ULL, psize); + uint8_t* const part0_buf = (uint8_t*)WebPSafeMalloc(1ULL, part_size); if (part0_buf == NULL) { - return 0; + return VP8_STATUS_OUT_OF_MEMORY; } - memcpy(part0_buf, br->buf_, psize); + memcpy(part0_buf, br->buf_, part_size); mem->part0_buf_ = part0_buf; br->buf_ = part0_buf; - br->buf_end_ = part0_buf + psize; + br->buf_end_ = part0_buf + part_size; } else { // Else: just keep pointers to the partition #0's data in dec_->br_. } - mem->start_ += psize; - return 1; + mem->start_ += part_size; + return VP8_STATUS_OK; } static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) { @@ -414,8 +417,10 @@ static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) { dec->mt_method_ = VP8GetThreadMethod(params->options, NULL, io->width, io->height); VP8InitDithering(params->options, dec); - if (!CopyParts0Data(idec)) { - return IDecError(idec, VP8_STATUS_OUT_OF_MEMORY); + + dec->status_ = CopyParts0Data(idec); + if (dec->status_ != VP8_STATUS_OK) { + return IDecError(idec, dec->status_); } // Finish setting up the decoding parameters. Will call io->setup(). diff --git a/src/dec/tree.c b/src/dec/tree.c index 88238885..31208d9d 100644 --- a/src/dec/tree.c +++ b/src/dec/tree.c @@ -11,7 +11,7 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "vp8i.h" +#include "./vp8i.h" #include "../utils/bit_reader_inl.h" #define USE_GENERIC_TREE diff --git a/src/dec/vp8.c b/src/dec/vp8.c index 47249d64..89d478a4 100644 --- a/src/dec/vp8.c +++ b/src/dec/vp8.c @@ -562,6 +562,7 @@ int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) { } block->non_zero_y_ = 0; block->non_zero_uv_ = 0; + block->dither_ = 0; } if (dec->filter_type_ > 0) { // store filter info diff --git a/src/dec/vp8i.h b/src/dec/vp8i.h index 29701be7..a02d9ff7 100644 --- a/src/dec/vp8i.h +++ b/src/dec/vp8i.h @@ -31,7 +31,7 @@ extern "C" { // version numbers #define DEC_MAJ_VERSION 0 #define DEC_MIN_VERSION 4 -#define DEC_REV_VERSION 2 +#define DEC_REV_VERSION 3 // intra prediction modes enum { B_DC_PRED = 0, // 4x4 modes diff --git a/src/dec/webp.c b/src/dec/webp.c index c5f8f94d..59e21a9d 100644 --- a/src/dec/webp.c +++ b/src/dec/webp.c @@ -16,7 +16,7 @@ #include "./vp8i.h" #include "./vp8li.h" #include "./webpi.h" -#include "webp/mux_types.h" // ALPHA_FLAG +#include "../webp/mux_types.h" // ALPHA_FLAG //------------------------------------------------------------------------------ // RIFF layout is: diff --git a/src/demux/demux.c b/src/demux/demux.c index 5aabdd25..55a7918f 100644 --- a/src/demux/demux.c +++ b/src/demux/demux.c @@ -11,7 +11,7 @@ // #ifdef HAVE_CONFIG_H -#include "webp/config.h" +#include "../webp/config.h" #endif #include <assert.h> @@ -19,9 +19,9 @@ #include <string.h> #include "../utils/utils.h" -#include "webp/decode.h" // WebPGetFeatures -#include "webp/demux.h" -#include "webp/format_constants.h" +#include "../webp/decode.h" // WebPGetFeatures +#include "../webp/demux.h" +#include "../webp/format_constants.h" #define DMUX_MAJ_VERSION 0 #define DMUX_MIN_VERSION 2 diff --git a/src/dsp/alpha_processing.c b/src/dsp/alpha_processing.c index d0f7a6cc..c8e0b4bc 100644 --- a/src/dsp/alpha_processing.c +++ b/src/dsp/alpha_processing.c @@ -311,7 +311,12 @@ int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int); extern void WebPInitAlphaProcessingSSE2(void); +static volatile VP8CPUInfo alpha_processing_last_cpuinfo_used = + (VP8CPUInfo)&alpha_processing_last_cpuinfo_used; + void WebPInitAlphaProcessing(void) { + if (alpha_processing_last_cpuinfo_used == VP8GetCPUInfo) return; + WebPMultARGBRow = MultARGBRow; WebPMultRow = MultRow; WebPApplyAlphaMultiply = ApplyAlphaMultiply; @@ -326,4 +331,5 @@ void WebPInitAlphaProcessing(void) { } #endif } + alpha_processing_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/src/dsp/cpu.c b/src/dsp/cpu.c index 70ba2ab0..45329349 100644 --- a/src/dsp/cpu.c +++ b/src/dsp/cpu.c @@ -29,16 +29,18 @@ static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { "cpuid\n" "xchg %%edi, %%ebx\n" : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) - : "a"(info_type)); + : "a"(info_type), "c"(0)); } #elif defined(__i386__) || defined(__x86_64__) static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { __asm__ volatile ( "cpuid\n" : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) - : "a"(info_type)); + : "a"(info_type), "c"(0)); } -#elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1 +#elif (defined(_M_X64) || defined(_M_IX86)) && \ + defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1 +#include <intrin.h> #define GetCPUInfo(info, type) __cpuidex(info, type, 0) // set ecx=0 #elif defined(WEBP_MSC_SSE2) #define GetCPUInfo __cpuid @@ -55,7 +57,9 @@ static WEBP_INLINE uint64_t xgetbv(void) { : "=a"(eax), "=d"(edx) : "c" (ecx)); return ((uint64_t)edx << 32) | eax; } -#elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1 +#elif (defined(_M_X64) || defined(_M_IX86)) && \ + defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1 +#include <immintrin.h> #define xgetbv() _xgetbv(0) #elif defined(_MSC_VER) && defined(_M_IX86) static WEBP_INLINE uint64_t xgetbv(void) { diff --git a/src/dsp/dec.c b/src/dsp/dec.c index 65a2a885..3a8dc81f 100644 --- a/src/dsp/dec.c +++ b/src/dsp/dec.c @@ -688,7 +688,12 @@ extern void VP8DspInitSSE2(void); extern void VP8DspInitNEON(void); extern void VP8DspInitMIPS32(void); +static volatile VP8CPUInfo dec_last_cpuinfo_used = + (VP8CPUInfo)&dec_last_cpuinfo_used; + void VP8DspInit(void) { + if (dec_last_cpuinfo_used == VP8GetCPUInfo) return; + VP8InitClipTables(); VP8TransformWHT = TransformWHT; @@ -727,5 +732,5 @@ void VP8DspInit(void) { } #endif } + dec_last_cpuinfo_used = VP8GetCPUInfo; } - diff --git a/src/dsp/dsp.h b/src/dsp/dsp.h index 3b31ae08..838a70a1 100644 --- a/src/dsp/dsp.h +++ b/src/dsp/dsp.h @@ -15,10 +15,10 @@ #define WEBP_DSP_DSP_H_ #ifdef HAVE_CONFIG_H -#include "config.h" +#include "../webp/config.h" #endif -#include "webp/types.h" +#include "../webp/types.h" #ifdef __cplusplus extern "C" { @@ -66,7 +66,10 @@ extern "C" { #define WEBP_ANDROID_NEON // Android targets that might support NEON #endif -#if defined(__ARM_NEON__) || defined(__aarch64__) +// The intrinsics currently cause compiler errors with arm-nacl-gcc and the +// inline assembly would need to be modified for use with Native Client. +#if (defined(__ARM_NEON__) || defined(__aarch64__)) \ + && !defined(__native_client__) #define WEBP_USE_NEON #endif diff --git a/src/dsp/enc.c b/src/dsp/enc.c index e4ea8cb8..f4e72d45 100644 --- a/src/dsp/enc.c +++ b/src/dsp/enc.c @@ -692,7 +692,12 @@ extern void VP8EncDspInitAVX2(void); extern void VP8EncDspInitNEON(void); extern void VP8EncDspInitMIPS32(void); +static volatile VP8CPUInfo enc_last_cpuinfo_used = + (VP8CPUInfo)&enc_last_cpuinfo_used; + void VP8EncDspInit(void) { + if (enc_last_cpuinfo_used == VP8GetCPUInfo) return; + VP8DspInit(); // common inverse transforms InitTables(); @@ -737,5 +742,6 @@ void VP8EncDspInit(void) { } #endif } + enc_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/src/dsp/enc_neon.c b/src/dsp/enc_neon.c index 42041f73..5814fac9 100644 --- a/src/dsp/enc_neon.c +++ b/src/dsp/enc_neon.c @@ -1012,8 +1012,10 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16], const int16x8_t out0 = Quantize(in, mtx, 0); const int16x8_t out1 = Quantize(in, mtx, 8); uint8x8x4_t shuffles; - // vtbl4_u8 is marked unavailable for iOS arm64, use wider versions there. -#if defined(__APPLE__) && defined(__aarch64__) + // vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use + // non-standard versions there. +#if defined(__APPLE__) && defined(__aarch64__) && \ + defined(__apple_build_version__) && (__apple_build_version__< 6020037) uint8x16x2_t all_out; INIT_VECTOR2(all_out, vreinterpretq_u8_s16(out0), vreinterpretq_u8_s16(out1)); INIT_VECTOR4(shuffles, diff --git a/src/dsp/lossless.c b/src/dsp/lossless.c index a1bf3584..ee334bce 100644 --- a/src/dsp/lossless.c +++ b/src/dsp/lossless.c @@ -1590,7 +1590,12 @@ extern void VP8LDspInitSSE2(void); extern void VP8LDspInitNEON(void); extern void VP8LDspInitMIPS32(void); +static volatile VP8CPUInfo lossless_last_cpuinfo_used = + (VP8CPUInfo)&lossless_last_cpuinfo_used; + void VP8LDspInit(void) { + if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return; + memcpy(VP8LPredictors, kPredictorsC, sizeof(VP8LPredictors)); VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C; @@ -1634,6 +1639,7 @@ void VP8LDspInit(void) { } #endif } + lossless_last_cpuinfo_used = VP8GetCPUInfo; } //------------------------------------------------------------------------------ diff --git a/src/dsp/lossless.h b/src/dsp/lossless.h index 08be9375..8c7551c9 100644 --- a/src/dsp/lossless.h +++ b/src/dsp/lossless.h @@ -15,8 +15,8 @@ #ifndef WEBP_DSP_LOSSLESS_H_ #define WEBP_DSP_LOSSLESS_H_ -#include "webp/types.h" -#include "webp/decode.h" +#include "../webp/types.h" +#include "../webp/decode.h" #include "../enc/histogram.h" #include "../utils/utils.h" diff --git a/src/dsp/lossless_neon.c b/src/dsp/lossless_neon.c index 987767b5..8c82b197 100644 --- a/src/dsp/lossless_neon.c +++ b/src/dsp/lossless_neon.c @@ -259,20 +259,45 @@ static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { //------------------------------------------------------------------------------ // Subtract-Green Transform -// vtbl? are unavailable in iOS/arm64 builds. -#if !defined(__aarch64__) +// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use +// non-standard versions there. +#if defined(__APPLE__) && defined(__aarch64__) && \ + defined(__apple_build_version__) && (__apple_build_version__< 6020037) +#define USE_VTBLQ +#endif + +#ifdef USE_VTBLQ +// 255 = byte will be zeroed +static const uint8_t kGreenShuffle[16] = { + 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255 +}; -// 255 = byte will be zero'd +static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, + const uint8x16_t shuffle) { + return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)), + vtbl1q_u8(argb, vget_high_u8(shuffle))); +} +#else // !USE_VTBLQ +// 255 = byte will be zeroed static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 }; +static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, + const uint8x8_t shuffle) { + return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), + vtbl1_u8(vget_high_u8(argb), shuffle)); +} +#endif // USE_VTBLQ + static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { const uint32_t* const end = argb_data + (num_pixels & ~3); +#ifdef USE_VTBLQ + const uint8x16_t shuffle = vld1q_u8(kGreenShuffle); +#else const uint8x8_t shuffle = vld1_u8(kGreenShuffle); +#endif for (; argb_data < end; argb_data += 4) { const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data); - const uint8x16_t greens = - vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), - vtbl1_u8(vget_high_u8(argb), shuffle)); + const uint8x16_t greens = DoGreenShuffle(argb, shuffle); vst1q_u8((uint8_t*)argb_data, vsubq_u8(argb, greens)); } // fallthrough and finish off with plain-C @@ -281,19 +306,21 @@ static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) { const uint32_t* const end = argb_data + (num_pixels & ~3); +#ifdef USE_VTBLQ + const uint8x16_t shuffle = vld1q_u8(kGreenShuffle); +#else const uint8x8_t shuffle = vld1_u8(kGreenShuffle); +#endif for (; argb_data < end; argb_data += 4) { const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data); - const uint8x16_t greens = - vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), - vtbl1_u8(vget_high_u8(argb), shuffle)); + const uint8x16_t greens = DoGreenShuffle(argb, shuffle); vst1q_u8((uint8_t*)argb_data, vaddq_u8(argb, greens)); } // fallthrough and finish off with plain-C VP8LAddGreenToBlueAndRed_C(argb_data, num_pixels & 3); } -#endif // !__aarch64__ +#undef USE_VTBLQ #endif // USE_INTRINSICS @@ -320,11 +347,9 @@ void VP8LDspInitNEON(void) { VP8LPredictors[12] = Predictor12; VP8LPredictors[13] = Predictor13; -#if !defined(__aarch64__) VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed; #endif -#endif #endif // WEBP_USE_NEON } diff --git a/src/dsp/upsampling.c b/src/dsp/upsampling.c index 2b1656bf..53c68d5a 100644 --- a/src/dsp/upsampling.c +++ b/src/dsp/upsampling.c @@ -189,7 +189,12 @@ const WebPYUV444Converter WebPYUV444Converters[MODE_LAST] = { extern void WebPInitUpsamplersSSE2(void); extern void WebPInitUpsamplersNEON(void); +static volatile VP8CPUInfo upsampling_last_cpuinfo_used2 = + (VP8CPUInfo)&upsampling_last_cpuinfo_used2; + void WebPInitUpsamplers(void) { + if (upsampling_last_cpuinfo_used2 == VP8GetCPUInfo) return; + #ifdef FANCY_UPSAMPLING WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; @@ -217,6 +222,7 @@ void WebPInitUpsamplers(void) { #endif } #endif // FANCY_UPSAMPLING + upsampling_last_cpuinfo_used2 = VP8GetCPUInfo; } //------------------------------------------------------------------------------ diff --git a/src/dsp/yuv.c b/src/dsp/yuv.c index d7cb4ebc..6f422da5 100644 --- a/src/dsp/yuv.c +++ b/src/dsp/yuv.c @@ -123,7 +123,12 @@ WebPSamplerRowFunc WebPSamplers[MODE_LAST]; extern void WebPInitSamplersSSE2(void); extern void WebPInitSamplersMIPS32(void); +static volatile VP8CPUInfo yuv_last_cpuinfo_used = + (VP8CPUInfo)&yuv_last_cpuinfo_used; + void WebPInitSamplers(void) { + if (yuv_last_cpuinfo_used == VP8GetCPUInfo) return; + WebPSamplers[MODE_RGB] = YuvToRgbRow; WebPSamplers[MODE_RGBA] = YuvToRgbaRow; WebPSamplers[MODE_BGR] = YuvToBgrRow; @@ -149,6 +154,7 @@ void WebPInitSamplers(void) { } #endif // WEBP_USE_MIPS32 } + yuv_last_cpuinfo_used = VP8GetCPUInfo; } //----------------------------------------------------------------------------- diff --git a/src/utils/bit_reader.c b/src/utils/bit_reader.c index bbddd42c..64503e6b 100644 --- a/src/utils/bit_reader.c +++ b/src/utils/bit_reader.c @@ -12,7 +12,7 @@ // Author: Skal (pascal.massimino@gmail.com) #ifdef HAVE_CONFIG_H -#include "webp/config.h" +#include "../webp/config.h" #endif #include "./bit_reader_inl.h" diff --git a/src/utils/bit_reader.h b/src/utils/bit_reader.h index a6ae85e5..f569734f 100644 --- a/src/utils/bit_reader.h +++ b/src/utils/bit_reader.h @@ -19,7 +19,7 @@ #ifdef _MSC_VER #include <stdlib.h> // _byteswap_ulong #endif -#include "webp/types.h" +#include "../webp/types.h" #ifdef __cplusplus extern "C" { diff --git a/src/utils/bit_reader_inl.h b/src/utils/bit_reader_inl.h index 9f59ca3d..81427c62 100644 --- a/src/utils/bit_reader_inl.h +++ b/src/utils/bit_reader_inl.h @@ -17,7 +17,7 @@ #define WEBP_UTILS_BIT_READER_INL_H_ #ifdef HAVE_CONFIG_H -#include "webp/config.h" +#include "../webp/config.h" #endif #ifdef WEBP_FORCE_ALIGNED diff --git a/src/utils/bit_writer.h b/src/utils/bit_writer.h index 107a2b18..c80d22ae 100644 --- a/src/utils/bit_writer.h +++ b/src/utils/bit_writer.h @@ -14,7 +14,7 @@ #ifndef WEBP_UTILS_BIT_WRITER_H_ #define WEBP_UTILS_BIT_WRITER_H_ -#include "webp/types.h" +#include "../webp/types.h" #ifdef __cplusplus extern "C" { diff --git a/src/utils/color_cache.h b/src/utils/color_cache.h index 26aac997..0f824ed4 100644 --- a/src/utils/color_cache.h +++ b/src/utils/color_cache.h @@ -15,7 +15,7 @@ #ifndef WEBP_UTILS_COLOR_CACHE_H_ #define WEBP_UTILS_COLOR_CACHE_H_ -#include "webp/types.h" +#include "../webp/types.h" #ifdef __cplusplus extern "C" { diff --git a/src/utils/endian_inl.h b/src/utils/endian_inl.h index f362a6e8..cd56c37f 100644 --- a/src/utils/endian_inl.h +++ b/src/utils/endian_inl.h @@ -13,11 +13,11 @@ #define WEBP_UTILS_ENDIAN_INL_H_ #ifdef HAVE_CONFIG_H -#include "webp/config.h" +#include "../webp/config.h" #endif #include "../dsp/dsp.h" -#include "webp/types.h" +#include "../webp/types.h" // some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__) #if !defined(WORDS_BIGENDIAN) && \ diff --git a/src/utils/filters.h b/src/utils/filters.h index 5676279e..dde39cb5 100644 --- a/src/utils/filters.h +++ b/src/utils/filters.h @@ -14,7 +14,7 @@ #ifndef WEBP_UTILS_FILTERS_H_ #define WEBP_UTILS_FILTERS_H_ -#include "webp/types.h" +#include "../webp/types.h" #ifdef __cplusplus extern "C" { diff --git a/src/utils/huffman.c b/src/utils/huffman.c index 1916a008..c4c16d9e 100644 --- a/src/utils/huffman.c +++ b/src/utils/huffman.c @@ -16,7 +16,7 @@ #include <string.h> #include "./huffman.h" #include "../utils/utils.h" -#include "webp/format_constants.h" +#include "../webp/format_constants.h" // Uncomment the following to use look-up table for ReverseBits() // (might be faster on some platform) diff --git a/src/utils/huffman.h b/src/utils/huffman.h index bf1588dd..624bc175 100644 --- a/src/utils/huffman.h +++ b/src/utils/huffman.h @@ -15,8 +15,8 @@ #define WEBP_UTILS_HUFFMAN_H_ #include <assert.h> -#include "webp/format_constants.h" -#include "webp/types.h" +#include "../webp/format_constants.h" +#include "../webp/types.h" #ifdef __cplusplus extern "C" { diff --git a/src/utils/huffman_encode.c b/src/utils/huffman_encode.c index d7aad6f5..6421c2be 100644 --- a/src/utils/huffman_encode.c +++ b/src/utils/huffman_encode.c @@ -16,7 +16,7 @@ #include <string.h> #include "./huffman_encode.h" #include "../utils/utils.h" -#include "webp/format_constants.h" +#include "../webp/format_constants.h" // ----------------------------------------------------------------------------- // Util function to optimize the symbol map for RLE coding diff --git a/src/utils/huffman_encode.h b/src/utils/huffman_encode.h index daea39ff..91aa18f4 100644 --- a/src/utils/huffman_encode.h +++ b/src/utils/huffman_encode.h @@ -14,7 +14,7 @@ #ifndef WEBP_UTILS_HUFFMAN_ENCODE_H_ #define WEBP_UTILS_HUFFMAN_ENCODE_H_ -#include "webp/types.h" +#include "../webp/types.h" #ifdef __cplusplus extern "C" { diff --git a/src/utils/quant_levels.h b/src/utils/quant_levels.h index 3916b977..1cb5a32c 100644 --- a/src/utils/quant_levels.h +++ b/src/utils/quant_levels.h @@ -16,7 +16,7 @@ #include <stdlib.h> -#include "webp/types.h" +#include "../webp/types.h" #ifdef __cplusplus extern "C" { diff --git a/src/utils/quant_levels_dec.h b/src/utils/quant_levels_dec.h index 29c7e6e2..9aab0680 100644 --- a/src/utils/quant_levels_dec.h +++ b/src/utils/quant_levels_dec.h @@ -14,7 +14,7 @@ #ifndef WEBP_UTILS_QUANT_LEVELS_DEC_H_ #define WEBP_UTILS_QUANT_LEVELS_DEC_H_ -#include "webp/types.h" +#include "../webp/types.h" #ifdef __cplusplus extern "C" { diff --git a/src/utils/random.h b/src/utils/random.h index 745f3e2e..c392a615 100644 --- a/src/utils/random.h +++ b/src/utils/random.h @@ -15,7 +15,7 @@ #define WEBP_UTILS_RANDOM_H_ #include <assert.h> -#include "webp/types.h" +#include "../webp/types.h" #ifdef __cplusplus extern "C" { diff --git a/src/utils/rescaler.h b/src/utils/rescaler.h index 6699c5b4..a6f37871 100644 --- a/src/utils/rescaler.h +++ b/src/utils/rescaler.h @@ -18,7 +18,7 @@ extern "C" { #endif -#include "webp/types.h" +#include "../webp/types.h" // Structure used for on-the-fly rescaling typedef struct { diff --git a/src/utils/thread.h b/src/utils/thread.h index eb714e1d..7bd451b1 100644 --- a/src/utils/thread.h +++ b/src/utils/thread.h @@ -15,10 +15,10 @@ #define WEBP_UTILS_THREAD_H_ #ifdef HAVE_CONFIG_H -#include "config.h" +#include "../webp/config.h" #endif -#include "webp/types.h" +#include "../webp/types.h" #ifdef __cplusplus extern "C" { diff --git a/src/utils/utils.h b/src/utils/utils.h index a8e8c3d6..f2c498a9 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -17,7 +17,7 @@ #include <assert.h> -#include "webp/types.h" +#include "../webp/types.h" #ifdef __cplusplus extern "C" { diff --git a/src/webp/decode.h b/src/webp/decode.h new file mode 100644 index 00000000..8d3f7be9 --- /dev/null +++ b/src/webp/decode.h @@ -0,0 +1,503 @@ +// Copyright 2010 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. +// ----------------------------------------------------------------------------- +// +// Main decoding functions for WebP images. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_WEBP_DECODE_H_ +#define WEBP_WEBP_DECODE_H_ + +#include "./types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_DECODER_ABI_VERSION 0x0203 // MAJOR(8b) + MINOR(8b) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum VP8StatusCode VP8StatusCode; +// typedef enum WEBP_CSP_MODE WEBP_CSP_MODE; +typedef struct WebPRGBABuffer WebPRGBABuffer; +typedef struct WebPYUVABuffer WebPYUVABuffer; +typedef struct WebPDecBuffer WebPDecBuffer; +typedef struct WebPIDecoder WebPIDecoder; +typedef struct WebPBitstreamFeatures WebPBitstreamFeatures; +typedef struct WebPDecoderOptions WebPDecoderOptions; +typedef struct WebPDecoderConfig WebPDecoderConfig; + +// Return the decoder's version number, packed in hexadecimal using 8bits for +// each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN(int) WebPGetDecoderVersion(void); + +// Retrieve basic header information: width, height. +// This function will also validate the header and return 0 in +// case of formatting error. +// Pointers 'width' and 'height' can be passed NULL if deemed irrelevant. +WEBP_EXTERN(int) WebPGetInfo(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Decodes WebP images pointed to by 'data' and returns RGBA samples, along +// with the dimensions in *width and *height. The ordering of samples in +// memory is R, G, B, A, R, G, B, A... in scan order (endian-independent). +// The returned pointer should be deleted calling free(). +// Returns NULL in case of error. +WEBP_EXTERN(uint8_t*) WebPDecodeRGBA(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data. +WEBP_EXTERN(uint8_t*) WebPDecodeARGB(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data. +WEBP_EXTERN(uint8_t*) WebPDecodeBGRA(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data. +// If the bitstream contains transparency, it is ignored. +WEBP_EXTERN(uint8_t*) WebPDecodeRGB(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data. +WEBP_EXTERN(uint8_t*) WebPDecodeBGR(const uint8_t* data, size_t data_size, + int* width, int* height); + + +// Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer +// returned is the Y samples buffer. Upon return, *u and *v will point to +// the U and V chroma data. These U and V buffers need NOT be free()'d, +// unlike the returned Y luma one. The dimension of the U and V planes +// are both (*width + 1) / 2 and (*height + 1)/ 2. +// Upon return, the Y buffer has a stride returned as '*stride', while U and V +// have a common stride returned as '*uv_stride'. +// Return NULL in case of error. +// (*) Also named Y'CbCr. See: http://en.wikipedia.org/wiki/YCbCr +WEBP_EXTERN(uint8_t*) WebPDecodeYUV(const uint8_t* data, size_t data_size, + int* width, int* height, + uint8_t** u, uint8_t** v, + int* stride, int* uv_stride); + +// These five functions are variants of the above ones, that decode the image +// directly into a pre-allocated buffer 'output_buffer'. The maximum storage +// available in this buffer is indicated by 'output_buffer_size'. If this +// storage is not sufficient (or an error occurred), NULL is returned. +// Otherwise, output_buffer is returned, for convenience. +// The parameter 'output_stride' specifies the distance (in bytes) +// between scanlines. Hence, output_buffer_size is expected to be at least +// output_stride x picture-height. +WEBP_EXTERN(uint8_t*) WebPDecodeRGBAInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); +WEBP_EXTERN(uint8_t*) WebPDecodeARGBInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); +WEBP_EXTERN(uint8_t*) WebPDecodeBGRAInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); + +// RGB and BGR variants. Here too the transparency information, if present, +// will be dropped and ignored. +WEBP_EXTERN(uint8_t*) WebPDecodeRGBInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); +WEBP_EXTERN(uint8_t*) WebPDecodeBGRInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); + +// WebPDecodeYUVInto() is a variant of WebPDecodeYUV() that operates directly +// into pre-allocated luma/chroma plane buffers. This function requires the +// strides to be passed: one for the luma plane and one for each of the +// chroma ones. The size of each plane buffer is passed as 'luma_size', +// 'u_size' and 'v_size' respectively. +// Pointer to the luma plane ('*luma') is returned or NULL if an error occurred +// during decoding (or because some buffers were found to be too small). +WEBP_EXTERN(uint8_t*) WebPDecodeYUVInto( + const uint8_t* data, size_t data_size, + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride); + +//------------------------------------------------------------------------------ +// Output colorspaces and buffer + +// Colorspaces +// Note: the naming describes the byte-ordering of packed samples in memory. +// For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,... +// Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels. +// RGBA-4444 and RGB-565 colorspaces are represented by following byte-order: +// RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ... +// RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ... +// In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for +// these two modes: +// RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ... +// RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ... + +typedef enum WEBP_CSP_MODE { + MODE_RGB = 0, MODE_RGBA = 1, + MODE_BGR = 2, MODE_BGRA = 3, + MODE_ARGB = 4, MODE_RGBA_4444 = 5, + MODE_RGB_565 = 6, + // RGB-premultiplied transparent modes (alpha value is preserved) + MODE_rgbA = 7, + MODE_bgrA = 8, + MODE_Argb = 9, + MODE_rgbA_4444 = 10, + // YUV modes must come after RGB ones. + MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0 + MODE_LAST = 13 +} WEBP_CSP_MODE; + +// Some useful macros: +static WEBP_INLINE int WebPIsPremultipliedMode(WEBP_CSP_MODE mode) { + return (mode == MODE_rgbA || mode == MODE_bgrA || mode == MODE_Argb || + mode == MODE_rgbA_4444); +} + +static WEBP_INLINE int WebPIsAlphaMode(WEBP_CSP_MODE mode) { + return (mode == MODE_RGBA || mode == MODE_BGRA || mode == MODE_ARGB || + mode == MODE_RGBA_4444 || mode == MODE_YUVA || + WebPIsPremultipliedMode(mode)); +} + +static WEBP_INLINE int WebPIsRGBMode(WEBP_CSP_MODE mode) { + return (mode < MODE_YUV); +} + +//------------------------------------------------------------------------------ +// WebPDecBuffer: Generic structure for describing the output sample buffer. + +struct WebPRGBABuffer { // view as RGBA + uint8_t* rgba; // pointer to RGBA samples + int stride; // stride in bytes from one scanline to the next. + size_t size; // total size of the *rgba buffer. +}; + +struct WebPYUVABuffer { // view as YUVA + uint8_t* y, *u, *v, *a; // pointer to luma, chroma U/V, alpha samples + int y_stride; // luma stride + int u_stride, v_stride; // chroma strides + int a_stride; // alpha stride + size_t y_size; // luma plane size + size_t u_size, v_size; // chroma planes size + size_t a_size; // alpha-plane size +}; + +// Output buffer +struct WebPDecBuffer { + WEBP_CSP_MODE colorspace; // Colorspace. + int width, height; // Dimensions. + int is_external_memory; // If true, 'internal_memory' pointer is not used. + union { + WebPRGBABuffer RGBA; + WebPYUVABuffer YUVA; + } u; // Nameless union of buffer parameters. + uint32_t pad[4]; // padding for later use + + uint8_t* private_memory; // Internally allocated memory (only when + // is_external_memory is false). Should not be used + // externally, but accessed via the buffer union. +}; + +// Internal, version-checked, entry point +WEBP_EXTERN(int) WebPInitDecBufferInternal(WebPDecBuffer*, int); + +// Initialize the structure as empty. Must be called before any other use. +// Returns false in case of version mismatch +static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) { + return WebPInitDecBufferInternal(buffer, WEBP_DECODER_ABI_VERSION); +} + +// Free any memory associated with the buffer. Must always be called last. +// Note: doesn't free the 'buffer' structure itself. +WEBP_EXTERN(void) WebPFreeDecBuffer(WebPDecBuffer* buffer); + +//------------------------------------------------------------------------------ +// Enumeration of the status codes + +typedef enum VP8StatusCode { + VP8_STATUS_OK = 0, + VP8_STATUS_OUT_OF_MEMORY, + VP8_STATUS_INVALID_PARAM, + VP8_STATUS_BITSTREAM_ERROR, + VP8_STATUS_UNSUPPORTED_FEATURE, + VP8_STATUS_SUSPENDED, + VP8_STATUS_USER_ABORT, + VP8_STATUS_NOT_ENOUGH_DATA +} VP8StatusCode; + +//------------------------------------------------------------------------------ +// Incremental decoding +// +// This API allows streamlined decoding of partial data. +// Picture can be incrementally decoded as data become available thanks to the +// WebPIDecoder object. This object can be left in a SUSPENDED state if the +// picture is only partially decoded, pending additional input. +// Code example: +// +// WebPInitDecBuffer(&buffer); +// buffer.colorspace = mode; +// ... +// WebPIDecoder* idec = WebPINewDecoder(&buffer); +// while (has_more_data) { +// // ... (get additional data) +// status = WebPIAppend(idec, new_data, new_data_size); +// if (status != VP8_STATUS_SUSPENDED || +// break; +// } +// +// // The above call decodes the current available buffer. +// // Part of the image can now be refreshed by calling to +// // WebPIDecGetRGB()/WebPIDecGetYUVA() etc. +// } +// WebPIDelete(idec); + +// Creates a new incremental decoder with the supplied buffer parameter. +// This output_buffer can be passed NULL, in which case a default output buffer +// is used (with MODE_RGB). Otherwise, an internal reference to 'output_buffer' +// is kept, which means that the lifespan of 'output_buffer' must be larger than +// that of the returned WebPIDecoder object. +// The supplied 'output_buffer' content MUST NOT be changed between calls to +// WebPIAppend() or WebPIUpdate() unless 'output_buffer.is_external_memory' is +// set to 1. In such a case, it is allowed to modify the pointers, size and +// stride of output_buffer.u.RGBA or output_buffer.u.YUVA, provided they remain +// within valid bounds. +// All other fields of WebPDecBuffer MUST remain constant between calls. +// Returns NULL if the allocation failed. +WEBP_EXTERN(WebPIDecoder*) WebPINewDecoder(WebPDecBuffer* output_buffer); + +// This function allocates and initializes an incremental-decoder object, which +// will output the RGB/A samples specified by 'csp' into a preallocated +// buffer 'output_buffer'. The size of this buffer is at least +// 'output_buffer_size' and the stride (distance in bytes between two scanlines) +// is specified by 'output_stride'. +// Additionally, output_buffer can be passed NULL in which case the output +// buffer will be allocated automatically when the decoding starts. The +// colorspace 'csp' is taken into account for allocating this buffer. All other +// parameters are ignored. +// Returns NULL if the allocation failed, or if some parameters are invalid. +WEBP_EXTERN(WebPIDecoder*) WebPINewRGB( + WEBP_CSP_MODE csp, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); + +// This function allocates and initializes an incremental-decoder object, which +// will output the raw luma/chroma samples into a preallocated planes if +// supplied. The luma plane is specified by its pointer 'luma', its size +// 'luma_size' and its stride 'luma_stride'. Similarly, the chroma-u plane +// is specified by the 'u', 'u_size' and 'u_stride' parameters, and the chroma-v +// plane by 'v' and 'v_size'. And same for the alpha-plane. The 'a' pointer +// can be pass NULL in case one is not interested in the transparency plane. +// Conversely, 'luma' can be passed NULL if no preallocated planes are supplied. +// In this case, the output buffer will be automatically allocated (using +// MODE_YUVA) when decoding starts. All parameters are then ignored. +// Returns NULL if the allocation failed or if a parameter is invalid. +WEBP_EXTERN(WebPIDecoder*) WebPINewYUVA( + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride, + uint8_t* a, size_t a_size, int a_stride); + +// Deprecated version of the above, without the alpha plane. +// Kept for backward compatibility. +WEBP_EXTERN(WebPIDecoder*) WebPINewYUV( + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride); + +// Deletes the WebPIDecoder object and associated memory. Must always be called +// if WebPINewDecoder, WebPINewRGB or WebPINewYUV succeeded. +WEBP_EXTERN(void) WebPIDelete(WebPIDecoder* idec); + +// Copies and decodes the next available data. Returns VP8_STATUS_OK when +// the image is successfully decoded. Returns VP8_STATUS_SUSPENDED when more +// data is expected. Returns error in other cases. +WEBP_EXTERN(VP8StatusCode) WebPIAppend( + WebPIDecoder* idec, const uint8_t* data, size_t data_size); + +// A variant of the above function to be used when data buffer contains +// partial data from the beginning. In this case data buffer is not copied +// to the internal memory. +// Note that the value of the 'data' pointer can change between calls to +// WebPIUpdate, for instance when the data buffer is resized to fit larger data. +WEBP_EXTERN(VP8StatusCode) WebPIUpdate( + WebPIDecoder* idec, const uint8_t* data, size_t data_size); + +// Returns the RGB/A image decoded so far. Returns NULL if output params +// are not initialized yet. The RGB/A output type corresponds to the colorspace +// specified during call to WebPINewDecoder() or WebPINewRGB(). +// *last_y is the index of last decoded row in raster scan order. Some pointers +// (*last_y, *width etc.) can be NULL if corresponding information is not +// needed. +WEBP_EXTERN(uint8_t*) WebPIDecGetRGB( + const WebPIDecoder* idec, int* last_y, + int* width, int* height, int* stride); + +// Same as above function to get a YUVA image. Returns pointer to the luma +// plane or NULL in case of error. If there is no alpha information +// the alpha pointer '*a' will be returned NULL. +WEBP_EXTERN(uint8_t*) WebPIDecGetYUVA( + const WebPIDecoder* idec, int* last_y, + uint8_t** u, uint8_t** v, uint8_t** a, + int* width, int* height, int* stride, int* uv_stride, int* a_stride); + +// Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the +// alpha information (if present). Kept for backward compatibility. +static WEBP_INLINE uint8_t* WebPIDecGetYUV( + const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v, + int* width, int* height, int* stride, int* uv_stride) { + return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height, + stride, uv_stride, NULL); +} + +// Generic call to retrieve information about the displayable area. +// If non NULL, the left/right/width/height pointers are filled with the visible +// rectangular area so far. +// Returns NULL in case the incremental decoder object is in an invalid state. +// Otherwise returns the pointer to the internal representation. This structure +// is read-only, tied to WebPIDecoder's lifespan and should not be modified. +WEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea( + const WebPIDecoder* idec, int* left, int* top, int* width, int* height); + +//------------------------------------------------------------------------------ +// Advanced decoding parametrization +// +// Code sample for using the advanced decoding API +/* + // 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', if needed + config.no_fancy_upsampling = 1; + config.output.colorspace = MODE_BGRA; + // etc. + + // Note that you can also make config.output point to an externally + // supplied memory buffer, provided it's big enough to store the decoded + // picture. Otherwise, config.output will just be used to allocate memory + // and store the decoded picture. + + // D) Decode! + CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK); + + // E) Decoded image is now in config.output (and config.output.u.RGBA) + + // F) 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); +*/ + +// Features gathered from the bitstream +struct WebPBitstreamFeatures { + int width; // Width in pixels, as read from the bitstream. + int height; // Height in pixels, as read from the bitstream. + int has_alpha; // True if the bitstream contains an alpha channel. + int has_animation; // True if the bitstream is an animation. + int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless + + // Unused for now: + int no_incremental_decoding; // if true, using incremental decoding is not + // recommended. + int rotate; // TODO(later) + int uv_sampling; // should be 0 for now. TODO(later) + uint32_t pad[2]; // padding for later use +}; + +// Internal, version-checked, entry point +WEBP_EXTERN(VP8StatusCode) WebPGetFeaturesInternal( + const uint8_t*, size_t, WebPBitstreamFeatures*, int); + +// Retrieve features from the bitstream. The *features structure is filled +// with information gathered from the bitstream. +// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns +// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the +// features from headers. Returns error in other cases. +static WEBP_INLINE VP8StatusCode WebPGetFeatures( + const uint8_t* data, size_t data_size, + WebPBitstreamFeatures* features) { + return WebPGetFeaturesInternal(data, data_size, features, + WEBP_DECODER_ABI_VERSION); +} + +// Decoding options +struct WebPDecoderOptions { + int bypass_filtering; // if true, skip the in-loop filtering + int no_fancy_upsampling; // if true, use faster pointwise upsampler + int use_cropping; // if true, cropping is applied _first_ + int crop_left, crop_top; // top-left position for cropping. + // Will be snapped to even values. + int crop_width, crop_height; // dimension of the cropping area + int use_scaling; // if true, scaling is applied _afterward_ + int scaled_width, scaled_height; // final resolution + int use_threads; // if true, use multi-threaded decoding + int dithering_strength; // dithering strength (0=Off, 100=full) +#if WEBP_DECODER_ABI_VERSION > 0x0203 + int flip; // flip output vertically +#endif +#if WEBP_DECODER_ABI_VERSION > 0x0204 + int alpha_dithering_strength; // alpha dithering strength in [0..100] +#endif + + // Unused for now: + int force_rotation; // forced rotation (to be applied _last_) + int no_enhancement; // if true, discard enhancement layer +#if WEBP_DECODER_ABI_VERSION < 0x0203 + uint32_t pad[5]; // padding for later use +#elif WEBP_DECODER_ABI_VERSION < 0x0204 + uint32_t pad[4]; // padding for later use +#else + uint32_t pad[3]; // padding for later use +#endif +}; + +// Main object storing the configuration for advanced decoding. +struct WebPDecoderConfig { + WebPBitstreamFeatures input; // Immutable bitstream features (optional) + WebPDecBuffer output; // Output buffer (can point to external mem) + WebPDecoderOptions options; // Decoding options +}; + +// Internal, version-checked, entry point +WEBP_EXTERN(int) WebPInitDecoderConfigInternal(WebPDecoderConfig*, int); + +// Initialize the configuration as empty. This function must always be +// called first, unless WebPGetFeatures() is to be called. +// Returns false in case of mismatched version. +static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) { + return WebPInitDecoderConfigInternal(config, WEBP_DECODER_ABI_VERSION); +} + +// Instantiate a new incremental decoder object with the requested +// configuration. The bitstream can be passed using 'data' and 'data_size' +// parameter, in which case the features will be parsed and stored into +// config->input. Otherwise, 'data' can be NULL and no parsing will occur. +// Note that 'config' can be NULL too, in which case a default configuration +// is used. +// The return WebPIDecoder object must always be deleted calling WebPIDelete(). +// Returns NULL in case of error (and config->status will then reflect +// the error condition). +WEBP_EXTERN(WebPIDecoder*) WebPIDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config); + +// Non-incremental version. This version decodes the full data at once, taking +// 'config' into account. Returns decoding status (which should be VP8_STATUS_OK +// if the decoding was successful). +WEBP_EXTERN(VP8StatusCode) WebPDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_WEBP_DECODE_H_ */ diff --git a/src/webp/demux.h b/src/webp/demux.h new file mode 100644 index 00000000..2da3239d --- /dev/null +++ b/src/webp/demux.h @@ -0,0 +1,224 @@ +// Copyright 2012 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. +// ----------------------------------------------------------------------------- +// +// Demux API. +// Enables extraction of image and extended format data from WebP files. + +// 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); +*/ + +#ifndef WEBP_WEBP_DEMUX_H_ +#define WEBP_WEBP_DEMUX_H_ + +#include "./mux_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_DEMUX_ABI_VERSION 0x0101 // MAJOR(8b) + MINOR(8b) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPDemuxState WebPDemuxState; +// typedef enum WebPFormatFeature WebPFormatFeature; +typedef struct WebPDemuxer WebPDemuxer; +typedef struct WebPIterator WebPIterator; +typedef struct WebPChunkIterator WebPChunkIterator; + +//------------------------------------------------------------------------------ + +// Returns the version number of the demux library, packed in hexadecimal using +// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN(int) WebPGetDemuxVersion(void); + +//------------------------------------------------------------------------------ +// Life of a Demux object + +typedef enum WebPDemuxState { + WEBP_DEMUX_PARSE_ERROR = -1, // An error occurred while parsing. + WEBP_DEMUX_PARSING_HEADER = 0, // Not enough data to parse full header. + WEBP_DEMUX_PARSED_HEADER = 1, // Header parsing complete, + // data may be available. + WEBP_DEMUX_DONE = 2 // Entire file has been parsed. +} WebPDemuxState; + +// Internal, version-checked, entry point +WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal( + const WebPData*, int, WebPDemuxState*, int); + +// Parses the full WebP file given by 'data'. +// Returns a WebPDemuxer object on successful parse, NULL otherwise. +static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { + return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION); +} + +// Parses the possibly incomplete WebP file given by 'data'. +// If 'state' is non-NULL it will be set to indicate the status of the demuxer. +// Returns NULL in case of error or if there isn't enough data to start parsing; +// and a WebPDemuxer object on successful parse. +// Note that WebPDemuxer keeps internal pointers to 'data' memory segment. +// If this data is volatile, the demuxer object should be deleted (by calling +// WebPDemuxDelete()) and WebPDemuxPartial() called again on the new data. +// This is usually an inexpensive operation. +static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( + const WebPData* data, WebPDemuxState* state) { + return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION); +} + +// Frees memory associated with 'dmux'. +WEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux); + +//------------------------------------------------------------------------------ +// Data/information extraction. + +typedef enum WebPFormatFeature { + WEBP_FF_FORMAT_FLAGS, // Extended format flags present in the 'VP8X' chunk. + WEBP_FF_CANVAS_WIDTH, + WEBP_FF_CANVAS_HEIGHT, + WEBP_FF_LOOP_COUNT, + WEBP_FF_BACKGROUND_COLOR, + WEBP_FF_FRAME_COUNT // Number of frames present in the demux object. + // In case of a partial demux, this is the number of + // frames seen so far, with the last frame possibly + // being partial. +} WebPFormatFeature; + +// Get the 'feature' value from the 'dmux'. +// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial() +// returned a state > WEBP_DEMUX_PARSING_HEADER. +WEBP_EXTERN(uint32_t) WebPDemuxGetI( + const WebPDemuxer* dmux, WebPFormatFeature feature); + +//------------------------------------------------------------------------------ +// Frame iteration. + +struct WebPIterator { + int frame_num; + int num_frames; // equivalent to WEBP_FF_FRAME_COUNT. + int fragment_num; + int num_fragments; + int x_offset, y_offset; // offset relative to the canvas. + int width, height; // dimensions of this frame or fragment. + int duration; // display duration in milliseconds. + WebPMuxAnimDispose dispose_method; // dispose method for the frame. + int complete; // true if 'fragment' contains a full frame. partial images + // may still be decoded with the WebP incremental decoder. + WebPData fragment; // The frame or fragment given by 'frame_num' and + // 'fragment_num'. + int has_alpha; // True if the frame or fragment contains transparency. + WebPMuxAnimBlend blend_method; // Blend operation for the frame. + + uint32_t pad[2]; // padding for later use. + void* private_; // for internal use only. +}; + +// Retrieves frame 'frame_number' from 'dmux'. +// 'iter->fragment' points to the first fragment on return from this function. +// Individual fragments may be extracted using WebPDemuxSelectFragment(). +// Setting 'frame_number' equal to 0 will return the last frame of the image. +// Returns false if 'dmux' is NULL or frame 'frame_number' is not present. +// Call WebPDemuxReleaseIterator() when use of the iterator is complete. +// NOTE: 'dmux' must persist for the lifetime of 'iter'. +WEBP_EXTERN(int) WebPDemuxGetFrame( + const WebPDemuxer* dmux, int frame_number, WebPIterator* iter); + +// Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or +// previous ('iter->frame_num' - 1) frame. These functions do not loop. +// Returns true on success, false otherwise. +WEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter); +WEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter); + +// Sets 'iter->fragment' to reflect fragment number 'fragment_num'. +// Returns true if fragment 'fragment_num' is present, false otherwise. +WEBP_EXTERN(int) WebPDemuxSelectFragment(WebPIterator* iter, int fragment_num); + +// Releases any memory associated with 'iter'. +// Must be called before any subsequent calls to WebPDemuxGetChunk() on the same +// iter. Also, must be called before destroying the associated WebPDemuxer with +// WebPDemuxDelete(). +WEBP_EXTERN(void) WebPDemuxReleaseIterator(WebPIterator* iter); + +//------------------------------------------------------------------------------ +// Chunk iteration. + +struct WebPChunkIterator { + // The current and total number of chunks with the fourcc given to + // WebPDemuxGetChunk(). + int chunk_num; + int num_chunks; + WebPData chunk; // The payload of the chunk. + + uint32_t pad[6]; // padding for later use + void* private_; +}; + +// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from +// 'dmux'. +// 'fourcc' is a character array containing the fourcc of the chunk to return, +// e.g., "ICCP", "XMP ", "EXIF", etc. +// Setting 'chunk_number' equal to 0 will return the last chunk in a set. +// Returns true if the chunk is found, false otherwise. Image related chunk +// payloads are accessed through WebPDemuxGetFrame() and related functions. +// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete. +// NOTE: 'dmux' must persist for the lifetime of the iterator. +WEBP_EXTERN(int) WebPDemuxGetChunk(const WebPDemuxer* dmux, + const char fourcc[4], int chunk_number, + WebPChunkIterator* iter); + +// Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous +// ('iter->chunk_num' - 1) chunk. These functions do not loop. +// Returns true on success, false otherwise. +WEBP_EXTERN(int) WebPDemuxNextChunk(WebPChunkIterator* iter); +WEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter); + +// Releases any memory associated with 'iter'. +// Must be called before destroying the associated WebPDemuxer with +// WebPDemuxDelete(). +WEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_WEBP_DEMUX_H_ */ diff --git a/src/webp/encode.h b/src/webp/encode.h new file mode 100644 index 00000000..b3f05b1f --- /dev/null +++ b/src/webp/encode.h @@ -0,0 +1,520 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: main interface +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_WEBP_ENCODE_H_ +#define WEBP_WEBP_ENCODE_H_ + +#include "./types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_ENCODER_ABI_VERSION 0x0202 // MAJOR(8b) + MINOR(8b) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPImageHint WebPImageHint; +// typedef enum WebPEncCSP WebPEncCSP; +// typedef enum WebPPreset WebPPreset; +// typedef enum WebPEncodingError WebPEncodingError; +typedef struct WebPConfig WebPConfig; +typedef struct WebPPicture WebPPicture; // main structure for I/O +typedef struct WebPAuxStats WebPAuxStats; +typedef struct WebPMemoryWriter WebPMemoryWriter; + +// Return the encoder's version number, packed in hexadecimal using 8bits for +// each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN(int) WebPGetEncoderVersion(void); + +//------------------------------------------------------------------------------ +// One-stop-shop call! No questions asked: + +// Returns the size of the compressed data (pointed to by *output), or 0 if +// an error occurred. The compressed data must be released by the caller +// using the call 'free(*output)'. +// These functions compress using the lossy format, and the quality_factor +// can go from 0 (smaller output, lower quality) to 100 (best quality, +// larger output). +WEBP_EXTERN(size_t) WebPEncodeRGB(const uint8_t* rgb, + int width, int height, int stride, + float quality_factor, uint8_t** output); +WEBP_EXTERN(size_t) WebPEncodeBGR(const uint8_t* bgr, + int width, int height, int stride, + float quality_factor, uint8_t** output); +WEBP_EXTERN(size_t) WebPEncodeRGBA(const uint8_t* rgba, + int width, int height, int stride, + float quality_factor, uint8_t** output); +WEBP_EXTERN(size_t) WebPEncodeBGRA(const uint8_t* bgra, + int width, int height, int stride, + float quality_factor, uint8_t** output); + +// These functions are the equivalent of the above, but compressing in a +// lossless manner. Files are usually larger than lossy format, but will +// not suffer any compression loss. +WEBP_EXTERN(size_t) WebPEncodeLosslessRGB(const uint8_t* rgb, + int width, int height, int stride, + uint8_t** output); +WEBP_EXTERN(size_t) WebPEncodeLosslessBGR(const uint8_t* bgr, + int width, int height, int stride, + uint8_t** output); +WEBP_EXTERN(size_t) WebPEncodeLosslessRGBA(const uint8_t* rgba, + int width, int height, int stride, + uint8_t** output); +WEBP_EXTERN(size_t) WebPEncodeLosslessBGRA(const uint8_t* bgra, + int width, int height, int stride, + uint8_t** output); + +//------------------------------------------------------------------------------ +// Coding parameters + +// Image characteristics hint for the underlying encoder. +typedef enum WebPImageHint { + WEBP_HINT_DEFAULT = 0, // default preset. + WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot + WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting + WEBP_HINT_GRAPH, // Discrete tone image (graph, map-tile etc). + WEBP_HINT_LAST +} WebPImageHint; + +// Compression parameters. +struct WebPConfig { + int lossless; // Lossless encoding (0=lossy(default), 1=lossless). + float quality; // between 0 (smallest file) and 100 (biggest) + int method; // quality/speed trade-off (0=fast, 6=slower-better) + + WebPImageHint image_hint; // Hint for image type (lossless only for now). + + // Parameters related to lossy compression only: + int target_size; // if non-zero, set the desired target size in bytes. + // Takes precedence over the 'compression' parameter. + float target_PSNR; // if non-zero, specifies the minimal distortion to + // try to achieve. Takes precedence over target_size. + int segments; // maximum number of segments to use, in [1..4] + int sns_strength; // Spatial Noise Shaping. 0=off, 100=maximum. + int filter_strength; // range: [0 = off .. 100 = strongest] + int filter_sharpness; // range: [0 = off .. 7 = least sharp] + int filter_type; // filtering type: 0 = simple, 1 = strong (only used + // if filter_strength > 0 or autofilter > 0) + int autofilter; // Auto adjust filter's strength [0 = off, 1 = on] + int alpha_compression; // Algorithm for encoding the alpha plane (0 = none, + // 1 = compressed with WebP lossless). Default is 1. + int alpha_filtering; // Predictive filtering method for alpha plane. + // 0: none, 1: fast, 2: best. Default if 1. + int alpha_quality; // Between 0 (smallest size) and 100 (lossless). + // Default is 100. + int pass; // number of entropy-analysis passes (in [1..10]). + + int show_compressed; // if true, export the compressed picture back. + // In-loop filtering is not applied. + int preprocessing; // preprocessing filter: + // 0=none, 1=segment-smooth, 2=pseudo-random dithering + int partitions; // log2(number of token partitions) in [0..3]. Default + // is set to 0 for easier progressive decoding. + int partition_limit; // quality degradation allowed to fit the 512k limit + // on prediction modes coding (0: no degradation, + // 100: maximum possible degradation). + int emulate_jpeg_size; // If true, compression parameters will be remapped + // to better match the expected output size from + // JPEG compression. Generally, the output size will + // be similar but the degradation will be lower. + int thread_level; // If non-zero, try and use multi-threaded encoding. + int low_memory; // If set, reduce memory usage (but increase CPU use). + + uint32_t pad[5]; // padding for later use +}; + +// Enumerate some predefined settings for WebPConfig, depending on the type +// of source picture. These presets are used when calling WebPConfigPreset(). +typedef enum WebPPreset { + WEBP_PRESET_DEFAULT = 0, // default preset. + WEBP_PRESET_PICTURE, // digital picture, like portrait, inner shot + WEBP_PRESET_PHOTO, // outdoor photograph, with natural lighting + WEBP_PRESET_DRAWING, // hand or line drawing, with high-contrast details + WEBP_PRESET_ICON, // small-sized colorful images + WEBP_PRESET_TEXT // text-like +} WebPPreset; + +// Internal, version-checked, entry point +WEBP_EXTERN(int) WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int); + +// Should always be called, to initialize a fresh WebPConfig structure before +// modification. Returns false in case of version mismatch. WebPConfigInit() +// must have succeeded before using the 'config' object. +// Note that the default values are lossless=0 and quality=75. +static WEBP_INLINE int WebPConfigInit(WebPConfig* config) { + return WebPConfigInitInternal(config, WEBP_PRESET_DEFAULT, 75.f, + WEBP_ENCODER_ABI_VERSION); +} + +// This function will initialize the configuration according to a predefined +// set of parameters (referred to by 'preset') and a given quality factor. +// This function can be called as a replacement to WebPConfigInit(). Will +// return false in case of error. +static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, + WebPPreset preset, float quality) { + return WebPConfigInitInternal(config, preset, quality, + WEBP_ENCODER_ABI_VERSION); +} + +#if WEBP_ENCODER_ABI_VERSION > 0x0202 +// Activate the lossless compression mode with the desired efficiency level +// between 0 (fastest, lowest compression) and 9 (slower, best compression). +// A good default level is '6', providing a fair tradeoff between compression +// speed and final compressed size. +// This function will overwrite several fields from config: 'method', 'quality' +// and 'lossless'. Returns false in case of parameter error. +WEBP_EXTERN(int) WebPConfigLosslessPreset(WebPConfig* config, int level); +#endif + +// Returns true if 'config' is non-NULL and all configuration parameters are +// within their valid ranges. +WEBP_EXTERN(int) WebPValidateConfig(const WebPConfig* config); + +//------------------------------------------------------------------------------ +// Input / Output +// Structure for storing auxiliary statistics (mostly for lossy encoding). + +struct WebPAuxStats { + int coded_size; // final size + + float PSNR[5]; // peak-signal-to-noise ratio for Y/U/V/All/Alpha + int block_count[3]; // number of intra4/intra16/skipped macroblocks + int header_bytes[2]; // approximate number of bytes spent for header + // and mode-partition #0 + int residual_bytes[3][4]; // approximate number of bytes spent for + // DC/AC/uv coefficients for each (0..3) segments. + int segment_size[4]; // number of macroblocks in each segments + int segment_quant[4]; // quantizer values for each segments + int segment_level[4]; // filtering strength for each segments [0..63] + + int alpha_data_size; // size of the transparency data + int layer_data_size; // size of the enhancement layer data + + // lossless encoder statistics + uint32_t lossless_features; // bit0:predictor bit1:cross-color transform + // bit2:subtract-green bit3:color indexing + int histogram_bits; // number of precision bits of histogram + int transform_bits; // precision bits for transform + int cache_bits; // number of bits for color cache lookup + int palette_size; // number of color in palette, if used + int lossless_size; // final lossless size + + uint32_t pad[4]; // padding for later use +}; + +// Signature for output function. Should return true if writing was successful. +// data/data_size is the segment of data to write, and 'picture' is for +// reference (and so one can make use of picture->custom_ptr). +typedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size, + const WebPPicture* picture); + +// WebPMemoryWrite: a special WebPWriterFunction that writes to memory using +// the following WebPMemoryWriter object (to be set as a custom_ptr). +struct WebPMemoryWriter { + uint8_t* mem; // final buffer (of size 'max_size', larger than 'size'). + size_t size; // final size + size_t max_size; // total capacity + uint32_t pad[1]; // padding for later use +}; + +// The following must be called first before any use. +WEBP_EXTERN(void) WebPMemoryWriterInit(WebPMemoryWriter* writer); + +#if WEBP_ENCODER_ABI_VERSION > 0x0203 +// The following must be called to deallocate writer->mem memory. The 'writer' +// object itself is not deallocated. +WEBP_EXTERN(void) WebPMemoryWriterClear(WebPMemoryWriter* writer); +#endif +// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon +// completion, writer.mem and writer.size will hold the coded data. +#if WEBP_ENCODER_ABI_VERSION > 0x0203 +// writer.mem must be freed by calling WebPMemoryWriterClear. +#else +// writer.mem must be freed by calling 'free(writer.mem)'. +#endif +WEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size, + const WebPPicture* picture); + +// Progress hook, called from time to time to report progress. It can return +// false to request an abort of the encoding process, or true otherwise if +// everything is OK. +typedef int (*WebPProgressHook)(int percent, const WebPPicture* picture); + +// Color spaces. +typedef enum WebPEncCSP { + // chroma sampling + WEBP_YUV420 = 0, // 4:2:0 + WEBP_YUV420A = 4, // alpha channel variant + WEBP_CSP_UV_MASK = 3, // bit-mask to get the UV sampling factors + WEBP_CSP_ALPHA_BIT = 4 // bit that is set if alpha is present +} WebPEncCSP; + +// Encoding error conditions. +typedef enum WebPEncodingError { + VP8_ENC_OK = 0, + VP8_ENC_ERROR_OUT_OF_MEMORY, // memory error allocating objects + VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, // memory error while flushing bits + VP8_ENC_ERROR_NULL_PARAMETER, // a pointer parameter is NULL + VP8_ENC_ERROR_INVALID_CONFIGURATION, // configuration is invalid + VP8_ENC_ERROR_BAD_DIMENSION, // picture has invalid width/height + VP8_ENC_ERROR_PARTITION0_OVERFLOW, // partition is bigger than 512k + VP8_ENC_ERROR_PARTITION_OVERFLOW, // partition is bigger than 16M + VP8_ENC_ERROR_BAD_WRITE, // error while flushing bytes + VP8_ENC_ERROR_FILE_TOO_BIG, // file is bigger than 4G + VP8_ENC_ERROR_USER_ABORT, // abort request by user + VP8_ENC_ERROR_LAST // list terminator. always last. +} WebPEncodingError; + +// maximum width/height allowed (inclusive), in pixels +#define WEBP_MAX_DIMENSION 16383 + +// Main exchange structure (input samples, output bytes, statistics) +struct WebPPicture { + // INPUT + ////////////// + // Main flag for encoder selecting between ARGB or YUV input. + // It is recommended to use ARGB input (*argb, argb_stride) for lossless + // compression, and YUV input (*y, *u, *v, etc.) for lossy compression + // since these are the respective native colorspace for these formats. + int use_argb; + + // YUV input (mostly used for input to lossy compression) + WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr). + int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION) + uint8_t *y, *u, *v; // pointers to luma/chroma planes. + int y_stride, uv_stride; // luma/chroma strides. + uint8_t* a; // pointer to the alpha plane + int a_stride; // stride of the alpha plane + uint32_t pad1[2]; // padding for later use + + // ARGB input (mostly used for input to lossless compression) + uint32_t* argb; // Pointer to argb (32 bit) plane. + int argb_stride; // This is stride in pixels units, not bytes. + uint32_t pad2[3]; // padding for later use + + // OUTPUT + /////////////// + // Byte-emission hook, to store compressed bytes as they are ready. + WebPWriterFunction writer; // can be NULL + void* custom_ptr; // can be used by the writer. + + // map for extra information (only for lossy compression mode) + int extra_info_type; // 1: intra type, 2: segment, 3: quant + // 4: intra-16 prediction mode, + // 5: chroma prediction mode, + // 6: bit cost, 7: distortion + uint8_t* extra_info; // if not NULL, points to an array of size + // ((width + 15) / 16) * ((height + 15) / 16) that + // will be filled with a macroblock map, depending + // on extra_info_type. + + // STATS AND REPORTS + /////////////////////////// + // Pointer to side statistics (updated only if not NULL) + WebPAuxStats* stats; + + // Error code for the latest error encountered during encoding + WebPEncodingError error_code; + + // If not NULL, report progress during encoding. + WebPProgressHook progress_hook; + + void* user_data; // this field is free to be set to any value and + // used during callbacks (like progress-report e.g.). + + uint32_t pad3[3]; // padding for later use + + // Unused for now + uint8_t *pad4, *pad5; + uint32_t pad6[8]; // padding for later use + + // PRIVATE FIELDS + //////////////////// + void* memory_; // row chunk of memory for yuva planes + void* memory_argb_; // and for argb too. + void* pad7[2]; // padding for later use +}; + +// Internal, version-checked, entry point +WEBP_EXTERN(int) WebPPictureInitInternal(WebPPicture*, int); + +// Should always be called, to initialize the structure. Returns false in case +// of version mismatch. WebPPictureInit() must have succeeded before using the +// 'picture' object. +// Note that, by default, use_argb is false and colorspace is WEBP_YUV420. +static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { + return WebPPictureInitInternal(picture, WEBP_ENCODER_ABI_VERSION); +} + +//------------------------------------------------------------------------------ +// WebPPicture utils + +// Convenience allocation / deallocation based on picture->width/height: +// Allocate y/u/v buffers as per colorspace/width/height specification. +// Note! This function will free the previous buffer if needed. +// Returns false in case of memory error. +WEBP_EXTERN(int) WebPPictureAlloc(WebPPicture* picture); + +// Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*(). +// Note that this function does _not_ free the memory used by the 'picture' +// object itself. +// Besides memory (which is reclaimed) all other fields of 'picture' are +// preserved. +WEBP_EXTERN(void) WebPPictureFree(WebPPicture* picture); + +// Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, *dst +// will fully own the copied pixels (this is not a view). The 'dst' picture need +// not be initialized as its content is overwritten. +// Returns false in case of memory allocation error. +WEBP_EXTERN(int) WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); + +// Compute PSNR, SSIM or LSIM distortion metric between two pictures. +// Result is in dB, stores in result[] in the Y/U/V/Alpha/All order. +// Returns false in case of error (src and ref don't have same dimension, ...) +// Warning: this function is rather CPU-intensive. +WEBP_EXTERN(int) WebPPictureDistortion( + const WebPPicture* src, const WebPPicture* ref, + int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM + float result[5]); + +// self-crops a picture to the rectangle defined by top/left/width/height. +// Returns false in case of memory allocation error, or if the rectangle is +// outside of the source picture. +// The rectangle for the view is defined by the top-left corner pixel +// coordinates (left, top) as well as its width and height. This rectangle +// must be fully be comprised inside the 'src' source picture. If the source +// picture uses the YUV420 colorspace, the top and left coordinates will be +// snapped to even values. +WEBP_EXTERN(int) WebPPictureCrop(WebPPicture* picture, + int left, int top, int width, int height); + +// Extracts a view from 'src' picture into 'dst'. The rectangle for the view +// is defined by the top-left corner pixel coordinates (left, top) as well +// as its width and height. This rectangle must be fully be comprised inside +// the 'src' source picture. If the source picture uses the YUV420 colorspace, +// the top and left coordinates will be snapped to even values. +// Picture 'src' must out-live 'dst' picture. Self-extraction of view is allowed +// ('src' equal to 'dst') as a mean of fast-cropping (but note that doing so, +// the original dimension will be lost). Picture 'dst' need not be initialized +// with WebPPictureInit() if it is different from 'src', since its content will +// be overwritten. +// Returns false in case of memory allocation error or invalid parameters. +WEBP_EXTERN(int) WebPPictureView(const WebPPicture* src, + int left, int top, int width, int height, + WebPPicture* dst); + +// Returns true if the 'picture' is actually a view and therefore does +// not own the memory for pixels. +WEBP_EXTERN(int) WebPPictureIsView(const WebPPicture* picture); + +// Rescale a picture to new dimension width x height. +// If either 'width' or 'height' (but not both) is 0 the corresponding +// dimension will be calculated preserving the aspect ratio. +// No gamma correction is applied. +// Returns false in case of error (invalid parameter or insufficient memory). +WEBP_EXTERN(int) WebPPictureRescale(WebPPicture* pic, int width, int height); + +// Colorspace conversion function to import RGB samples. +// Previous buffer will be free'd, if any. +// *rgb buffer should have a size of at least height * rgb_stride. +// Returns false in case of memory error. +WEBP_EXTERN(int) WebPPictureImportRGB( + WebPPicture* picture, const uint8_t* rgb, int rgb_stride); +// Same, but for RGBA buffer. +WEBP_EXTERN(int) WebPPictureImportRGBA( + WebPPicture* picture, const uint8_t* rgba, int rgba_stride); +// Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format +// input buffer ignoring the alpha channel. Avoids needing to copy the data +// to a temporary 24-bit RGB buffer to import the RGB only. +WEBP_EXTERN(int) WebPPictureImportRGBX( + WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride); + +// Variants of the above, but taking BGR(A|X) input. +WEBP_EXTERN(int) WebPPictureImportBGR( + WebPPicture* picture, const uint8_t* bgr, int bgr_stride); +WEBP_EXTERN(int) WebPPictureImportBGRA( + WebPPicture* picture, const uint8_t* bgra, int bgra_stride); +WEBP_EXTERN(int) WebPPictureImportBGRX( + WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride); + +// Converts picture->argb data to the YUV420A format. The 'colorspace' +// parameter is deprecated and should be equal to WEBP_YUV420. +// Upon return, picture->use_argb is set to false. The presence of real +// non-opaque transparent values is detected, and 'colorspace' will be +// adjusted accordingly. Note that this method is lossy. +// Returns false in case of error. +WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture, + WebPEncCSP /*colorspace = WEBP_YUV420*/); + +// Same as WebPPictureARGBToYUVA(), but the conversion is done using +// pseudo-random dithering with a strength 'dithering' between +// 0.0 (no dithering) and 1.0 (maximum dithering). This is useful +// for photographic picture. +WEBP_EXTERN(int) WebPPictureARGBToYUVADithered( + WebPPicture* picture, WebPEncCSP colorspace, float dithering); + +#if WEBP_ENCODER_ABI_VERSION > 0x0204 +// Performs 'smart' RGBA->YUVA420 downsampling and colorspace conversion. +// Downsampling is handled with extra care in case of color clipping. This +// method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better +// YUV representation. +// Returns false in case of error. +WEBP_EXTERN(int) WebPPictureSmartARGBToYUVA(WebPPicture* picture); +#endif + +// Converts picture->yuv to picture->argb and sets picture->use_argb to true. +// The input format must be YUV_420 or YUV_420A. +// Note that the use of this method is discouraged if one has access to the +// raw ARGB samples, since using YUV420 is comparatively lossy. Also, the +// conversion from YUV420 to ARGB incurs a small loss too. +// Returns false in case of error. +WEBP_EXTERN(int) WebPPictureYUVAToARGB(WebPPicture* picture); + +// Helper function: given a width x height plane of RGBA or YUV(A) samples +// clean-up the YUV or RGB samples under fully transparent area, to help +// compressibility (no guarantee, though). +WEBP_EXTERN(void) WebPCleanupTransparentArea(WebPPicture* picture); + +// Scan the picture 'picture' for the presence of non fully opaque alpha values. +// Returns true in such case. Otherwise returns false (indicating that the +// alpha plane can be ignored altogether e.g.). +WEBP_EXTERN(int) WebPPictureHasTransparency(const WebPPicture* picture); + +// Remove the transparency information (if present) by blending the color with +// the background color 'background_rgb' (specified as 24bit RGB triplet). +// After this call, all alpha values are reset to 0xff. +WEBP_EXTERN(void) WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb); + +//------------------------------------------------------------------------------ +// Main call + +// Main encoding call, after config and picture have been initialized. +// 'picture' must be less than 16384x16384 in dimension (cf WEBP_MAX_DIMENSION), +// and the 'config' object must be a valid one. +// Returns false in case of error, true otherwise. +// In case of error, picture->error_code is updated accordingly. +// 'picture' can hold the source samples in both YUV(A) or ARGB input, depending +// on the value of 'picture->use_argb'. It is highly recommended to use +// the former for lossy encoding, and the latter for lossless encoding +// (when config.lossless is true). Automatic conversion from one format to +// another is provided but they both incur some loss. +WEBP_EXTERN(int) WebPEncode(const WebPConfig* config, WebPPicture* picture); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_WEBP_ENCODE_H_ */ diff --git a/src/webp/format_constants.h b/src/webp/format_constants.h new file mode 100644 index 00000000..4c04b50c --- /dev/null +++ b/src/webp/format_constants.h @@ -0,0 +1,88 @@ +// Copyright 2012 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. +// ----------------------------------------------------------------------------- +// +// Internal header for constants related to WebP file format. +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_ +#define WEBP_WEBP_FORMAT_CONSTANTS_H_ + +// Create fourcc of the chunk from the chunk tag characters. +#define MKFOURCC(a, b, c, d) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (d) << 24) + +// VP8 related constants. +#define VP8_SIGNATURE 0x9d012a // Signature in VP8 data. +#define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition +#define VP8_MAX_PARTITION_SIZE (1 << 24) // max size for token partition +#define VP8_FRAME_HEADER_SIZE 10 // Size of the frame header within VP8 data. + +// VP8L related constants. +#define VP8L_SIGNATURE_SIZE 1 // VP8L signature size. +#define VP8L_MAGIC_BYTE 0x2f // VP8L signature byte. +#define VP8L_IMAGE_SIZE_BITS 14 // Number of bits used to store + // width and height. +#define VP8L_VERSION_BITS 3 // 3 bits reserved for version. +#define VP8L_VERSION 0 // version 0 +#define VP8L_FRAME_HEADER_SIZE 5 // Size of the VP8L frame header. + +#define MAX_PALETTE_SIZE 256 +#define MAX_CACHE_BITS 11 +#define HUFFMAN_CODES_PER_META_CODE 5 +#define ARGB_BLACK 0xff000000 + +#define DEFAULT_CODE_LENGTH 8 +#define MAX_ALLOWED_CODE_LENGTH 15 + +#define NUM_LITERAL_CODES 256 +#define NUM_LENGTH_CODES 24 +#define NUM_DISTANCE_CODES 40 +#define CODE_LENGTH_CODES 19 + +#define MIN_HUFFMAN_BITS 2 // min number of Huffman bits +#define MAX_HUFFMAN_BITS 9 // max number of Huffman bits + +#define TRANSFORM_PRESENT 1 // The bit to be written when next data + // to be read is a transform. +#define NUM_TRANSFORMS 4 // Maximum number of allowed transform + // in a bitstream. +typedef enum { + PREDICTOR_TRANSFORM = 0, + CROSS_COLOR_TRANSFORM = 1, + SUBTRACT_GREEN = 2, + COLOR_INDEXING_TRANSFORM = 3 +} VP8LImageTransformType; + +// Alpha related constants. +#define ALPHA_HEADER_LEN 1 +#define ALPHA_NO_COMPRESSION 0 +#define ALPHA_LOSSLESS_COMPRESSION 1 +#define ALPHA_PREPROCESSED_LEVELS 1 + +// Mux related constants. +#define TAG_SIZE 4 // Size of a chunk tag (e.g. "VP8L"). +#define CHUNK_SIZE_BYTES 4 // Size needed to store chunk's size. +#define CHUNK_HEADER_SIZE 8 // Size of a chunk header. +#define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP"). +#define ANMF_CHUNK_SIZE 16 // Size of an ANMF chunk. +#define ANIM_CHUNK_SIZE 6 // Size of an ANIM chunk. +#define FRGM_CHUNK_SIZE 6 // Size of a FRGM chunk. +#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk. + +#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height. +#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height. +#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count +#define MAX_DURATION (1 << 24) // maximum duration +#define MAX_POSITION_OFFSET (1 << 24) // maximum frame/fragment x/y offset + +// Maximum chunk payload is such that adding the header and padding won't +// overflow a uint32_t. +#define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1) + +#endif /* WEBP_WEBP_FORMAT_CONSTANTS_H_ */ diff --git a/src/webp/mux_types.h b/src/webp/mux_types.h new file mode 100644 index 00000000..c94043a3 --- /dev/null +++ b/src/webp/mux_types.h @@ -0,0 +1,97 @@ +// Copyright 2012 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. +// ----------------------------------------------------------------------------- +// +// Data-types common to the mux and demux libraries. +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_WEBP_MUX_TYPES_H_ +#define WEBP_WEBP_MUX_TYPES_H_ + +#include <stdlib.h> // free() +#include <string.h> // memset() +#include "./types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPFeatureFlags WebPFeatureFlags; +// typedef enum WebPMuxAnimDispose WebPMuxAnimDispose; +// typedef enum WebPMuxAnimBlend WebPMuxAnimBlend; +typedef struct WebPData WebPData; + +// VP8X Feature Flags. +typedef enum WebPFeatureFlags { + FRAGMENTS_FLAG = 0x00000001, + ANIMATION_FLAG = 0x00000002, + XMP_FLAG = 0x00000004, + EXIF_FLAG = 0x00000008, + ALPHA_FLAG = 0x00000010, + ICCP_FLAG = 0x00000020 +} WebPFeatureFlags; + +// Dispose method (animation only). Indicates how the area used by the current +// frame is to be treated before rendering the next frame on the canvas. +typedef enum WebPMuxAnimDispose { + WEBP_MUX_DISPOSE_NONE, // Do not dispose. + WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color. +} WebPMuxAnimDispose; + +// Blend operation (animation only). Indicates how transparent pixels of the +// current frame are blended with those of the previous canvas. +typedef enum WebPMuxAnimBlend { + WEBP_MUX_BLEND, // Blend. + WEBP_MUX_NO_BLEND // Do not blend. +} WebPMuxAnimBlend; + +// Data type used to describe 'raw' data, e.g., chunk data +// (ICC profile, metadata) and WebP compressed image data. +struct WebPData { + const uint8_t* bytes; + size_t size; +}; + +// Initializes the contents of the 'webp_data' object with default values. +static WEBP_INLINE void WebPDataInit(WebPData* webp_data) { + if (webp_data != NULL) { + memset(webp_data, 0, sizeof(*webp_data)); + } +} + +// Clears the contents of the 'webp_data' object by calling free(). Does not +// deallocate the object itself. +static WEBP_INLINE void WebPDataClear(WebPData* webp_data) { + if (webp_data != NULL) { + free((void*)webp_data->bytes); + WebPDataInit(webp_data); + } +} + +// Allocates necessary storage for 'dst' and copies the contents of 'src'. +// Returns true on success. +static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) { + if (src == NULL || dst == NULL) return 0; + WebPDataInit(dst); + if (src->bytes != NULL && src->size != 0) { + dst->bytes = (uint8_t*)malloc(src->size); + if (dst->bytes == NULL) return 0; + memcpy((void*)dst->bytes, src->bytes, src->size); + dst->size = src->size; + } + return 1; +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_WEBP_MUX_TYPES_H_ */ diff --git a/src/webp/types.h b/src/webp/types.h new file mode 100644 index 00000000..9b036e0c --- /dev/null +++ b/src/webp/types.h @@ -0,0 +1,48 @@ +// Copyright 2010 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. +// ----------------------------------------------------------------------------- +// +// Common types +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_WEBP_TYPES_H_ +#define WEBP_WEBP_TYPES_H_ + +#include <stddef.h> // for size_t + +#ifndef _MSC_VER +#include <inttypes.h> +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) +#define WEBP_INLINE inline +#else +#define WEBP_INLINE +#endif +#else +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef unsigned long long int uint64_t; +typedef long long int int64_t; +#define WEBP_INLINE __forceinline +#endif /* _MSC_VER */ + +#ifndef WEBP_EXTERN +// This explicitly marks library functions and allows for changing the +// signature for e.g., Windows DLL builds. +#define WEBP_EXTERN(type) extern type +#endif /* WEBP_EXTERN */ + +// Macro to check ABI compatibility (same major revision number) +#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8)) + +#endif /* WEBP_WEBP_TYPES_H_ */ |