1 /*
2 Copyright (c) 2014 - 2019, Syoyo Fujita and many contributors.
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright
10       notice, this list of conditions and the following disclaimer in the
11       documentation and/or other materials provided with the distribution.
12     * Neither the name of the Syoyo Fujita nor the
13       names of its contributors may be used to endorse or promote products
14       derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 
28 // TinyEXR contains some OpenEXR code, which is licensed under ------------
29 
30 ///////////////////////////////////////////////////////////////////////////
31 //
32 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
33 // Digital Ltd. LLC
34 //
35 // All rights reserved.
36 //
37 // Redistribution and use in source and binary forms, with or without
38 // modification, are permitted provided that the following conditions are
39 // met:
40 // *       Redistributions of source code must retain the above copyright
41 // notice, this list of conditions and the following disclaimer.
42 // *       Redistributions in binary form must reproduce the above
43 // copyright notice, this list of conditions and the following disclaimer
44 // in the documentation and/or other materials provided with the
45 // distribution.
46 // *       Neither the name of Industrial Light & Magic nor the names of
47 // its contributors may be used to endorse or promote products derived
48 // from this software without specific prior written permission.
49 //
50 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 //
62 ///////////////////////////////////////////////////////////////////////////
63 
64 // End of OpenEXR license -------------------------------------------------
65 
66 #ifndef TINYEXR_H_
67 #define TINYEXR_H_
68 
69 //
70 //
71 //   Do this:
72 //    #define TINYEXR_IMPLEMENTATION
73 //   before you include this file in *one* C or C++ file to create the
74 //   implementation.
75 //
76 //   // i.e. it should look like this:
77 //   #include ...
78 //   #include ...
79 //   #include ...
80 //   #define TINYEXR_IMPLEMENTATION
81 //   #include "tinyexr.h"
82 //
83 //
84 
85 #include <stddef.h>  // for size_t
86 #include <stdint.h>  // guess stdint.h is available(C99)
87 
88 #ifdef __cplusplus
89 extern "C" {
90 #endif
91 
92 // Use embedded miniz or not to decode ZIP format pixel. Linking with zlib
93 // required if this flas is 0.
94 #ifndef TINYEXR_USE_MINIZ
95 #define TINYEXR_USE_MINIZ (1)
96 #endif
97 
98 // Disable PIZ comporession when applying cpplint.
99 #ifndef TINYEXR_USE_PIZ
100 #define TINYEXR_USE_PIZ (1)
101 #endif
102 
103 #ifndef TINYEXR_USE_ZFP
104 #define TINYEXR_USE_ZFP (0)  // TinyEXR extension.
105 // http://computation.llnl.gov/projects/floating-point-compression
106 #endif
107 
108 #define TINYEXR_SUCCESS (0)
109 #define TINYEXR_ERROR_INVALID_MAGIC_NUMBER (-1)
110 #define TINYEXR_ERROR_INVALID_EXR_VERSION (-2)
111 #define TINYEXR_ERROR_INVALID_ARGUMENT (-3)
112 #define TINYEXR_ERROR_INVALID_DATA (-4)
113 #define TINYEXR_ERROR_INVALID_FILE (-5)
114 #define TINYEXR_ERROR_INVALID_PARAMETER (-6)
115 #define TINYEXR_ERROR_CANT_OPEN_FILE (-7)
116 #define TINYEXR_ERROR_UNSUPPORTED_FORMAT (-8)
117 #define TINYEXR_ERROR_INVALID_HEADER (-9)
118 #define TINYEXR_ERROR_UNSUPPORTED_FEATURE (-10)
119 #define TINYEXR_ERROR_CANT_WRITE_FILE (-11)
120 #define TINYEXR_ERROR_SERIALZATION_FAILED (-12)
121 
122 // @note { OpenEXR file format: http://www.openexr.com/openexrfilelayout.pdf }
123 
124 // pixel type: possible values are: UINT = 0 HALF = 1 FLOAT = 2
125 #define TINYEXR_PIXELTYPE_UINT (0)
126 #define TINYEXR_PIXELTYPE_HALF (1)
127 #define TINYEXR_PIXELTYPE_FLOAT (2)
128 
129 #define TINYEXR_MAX_HEADER_ATTRIBUTES (1024)
130 #define TINYEXR_MAX_CUSTOM_ATTRIBUTES (128)
131 
132 #define TINYEXR_COMPRESSIONTYPE_NONE (0)
133 #define TINYEXR_COMPRESSIONTYPE_RLE (1)
134 #define TINYEXR_COMPRESSIONTYPE_ZIPS (2)
135 #define TINYEXR_COMPRESSIONTYPE_ZIP (3)
136 #define TINYEXR_COMPRESSIONTYPE_PIZ (4)
137 #define TINYEXR_COMPRESSIONTYPE_ZFP (128)  // TinyEXR extension
138 
139 #define TINYEXR_ZFP_COMPRESSIONTYPE_RATE (0)
140 #define TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION (1)
141 #define TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY (2)
142 
143 #define TINYEXR_TILE_ONE_LEVEL (0)
144 #define TINYEXR_TILE_MIPMAP_LEVELS (1)
145 #define TINYEXR_TILE_RIPMAP_LEVELS (2)
146 
147 #define TINYEXR_TILE_ROUND_DOWN (0)
148 #define TINYEXR_TILE_ROUND_UP (1)
149 
150 typedef struct _EXRVersion {
151   int version;    // this must be 2
152   int tiled;      // tile format image
153   int long_name;  // long name attribute
154   int non_image;  // deep image(EXR 2.0)
155   int multipart;  // multi-part(EXR 2.0)
156 } EXRVersion;
157 
158 typedef struct _EXRAttribute {
159   char name[256];  // name and type are up to 255 chars long.
160   char type[256];
161   unsigned char *value;  // uint8_t*
162   int size;
163   int pad0;
164 } EXRAttribute;
165 
166 typedef struct _EXRChannelInfo {
167   char name[256];  // less than 255 bytes long
168   int pixel_type;
169   int x_sampling;
170   int y_sampling;
171   unsigned char p_linear;
172   unsigned char pad[3];
173 } EXRChannelInfo;
174 
175 typedef struct _EXRTile {
176   int offset_x;
177   int offset_y;
178   int level_x;
179   int level_y;
180 
181   int width;   // actual width in a tile.
182   int height;  // actual height int a tile.
183 
184   unsigned char **images;  // image[channels][pixels]
185 } EXRTile;
186 
187 typedef struct _EXRHeader {
188   float pixel_aspect_ratio;
189   int line_order;
190   int data_window[4];
191   int display_window[4];
192   float screen_window_center[2];
193   float screen_window_width;
194 
195   int chunk_count;
196 
197   // Properties for tiled format(`tiledesc`).
198   int tiled;
199   int tile_size_x;
200   int tile_size_y;
201   int tile_level_mode;
202   int tile_rounding_mode;
203 
204   int long_name;
205   int non_image;
206   int multipart;
207   unsigned int header_len;
208 
209   // Custom attributes(exludes required attributes(e.g. `channels`,
210   // `compression`, etc)
211   int num_custom_attributes;
212   EXRAttribute *custom_attributes;  // array of EXRAttribute. size =
213                                     // `num_custom_attributes`.
214 
215   EXRChannelInfo *channels;  // [num_channels]
216 
217   int *pixel_types;  // Loaded pixel type(TINYEXR_PIXELTYPE_*) of `images` for
218   // each channel. This is overwritten with `requested_pixel_types` when
219   // loading.
220   int num_channels;
221 
222   int compression_type;        // compression type(TINYEXR_COMPRESSIONTYPE_*)
223   int *requested_pixel_types;  // Filled initially by
224                                // ParseEXRHeaderFrom(Meomory|File), then users
225                                // can edit it(only valid for HALF pixel type
226                                // channel)
227 
228 } EXRHeader;
229 
230 typedef struct _EXRMultiPartHeader {
231   int num_headers;
232   EXRHeader *headers;
233 
234 } EXRMultiPartHeader;
235 
236 typedef struct _EXRImage {
237   EXRTile *tiles;  // Tiled pixel data. The application must reconstruct image
238                    // from tiles manually. NULL if scanline format.
239   unsigned char **images;  // image[channels][pixels]. NULL if tiled format.
240 
241   int width;
242   int height;
243   int num_channels;
244 
245   // Properties for tile format.
246   int num_tiles;
247 
248 } EXRImage;
249 
250 typedef struct _EXRMultiPartImage {
251   int num_images;
252   EXRImage *images;
253 
254 } EXRMultiPartImage;
255 
256 typedef struct _DeepImage {
257   const char **channel_names;
258   float ***image;      // image[channels][scanlines][samples]
259   int **offset_table;  // offset_table[scanline][offsets]
260   int num_channels;
261   int width;
262   int height;
263   int pad0;
264 } DeepImage;
265 
266 // @deprecated { to be removed. }
267 // Loads single-frame OpenEXR image. Assume EXR image contains A(single channel
268 // alpha) or RGB(A) channels.
269 // Application must free image data as returned by `out_rgba`
270 // Result image format is: float x RGBA x width x hight
271 // Returns negative value and may set error string in `err` when there's an
272 // error
273 extern int LoadEXR(float **out_rgba, int *width, int *height,
274                    const char *filename, const char **err);
275 
276 // @deprecated { to be removed. }
277 // Simple wrapper API for ParseEXRHeaderFromFile.
278 // checking given file is a EXR file(by just look up header)
279 // @return TINYEXR_SUCCEES for EXR image, TINYEXR_ERROR_INVALID_HEADER for
280 // others
281 extern int IsEXR(const char *filename);
282 
283 // @deprecated { to be removed. }
284 // Saves single-frame OpenEXR image. Assume EXR image contains RGB(A) channels.
285 // components must be 1(Grayscale), 3(RGB) or 4(RGBA).
286 // Input image format is: `float x width x height`, or `float x RGB(A) x width x
287 // hight`
288 // Save image as fp16(HALF) format when `save_as_fp16` is positive non-zero
289 // value.
290 // Save image as fp32(FLOAT) format when `save_as_fp16` is 0.
291 // Use ZIP compression by default.
292 // Returns negative value and may set error string in `err` when there's an
293 // error
294 extern int SaveEXR(const float *data, const int width, const int height,
295                    const int components, const int save_as_fp16,
296                    const char *filename, const char **err);
297 
298 // Initialize EXRHeader struct
299 extern void InitEXRHeader(EXRHeader *exr_header);
300 
301 // Initialize EXRImage struct
302 extern void InitEXRImage(EXRImage *exr_image);
303 
304 // Free's internal data of EXRHeader struct
305 extern int FreeEXRHeader(EXRHeader *exr_header);
306 
307 // Free's internal data of EXRImage struct
308 extern int FreeEXRImage(EXRImage *exr_image);
309 
310 // Free's error message
311 extern void FreeEXRErrorMessage(const char *msg);
312 
313 // Parse EXR version header of a file.
314 extern int ParseEXRVersionFromFile(EXRVersion *version, const char *filename);
315 
316 // Parse EXR version header from memory-mapped EXR data.
317 extern int ParseEXRVersionFromMemory(EXRVersion *version,
318                                      const unsigned char *memory, size_t size);
319 
320 // Parse single-part OpenEXR header from a file and initialize `EXRHeader`.
321 // When there was an error message, Application must free `err` with
322 // FreeEXRErrorMessage()
323 extern int ParseEXRHeaderFromFile(EXRHeader *header, const EXRVersion *version,
324                                   const char *filename, const char **err);
325 
326 // Parse single-part OpenEXR header from a memory and initialize `EXRHeader`.
327 // When there was an error message, Application must free `err` with
328 // FreeEXRErrorMessage()
329 extern int ParseEXRHeaderFromMemory(EXRHeader *header,
330                                     const EXRVersion *version,
331                                     const unsigned char *memory, size_t size,
332                                     const char **err);
333 
334 // Parse multi-part OpenEXR headers from a file and initialize `EXRHeader*`
335 // array.
336 // When there was an error message, Application must free `err` with
337 // FreeEXRErrorMessage()
338 extern int ParseEXRMultipartHeaderFromFile(EXRHeader ***headers,
339                                            int *num_headers,
340                                            const EXRVersion *version,
341                                            const char *filename,
342                                            const char **err);
343 
344 // Parse multi-part OpenEXR headers from a memory and initialize `EXRHeader*`
345 // array
346 // When there was an error message, Application must free `err` with
347 // FreeEXRErrorMessage()
348 extern int ParseEXRMultipartHeaderFromMemory(EXRHeader ***headers,
349                                              int *num_headers,
350                                              const EXRVersion *version,
351                                              const unsigned char *memory,
352                                              size_t size, const char **err);
353 
354 // Loads single-part OpenEXR image from a file.
355 // Application must setup `ParseEXRHeaderFromFile` before calling this function.
356 // Application can free EXRImage using `FreeEXRImage`
357 // Returns negative value and may set error string in `err` when there's an
358 // error
359 // When there was an error message, Application must free `err` with
360 // FreeEXRErrorMessage()
361 extern int LoadEXRImageFromFile(EXRImage *image, const EXRHeader *header,
362                                 const char *filename, const char **err);
363 
364 // Loads single-part OpenEXR image from a memory.
365 // Application must setup `EXRHeader` with
366 // `ParseEXRHeaderFromMemory` before calling this function.
367 // Application can free EXRImage using `FreeEXRImage`
368 // Returns negative value and may set error string in `err` when there's an
369 // error
370 // When there was an error message, Application must free `err` with
371 // FreeEXRErrorMessage()
372 extern int LoadEXRImageFromMemory(EXRImage *image, const EXRHeader *header,
373                                   const unsigned char *memory,
374                                   const size_t size, const char **err);
375 
376 // Loads multi-part OpenEXR image from a file.
377 // Application must setup `ParseEXRMultipartHeaderFromFile` before calling this
378 // function.
379 // Application can free EXRImage using `FreeEXRImage`
380 // Returns negative value and may set error string in `err` when there's an
381 // error
382 // When there was an error message, Application must free `err` with
383 // FreeEXRErrorMessage()
384 extern int LoadEXRMultipartImageFromFile(EXRImage *images,
385                                          const EXRHeader **headers,
386                                          unsigned int num_parts,
387                                          const char *filename,
388                                          const char **err);
389 
390 // Loads multi-part OpenEXR image from a memory.
391 // Application must setup `EXRHeader*` array with
392 // `ParseEXRMultipartHeaderFromMemory` before calling this function.
393 // Application can free EXRImage using `FreeEXRImage`
394 // Returns negative value and may set error string in `err` when there's an
395 // error
396 // When there was an error message, Application must free `err` with
397 // FreeEXRErrorMessage()
398 extern int LoadEXRMultipartImageFromMemory(EXRImage *images,
399                                            const EXRHeader **headers,
400                                            unsigned int num_parts,
401                                            const unsigned char *memory,
402                                            const size_t size, const char **err);
403 
404 // Saves multi-channel, single-frame OpenEXR image to a file.
405 // Returns negative value and may set error string in `err` when there's an
406 // error
407 // When there was an error message, Application must free `err` with
408 // FreeEXRErrorMessage()
409 extern int SaveEXRImageToFile(const EXRImage *image,
410                               const EXRHeader *exr_header, const char *filename,
411                               const char **err);
412 
413 // Saves multi-channel, single-frame OpenEXR image to a memory.
414 // Image is compressed using EXRImage.compression value.
415 // Return the number of bytes if success.
416 // Return zero and will set error string in `err` when there's an
417 // error.
418 // When there was an error message, Application must free `err` with
419 // FreeEXRErrorMessage()
420 extern size_t SaveEXRImageToMemory(const EXRImage *image,
421                                    const EXRHeader *exr_header,
422                                    unsigned char **memory, const char **err);
423 
424 // Loads single-frame OpenEXR deep image.
425 // Application must free memory of variables in DeepImage(image, offset_table)
426 // Returns negative value and may set error string in `err` when there's an
427 // error
428 // When there was an error message, Application must free `err` with
429 // FreeEXRErrorMessage()
430 extern int LoadDeepEXR(DeepImage *out_image, const char *filename,
431                        const char **err);
432 
433 // NOT YET IMPLEMENTED:
434 // Saves single-frame OpenEXR deep image.
435 // Returns negative value and may set error string in `err` when there's an
436 // error
437 // extern int SaveDeepEXR(const DeepImage *in_image, const char *filename,
438 //                       const char **err);
439 
440 // NOT YET IMPLEMENTED:
441 // Loads multi-part OpenEXR deep image.
442 // Application must free memory of variables in DeepImage(image, offset_table)
443 // extern int LoadMultiPartDeepEXR(DeepImage **out_image, int num_parts, const
444 // char *filename,
445 //                       const char **err);
446 
447 // For emscripten.
448 // Loads single-frame OpenEXR image from memory. Assume EXR image contains
449 // RGB(A) channels.
450 // Returns negative value and may set error string in `err` when there's an
451 // error
452 // When there was an error message, Application must free `err` with
453 // FreeEXRErrorMessage()
454 extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
455                              const unsigned char *memory, size_t size,
456                              const char **err);
457 
458 #ifdef __cplusplus
459 }
460 #endif
461 
462 #endif  // TINYEXR_H_
463 
464 #ifdef TINYEXR_IMPLEMENTATION
465 #ifndef TINYEXR_IMPLEMENTATION_DEIFNED
466 #define TINYEXR_IMPLEMENTATION_DEIFNED
467 
468 #include <algorithm>
469 #include <cassert>
470 #include <cstdio>
471 #include <cstdlib>
472 #include <cstring>
473 #include <sstream>
474 
475 //#include <iostream> // debug
476 
477 #include <limits>
478 #include <string>
479 #include <vector>
480 
481 #if __cplusplus > 199711L
482 // C++11
483 #include <cstdint>
484 #endif  // __cplusplus > 199711L
485 
486 #ifdef _OPENMP
487 #include <omp.h>
488 #endif
489 
490 #if TINYEXR_USE_MINIZ
491 #else
492 //  Issue #46. Please include your own zlib-compatible API header before
493 //  including `tinyexr.h`
494 //#include "zlib.h"
495 #endif
496 
497 #if TINYEXR_USE_ZFP
498 #include "zfp.h"
499 #endif
500 
501 namespace tinyexr {
502 
503 #if __cplusplus > 199711L
504 // C++11
505 typedef uint64_t tinyexr_uint64;
506 typedef int64_t tinyexr_int64;
507 #else
508 // Although `long long` is not a standard type pre C++11, assume it is defined
509 // as a compiler's extension.
510 #ifdef __clang__
511 #pragma clang diagnostic push
512 #pragma clang diagnostic ignored "-Wc++11-long-long"
513 #endif
514 typedef unsigned long long tinyexr_uint64;
515 typedef long long tinyexr_int64;
516 #ifdef __clang__
517 #pragma clang diagnostic pop
518 #endif
519 #endif
520 
521 #if TINYEXR_USE_MINIZ
522 
523 namespace miniz {
524 
525 #ifdef __clang__
526 #pragma clang diagnostic push
527 #pragma clang diagnostic ignored "-Wc++11-long-long"
528 #pragma clang diagnostic ignored "-Wold-style-cast"
529 #pragma clang diagnostic ignored "-Wpadded"
530 #pragma clang diagnostic ignored "-Wsign-conversion"
531 #pragma clang diagnostic ignored "-Wc++11-extensions"
532 #pragma clang diagnostic ignored "-Wconversion"
533 #pragma clang diagnostic ignored "-Wunused-function"
534 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
535 #pragma clang diagnostic ignored "-Wundef"
536 
537 #if __has_warning("-Wcomma")
538 #pragma clang diagnostic ignored "-Wcomma"
539 #endif
540 
541 #if __has_warning("-Wmacro-redefined")
542 #pragma clang diagnostic ignored "-Wmacro-redefined"
543 #endif
544 
545 #if __has_warning("-Wcast-qual")
546 #pragma clang diagnostic ignored "-Wcast-qual"
547 #endif
548 
549 #if __has_warning("-Wzero-as-null-pointer-constant")
550 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
551 #endif
552 
553 #if __has_warning("-Wtautological-constant-compare")
554 #pragma clang diagnostic ignored "-Wtautological-constant-compare"
555 #endif
556 
557 #if __has_warning("-Wextra-semi-stmt")
558 #pragma clang diagnostic ignored "-Wextra-semi-stmt"
559 #endif
560 
561 #endif
562 
563 /* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP
564    reading/writing/appending, PNG writing
565    See "unlicense" statement at the end of this file.
566    Rich Geldreich <richgel99@gmail.com>, last updated Oct. 13, 2013
567    Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951:
568    http://www.ietf.org/rfc/rfc1951.txt
569 
570    Most API's defined in miniz.c are optional. For example, to disable the
571    archive related functions just define
572    MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO
573    (see the list below for more macros).
574 
575    * Change History
576      10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major
577    release with Zip64 support (almost there!):
578        - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug
579    (thanks kahmyong.moon@hp.com) which could cause locate files to not find
580    files. This bug
581         would only have occured in earlier versions if you explicitly used this
582    flag, OR if you used mz_zip_extract_archive_file_to_heap() or
583    mz_zip_add_mem_to_archive_file_in_place()
584         (which used this flag). If you can't switch to v1.15 but want to fix
585    this bug, just remove the uses of this flag from both helper funcs (and of
586    course don't use the flag).
587        - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when
588    pUser_read_buf is not NULL and compressed size is > uncompressed size
589        - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract
590    compressed data from directory entries, to account for weird zipfiles which
591    contain zero-size compressed data on dir entries.
592          Hopefully this fix won't cause any issues on weird zip archives,
593    because it assumes the low 16-bits of zip external attributes are DOS
594    attributes (which I believe they always are in practice).
595        - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the
596    internal attributes, just the filename and external attributes
597        - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed
598        - Added cmake support for Linux builds which builds all the examples,
599    tested with clang v3.3 and gcc v4.6.
600        - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti
601        - Merged MZ_FORCEINLINE fix from hdeanclark
602        - Fix <time.h> include before config #ifdef, thanks emil.brink
603        - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping
604    (super useful for OpenGL apps), and explicit control over the compression
605    level (so you can
606         set it to 1 for real-time compression).
607        - Merged in some compiler fixes from paulharris's github repro.
608        - Retested this build under Windows (VS 2010, including static analysis),
609    tcc  0.9.26, gcc v4.6 and clang v3.3.
610        - Added example6.c, which dumps an image of the mandelbrot set to a PNG
611    file.
612        - Modified example2 to help test the
613    MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more.
614        - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix
615    possible src file fclose() leak if alignment bytes+local header file write
616    faiiled
617                  - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader():
618    Was pushing the wrong central dir header offset, appears harmless in this
619    release, but it became a problem in the zip64 branch
620      5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE,
621    #include <time.h> (thanks fermtect).
622      5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix
623    mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit.
624        - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and
625    re-ran a randomized regression test on ~500k files.
626        - Eliminated a bunch of warnings when compiling with GCC 32-bit/64.
627        - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze
628    (static analysis) option and fixed all warnings (except for the silly
629         "Use of the comma-operator in a tested expression.." analysis warning,
630    which I purposely use to work around a MSVC compiler warning).
631        - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and
632    tested Linux executables. The codeblocks workspace is compatible with
633    Linux+Win32/x64.
634        - Added miniz_tester solution/project, which is a useful little app
635    derived from LZHAM's tester app that I use as part of the regression test.
636        - Ran miniz.c and tinfl.c through another series of regression testing on
637    ~500,000 files and archives.
638        - Modified example5.c so it purposely disables a bunch of high-level
639    functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the
640    MINIZ_NO_STDIO bug report.)
641        - Fix ftell() usage in examples so they exit with an error on files which
642    are too large (a limitation of the examples, not miniz itself).
643      4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple
644    minor level_and_flags issues in the archive API's.
645       level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce
646    Dawson <bruced@valvesoftware.com> for the feedback/bug report.
647      5/28/11 v1.11 - Added statement from unlicense.org
648      5/27/11 v1.10 - Substantial compressor optimizations:
649       - Level 1 is now ~4x faster than before. The L1 compressor's throughput
650    now varies between 70-110MB/sec. on a
651       - Core i7 (actual throughput varies depending on the type of data, and x64
652    vs. x86).
653       - Improved baseline L2-L9 compression perf. Also, greatly improved
654    compression perf. issues on some file types.
655       - Refactored the compression code for better readability and
656    maintainability.
657       - Added level 10 compression level (L10 has slightly better ratio than
658    level 9, but could have a potentially large
659        drop in throughput on some files).
660      5/15/11 v1.09 - Initial stable release.
661 
662    * Low-level Deflate/Inflate implementation notes:
663 
664      Compression: Use the "tdefl" API's. The compressor supports raw, static,
665    and dynamic blocks, lazy or
666      greedy parsing, match length filtering, RLE-only, and Huffman-only streams.
667    It performs and compresses
668      approximately as well as zlib.
669 
670      Decompression: Use the "tinfl" API's. The entire decompressor is
671    implemented as a single function
672      coroutine: see tinfl_decompress(). It supports decompression into a 32KB
673    (or larger power of 2) wrapping buffer, or into a memory
674      block large enough to hold the entire file.
675 
676      The low-level tdefl/tinfl API's do not make any use of dynamic memory
677    allocation.
678 
679    * zlib-style API notes:
680 
681      miniz.c implements a fairly large subset of zlib. There's enough
682    functionality present for it to be a drop-in
683      zlib replacement in many apps:
684         The z_stream struct, optional memory allocation callbacks
685         deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound
686         inflateInit/inflateInit2/inflate/inflateEnd
687         compress, compress2, compressBound, uncompress
688         CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly
689    routines.
690         Supports raw deflate streams or standard zlib streams with adler-32
691    checking.
692 
693      Limitations:
694       The callback API's are not implemented yet. No support for gzip headers or
695    zlib static dictionaries.
696       I've tried to closely emulate zlib's various flavors of stream flushing
697    and return status codes, but
698       there are no guarantees that miniz.c pulls this off perfectly.
699 
700    * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function,
701    originally written by
702      Alex Evans. Supports 1-4 bytes/pixel images.
703 
704    * ZIP archive API notes:
705 
706      The ZIP archive API's where designed with simplicity and efficiency in
707    mind, with just enough abstraction to
708      get the job done with minimal fuss. There are simple API's to retrieve file
709    information, read files from
710      existing archives, create new archives, append new files to existing
711    archives, or clone archive data from
712      one archive to another. It supports archives located in memory or the heap,
713    on disk (using stdio.h),
714      or you can specify custom file read/write callbacks.
715 
716      - Archive reading: Just call this function to read a single file from a
717    disk archive:
718 
719       void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const
720    char *pArchive_name,
721         size_t *pSize, mz_uint zip_flags);
722 
723      For more complex cases, use the "mz_zip_reader" functions. Upon opening an
724    archive, the entire central
725      directory is located and read as-is into memory, and subsequent file access
726    only occurs when reading individual files.
727 
728      - Archives file scanning: The simple way is to use this function to scan a
729    loaded archive for a specific file:
730 
731      int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
732    const char *pComment, mz_uint flags);
733 
734      The locate operation can optionally check file comments too, which (as one
735    example) can be used to identify
736      multiple versions of the same file in an archive. This function uses a
737    simple linear search through the central
738      directory, so it's not very fast.
739 
740      Alternately, you can iterate through all the files in an archive (using
741    mz_zip_reader_get_num_files()) and
742      retrieve detailed info on each file by calling mz_zip_reader_file_stat().
743 
744      - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer
745    immediately writes compressed file data
746      to disk and builds an exact image of the central directory in memory. The
747    central directory image is written
748      all at once at the end of the archive file when the archive is finalized.
749 
750      The archive writer can optionally align each file's local header and file
751    data to any power of 2 alignment,
752      which can be useful when the archive will be read from optical media. Also,
753    the writer supports placing
754      arbitrary data blobs at the very beginning of ZIP archives. Archives
755    written using either feature are still
756      readable by any ZIP tool.
757 
758      - Archive appending: The simple way to add a single file to an archive is
759    to call this function:
760 
761       mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename,
762    const char *pArchive_name,
763         const void *pBuf, size_t buf_size, const void *pComment, mz_uint16
764    comment_size, mz_uint level_and_flags);
765 
766      The archive will be created if it doesn't already exist, otherwise it'll be
767    appended to.
768      Note the appending is done in-place and is not an atomic operation, so if
769    something goes wrong
770      during the operation it's possible the archive could be left without a
771    central directory (although the local
772      file headers and file data will be fine, so the archive will be
773    recoverable).
774 
775      For more complex archive modification scenarios:
776      1. The safest way is to use a mz_zip_reader to read the existing archive,
777    cloning only those bits you want to
778      preserve into a new archive using using the
779    mz_zip_writer_add_from_zip_reader() function (which compiles the
780      compressed file data as-is). When you're done, delete the old archive and
781    rename the newly written archive, and
782      you're done. This is safe but requires a bunch of temporary disk space or
783    heap memory.
784 
785      2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using
786    mz_zip_writer_init_from_reader(),
787      append new files as needed, then finalize the archive which will write an
788    updated central directory to the
789      original archive. (This is basically what
790    mz_zip_add_mem_to_archive_file_in_place() does.) There's a
791      possibility that the archive's central directory could be lost with this
792    method if anything goes wrong, though.
793 
794      - ZIP archive support limitations:
795      No zip64 or spanning support. Extraction functions can only handle
796    unencrypted, stored or deflated files.
797      Requires streams capable of seeking.
798 
799    * This is a header file library, like stb_image.c. To get only a header file,
800    either cut and paste the
801      below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then
802    include miniz.c from it.
803 
804    * Important: For best perf. be sure to customize the below macros for your
805    target platform:
806      #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
807      #define MINIZ_LITTLE_ENDIAN 1
808      #define MINIZ_HAS_64BIT_REGISTERS 1
809 
810    * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before
811    including miniz.c to ensure miniz
812      uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be
813    able to process large files
814      (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes).
815 */
816 
817 #ifndef MINIZ_HEADER_INCLUDED
818 #define MINIZ_HEADER_INCLUDED
819 
820 //#include <stdlib.h>
821 
822 // Defines to completely disable specific portions of miniz.c:
823 // If all macros here are defined the only functionality remaining will be
824 // CRC-32, adler-32, tinfl, and tdefl.
825 
826 // Define MINIZ_NO_STDIO to disable all usage and any functions which rely on
827 // stdio for file I/O.
828 //#define MINIZ_NO_STDIO
829 
830 // If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able
831 // to get the current time, or
832 // get/set file times, and the C run-time funcs that get/set times won't be
833 // called.
834 // The current downside is the times written to your archives will be from 1979.
835 #define MINIZ_NO_TIME
836 
837 // Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's.
838 #define MINIZ_NO_ARCHIVE_APIS
839 
840 // Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive
841 // API's.
842 //#define MINIZ_NO_ARCHIVE_WRITING_APIS
843 
844 // Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression
845 // API's.
846 //#define MINIZ_NO_ZLIB_APIS
847 
848 // Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent
849 // conflicts against stock zlib.
850 //#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
851 
852 // Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
853 // Note if MINIZ_NO_MALLOC is defined then the user must always provide custom
854 // user alloc/free/realloc
855 // callbacks to the zlib and archive API's, and a few stand-alone helper API's
856 // which don't provide custom user
857 // functions (such as tdefl_compress_mem_to_heap() and
858 // tinfl_decompress_mem_to_heap()) won't work.
859 //#define MINIZ_NO_MALLOC
860 
861 #if defined(__TINYC__) && (defined(__linux) || defined(__linux__))
862 // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc
863 // on Linux
864 #define MINIZ_NO_TIME
865 #endif
866 
867 #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
868 //#include <time.h>
869 #endif
870 
871 #if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \
872     defined(__i386) || defined(__i486__) || defined(__i486) ||  \
873     defined(i386) || defined(__ia64__) || defined(__x86_64__)
874 // MINIZ_X86_OR_X64_CPU is only used to help set the below macros.
875 #define MINIZ_X86_OR_X64_CPU 1
876 #endif
877 
878 #if defined(__sparcv9)
879 // Big endian
880 #else
881 #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
882 // Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
883 #define MINIZ_LITTLE_ENDIAN 1
884 #endif
885 #endif
886 
887 #if MINIZ_X86_OR_X64_CPU
888 // Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient
889 // integer loads and stores from unaligned addresses.
890 //#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
891 #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES \
892   0  // disable to suppress compiler warnings
893 #endif
894 
895 #if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || \
896     defined(_LP64) || defined(__LP64__) || defined(__ia64__) ||   \
897     defined(__x86_64__)
898 // Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are
899 // reasonably fast (and don't involve compiler generated calls to helper
900 // functions).
901 #define MINIZ_HAS_64BIT_REGISTERS 1
902 #endif
903 
904 #ifdef __cplusplus
905 extern "C" {
906 #endif
907 
908 // ------------------- zlib-style API Definitions.
909 
910 // For more compatibility with zlib, miniz.c uses unsigned long for some
911 // parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits!
912 typedef unsigned long mz_ulong;
913 
914 // mz_free() internally uses the MZ_FREE() macro (which by default calls free()
915 // unless you've modified the MZ_MALLOC macro) to release a block allocated from
916 // the heap.
917 void mz_free(void *p);
918 
919 #define MZ_ADLER32_INIT (1)
920 // mz_adler32() returns the initial adler-32 value to use when called with
921 // ptr==NULL.
922 mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
923 
924 #define MZ_CRC32_INIT (0)
925 // mz_crc32() returns the initial CRC-32 value to use when called with
926 // ptr==NULL.
927 mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
928 
929 // Compression strategies.
930 enum {
931   MZ_DEFAULT_STRATEGY = 0,
932   MZ_FILTERED = 1,
933   MZ_HUFFMAN_ONLY = 2,
934   MZ_RLE = 3,
935   MZ_FIXED = 4
936 };
937 
938 // Method
939 #define MZ_DEFLATED 8
940 
941 #ifndef MINIZ_NO_ZLIB_APIS
942 
943 // Heap allocation callbacks.
944 // Note that mz_alloc_func parameter types purpsosely differ from zlib's:
945 // items/size is size_t, not unsigned long.
946 typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
947 typedef void (*mz_free_func)(void *opaque, void *address);
948 typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items,
949                                  size_t size);
950 
951 #define MZ_VERSION "9.1.15"
952 #define MZ_VERNUM 0x91F0
953 #define MZ_VER_MAJOR 9
954 #define MZ_VER_MINOR 1
955 #define MZ_VER_REVISION 15
956 #define MZ_VER_SUBREVISION 0
957 
958 // Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The
959 // other values are for advanced use (refer to the zlib docs).
960 enum {
961   MZ_NO_FLUSH = 0,
962   MZ_PARTIAL_FLUSH = 1,
963   MZ_SYNC_FLUSH = 2,
964   MZ_FULL_FLUSH = 3,
965   MZ_FINISH = 4,
966   MZ_BLOCK = 5
967 };
968 
969 // Return status codes. MZ_PARAM_ERROR is non-standard.
970 enum {
971   MZ_OK = 0,
972   MZ_STREAM_END = 1,
973   MZ_NEED_DICT = 2,
974   MZ_ERRNO = -1,
975   MZ_STREAM_ERROR = -2,
976   MZ_DATA_ERROR = -3,
977   MZ_MEM_ERROR = -4,
978   MZ_BUF_ERROR = -5,
979   MZ_VERSION_ERROR = -6,
980   MZ_PARAM_ERROR = -10000
981 };
982 
983 // Compression levels: 0-9 are the standard zlib-style levels, 10 is best
984 // possible compression (not zlib compatible, and may be very slow),
985 // MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
986 enum {
987   MZ_NO_COMPRESSION = 0,
988   MZ_BEST_SPEED = 1,
989   MZ_BEST_COMPRESSION = 9,
990   MZ_UBER_COMPRESSION = 10,
991   MZ_DEFAULT_LEVEL = 6,
992   MZ_DEFAULT_COMPRESSION = -1
993 };
994 
995 // Window bits
996 #define MZ_DEFAULT_WINDOW_BITS 15
997 
998 struct mz_internal_state;
999 
1000 // Compression/decompression stream struct.
1001 typedef struct mz_stream_s {
1002   const unsigned char *next_in;  // pointer to next byte to read
1003   unsigned int avail_in;         // number of bytes available at next_in
1004   mz_ulong total_in;             // total number of bytes consumed so far
1005 
1006   unsigned char *next_out;  // pointer to next byte to write
1007   unsigned int avail_out;   // number of bytes that can be written to next_out
1008   mz_ulong total_out;       // total number of bytes produced so far
1009 
1010   char *msg;                        // error msg (unused)
1011   struct mz_internal_state *state;  // internal state, allocated by zalloc/zfree
1012 
1013   mz_alloc_func
1014       zalloc;          // optional heap allocation function (defaults to malloc)
1015   mz_free_func zfree;  // optional heap free function (defaults to free)
1016   void *opaque;        // heap alloc function user pointer
1017 
1018   int data_type;      // data_type (unused)
1019   mz_ulong adler;     // adler32 of the source or uncompressed data
1020   mz_ulong reserved;  // not used
1021 } mz_stream;
1022 
1023 typedef mz_stream *mz_streamp;
1024 
1025 // Returns the version string of miniz.c.
1026 const char *mz_version(void);
1027 
1028 // mz_deflateInit() initializes a compressor with default options:
1029 // Parameters:
1030 //  pStream must point to an initialized mz_stream struct.
1031 //  level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION].
1032 //  level 1 enables a specially optimized compression function that's been
1033 //  optimized purely for performance, not ratio.
1034 //  (This special func. is currently only enabled when
1035 //  MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.)
1036 // Return values:
1037 //  MZ_OK on success.
1038 //  MZ_STREAM_ERROR if the stream is bogus.
1039 //  MZ_PARAM_ERROR if the input parameters are bogus.
1040 //  MZ_MEM_ERROR on out of memory.
1041 int mz_deflateInit(mz_streamp pStream, int level);
1042 
1043 // mz_deflateInit2() is like mz_deflate(), except with more control:
1044 // Additional parameters:
1045 //   method must be MZ_DEFLATED
1046 //   window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with
1047 //   zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no
1048 //   header or footer)
1049 //   mem_level must be between [1, 9] (it's checked but ignored by miniz.c)
1050 int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits,
1051                     int mem_level, int strategy);
1052 
1053 // Quickly resets a compressor without having to reallocate anything. Same as
1054 // calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2().
1055 int mz_deflateReset(mz_streamp pStream);
1056 
1057 // mz_deflate() compresses the input to output, consuming as much of the input
1058 // and producing as much output as possible.
1059 // Parameters:
1060 //   pStream is the stream to read from and write to. You must initialize/update
1061 //   the next_in, avail_in, next_out, and avail_out members.
1062 //   flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or
1063 //   MZ_FINISH.
1064 // Return values:
1065 //   MZ_OK on success (when flushing, or if more input is needed but not
1066 //   available, and/or there's more output to be written but the output buffer
1067 //   is full).
1068 //   MZ_STREAM_END if all input has been consumed and all output bytes have been
1069 //   written. Don't call mz_deflate() on the stream anymore.
1070 //   MZ_STREAM_ERROR if the stream is bogus.
1071 //   MZ_PARAM_ERROR if one of the parameters is invalid.
1072 //   MZ_BUF_ERROR if no forward progress is possible because the input and/or
1073 //   output buffers are empty. (Fill up the input buffer or free up some output
1074 //   space and try again.)
1075 int mz_deflate(mz_streamp pStream, int flush);
1076 
1077 // mz_deflateEnd() deinitializes a compressor:
1078 // Return values:
1079 //  MZ_OK on success.
1080 //  MZ_STREAM_ERROR if the stream is bogus.
1081 int mz_deflateEnd(mz_streamp pStream);
1082 
1083 // mz_deflateBound() returns a (very) conservative upper bound on the amount of
1084 // data that could be generated by deflate(), assuming flush is set to only
1085 // MZ_NO_FLUSH or MZ_FINISH.
1086 mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
1087 
1088 // Single-call compression functions mz_compress() and mz_compress2():
1089 // Returns MZ_OK on success, or one of the error codes from mz_deflate() on
1090 // failure.
1091 int mz_compress(unsigned char *pDest, mz_ulong *pDest_len,
1092                 const unsigned char *pSource, mz_ulong source_len);
1093 int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len,
1094                  const unsigned char *pSource, mz_ulong source_len, int level);
1095 
1096 // mz_compressBound() returns a (very) conservative upper bound on the amount of
1097 // data that could be generated by calling mz_compress().
1098 mz_ulong mz_compressBound(mz_ulong source_len);
1099 
1100 // Initializes a decompressor.
1101 int mz_inflateInit(mz_streamp pStream);
1102 
1103 // mz_inflateInit2() is like mz_inflateInit() with an additional option that
1104 // controls the window size and whether or not the stream has been wrapped with
1105 // a zlib header/footer:
1106 // window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or
1107 // -MZ_DEFAULT_WINDOW_BITS (raw deflate).
1108 int mz_inflateInit2(mz_streamp pStream, int window_bits);
1109 
1110 // Decompresses the input stream to the output, consuming only as much of the
1111 // input as needed, and writing as much to the output as possible.
1112 // Parameters:
1113 //   pStream is the stream to read from and write to. You must initialize/update
1114 //   the next_in, avail_in, next_out, and avail_out members.
1115 //   flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH.
1116 //   On the first call, if flush is MZ_FINISH it's assumed the input and output
1117 //   buffers are both sized large enough to decompress the entire stream in a
1118 //   single call (this is slightly faster).
1119 //   MZ_FINISH implies that there are no more source bytes available beside
1120 //   what's already in the input buffer, and that the output buffer is large
1121 //   enough to hold the rest of the decompressed data.
1122 // Return values:
1123 //   MZ_OK on success. Either more input is needed but not available, and/or
1124 //   there's more output to be written but the output buffer is full.
1125 //   MZ_STREAM_END if all needed input has been consumed and all output bytes
1126 //   have been written. For zlib streams, the adler-32 of the decompressed data
1127 //   has also been verified.
1128 //   MZ_STREAM_ERROR if the stream is bogus.
1129 //   MZ_DATA_ERROR if the deflate stream is invalid.
1130 //   MZ_PARAM_ERROR if one of the parameters is invalid.
1131 //   MZ_BUF_ERROR if no forward progress is possible because the input buffer is
1132 //   empty but the inflater needs more input to continue, or if the output
1133 //   buffer is not large enough. Call mz_inflate() again
1134 //   with more input data, or with more room in the output buffer (except when
1135 //   using single call decompression, described above).
1136 int mz_inflate(mz_streamp pStream, int flush);
1137 
1138 // Deinitializes a decompressor.
1139 int mz_inflateEnd(mz_streamp pStream);
1140 
1141 // Single-call decompression.
1142 // Returns MZ_OK on success, or one of the error codes from mz_inflate() on
1143 // failure.
1144 int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len,
1145                   const unsigned char *pSource, mz_ulong source_len);
1146 
1147 // Returns a string description of the specified error code, or NULL if the
1148 // error code is invalid.
1149 const char *mz_error(int err);
1150 
1151 // Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used
1152 // as a drop-in replacement for the subset of zlib that miniz.c supports.
1153 // Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you
1154 // use zlib in the same project.
1155 #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
1156 typedef unsigned char Byte;
1157 typedef unsigned int uInt;
1158 typedef mz_ulong uLong;
1159 typedef Byte Bytef;
1160 typedef uInt uIntf;
1161 typedef char charf;
1162 typedef int intf;
1163 typedef void *voidpf;
1164 typedef uLong uLongf;
1165 typedef void *voidp;
1166 typedef void *const voidpc;
1167 #define Z_NULL 0
1168 #define Z_NO_FLUSH MZ_NO_FLUSH
1169 #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH
1170 #define Z_SYNC_FLUSH MZ_SYNC_FLUSH
1171 #define Z_FULL_FLUSH MZ_FULL_FLUSH
1172 #define Z_FINISH MZ_FINISH
1173 #define Z_BLOCK MZ_BLOCK
1174 #define Z_OK MZ_OK
1175 #define Z_STREAM_END MZ_STREAM_END
1176 #define Z_NEED_DICT MZ_NEED_DICT
1177 #define Z_ERRNO MZ_ERRNO
1178 #define Z_STREAM_ERROR MZ_STREAM_ERROR
1179 #define Z_DATA_ERROR MZ_DATA_ERROR
1180 #define Z_MEM_ERROR MZ_MEM_ERROR
1181 #define Z_BUF_ERROR MZ_BUF_ERROR
1182 #define Z_VERSION_ERROR MZ_VERSION_ERROR
1183 #define Z_PARAM_ERROR MZ_PARAM_ERROR
1184 #define Z_NO_COMPRESSION MZ_NO_COMPRESSION
1185 #define Z_BEST_SPEED MZ_BEST_SPEED
1186 #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION
1187 #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
1188 #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY
1189 #define Z_FILTERED MZ_FILTERED
1190 #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY
1191 #define Z_RLE MZ_RLE
1192 #define Z_FIXED MZ_FIXED
1193 #define Z_DEFLATED MZ_DEFLATED
1194 #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
1195 #define alloc_func mz_alloc_func
1196 #define free_func mz_free_func
1197 #define internal_state mz_internal_state
1198 #define z_stream mz_stream
1199 #define deflateInit mz_deflateInit
1200 #define deflateInit2 mz_deflateInit2
1201 #define deflateReset mz_deflateReset
1202 #define deflate mz_deflate
1203 #define deflateEnd mz_deflateEnd
1204 #define deflateBound mz_deflateBound
1205 #define compress mz_compress
1206 #define compress2 mz_compress2
1207 #define compressBound mz_compressBound
1208 #define inflateInit mz_inflateInit
1209 #define inflateInit2 mz_inflateInit2
1210 #define inflate mz_inflate
1211 #define inflateEnd mz_inflateEnd
1212 #define uncompress mz_uncompress
1213 #define crc32 mz_crc32
1214 #define adler32 mz_adler32
1215 #define MAX_WBITS 15
1216 #define MAX_MEM_LEVEL 9
1217 #define zError mz_error
1218 #define ZLIB_VERSION MZ_VERSION
1219 #define ZLIB_VERNUM MZ_VERNUM
1220 #define ZLIB_VER_MAJOR MZ_VER_MAJOR
1221 #define ZLIB_VER_MINOR MZ_VER_MINOR
1222 #define ZLIB_VER_REVISION MZ_VER_REVISION
1223 #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION
1224 #define zlibVersion mz_version
1225 #define zlib_version mz_version()
1226 #endif  // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
1227 
1228 #endif  // MINIZ_NO_ZLIB_APIS
1229 
1230 // ------------------- Types and macros
1231 
1232 typedef unsigned char mz_uint8;
1233 typedef signed short mz_int16;
1234 typedef unsigned short mz_uint16;
1235 typedef unsigned int mz_uint32;
1236 typedef unsigned int mz_uint;
1237 typedef long long mz_int64;
1238 typedef unsigned long long mz_uint64;
1239 typedef int mz_bool;
1240 
1241 #define MZ_FALSE (0)
1242 #define MZ_TRUE (1)
1243 
1244 // An attempt to work around MSVC's spammy "warning C4127: conditional
1245 // expression is constant" message.
1246 #ifdef _MSC_VER
1247 #define MZ_MACRO_END while (0, 0)
1248 #else
1249 #define MZ_MACRO_END while (0)
1250 #endif
1251 
1252 // ------------------- ZIP archive reading/writing
1253 
1254 #ifndef MINIZ_NO_ARCHIVE_APIS
1255 
1256 enum {
1257   MZ_ZIP_MAX_IO_BUF_SIZE = 64 * 1024,
1258   MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260,
1259   MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256
1260 };
1261 
1262 typedef struct {
1263   mz_uint32 m_file_index;
1264   mz_uint32 m_central_dir_ofs;
1265   mz_uint16 m_version_made_by;
1266   mz_uint16 m_version_needed;
1267   mz_uint16 m_bit_flag;
1268   mz_uint16 m_method;
1269 #ifndef MINIZ_NO_TIME
1270   time_t m_time;
1271 #endif
1272   mz_uint32 m_crc32;
1273   mz_uint64 m_comp_size;
1274   mz_uint64 m_uncomp_size;
1275   mz_uint16 m_internal_attr;
1276   mz_uint32 m_external_attr;
1277   mz_uint64 m_local_header_ofs;
1278   mz_uint32 m_comment_size;
1279   char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
1280   char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
1281 } mz_zip_archive_file_stat;
1282 
1283 typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs,
1284                                     void *pBuf, size_t n);
1285 typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs,
1286                                      const void *pBuf, size_t n);
1287 
1288 struct mz_zip_internal_state_tag;
1289 typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
1290 
1291 typedef enum {
1292   MZ_ZIP_MODE_INVALID = 0,
1293   MZ_ZIP_MODE_READING = 1,
1294   MZ_ZIP_MODE_WRITING = 2,
1295   MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
1296 } mz_zip_mode;
1297 
1298 typedef struct mz_zip_archive_tag {
1299   mz_uint64 m_archive_size;
1300   mz_uint64 m_central_directory_file_ofs;
1301   mz_uint m_total_files;
1302   mz_zip_mode m_zip_mode;
1303 
1304   mz_uint m_file_offset_alignment;
1305 
1306   mz_alloc_func m_pAlloc;
1307   mz_free_func m_pFree;
1308   mz_realloc_func m_pRealloc;
1309   void *m_pAlloc_opaque;
1310 
1311   mz_file_read_func m_pRead;
1312   mz_file_write_func m_pWrite;
1313   void *m_pIO_opaque;
1314 
1315   mz_zip_internal_state *m_pState;
1316 
1317 } mz_zip_archive;
1318 
1319 typedef enum {
1320   MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100,
1321   MZ_ZIP_FLAG_IGNORE_PATH = 0x0200,
1322   MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400,
1323   MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
1324 } mz_zip_flags;
1325 
1326 // ZIP archive reading
1327 
1328 // Inits a ZIP archive reader.
1329 // These functions read and validate the archive's central directory.
1330 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
1331                            mz_uint32 flags);
1332 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem,
1333                                size_t size, mz_uint32 flags);
1334 
1335 #ifndef MINIZ_NO_STDIO
1336 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename,
1337                                 mz_uint32 flags);
1338 #endif
1339 
1340 // Returns the total number of files in the archive.
1341 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
1342 
1343 // Returns detailed information about an archive file entry.
1344 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
1345                                 mz_zip_archive_file_stat *pStat);
1346 
1347 // Determines if an archive file entry is a directory entry.
1348 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
1349                                           mz_uint file_index);
1350 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip,
1351                                         mz_uint file_index);
1352 
1353 // Retrieves the filename of an archive file entry.
1354 // Returns the number of bytes written to pFilename, or if filename_buf_size is
1355 // 0 this function returns the number of bytes needed to fully store the
1356 // filename.
1357 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index,
1358                                    char *pFilename, mz_uint filename_buf_size);
1359 
1360 // Attempts to locates a file in the archive's central directory.
1361 // Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
1362 // Returns -1 if the file cannot be found.
1363 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
1364                               const char *pComment, mz_uint flags);
1365 
1366 // Extracts a archive file to a memory buffer using no memory allocation.
1367 mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
1368                                               mz_uint file_index, void *pBuf,
1369                                               size_t buf_size, mz_uint flags,
1370                                               void *pUser_read_buf,
1371                                               size_t user_read_buf_size);
1372 mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(
1373     mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size,
1374     mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
1375 
1376 // Extracts a archive file to a memory buffer.
1377 mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index,
1378                                      void *pBuf, size_t buf_size,
1379                                      mz_uint flags);
1380 mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip,
1381                                           const char *pFilename, void *pBuf,
1382                                           size_t buf_size, mz_uint flags);
1383 
1384 // Extracts a archive file to a dynamically allocated heap buffer.
1385 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
1386                                     size_t *pSize, mz_uint flags);
1387 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip,
1388                                          const char *pFilename, size_t *pSize,
1389                                          mz_uint flags);
1390 
1391 // Extracts a archive file using a callback function to output the file's data.
1392 mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
1393                                           mz_uint file_index,
1394                                           mz_file_write_func pCallback,
1395                                           void *pOpaque, mz_uint flags);
1396 mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip,
1397                                                const char *pFilename,
1398                                                mz_file_write_func pCallback,
1399                                                void *pOpaque, mz_uint flags);
1400 
1401 #ifndef MINIZ_NO_STDIO
1402 // Extracts a archive file to a disk file and sets its last accessed and
1403 // modified times.
1404 // This function only extracts files, not archive directory records.
1405 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
1406                                       const char *pDst_filename, mz_uint flags);
1407 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip,
1408                                            const char *pArchive_filename,
1409                                            const char *pDst_filename,
1410                                            mz_uint flags);
1411 #endif
1412 
1413 // Ends archive reading, freeing all allocations, and closing the input archive
1414 // file if mz_zip_reader_init_file() was used.
1415 mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
1416 
1417 // ZIP archive writing
1418 
1419 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
1420 
1421 // Inits a ZIP archive writer.
1422 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
1423 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip,
1424                                 size_t size_to_reserve_at_beginning,
1425                                 size_t initial_allocation_size);
1426 
1427 #ifndef MINIZ_NO_STDIO
1428 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename,
1429                                 mz_uint64 size_to_reserve_at_beginning);
1430 #endif
1431 
1432 // Converts a ZIP archive reader object into a writer object, to allow efficient
1433 // in-place file appends to occur on an existing archive.
1434 // For archives opened using mz_zip_reader_init_file, pFilename must be the
1435 // archive's filename so it can be reopened for writing. If the file can't be
1436 // reopened, mz_zip_reader_end() will be called.
1437 // For archives opened using mz_zip_reader_init_mem, the memory block must be
1438 // growable using the realloc callback (which defaults to realloc unless you've
1439 // overridden it).
1440 // Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's
1441 // user provided m_pWrite function cannot be NULL.
1442 // Note: In-place archive modification is not recommended unless you know what
1443 // you're doing, because if execution stops or something goes wrong before
1444 // the archive is finalized the file's central directory will be hosed.
1445 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip,
1446                                        const char *pFilename);
1447 
1448 // Adds the contents of a memory buffer to an archive. These functions record
1449 // the current local time into the archive.
1450 // To add a directory entry, call this method with an archive name ending in a
1451 // forwardslash with empty buffer.
1452 // level_and_flags - compression level (0-10, see MZ_BEST_SPEED,
1453 // MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or
1454 // just set to MZ_DEFAULT_COMPRESSION.
1455 mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name,
1456                               const void *pBuf, size_t buf_size,
1457                               mz_uint level_and_flags);
1458 mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
1459                                  const char *pArchive_name, const void *pBuf,
1460                                  size_t buf_size, const void *pComment,
1461                                  mz_uint16 comment_size,
1462                                  mz_uint level_and_flags, mz_uint64 uncomp_size,
1463                                  mz_uint32 uncomp_crc32);
1464 
1465 #ifndef MINIZ_NO_STDIO
1466 // Adds the contents of a disk file to an archive. This function also records
1467 // the disk file's modified time into the archive.
1468 // level_and_flags - compression level (0-10, see MZ_BEST_SPEED,
1469 // MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or
1470 // just set to MZ_DEFAULT_COMPRESSION.
1471 mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
1472                                const char *pSrc_filename, const void *pComment,
1473                                mz_uint16 comment_size, mz_uint level_and_flags);
1474 #endif
1475 
1476 // Adds a file to an archive by fully cloning the data from another archive.
1477 // This function fully clones the source file's compressed data (no
1478 // recompression), along with its full filename, extra data, and comment fields.
1479 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip,
1480                                           mz_zip_archive *pSource_zip,
1481                                           mz_uint file_index);
1482 
1483 // Finalizes the archive by writing the central directory records followed by
1484 // the end of central directory record.
1485 // After an archive is finalized, the only valid call on the mz_zip_archive
1486 // struct is mz_zip_writer_end().
1487 // An archive must be manually finalized by calling this function for it to be
1488 // valid.
1489 mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
1490 mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf,
1491                                             size_t *pSize);
1492 
1493 // Ends archive writing, freeing all allocations, and closing the output file if
1494 // mz_zip_writer_init_file() was used.
1495 // Note for the archive to be valid, it must have been finalized before ending.
1496 mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
1497 
1498 // Misc. high-level helper functions:
1499 
1500 // mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically)
1501 // appends a memory blob to a ZIP archive.
1502 // level_and_flags - compression level (0-10, see MZ_BEST_SPEED,
1503 // MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or
1504 // just set to MZ_DEFAULT_COMPRESSION.
1505 mz_bool mz_zip_add_mem_to_archive_file_in_place(
1506     const char *pZip_filename, const char *pArchive_name, const void *pBuf,
1507     size_t buf_size, const void *pComment, mz_uint16 comment_size,
1508     mz_uint level_and_flags);
1509 
1510 // Reads a single file from an archive into a heap block.
1511 // Returns NULL on failure.
1512 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
1513                                           const char *pArchive_name,
1514                                           size_t *pSize, mz_uint zip_flags);
1515 
1516 #endif  // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
1517 
1518 #endif  // #ifndef MINIZ_NO_ARCHIVE_APIS
1519 
1520 // ------------------- Low-level Decompression API Definitions
1521 
1522 // Decompression flags used by tinfl_decompress().
1523 // TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and
1524 // ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the
1525 // input is a raw deflate stream.
1526 // TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available
1527 // beyond the end of the supplied input buffer. If clear, the input buffer
1528 // contains all remaining input.
1529 // TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large
1530 // enough to hold the entire decompressed stream. If clear, the output buffer is
1531 // at least the size of the dictionary (typically 32KB).
1532 // TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the
1533 // decompressed bytes.
1534 enum {
1535   TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
1536   TINFL_FLAG_HAS_MORE_INPUT = 2,
1537   TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
1538   TINFL_FLAG_COMPUTE_ADLER32 = 8
1539 };
1540 
1541 // High level decompression functions:
1542 // tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block
1543 // allocated via malloc().
1544 // On entry:
1545 //  pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data
1546 //  to decompress.
1547 // On return:
1548 //  Function returns a pointer to the decompressed data, or NULL on failure.
1549 //  *pOut_len will be set to the decompressed data's size, which could be larger
1550 //  than src_buf_len on uncompressible data.
1551 //  The caller must call mz_free() on the returned block when it's no longer
1552 //  needed.
1553 void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
1554                                    size_t *pOut_len, int flags);
1555 
1556 // tinfl_decompress_mem_to_mem() decompresses a block in memory to another block
1557 // in memory.
1558 // Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes
1559 // written on success.
1560 #define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
1561 size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
1562                                    const void *pSrc_buf, size_t src_buf_len,
1563                                    int flags);
1564 
1565 // tinfl_decompress_mem_to_callback() decompresses a block in memory to an
1566 // internal 32KB buffer, and a user provided callback function will be called to
1567 // flush the buffer.
1568 // Returns 1 on success or 0 on failure.
1569 typedef int (*tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);
1570 int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
1571                                      tinfl_put_buf_func_ptr pPut_buf_func,
1572                                      void *pPut_buf_user, int flags);
1573 
1574 struct tinfl_decompressor_tag;
1575 typedef struct tinfl_decompressor_tag tinfl_decompressor;
1576 
1577 // Max size of LZ dictionary.
1578 #define TINFL_LZ_DICT_SIZE 32768
1579 
1580 // Return status.
1581 typedef enum {
1582   TINFL_STATUS_BAD_PARAM = -3,
1583   TINFL_STATUS_ADLER32_MISMATCH = -2,
1584   TINFL_STATUS_FAILED = -1,
1585   TINFL_STATUS_DONE = 0,
1586   TINFL_STATUS_NEEDS_MORE_INPUT = 1,
1587   TINFL_STATUS_HAS_MORE_OUTPUT = 2
1588 } tinfl_status;
1589 
1590 // Initializes the decompressor to its initial state.
1591 #define tinfl_init(r) \
1592   do {                \
1593     (r)->m_state = 0; \
1594   }                   \
1595   MZ_MACRO_END
1596 #define tinfl_get_adler32(r) (r)->m_check_adler32
1597 
1598 // Main low-level decompressor coroutine function. This is the only function
1599 // actually needed for decompression. All the other functions are just
1600 // high-level helpers for improved usability.
1601 // This is a universal API, i.e. it can be used as a building block to build any
1602 // desired higher level decompression API. In the limit case, it can be called
1603 // once per every byte input or output.
1604 tinfl_status tinfl_decompress(tinfl_decompressor *r,
1605                               const mz_uint8 *pIn_buf_next,
1606                               size_t *pIn_buf_size, mz_uint8 *pOut_buf_start,
1607                               mz_uint8 *pOut_buf_next, size_t *pOut_buf_size,
1608                               const mz_uint32 decomp_flags);
1609 
1610 // Internal/private bits follow.
1611 enum {
1612   TINFL_MAX_HUFF_TABLES = 3,
1613   TINFL_MAX_HUFF_SYMBOLS_0 = 288,
1614   TINFL_MAX_HUFF_SYMBOLS_1 = 32,
1615   TINFL_MAX_HUFF_SYMBOLS_2 = 19,
1616   TINFL_FAST_LOOKUP_BITS = 10,
1617   TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
1618 };
1619 
1620 typedef struct {
1621   mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
1622   mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE],
1623       m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
1624 } tinfl_huff_table;
1625 
1626 #if MINIZ_HAS_64BIT_REGISTERS
1627 #define TINFL_USE_64BIT_BITBUF 1
1628 #endif
1629 
1630 #if TINFL_USE_64BIT_BITBUF
1631 typedef mz_uint64 tinfl_bit_buf_t;
1632 #define TINFL_BITBUF_SIZE (64)
1633 #else
1634 typedef mz_uint32 tinfl_bit_buf_t;
1635 #define TINFL_BITBUF_SIZE (32)
1636 #endif
1637 
1638 struct tinfl_decompressor_tag {
1639   mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type,
1640       m_check_adler32, m_dist, m_counter, m_num_extra,
1641       m_table_sizes[TINFL_MAX_HUFF_TABLES];
1642   tinfl_bit_buf_t m_bit_buf;
1643   size_t m_dist_from_out_buf_start;
1644   tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
1645   mz_uint8 m_raw_header[4],
1646       m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
1647 };
1648 
1649 // ------------------- Low-level Compression API Definitions
1650 
1651 // Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly
1652 // slower, and raw/dynamic blocks will be output more frequently).
1653 #define TDEFL_LESS_MEMORY 0
1654 
1655 // tdefl_init() compression flags logically OR'd together (low 12 bits contain
1656 // the max. number of probes per dictionary search):
1657 // TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes
1658 // per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap
1659 // compression), 4095=Huffman+LZ (slowest/best compression).
1660 enum {
1661   TDEFL_HUFFMAN_ONLY = 0,
1662   TDEFL_DEFAULT_MAX_PROBES = 128,
1663   TDEFL_MAX_PROBES_MASK = 0xFFF
1664 };
1665 
1666 // TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before
1667 // the deflate data, and the Adler-32 of the source data at the end. Otherwise,
1668 // you'll get raw deflate data.
1669 // TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even
1670 // when not writing zlib headers).
1671 // TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more
1672 // efficient lazy parsing.
1673 // TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's
1674 // initialization time to the minimum, but the output may vary from run to run
1675 // given the same input (depending on the contents of memory).
1676 // TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1)
1677 // TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
1678 // TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
1679 // TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
1680 // The low 12 bits are reserved to control the max # of hash probes per
1681 // dictionary lookup (see TDEFL_MAX_PROBES_MASK).
1682 enum {
1683   TDEFL_WRITE_ZLIB_HEADER = 0x01000,
1684   TDEFL_COMPUTE_ADLER32 = 0x02000,
1685   TDEFL_GREEDY_PARSING_FLAG = 0x04000,
1686   TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
1687   TDEFL_RLE_MATCHES = 0x10000,
1688   TDEFL_FILTER_MATCHES = 0x20000,
1689   TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000,
1690   TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000
1691 };
1692 
1693 // High level compression functions:
1694 // tdefl_compress_mem_to_heap() compresses a block in memory to a heap block
1695 // allocated via malloc().
1696 // On entry:
1697 //  pSrc_buf, src_buf_len: Pointer and size of source block to compress.
1698 //  flags: The max match finder probes (default is 128) logically OR'd against
1699 //  the above flags. Higher probes are slower but improve compression.
1700 // On return:
1701 //  Function returns a pointer to the compressed data, or NULL on failure.
1702 //  *pOut_len will be set to the compressed data's size, which could be larger
1703 //  than src_buf_len on uncompressible data.
1704 //  The caller must free() the returned block when it's no longer needed.
1705 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
1706                                  size_t *pOut_len, int flags);
1707 
1708 // tdefl_compress_mem_to_mem() compresses a block in memory to another block in
1709 // memory.
1710 // Returns 0 on failure.
1711 size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
1712                                  const void *pSrc_buf, size_t src_buf_len,
1713                                  int flags);
1714 
1715 // Compresses an image to a compressed PNG file in memory.
1716 // On entry:
1717 //  pImage, w, h, and num_chans describe the image to compress. num_chans may be
1718 //  1, 2, 3, or 4.
1719 //  The image pitch in bytes per scanline will be w*num_chans. The leftmost
1720 //  pixel on the top scanline is stored first in memory.
1721 //  level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED,
1722 //  MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL
1723 //  If flip is true, the image will be flipped on the Y axis (useful for OpenGL
1724 //  apps).
1725 // On return:
1726 //  Function returns a pointer to the compressed data, or NULL on failure.
1727 //  *pLen_out will be set to the size of the PNG image file.
1728 //  The caller must mz_free() the returned heap block (which will typically be
1729 //  larger than *pLen_out) when it's no longer needed.
1730 void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w,
1731                                                  int h, int num_chans,
1732                                                  size_t *pLen_out,
1733                                                  mz_uint level, mz_bool flip);
1734 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
1735                                               int num_chans, size_t *pLen_out);
1736 
1737 // Output stream interface. The compressor uses this interface to write
1738 // compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
1739 typedef mz_bool (*tdefl_put_buf_func_ptr)(const void *pBuf, int len,
1740                                           void *pUser);
1741 
1742 // tdefl_compress_mem_to_output() compresses a block to an output stream. The
1743 // above helpers use this function internally.
1744 mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len,
1745                                      tdefl_put_buf_func_ptr pPut_buf_func,
1746                                      void *pPut_buf_user, int flags);
1747 
1748 enum {
1749   TDEFL_MAX_HUFF_TABLES = 3,
1750   TDEFL_MAX_HUFF_SYMBOLS_0 = 288,
1751   TDEFL_MAX_HUFF_SYMBOLS_1 = 32,
1752   TDEFL_MAX_HUFF_SYMBOLS_2 = 19,
1753   TDEFL_LZ_DICT_SIZE = 32768,
1754   TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1,
1755   TDEFL_MIN_MATCH_LEN = 3,
1756   TDEFL_MAX_MATCH_LEN = 258
1757 };
1758 
1759 // TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed
1760 // output block (using static/fixed Huffman codes).
1761 #if TDEFL_LESS_MEMORY
1762 enum {
1763   TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024,
1764   TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
1765   TDEFL_MAX_HUFF_SYMBOLS = 288,
1766   TDEFL_LZ_HASH_BITS = 12,
1767   TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
1768   TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,
1769   TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS
1770 };
1771 #else
1772 enum {
1773   TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024,
1774   TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
1775   TDEFL_MAX_HUFF_SYMBOLS = 288,
1776   TDEFL_LZ_HASH_BITS = 15,
1777   TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
1778   TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,
1779   TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS
1780 };
1781 #endif
1782 
1783 // The low-level tdefl functions below may be used directly if the above helper
1784 // functions aren't flexible enough. The low-level functions don't make any heap
1785 // allocations, unlike the above helper functions.
1786 typedef enum {
1787   TDEFL_STATUS_BAD_PARAM = -2,
1788   TDEFL_STATUS_PUT_BUF_FAILED = -1,
1789   TDEFL_STATUS_OKAY = 0,
1790   TDEFL_STATUS_DONE = 1
1791 } tdefl_status;
1792 
1793 // Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
1794 typedef enum {
1795   TDEFL_NO_FLUSH = 0,
1796   TDEFL_SYNC_FLUSH = 2,
1797   TDEFL_FULL_FLUSH = 3,
1798   TDEFL_FINISH = 4
1799 } tdefl_flush;
1800 
1801 // tdefl's compression state structure.
1802 typedef struct {
1803   tdefl_put_buf_func_ptr m_pPut_buf_func;
1804   void *m_pPut_buf_user;
1805   mz_uint m_flags, m_max_probes[2];
1806   int m_greedy_parsing;
1807   mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
1808   mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
1809   mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in,
1810       m_bit_buffer;
1811   mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit,
1812       m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index,
1813       m_wants_to_finish;
1814   tdefl_status m_prev_return_status;
1815   const void *m_pIn_buf;
1816   void *m_pOut_buf;
1817   size_t *m_pIn_buf_size, *m_pOut_buf_size;
1818   tdefl_flush m_flush;
1819   const mz_uint8 *m_pSrc;
1820   size_t m_src_buf_left, m_out_buf_ofs;
1821   mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
1822   mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
1823   mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
1824   mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
1825   mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
1826   mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
1827   mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
1828   mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
1829 } tdefl_compressor;
1830 
1831 // Initializes the compressor.
1832 // There is no corresponding deinit() function because the tdefl API's do not
1833 // dynamically allocate memory.
1834 // pBut_buf_func: If NULL, output data will be supplied to the specified
1835 // callback. In this case, the user should call the tdefl_compress_buffer() API
1836 // for compression.
1837 // If pBut_buf_func is NULL the user should always call the tdefl_compress()
1838 // API.
1839 // flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER,
1840 // etc.)
1841 tdefl_status tdefl_init(tdefl_compressor *d,
1842                         tdefl_put_buf_func_ptr pPut_buf_func,
1843                         void *pPut_buf_user, int flags);
1844 
1845 // Compresses a block of data, consuming as much of the specified input buffer
1846 // as possible, and writing as much compressed data to the specified output
1847 // buffer as possible.
1848 tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf,
1849                             size_t *pIn_buf_size, void *pOut_buf,
1850                             size_t *pOut_buf_size, tdefl_flush flush);
1851 
1852 // tdefl_compress_buffer() is only usable when the tdefl_init() is called with a
1853 // non-NULL tdefl_put_buf_func_ptr.
1854 // tdefl_compress_buffer() always consumes the entire input buffer.
1855 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf,
1856                                    size_t in_buf_size, tdefl_flush flush);
1857 
1858 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
1859 mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
1860 
1861 // Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't
1862 // defined, because it uses some of its macros.
1863 #ifndef MINIZ_NO_ZLIB_APIS
1864 // Create tdefl_compress() flags given zlib-style compression parameters.
1865 // level may range from [0,10] (where 10 is absolute max compression, but may be
1866 // much slower on some files)
1867 // window_bits may be -15 (raw deflate) or 15 (zlib)
1868 // strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY,
1869 // MZ_RLE, or MZ_FIXED
1870 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
1871                                                 int strategy);
1872 #endif  // #ifndef MINIZ_NO_ZLIB_APIS
1873 
1874 #ifdef __cplusplus
1875 }
1876 #endif
1877 
1878 #endif  // MINIZ_HEADER_INCLUDED
1879 
1880 // ------------------- End of Header: Implementation follows. (If you only want
1881 // the header, define MINIZ_HEADER_FILE_ONLY.)
1882 
1883 #ifndef MINIZ_HEADER_FILE_ONLY
1884 
1885 typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
1886 typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
1887 typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
1888 
1889 //#include <assert.h>
1890 //#include <string.h>
1891 
1892 #define MZ_ASSERT(x) assert(x)
1893 
1894 #ifdef MINIZ_NO_MALLOC
1895 #define MZ_MALLOC(x) NULL
1896 #define MZ_FREE(x) (void)x, ((void)0)
1897 #define MZ_REALLOC(p, x) NULL
1898 #else
1899 #define MZ_MALLOC(x) malloc(x)
1900 #define MZ_FREE(x) free(x)
1901 #define MZ_REALLOC(p, x) realloc(p, x)
1902 #endif
1903 
1904 #define MZ_MAX(a, b) (((a) > (b)) ? (a) : (b))
1905 #define MZ_MIN(a, b) (((a) < (b)) ? (a) : (b))
1906 #define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
1907 
1908 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1909 #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
1910 #define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
1911 #else
1912 #define MZ_READ_LE16(p)                      \
1913   ((mz_uint32)(((const mz_uint8 *)(p))[0]) | \
1914    ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
1915 #define MZ_READ_LE32(p)                               \
1916   ((mz_uint32)(((const mz_uint8 *)(p))[0]) |          \
1917    ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) |  \
1918    ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | \
1919    ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
1920 #endif
1921 
1922 #ifdef _MSC_VER
1923 #define MZ_FORCEINLINE __forceinline
1924 #elif defined(__GNUC__)
1925 #define MZ_FORCEINLINE inline __attribute__((__always_inline__))
1926 #else
1927 #define MZ_FORCEINLINE inline
1928 #endif
1929 
1930 #ifdef __cplusplus
1931 extern "C" {
1932 #endif
1933 
1934 // ------------------- zlib-style API's
1935 
mz_adler32(mz_ulong adler,const unsigned char * ptr,size_t buf_len)1936 mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) {
1937   mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
1938   size_t block_len = buf_len % 5552;
1939   if (!ptr) return MZ_ADLER32_INIT;
1940   while (buf_len) {
1941     for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
1942       s1 += ptr[0], s2 += s1;
1943       s1 += ptr[1], s2 += s1;
1944       s1 += ptr[2], s2 += s1;
1945       s1 += ptr[3], s2 += s1;
1946       s1 += ptr[4], s2 += s1;
1947       s1 += ptr[5], s2 += s1;
1948       s1 += ptr[6], s2 += s1;
1949       s1 += ptr[7], s2 += s1;
1950     }
1951     for (; i < block_len; ++i) s1 += *ptr++, s2 += s1;
1952     s1 %= 65521U, s2 %= 65521U;
1953     buf_len -= block_len;
1954     block_len = 5552;
1955   }
1956   return (s2 << 16) + s1;
1957 }
1958 
1959 // Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C
1960 // implementation that balances processor cache usage against speed":
1961 // http://www.geocities.com/malbrain/
mz_crc32(mz_ulong crc,const mz_uint8 * ptr,size_t buf_len)1962 mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) {
1963   static const mz_uint32 s_crc32[16] = {
1964       0,          0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4,
1965       0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1966       0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c};
1967   mz_uint32 crcu32 = (mz_uint32)crc;
1968   if (!ptr) return MZ_CRC32_INIT;
1969   crcu32 = ~crcu32;
1970   while (buf_len--) {
1971     mz_uint8 b = *ptr++;
1972     crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
1973     crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
1974   }
1975   return ~crcu32;
1976 }
1977 
mz_free(void * p)1978 void mz_free(void *p) { MZ_FREE(p); }
1979 
1980 #ifndef MINIZ_NO_ZLIB_APIS
1981 
def_alloc_func(void * opaque,size_t items,size_t size)1982 static void *def_alloc_func(void *opaque, size_t items, size_t size) {
1983   (void)opaque, (void)items, (void)size;
1984   return MZ_MALLOC(items * size);
1985 }
def_free_func(void * opaque,void * address)1986 static void def_free_func(void *opaque, void *address) {
1987   (void)opaque, (void)address;
1988   MZ_FREE(address);
1989 }
1990 // static void *def_realloc_func(void *opaque, void *address, size_t items,
1991 //                              size_t size) {
1992 //  (void)opaque, (void)address, (void)items, (void)size;
1993 //  return MZ_REALLOC(address, items * size);
1994 //}
1995 
mz_version(void)1996 const char *mz_version(void) { return MZ_VERSION; }
1997 
mz_deflateInit(mz_streamp pStream,int level)1998 int mz_deflateInit(mz_streamp pStream, int level) {
1999   return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9,
2000                          MZ_DEFAULT_STRATEGY);
2001 }
2002 
mz_deflateInit2(mz_streamp pStream,int level,int method,int window_bits,int mem_level,int strategy)2003 int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits,
2004                     int mem_level, int strategy) {
2005   tdefl_compressor *pComp;
2006   mz_uint comp_flags =
2007       TDEFL_COMPUTE_ADLER32 |
2008       tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
2009 
2010   if (!pStream) return MZ_STREAM_ERROR;
2011   if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) ||
2012       ((window_bits != MZ_DEFAULT_WINDOW_BITS) &&
2013        (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
2014     return MZ_PARAM_ERROR;
2015 
2016   pStream->data_type = 0;
2017   pStream->adler = MZ_ADLER32_INIT;
2018   pStream->msg = NULL;
2019   pStream->reserved = 0;
2020   pStream->total_in = 0;
2021   pStream->total_out = 0;
2022   if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
2023   if (!pStream->zfree) pStream->zfree = def_free_func;
2024 
2025   pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1,
2026                                               sizeof(tdefl_compressor));
2027   if (!pComp) return MZ_MEM_ERROR;
2028 
2029   pStream->state = (struct mz_internal_state *)pComp;
2030 
2031   if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) {
2032     mz_deflateEnd(pStream);
2033     return MZ_PARAM_ERROR;
2034   }
2035 
2036   return MZ_OK;
2037 }
2038 
mz_deflateReset(mz_streamp pStream)2039 int mz_deflateReset(mz_streamp pStream) {
2040   if ((!pStream) || (!pStream->state) || (!pStream->zalloc) ||
2041       (!pStream->zfree))
2042     return MZ_STREAM_ERROR;
2043   pStream->total_in = pStream->total_out = 0;
2044   tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL,
2045              ((tdefl_compressor *)pStream->state)->m_flags);
2046   return MZ_OK;
2047 }
2048 
mz_deflate(mz_streamp pStream,int flush)2049 int mz_deflate(mz_streamp pStream, int flush) {
2050   size_t in_bytes, out_bytes;
2051   mz_ulong orig_total_in, orig_total_out;
2052   int mz_status = MZ_OK;
2053 
2054   if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) ||
2055       (!pStream->next_out))
2056     return MZ_STREAM_ERROR;
2057   if (!pStream->avail_out) return MZ_BUF_ERROR;
2058 
2059   if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
2060 
2061   if (((tdefl_compressor *)pStream->state)->m_prev_return_status ==
2062       TDEFL_STATUS_DONE)
2063     return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
2064 
2065   orig_total_in = pStream->total_in;
2066   orig_total_out = pStream->total_out;
2067   for (;;) {
2068     tdefl_status defl_status;
2069     in_bytes = pStream->avail_in;
2070     out_bytes = pStream->avail_out;
2071 
2072     defl_status = tdefl_compress((tdefl_compressor *)pStream->state,
2073                                  pStream->next_in, &in_bytes, pStream->next_out,
2074                                  &out_bytes, (tdefl_flush)flush);
2075     pStream->next_in += (mz_uint)in_bytes;
2076     pStream->avail_in -= (mz_uint)in_bytes;
2077     pStream->total_in += (mz_uint)in_bytes;
2078     pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
2079 
2080     pStream->next_out += (mz_uint)out_bytes;
2081     pStream->avail_out -= (mz_uint)out_bytes;
2082     pStream->total_out += (mz_uint)out_bytes;
2083 
2084     if (defl_status < 0) {
2085       mz_status = MZ_STREAM_ERROR;
2086       break;
2087     } else if (defl_status == TDEFL_STATUS_DONE) {
2088       mz_status = MZ_STREAM_END;
2089       break;
2090     } else if (!pStream->avail_out)
2091       break;
2092     else if ((!pStream->avail_in) && (flush != MZ_FINISH)) {
2093       if ((flush) || (pStream->total_in != orig_total_in) ||
2094           (pStream->total_out != orig_total_out))
2095         break;
2096       return MZ_BUF_ERROR;  // Can't make forward progress without some input.
2097     }
2098   }
2099   return mz_status;
2100 }
2101 
mz_deflateEnd(mz_streamp pStream)2102 int mz_deflateEnd(mz_streamp pStream) {
2103   if (!pStream) return MZ_STREAM_ERROR;
2104   if (pStream->state) {
2105     pStream->zfree(pStream->opaque, pStream->state);
2106     pStream->state = NULL;
2107   }
2108   return MZ_OK;
2109 }
2110 
mz_deflateBound(mz_streamp pStream,mz_ulong source_len)2111 mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) {
2112   (void)pStream;
2113   // This is really over conservative. (And lame, but it's actually pretty
2114   // tricky to compute a true upper bound given the way tdefl's blocking works.)
2115   return MZ_MAX(128 + (source_len * 110) / 100,
2116                 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
2117 }
2118 
mz_compress2(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len,int level)2119 int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len,
2120                  const unsigned char *pSource, mz_ulong source_len, int level) {
2121   int status;
2122   mz_stream stream;
2123   memset(&stream, 0, sizeof(stream));
2124 
2125   // In case mz_ulong is 64-bits (argh I hate longs).
2126   if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
2127 
2128   stream.next_in = pSource;
2129   stream.avail_in = (mz_uint32)source_len;
2130   stream.next_out = pDest;
2131   stream.avail_out = (mz_uint32)*pDest_len;
2132 
2133   status = mz_deflateInit(&stream, level);
2134   if (status != MZ_OK) return status;
2135 
2136   status = mz_deflate(&stream, MZ_FINISH);
2137   if (status != MZ_STREAM_END) {
2138     mz_deflateEnd(&stream);
2139     return (status == MZ_OK) ? MZ_BUF_ERROR : status;
2140   }
2141 
2142   *pDest_len = stream.total_out;
2143   return mz_deflateEnd(&stream);
2144 }
2145 
mz_compress(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len)2146 int mz_compress(unsigned char *pDest, mz_ulong *pDest_len,
2147                 const unsigned char *pSource, mz_ulong source_len) {
2148   return mz_compress2(pDest, pDest_len, pSource, source_len,
2149                       MZ_DEFAULT_COMPRESSION);
2150 }
2151 
mz_compressBound(mz_ulong source_len)2152 mz_ulong mz_compressBound(mz_ulong source_len) {
2153   return mz_deflateBound(NULL, source_len);
2154 }
2155 
2156 typedef struct {
2157   tinfl_decompressor m_decomp;
2158   mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
2159   int m_window_bits;
2160   mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
2161   tinfl_status m_last_status;
2162 } inflate_state;
2163 
mz_inflateInit2(mz_streamp pStream,int window_bits)2164 int mz_inflateInit2(mz_streamp pStream, int window_bits) {
2165   inflate_state *pDecomp;
2166   if (!pStream) return MZ_STREAM_ERROR;
2167   if ((window_bits != MZ_DEFAULT_WINDOW_BITS) &&
2168       (-window_bits != MZ_DEFAULT_WINDOW_BITS))
2169     return MZ_PARAM_ERROR;
2170 
2171   pStream->data_type = 0;
2172   pStream->adler = 0;
2173   pStream->msg = NULL;
2174   pStream->total_in = 0;
2175   pStream->total_out = 0;
2176   pStream->reserved = 0;
2177   if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
2178   if (!pStream->zfree) pStream->zfree = def_free_func;
2179 
2180   pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1,
2181                                              sizeof(inflate_state));
2182   if (!pDecomp) return MZ_MEM_ERROR;
2183 
2184   pStream->state = (struct mz_internal_state *)pDecomp;
2185 
2186   tinfl_init(&pDecomp->m_decomp);
2187   pDecomp->m_dict_ofs = 0;
2188   pDecomp->m_dict_avail = 0;
2189   pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
2190   pDecomp->m_first_call = 1;
2191   pDecomp->m_has_flushed = 0;
2192   pDecomp->m_window_bits = window_bits;
2193 
2194   return MZ_OK;
2195 }
2196 
mz_inflateInit(mz_streamp pStream)2197 int mz_inflateInit(mz_streamp pStream) {
2198   return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
2199 }
2200 
mz_inflate(mz_streamp pStream,int flush)2201 int mz_inflate(mz_streamp pStream, int flush) {
2202   inflate_state *pState;
2203   mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
2204   size_t in_bytes, out_bytes, orig_avail_in;
2205   tinfl_status status;
2206 
2207   if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR;
2208   if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
2209   if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
2210     return MZ_STREAM_ERROR;
2211 
2212   pState = (inflate_state *)pStream->state;
2213   if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
2214   orig_avail_in = pStream->avail_in;
2215 
2216   first_call = pState->m_first_call;
2217   pState->m_first_call = 0;
2218   if (pState->m_last_status < 0) return MZ_DATA_ERROR;
2219 
2220   if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
2221   pState->m_has_flushed |= (flush == MZ_FINISH);
2222 
2223   if ((flush == MZ_FINISH) && (first_call)) {
2224     // MZ_FINISH on the first call implies that the input and output buffers are
2225     // large enough to hold the entire compressed/decompressed file.
2226     decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
2227     in_bytes = pStream->avail_in;
2228     out_bytes = pStream->avail_out;
2229     status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes,
2230                               pStream->next_out, pStream->next_out, &out_bytes,
2231                               decomp_flags);
2232     pState->m_last_status = status;
2233     pStream->next_in += (mz_uint)in_bytes;
2234     pStream->avail_in -= (mz_uint)in_bytes;
2235     pStream->total_in += (mz_uint)in_bytes;
2236     pStream->adler = tinfl_get_adler32(&pState->m_decomp);
2237     pStream->next_out += (mz_uint)out_bytes;
2238     pStream->avail_out -= (mz_uint)out_bytes;
2239     pStream->total_out += (mz_uint)out_bytes;
2240 
2241     if (status < 0)
2242       return MZ_DATA_ERROR;
2243     else if (status != TINFL_STATUS_DONE) {
2244       pState->m_last_status = TINFL_STATUS_FAILED;
2245       return MZ_BUF_ERROR;
2246     }
2247     return MZ_STREAM_END;
2248   }
2249   // flush != MZ_FINISH then we must assume there's more input.
2250   if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
2251 
2252   if (pState->m_dict_avail) {
2253     n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
2254     memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
2255     pStream->next_out += n;
2256     pStream->avail_out -= n;
2257     pStream->total_out += n;
2258     pState->m_dict_avail -= n;
2259     pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
2260     return ((pState->m_last_status == TINFL_STATUS_DONE) &&
2261             (!pState->m_dict_avail))
2262                ? MZ_STREAM_END
2263                : MZ_OK;
2264   }
2265 
2266   for (;;) {
2267     in_bytes = pStream->avail_in;
2268     out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
2269 
2270     status = tinfl_decompress(
2271         &pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict,
2272         pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
2273     pState->m_last_status = status;
2274 
2275     pStream->next_in += (mz_uint)in_bytes;
2276     pStream->avail_in -= (mz_uint)in_bytes;
2277     pStream->total_in += (mz_uint)in_bytes;
2278     pStream->adler = tinfl_get_adler32(&pState->m_decomp);
2279 
2280     pState->m_dict_avail = (mz_uint)out_bytes;
2281 
2282     n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
2283     memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
2284     pStream->next_out += n;
2285     pStream->avail_out -= n;
2286     pStream->total_out += n;
2287     pState->m_dict_avail -= n;
2288     pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
2289 
2290     if (status < 0)
2291       return MZ_DATA_ERROR;  // Stream is corrupted (there could be some
2292     // uncompressed data left in the output dictionary -
2293     // oh well).
2294     else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
2295       return MZ_BUF_ERROR;  // Signal caller that we can't make forward progress
2296                             // without supplying more input or by setting flush
2297                             // to MZ_FINISH.
2298     else if (flush == MZ_FINISH) {
2299       // The output buffer MUST be large to hold the remaining uncompressed data
2300       // when flush==MZ_FINISH.
2301       if (status == TINFL_STATUS_DONE)
2302         return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
2303       // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's
2304       // at least 1 more byte on the way. If there's no more room left in the
2305       // output buffer then something is wrong.
2306       else if (!pStream->avail_out)
2307         return MZ_BUF_ERROR;
2308     } else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) ||
2309                (!pStream->avail_out) || (pState->m_dict_avail))
2310       break;
2311   }
2312 
2313   return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail))
2314              ? MZ_STREAM_END
2315              : MZ_OK;
2316 }
2317 
mz_inflateEnd(mz_streamp pStream)2318 int mz_inflateEnd(mz_streamp pStream) {
2319   if (!pStream) return MZ_STREAM_ERROR;
2320   if (pStream->state) {
2321     pStream->zfree(pStream->opaque, pStream->state);
2322     pStream->state = NULL;
2323   }
2324   return MZ_OK;
2325 }
2326 
mz_uncompress(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len)2327 int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len,
2328                   const unsigned char *pSource, mz_ulong source_len) {
2329   mz_stream stream;
2330   int status;
2331   memset(&stream, 0, sizeof(stream));
2332 
2333   // In case mz_ulong is 64-bits (argh I hate longs).
2334   if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
2335 
2336   stream.next_in = pSource;
2337   stream.avail_in = (mz_uint32)source_len;
2338   stream.next_out = pDest;
2339   stream.avail_out = (mz_uint32)*pDest_len;
2340 
2341   status = mz_inflateInit(&stream);
2342   if (status != MZ_OK) return status;
2343 
2344   status = mz_inflate(&stream, MZ_FINISH);
2345   if (status != MZ_STREAM_END) {
2346     mz_inflateEnd(&stream);
2347     return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR
2348                                                             : status;
2349   }
2350   *pDest_len = stream.total_out;
2351 
2352   return mz_inflateEnd(&stream);
2353 }
2354 
mz_error(int err)2355 const char *mz_error(int err) {
2356   static struct {
2357     int m_err;
2358     const char *m_pDesc;
2359   } s_error_descs[] = {{MZ_OK, ""},
2360                        {MZ_STREAM_END, "stream end"},
2361                        {MZ_NEED_DICT, "need dictionary"},
2362                        {MZ_ERRNO, "file error"},
2363                        {MZ_STREAM_ERROR, "stream error"},
2364                        {MZ_DATA_ERROR, "data error"},
2365                        {MZ_MEM_ERROR, "out of memory"},
2366                        {MZ_BUF_ERROR, "buf error"},
2367                        {MZ_VERSION_ERROR, "version error"},
2368                        {MZ_PARAM_ERROR, "parameter error"}};
2369   mz_uint i;
2370   for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
2371     if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc;
2372   return NULL;
2373 }
2374 
2375 #endif  // MINIZ_NO_ZLIB_APIS
2376 
2377 // ------------------- Low-level Decompression (completely independent from all
2378 // compression API's)
2379 
2380 #define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
2381 #define TINFL_MEMSET(p, c, l) memset(p, c, l)
2382 
2383 #define TINFL_CR_BEGIN  \
2384   switch (r->m_state) { \
2385     case 0:
2386 #define TINFL_CR_RETURN(state_index, result) \
2387   do {                                       \
2388     status = result;                         \
2389     r->m_state = state_index;                \
2390     goto common_exit;                        \
2391     case state_index:;                       \
2392   }                                          \
2393   MZ_MACRO_END
2394 #define TINFL_CR_RETURN_FOREVER(state_index, result) \
2395   do {                                               \
2396     for (;;) {                                       \
2397       TINFL_CR_RETURN(state_index, result);          \
2398     }                                                \
2399   }                                                  \
2400   MZ_MACRO_END
2401 #define TINFL_CR_FINISH }
2402 
2403 // TODO: If the caller has indicated that there's no more input, and we attempt
2404 // to read beyond the input buf, then something is wrong with the input because
2405 // the inflator never
2406 // reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of
2407 // the stream with 0's in this scenario.
2408 #define TINFL_GET_BYTE(state_index, c)                                 \
2409   do {                                                                 \
2410     if (pIn_buf_cur >= pIn_buf_end) {                                  \
2411       for (;;) {                                                       \
2412         if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) {                \
2413           TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
2414           if (pIn_buf_cur < pIn_buf_end) {                             \
2415             c = *pIn_buf_cur++;                                        \
2416             break;                                                     \
2417           }                                                            \
2418         } else {                                                       \
2419           c = 0;                                                       \
2420           break;                                                       \
2421         }                                                              \
2422       }                                                                \
2423     } else                                                             \
2424       c = *pIn_buf_cur++;                                              \
2425   }                                                                    \
2426   MZ_MACRO_END
2427 
2428 #define TINFL_NEED_BITS(state_index, n)            \
2429   do {                                             \
2430     mz_uint c;                                     \
2431     TINFL_GET_BYTE(state_index, c);                \
2432     bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2433     num_bits += 8;                                 \
2434   } while (num_bits < (mz_uint)(n))
2435 #define TINFL_SKIP_BITS(state_index, n) \
2436   do {                                  \
2437     if (num_bits < (mz_uint)(n)) {      \
2438       TINFL_NEED_BITS(state_index, n);  \
2439     }                                   \
2440     bit_buf >>= (n);                    \
2441     num_bits -= (n);                    \
2442   }                                     \
2443   MZ_MACRO_END
2444 #define TINFL_GET_BITS(state_index, b, n) \
2445   do {                                    \
2446     if (num_bits < (mz_uint)(n)) {        \
2447       TINFL_NEED_BITS(state_index, n);    \
2448     }                                     \
2449     b = bit_buf & ((1 << (n)) - 1);       \
2450     bit_buf >>= (n);                      \
2451     num_bits -= (n);                      \
2452   }                                       \
2453   MZ_MACRO_END
2454 
2455 // TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes
2456 // remaining in the input buffer falls below 2.
2457 // It reads just enough bytes from the input stream that are needed to decode
2458 // the next Huffman code (and absolutely no more). It works by trying to fully
2459 // decode a
2460 // Huffman code by using whatever bits are currently present in the bit buffer.
2461 // If this fails, it reads another byte, and tries again until it succeeds or
2462 // until the
2463 // bit buffer contains >=15 bits (deflate's max. Huffman code size).
2464 #define TINFL_HUFF_BITBUF_FILL(state_index, pHuff)                     \
2465   do {                                                                 \
2466     temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
2467     if (temp >= 0) {                                                   \
2468       code_len = temp >> 9;                                            \
2469       if ((code_len) && (num_bits >= code_len)) break;                 \
2470     } else if (num_bits > TINFL_FAST_LOOKUP_BITS) {                    \
2471       code_len = TINFL_FAST_LOOKUP_BITS;                               \
2472       do {                                                             \
2473         temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
2474       } while ((temp < 0) && (num_bits >= (code_len + 1)));            \
2475       if (temp >= 0) break;                                            \
2476     }                                                                  \
2477     TINFL_GET_BYTE(state_index, c);                                    \
2478     bit_buf |= (((tinfl_bit_buf_t)c) << num_bits);                     \
2479     num_bits += 8;                                                     \
2480   } while (num_bits < 15);
2481 
2482 // TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex
2483 // than you would initially expect because the zlib API expects the decompressor
2484 // to never read
2485 // beyond the final byte of the deflate stream. (In other words, when this macro
2486 // wants to read another byte from the input, it REALLY needs another byte in
2487 // order to fully
2488 // decode the next Huffman code.) Handling this properly is particularly
2489 // important on raw deflate (non-zlib) streams, which aren't followed by a byte
2490 // aligned adler-32.
2491 // The slow path is only executed at the very end of the input buffer.
2492 #define TINFL_HUFF_DECODE(state_index, sym, pHuff)                             \
2493   do {                                                                         \
2494     int temp;                                                                  \
2495     mz_uint code_len, c;                                                       \
2496     if (num_bits < 15) {                                                       \
2497       if ((pIn_buf_end - pIn_buf_cur) < 2) {                                   \
2498         TINFL_HUFF_BITBUF_FILL(state_index, pHuff);                            \
2499       } else {                                                                 \
2500         bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) |           \
2501                    (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8));      \
2502         pIn_buf_cur += 2;                                                      \
2503         num_bits += 16;                                                        \
2504       }                                                                        \
2505     }                                                                          \
2506     if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= \
2507         0)                                                                     \
2508       code_len = temp >> 9, temp &= 511;                                       \
2509     else {                                                                     \
2510       code_len = TINFL_FAST_LOOKUP_BITS;                                       \
2511       do {                                                                     \
2512         temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)];         \
2513       } while (temp < 0);                                                      \
2514     }                                                                          \
2515     sym = temp;                                                                \
2516     bit_buf >>= code_len;                                                      \
2517     num_bits -= code_len;                                                      \
2518   }                                                                            \
2519   MZ_MACRO_END
2520 
tinfl_decompress(tinfl_decompressor * r,const mz_uint8 * pIn_buf_next,size_t * pIn_buf_size,mz_uint8 * pOut_buf_start,mz_uint8 * pOut_buf_next,size_t * pOut_buf_size,const mz_uint32 decomp_flags)2521 tinfl_status tinfl_decompress(tinfl_decompressor *r,
2522                               const mz_uint8 *pIn_buf_next,
2523                               size_t *pIn_buf_size, mz_uint8 *pOut_buf_start,
2524                               mz_uint8 *pOut_buf_next, size_t *pOut_buf_size,
2525                               const mz_uint32 decomp_flags) {
2526   static const int s_length_base[31] = {
2527       3,  4,  5,  6,  7,  8,  9,  10,  11,  13,  15,  17,  19,  23, 27, 31,
2528       35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0,  0};
2529   static const int s_length_extra[31] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
2530                                          1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
2531                                          4, 4, 5, 5, 5, 5, 0, 0, 0};
2532   static const int s_dist_base[32] = {
2533       1,    2,    3,    4,    5,    7,     9,     13,    17,  25,   33,
2534       49,   65,   97,   129,  193,  257,   385,   513,   769, 1025, 1537,
2535       2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0,   0};
2536   static const int s_dist_extra[32] = {0, 0, 0,  0,  1,  1,  2,  2,  3,  3,
2537                                        4, 4, 5,  5,  6,  6,  7,  7,  8,  8,
2538                                        9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
2539   static const mz_uint8 s_length_dezigzag[19] = {
2540       16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
2541   static const int s_min_table_sizes[3] = {257, 1, 4};
2542 
2543   tinfl_status status = TINFL_STATUS_FAILED;
2544   mz_uint32 num_bits, dist, counter, num_extra;
2545   tinfl_bit_buf_t bit_buf;
2546   const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end =
2547                                                   pIn_buf_next + *pIn_buf_size;
2548   mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end =
2549                                               pOut_buf_next + *pOut_buf_size;
2550   size_t out_buf_size_mask =
2551              (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)
2552                  ? (size_t)-1
2553                  : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1,
2554          dist_from_out_buf_start;
2555 
2556   // Ensure the output buffer's size is a power of 2, unless the output buffer
2557   // is large enough to hold the entire output file (in which case it doesn't
2558   // matter).
2559   if (((out_buf_size_mask + 1) & out_buf_size_mask) ||
2560       (pOut_buf_next < pOut_buf_start)) {
2561     *pIn_buf_size = *pOut_buf_size = 0;
2562     return TINFL_STATUS_BAD_PARAM;
2563   }
2564 
2565   num_bits = r->m_num_bits;
2566   bit_buf = r->m_bit_buf;
2567   dist = r->m_dist;
2568   counter = r->m_counter;
2569   num_extra = r->m_num_extra;
2570   dist_from_out_buf_start = r->m_dist_from_out_buf_start;
2571   TINFL_CR_BEGIN
2572 
2573   bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
2574   r->m_z_adler32 = r->m_check_adler32 = 1;
2575   if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) {
2576     TINFL_GET_BYTE(1, r->m_zhdr0);
2577     TINFL_GET_BYTE(2, r->m_zhdr1);
2578     counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) ||
2579                (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
2580     if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2581       counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) ||
2582                   ((out_buf_size_mask + 1) <
2583                    (size_t)(1ULL << (8U + (r->m_zhdr0 >> 4)))));
2584     if (counter) {
2585       TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
2586     }
2587   }
2588 
2589   do {
2590     TINFL_GET_BITS(3, r->m_final, 3);
2591     r->m_type = r->m_final >> 1;
2592     if (r->m_type == 0) {
2593       TINFL_SKIP_BITS(5, num_bits & 7);
2594       for (counter = 0; counter < 4; ++counter) {
2595         if (num_bits)
2596           TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
2597         else
2598           TINFL_GET_BYTE(7, r->m_raw_header[counter]);
2599       }
2600       if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) !=
2601           (mz_uint)(0xFFFF ^
2602                     (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) {
2603         TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
2604       }
2605       while ((counter) && (num_bits)) {
2606         TINFL_GET_BITS(51, dist, 8);
2607         while (pOut_buf_cur >= pOut_buf_end) {
2608           TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
2609         }
2610         *pOut_buf_cur++ = (mz_uint8)dist;
2611         counter--;
2612       }
2613       while (counter) {
2614         size_t n;
2615         while (pOut_buf_cur >= pOut_buf_end) {
2616           TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
2617         }
2618         while (pIn_buf_cur >= pIn_buf_end) {
2619           if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) {
2620             TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
2621           } else {
2622             TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
2623           }
2624         }
2625         n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur),
2626                           (size_t)(pIn_buf_end - pIn_buf_cur)),
2627                    counter);
2628         TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
2629         pIn_buf_cur += n;
2630         pOut_buf_cur += n;
2631         counter -= (mz_uint)n;
2632       }
2633     } else if (r->m_type == 3) {
2634       TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
2635     } else {
2636       if (r->m_type == 1) {
2637         mz_uint8 *p = r->m_tables[0].m_code_size;
2638         mz_uint i;
2639         r->m_table_sizes[0] = 288;
2640         r->m_table_sizes[1] = 32;
2641         TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
2642         for (i = 0; i <= 143; ++i) *p++ = 8;
2643         for (; i <= 255; ++i) *p++ = 9;
2644         for (; i <= 279; ++i) *p++ = 7;
2645         for (; i <= 287; ++i) *p++ = 8;
2646       } else {
2647         for (counter = 0; counter < 3; counter++) {
2648           TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
2649           r->m_table_sizes[counter] += s_min_table_sizes[counter];
2650         }
2651         MZ_CLEAR_OBJ(r->m_tables[2].m_code_size);
2652         for (counter = 0; counter < r->m_table_sizes[2]; counter++) {
2653           mz_uint s;
2654           TINFL_GET_BITS(14, s, 3);
2655           r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
2656         }
2657         r->m_table_sizes[2] = 19;
2658       }
2659       for (; (int)r->m_type >= 0; r->m_type--) {
2660         int tree_next, tree_cur;
2661         tinfl_huff_table *pTable;
2662         mz_uint i, j, used_syms, total, sym_index, next_code[17],
2663             total_syms[16];
2664         pTable = &r->m_tables[r->m_type];
2665         MZ_CLEAR_OBJ(total_syms);
2666         MZ_CLEAR_OBJ(pTable->m_look_up);
2667         MZ_CLEAR_OBJ(pTable->m_tree);
2668         for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
2669           total_syms[pTable->m_code_size[i]]++;
2670         used_syms = 0, total = 0;
2671         next_code[0] = next_code[1] = 0;
2672         for (i = 1; i <= 15; ++i) {
2673           used_syms += total_syms[i];
2674           next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
2675         }
2676         if ((65536 != total) && (used_syms > 1)) {
2677           TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
2678         }
2679         for (tree_next = -1, sym_index = 0;
2680              sym_index < r->m_table_sizes[r->m_type]; ++sym_index) {
2681           mz_uint rev_code = 0, l, cur_code,
2682                   code_size = pTable->m_code_size[sym_index];
2683           if (!code_size) continue;
2684           cur_code = next_code[code_size]++;
2685           for (l = code_size; l > 0; l--, cur_code >>= 1)
2686             rev_code = (rev_code << 1) | (cur_code & 1);
2687           if (code_size <= TINFL_FAST_LOOKUP_BITS) {
2688             mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
2689             while (rev_code < TINFL_FAST_LOOKUP_SIZE) {
2690               pTable->m_look_up[rev_code] = k;
2691               rev_code += (1 << code_size);
2692             }
2693             continue;
2694           }
2695           if (0 ==
2696               (tree_cur = pTable->m_look_up[rev_code &
2697                                             (TINFL_FAST_LOOKUP_SIZE - 1)])) {
2698             pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] =
2699                 (mz_int16)tree_next;
2700             tree_cur = tree_next;
2701             tree_next -= 2;
2702           }
2703           rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
2704           for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) {
2705             tree_cur -= ((rev_code >>= 1) & 1);
2706             if (!pTable->m_tree[-tree_cur - 1]) {
2707               pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
2708               tree_cur = tree_next;
2709               tree_next -= 2;
2710             } else
2711               tree_cur = pTable->m_tree[-tree_cur - 1];
2712           }
2713           tree_cur -= ((rev_code >>= 1) & 1);
2714           pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
2715         }
2716         if (r->m_type == 2) {
2717           for (counter = 0;
2718                counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);) {
2719             mz_uint s;
2720             TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
2721             if (dist < 16) {
2722               r->m_len_codes[counter++] = (mz_uint8)dist;
2723               continue;
2724             }
2725             if ((dist == 16) && (!counter)) {
2726               TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
2727             }
2728             num_extra = "\02\03\07"[dist - 16];
2729             TINFL_GET_BITS(18, s, num_extra);
2730             s += "\03\03\013"[dist - 16];
2731             TINFL_MEMSET(r->m_len_codes + counter,
2732                          (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
2733             counter += s;
2734           }
2735           if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) {
2736             TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
2737           }
2738           TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes,
2739                        r->m_table_sizes[0]);
2740           TINFL_MEMCPY(r->m_tables[1].m_code_size,
2741                        r->m_len_codes + r->m_table_sizes[0],
2742                        r->m_table_sizes[1]);
2743         }
2744       }
2745       for (;;) {
2746         mz_uint8 *pSrc;
2747         for (;;) {
2748           if (((pIn_buf_end - pIn_buf_cur) < 4) ||
2749               ((pOut_buf_end - pOut_buf_cur) < 2)) {
2750             TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
2751             if (counter >= 256) break;
2752             while (pOut_buf_cur >= pOut_buf_end) {
2753               TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
2754             }
2755             *pOut_buf_cur++ = (mz_uint8)counter;
2756           } else {
2757             int sym2;
2758             mz_uint code_len;
2759 #if TINFL_USE_64BIT_BITBUF
2760             if (num_bits < 30) {
2761               bit_buf |=
2762                   (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
2763               pIn_buf_cur += 4;
2764               num_bits += 32;
2765             }
2766 #else
2767             if (num_bits < 15) {
2768               bit_buf |=
2769                   (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2770               pIn_buf_cur += 2;
2771               num_bits += 16;
2772             }
2773 #endif
2774             if ((sym2 =
2775                      r->m_tables[0]
2776                          .m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >=
2777                 0)
2778               code_len = sym2 >> 9;
2779             else {
2780               code_len = TINFL_FAST_LOOKUP_BITS;
2781               do {
2782                 sym2 = r->m_tables[0]
2783                            .m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2784               } while (sym2 < 0);
2785             }
2786             counter = sym2;
2787             bit_buf >>= code_len;
2788             num_bits -= code_len;
2789             if (counter & 256) break;
2790 
2791 #if !TINFL_USE_64BIT_BITBUF
2792             if (num_bits < 15) {
2793               bit_buf |=
2794                   (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2795               pIn_buf_cur += 2;
2796               num_bits += 16;
2797             }
2798 #endif
2799             if ((sym2 =
2800                      r->m_tables[0]
2801                          .m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >=
2802                 0)
2803               code_len = sym2 >> 9;
2804             else {
2805               code_len = TINFL_FAST_LOOKUP_BITS;
2806               do {
2807                 sym2 = r->m_tables[0]
2808                            .m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2809               } while (sym2 < 0);
2810             }
2811             bit_buf >>= code_len;
2812             num_bits -= code_len;
2813 
2814             pOut_buf_cur[0] = (mz_uint8)counter;
2815             if (sym2 & 256) {
2816               pOut_buf_cur++;
2817               counter = sym2;
2818               break;
2819             }
2820             pOut_buf_cur[1] = (mz_uint8)sym2;
2821             pOut_buf_cur += 2;
2822           }
2823         }
2824         if ((counter &= 511) == 256) break;
2825 
2826         num_extra = s_length_extra[counter - 257];
2827         counter = s_length_base[counter - 257];
2828         if (num_extra) {
2829           mz_uint extra_bits;
2830           TINFL_GET_BITS(25, extra_bits, num_extra);
2831           counter += extra_bits;
2832         }
2833 
2834         TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
2835         num_extra = s_dist_extra[dist];
2836         dist = s_dist_base[dist];
2837         if (num_extra) {
2838           mz_uint extra_bits;
2839           TINFL_GET_BITS(27, extra_bits, num_extra);
2840           dist += extra_bits;
2841         }
2842 
2843         dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
2844         if ((dist > dist_from_out_buf_start) &&
2845             (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) {
2846           TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
2847         }
2848 
2849         pSrc = pOut_buf_start +
2850                ((dist_from_out_buf_start - dist) & out_buf_size_mask);
2851 
2852         if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) {
2853           while (counter--) {
2854             while (pOut_buf_cur >= pOut_buf_end) {
2855               TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
2856             }
2857             *pOut_buf_cur++ =
2858                 pOut_buf_start[(dist_from_out_buf_start++ - dist) &
2859                                out_buf_size_mask];
2860           }
2861           continue;
2862         }
2863 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2864         else if ((counter >= 9) && (counter <= dist)) {
2865           const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
2866           do {
2867             ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
2868             ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
2869             pOut_buf_cur += 8;
2870           } while ((pSrc += 8) < pSrc_end);
2871           if ((counter &= 7) < 3) {
2872             if (counter) {
2873               pOut_buf_cur[0] = pSrc[0];
2874               if (counter > 1) pOut_buf_cur[1] = pSrc[1];
2875               pOut_buf_cur += counter;
2876             }
2877             continue;
2878           }
2879         }
2880 #endif
2881         do {
2882           pOut_buf_cur[0] = pSrc[0];
2883           pOut_buf_cur[1] = pSrc[1];
2884           pOut_buf_cur[2] = pSrc[2];
2885           pOut_buf_cur += 3;
2886           pSrc += 3;
2887         } while ((int)(counter -= 3) > 2);
2888         if ((int)counter > 0) {
2889           pOut_buf_cur[0] = pSrc[0];
2890           if ((int)counter > 1) pOut_buf_cur[1] = pSrc[1];
2891           pOut_buf_cur += counter;
2892         }
2893       }
2894     }
2895   } while (!(r->m_final & 1));
2896   if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) {
2897     TINFL_SKIP_BITS(32, num_bits & 7);
2898     for (counter = 0; counter < 4; ++counter) {
2899       mz_uint s;
2900       if (num_bits)
2901         TINFL_GET_BITS(41, s, 8);
2902       else
2903         TINFL_GET_BYTE(42, s);
2904       r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
2905     }
2906   }
2907   TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
2908   TINFL_CR_FINISH
2909 
2910 common_exit:
2911   r->m_num_bits = num_bits;
2912   r->m_bit_buf = bit_buf;
2913   r->m_dist = dist;
2914   r->m_counter = counter;
2915   r->m_num_extra = num_extra;
2916   r->m_dist_from_out_buf_start = dist_from_out_buf_start;
2917   *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
2918   *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
2919   if ((decomp_flags &
2920        (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) &&
2921       (status >= 0)) {
2922     const mz_uint8 *ptr = pOut_buf_next;
2923     size_t buf_len = *pOut_buf_size;
2924     mz_uint32 i, s1 = r->m_check_adler32 & 0xffff,
2925                  s2 = r->m_check_adler32 >> 16;
2926     size_t block_len = buf_len % 5552;
2927     while (buf_len) {
2928       for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
2929         s1 += ptr[0], s2 += s1;
2930         s1 += ptr[1], s2 += s1;
2931         s1 += ptr[2], s2 += s1;
2932         s1 += ptr[3], s2 += s1;
2933         s1 += ptr[4], s2 += s1;
2934         s1 += ptr[5], s2 += s1;
2935         s1 += ptr[6], s2 += s1;
2936         s1 += ptr[7], s2 += s1;
2937       }
2938       for (; i < block_len; ++i) s1 += *ptr++, s2 += s1;
2939       s1 %= 65521U, s2 %= 65521U;
2940       buf_len -= block_len;
2941       block_len = 5552;
2942     }
2943     r->m_check_adler32 = (s2 << 16) + s1;
2944     if ((status == TINFL_STATUS_DONE) &&
2945         (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) &&
2946         (r->m_check_adler32 != r->m_z_adler32))
2947       status = TINFL_STATUS_ADLER32_MISMATCH;
2948   }
2949   return status;
2950 }
2951 
2952 // Higher level helper functions.
tinfl_decompress_mem_to_heap(const void * pSrc_buf,size_t src_buf_len,size_t * pOut_len,int flags)2953 void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
2954                                    size_t *pOut_len, int flags) {
2955   tinfl_decompressor decomp;
2956   void *pBuf = NULL, *pNew_buf;
2957   size_t src_buf_ofs = 0, out_buf_capacity = 0;
2958   *pOut_len = 0;
2959   tinfl_init(&decomp);
2960   for (;;) {
2961     size_t src_buf_size = src_buf_len - src_buf_ofs,
2962            dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
2963     tinfl_status status = tinfl_decompress(
2964         &decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size,
2965         (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL,
2966         &dst_buf_size,
2967         (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
2968             TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2969     if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) {
2970       MZ_FREE(pBuf);
2971       *pOut_len = 0;
2972       return NULL;
2973     }
2974     src_buf_ofs += src_buf_size;
2975     *pOut_len += dst_buf_size;
2976     if (status == TINFL_STATUS_DONE) break;
2977     new_out_buf_capacity = out_buf_capacity * 2;
2978     if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
2979     pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
2980     if (!pNew_buf) {
2981       MZ_FREE(pBuf);
2982       *pOut_len = 0;
2983       return NULL;
2984     }
2985     pBuf = pNew_buf;
2986     out_buf_capacity = new_out_buf_capacity;
2987   }
2988   return pBuf;
2989 }
2990 
tinfl_decompress_mem_to_mem(void * pOut_buf,size_t out_buf_len,const void * pSrc_buf,size_t src_buf_len,int flags)2991 size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
2992                                    const void *pSrc_buf, size_t src_buf_len,
2993                                    int flags) {
2994   tinfl_decompressor decomp;
2995   tinfl_status status;
2996   tinfl_init(&decomp);
2997   status =
2998       tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len,
2999                        (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len,
3000                        (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
3001                            TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
3002   return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED
3003                                        : out_buf_len;
3004 }
3005 
tinfl_decompress_mem_to_callback(const void * pIn_buf,size_t * pIn_buf_size,tinfl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)3006 int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
3007                                      tinfl_put_buf_func_ptr pPut_buf_func,
3008                                      void *pPut_buf_user, int flags) {
3009   int result = 0;
3010   tinfl_decompressor decomp;
3011   mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);
3012   size_t in_buf_ofs = 0, dict_ofs = 0;
3013   if (!pDict) return TINFL_STATUS_FAILED;
3014   tinfl_init(&decomp);
3015   for (;;) {
3016     size_t in_buf_size = *pIn_buf_size - in_buf_ofs,
3017            dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
3018     tinfl_status status =
3019         tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs,
3020                          &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
3021                          (flags & ~(TINFL_FLAG_HAS_MORE_INPUT |
3022                                     TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
3023     in_buf_ofs += in_buf_size;
3024     if ((dst_buf_size) &&
3025         (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
3026       break;
3027     if (status != TINFL_STATUS_HAS_MORE_OUTPUT) {
3028       result = (status == TINFL_STATUS_DONE);
3029       break;
3030     }
3031     dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
3032   }
3033   MZ_FREE(pDict);
3034   *pIn_buf_size = in_buf_ofs;
3035   return result;
3036 }
3037 
3038 // ------------------- Low-level Compression (independent from all decompression
3039 // API's)
3040 
3041 // Purposely making these tables static for faster init and thread safety.
3042 static const mz_uint16 s_tdefl_len_sym[256] = {
3043     257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268,
3044     268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272,
3045     272, 272, 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274,
3046     274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276,
3047     276, 276, 276, 276, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
3048     277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
3049     278, 278, 278, 278, 278, 278, 279, 279, 279, 279, 279, 279, 279, 279, 279,
3050     279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280,
3051     280, 280, 280, 280, 280, 280, 280, 280, 281, 281, 281, 281, 281, 281, 281,
3052     281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
3053     281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 282, 282, 282, 282, 282,
3054     282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
3055     282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 283, 283, 283,
3056     283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
3057     283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 284,
3058     284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
3059     284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
3060     285};
3061 
3062 static const mz_uint8 s_tdefl_len_extra[256] = {
3063     0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
3064     2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3065     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
3066     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3067     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3068     4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3069     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3070     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3071     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3072     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3073     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0};
3074 
3075 static const mz_uint8 s_tdefl_small_dist_sym[512] = {
3076     0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,
3077     8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,  10, 10, 10, 10, 10, 10,
3078     10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
3079     11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
3080     12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
3081     12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
3082     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14,
3083     14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
3084     14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
3085     14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
3086     14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
3087     15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
3088     15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
3089     15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3090     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3091     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3092     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3093     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3094     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3095     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
3096     16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
3097     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
3098     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
3099     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
3100     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
3101     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
3102     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17};
3103 
3104 static const mz_uint8 s_tdefl_small_dist_extra[512] = {
3105     0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3106     3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3107     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3108     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3109     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3110     5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3111     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3112     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3113     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3114     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3115     6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3116     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3117     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3118     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3119     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3120     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3121     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3122     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3123     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3124     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3125     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
3126 
3127 static const mz_uint8 s_tdefl_large_dist_sym[128] = {
3128     0,  0,  18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24,
3129     24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26,
3130     26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27,
3131     27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
3132     28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
3133     28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
3134     29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29};
3135 
3136 static const mz_uint8 s_tdefl_large_dist_extra[128] = {
3137     0,  0,  8,  8,  9,  9,  9,  9,  10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
3138     11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
3139     12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
3140     12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
3141     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
3142     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
3143     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13};
3144 
3145 // Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted
3146 // values.
3147 typedef struct {
3148   mz_uint16 m_key, m_sym_index;
3149 } tdefl_sym_freq;
tdefl_radix_sort_syms(mz_uint num_syms,tdefl_sym_freq * pSyms0,tdefl_sym_freq * pSyms1)3150 static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms,
3151                                              tdefl_sym_freq *pSyms0,
3152                                              tdefl_sym_freq *pSyms1) {
3153   mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
3154   tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
3155   MZ_CLEAR_OBJ(hist);
3156   for (i = 0; i < num_syms; i++) {
3157     mz_uint freq = pSyms0[i].m_key;
3158     hist[freq & 0xFF]++;
3159     hist[256 + ((freq >> 8) & 0xFF)]++;
3160   }
3161   while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
3162     total_passes--;
3163   for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) {
3164     const mz_uint32 *pHist = &hist[pass << 8];
3165     mz_uint offsets[256], cur_ofs = 0;
3166     for (i = 0; i < 256; i++) {
3167       offsets[i] = cur_ofs;
3168       cur_ofs += pHist[i];
3169     }
3170     for (i = 0; i < num_syms; i++)
3171       pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] =
3172           pCur_syms[i];
3173     {
3174       tdefl_sym_freq *t = pCur_syms;
3175       pCur_syms = pNew_syms;
3176       pNew_syms = t;
3177     }
3178   }
3179   return pCur_syms;
3180 }
3181 
3182 // tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat,
3183 // alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996.
tdefl_calculate_minimum_redundancy(tdefl_sym_freq * A,int n)3184 static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) {
3185   int root, leaf, next, avbl, used, dpth;
3186   if (n == 0)
3187     return;
3188   else if (n == 1) {
3189     A[0].m_key = 1;
3190     return;
3191   }
3192   A[0].m_key += A[1].m_key;
3193   root = 0;
3194   leaf = 2;
3195   for (next = 1; next < n - 1; next++) {
3196     if (leaf >= n || A[root].m_key < A[leaf].m_key) {
3197       A[next].m_key = A[root].m_key;
3198       A[root++].m_key = (mz_uint16)next;
3199     } else
3200       A[next].m_key = A[leaf++].m_key;
3201     if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) {
3202       A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
3203       A[root++].m_key = (mz_uint16)next;
3204     } else
3205       A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
3206   }
3207   A[n - 2].m_key = 0;
3208   for (next = n - 3; next >= 0; next--)
3209     A[next].m_key = A[A[next].m_key].m_key + 1;
3210   avbl = 1;
3211   used = dpth = 0;
3212   root = n - 2;
3213   next = n - 1;
3214   while (avbl > 0) {
3215     while (root >= 0 && (int)A[root].m_key == dpth) {
3216       used++;
3217       root--;
3218     }
3219     while (avbl > used) {
3220       A[next--].m_key = (mz_uint16)(dpth);
3221       avbl--;
3222     }
3223     avbl = 2 * used;
3224     dpth++;
3225     used = 0;
3226   }
3227 }
3228 
3229 // Limits canonical Huffman code table's max code size.
3230 enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
tdefl_huffman_enforce_max_code_size(int * pNum_codes,int code_list_len,int max_code_size)3231 static void tdefl_huffman_enforce_max_code_size(int *pNum_codes,
3232                                                 int code_list_len,
3233                                                 int max_code_size) {
3234   int i;
3235   mz_uint32 total = 0;
3236   if (code_list_len <= 1) return;
3237   for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
3238     pNum_codes[max_code_size] += pNum_codes[i];
3239   for (i = max_code_size; i > 0; i--)
3240     total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
3241   while (total != (1UL << max_code_size)) {
3242     pNum_codes[max_code_size]--;
3243     for (i = max_code_size - 1; i > 0; i--)
3244       if (pNum_codes[i]) {
3245         pNum_codes[i]--;
3246         pNum_codes[i + 1] += 2;
3247         break;
3248       }
3249     total--;
3250   }
3251 }
3252 
tdefl_optimize_huffman_table(tdefl_compressor * d,int table_num,int table_len,int code_size_limit,int static_table)3253 static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num,
3254                                          int table_len, int code_size_limit,
3255                                          int static_table) {
3256   int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
3257   mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];
3258   MZ_CLEAR_OBJ(num_codes);
3259   if (static_table) {
3260     for (i = 0; i < table_len; i++)
3261       num_codes[d->m_huff_code_sizes[table_num][i]]++;
3262   } else {
3263     tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS],
3264         *pSyms;
3265     int num_used_syms = 0;
3266     const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
3267     for (i = 0; i < table_len; i++)
3268       if (pSym_count[i]) {
3269         syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
3270         syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
3271       }
3272 
3273     pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
3274     tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
3275 
3276     for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++;
3277 
3278     tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms,
3279                                         code_size_limit);
3280 
3281     MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);
3282     MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
3283     for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
3284       for (l = num_codes[i]; l > 0; l--)
3285         d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
3286   }
3287 
3288   next_code[1] = 0;
3289   for (j = 0, i = 2; i <= code_size_limit; i++)
3290     next_code[i] = j = ((j + num_codes[i - 1]) << 1);
3291 
3292   for (i = 0; i < table_len; i++) {
3293     mz_uint rev_code = 0, code, code_size;
3294     if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue;
3295     code = next_code[code_size]++;
3296     for (l = code_size; l > 0; l--, code >>= 1)
3297       rev_code = (rev_code << 1) | (code & 1);
3298     d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
3299   }
3300 }
3301 
3302 #define TDEFL_PUT_BITS(b, l)                               \
3303   do {                                                     \
3304     mz_uint bits = b;                                      \
3305     mz_uint len = l;                                       \
3306     MZ_ASSERT(bits <= ((1U << len) - 1U));                 \
3307     d->m_bit_buffer |= (bits << d->m_bits_in);             \
3308     d->m_bits_in += len;                                   \
3309     while (d->m_bits_in >= 8) {                            \
3310       if (d->m_pOutput_buf < d->m_pOutput_buf_end)         \
3311         *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
3312       d->m_bit_buffer >>= 8;                               \
3313       d->m_bits_in -= 8;                                   \
3314     }                                                      \
3315   }                                                        \
3316   MZ_MACRO_END
3317 
3318 #define TDEFL_RLE_PREV_CODE_SIZE()                                        \
3319   {                                                                       \
3320     if (rle_repeat_count) {                                               \
3321       if (rle_repeat_count < 3) {                                         \
3322         d->m_huff_count[2][prev_code_size] = (mz_uint16)(                 \
3323             d->m_huff_count[2][prev_code_size] + rle_repeat_count);       \
3324         while (rle_repeat_count--)                                        \
3325           packed_code_sizes[num_packed_code_sizes++] = prev_code_size;    \
3326       } else {                                                            \
3327         d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); \
3328         packed_code_sizes[num_packed_code_sizes++] = 16;                  \
3329         packed_code_sizes[num_packed_code_sizes++] =                      \
3330             (mz_uint8)(rle_repeat_count - 3);                             \
3331       }                                                                   \
3332       rle_repeat_count = 0;                                               \
3333     }                                                                     \
3334   }
3335 
3336 #define TDEFL_RLE_ZERO_CODE_SIZE()                                            \
3337   {                                                                           \
3338     if (rle_z_count) {                                                        \
3339       if (rle_z_count < 3) {                                                  \
3340         d->m_huff_count[2][0] =                                               \
3341             (mz_uint16)(d->m_huff_count[2][0] + rle_z_count);                 \
3342         while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \
3343       } else if (rle_z_count <= 10) {                                         \
3344         d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1);     \
3345         packed_code_sizes[num_packed_code_sizes++] = 17;                      \
3346         packed_code_sizes[num_packed_code_sizes++] =                          \
3347             (mz_uint8)(rle_z_count - 3);                                      \
3348       } else {                                                                \
3349         d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1);     \
3350         packed_code_sizes[num_packed_code_sizes++] = 18;                      \
3351         packed_code_sizes[num_packed_code_sizes++] =                          \
3352             (mz_uint8)(rle_z_count - 11);                                     \
3353       }                                                                       \
3354       rle_z_count = 0;                                                        \
3355     }                                                                         \
3356   }
3357 
3358 static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = {
3359     16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
3360 
tdefl_start_dynamic_block(tdefl_compressor * d)3361 static void tdefl_start_dynamic_block(tdefl_compressor *d) {
3362   int num_lit_codes, num_dist_codes, num_bit_lengths;
3363   mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count,
3364       rle_repeat_count, packed_code_sizes_index;
3365   mz_uint8
3366       code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1],
3367       packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1],
3368       prev_code_size = 0xFF;
3369 
3370   d->m_huff_count[0][256] = 1;
3371 
3372   tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
3373   tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
3374 
3375   for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
3376     if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break;
3377   for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
3378     if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break;
3379 
3380   memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
3381   memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0],
3382          num_dist_codes);
3383   total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
3384   num_packed_code_sizes = 0;
3385   rle_z_count = 0;
3386   rle_repeat_count = 0;
3387 
3388   memset(&d->m_huff_count[2][0], 0,
3389          sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
3390   for (i = 0; i < total_code_sizes_to_pack; i++) {
3391     mz_uint8 code_size = code_sizes_to_pack[i];
3392     if (!code_size) {
3393       TDEFL_RLE_PREV_CODE_SIZE();
3394       if (++rle_z_count == 138) {
3395         TDEFL_RLE_ZERO_CODE_SIZE();
3396       }
3397     } else {
3398       TDEFL_RLE_ZERO_CODE_SIZE();
3399       if (code_size != prev_code_size) {
3400         TDEFL_RLE_PREV_CODE_SIZE();
3401         d->m_huff_count[2][code_size] =
3402             (mz_uint16)(d->m_huff_count[2][code_size] + 1);
3403         packed_code_sizes[num_packed_code_sizes++] = code_size;
3404       } else if (++rle_repeat_count == 6) {
3405         TDEFL_RLE_PREV_CODE_SIZE();
3406       }
3407     }
3408     prev_code_size = code_size;
3409   }
3410   if (rle_repeat_count) {
3411     TDEFL_RLE_PREV_CODE_SIZE();
3412   } else {
3413     TDEFL_RLE_ZERO_CODE_SIZE();
3414   }
3415 
3416   tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
3417 
3418   TDEFL_PUT_BITS(2, 2);
3419 
3420   TDEFL_PUT_BITS(num_lit_codes - 257, 5);
3421   TDEFL_PUT_BITS(num_dist_codes - 1, 5);
3422 
3423   for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
3424     if (d->m_huff_code_sizes
3425             [2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
3426       break;
3427   num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
3428   TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
3429   for (i = 0; (int)i < num_bit_lengths; i++)
3430     TDEFL_PUT_BITS(
3431         d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
3432 
3433   for (packed_code_sizes_index = 0;
3434        packed_code_sizes_index < num_packed_code_sizes;) {
3435     mz_uint code = packed_code_sizes[packed_code_sizes_index++];
3436     MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
3437     TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
3438     if (code >= 16)
3439       TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++],
3440                      "\02\03\07"[code - 16]);
3441   }
3442 }
3443 
tdefl_start_static_block(tdefl_compressor * d)3444 static void tdefl_start_static_block(tdefl_compressor *d) {
3445   mz_uint i;
3446   mz_uint8 *p = &d->m_huff_code_sizes[0][0];
3447 
3448   for (i = 0; i <= 143; ++i) *p++ = 8;
3449   for (; i <= 255; ++i) *p++ = 9;
3450   for (; i <= 279; ++i) *p++ = 7;
3451   for (; i <= 287; ++i) *p++ = 8;
3452 
3453   memset(d->m_huff_code_sizes[1], 5, 32);
3454 
3455   tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
3456   tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
3457 
3458   TDEFL_PUT_BITS(1, 2);
3459 }
3460 
3461 static const mz_uint mz_bitmasks[17] = {
3462     0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
3463     0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
3464 
3465 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && \
3466     MINIZ_HAS_64BIT_REGISTERS
tdefl_compress_lz_codes(tdefl_compressor * d)3467 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) {
3468   mz_uint flags;
3469   mz_uint8 *pLZ_codes;
3470   mz_uint8 *pOutput_buf = d->m_pOutput_buf;
3471   mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
3472   mz_uint64 bit_buffer = d->m_bit_buffer;
3473   mz_uint bits_in = d->m_bits_in;
3474 
3475 #define TDEFL_PUT_BITS_FAST(b, l)                \
3476   {                                              \
3477     bit_buffer |= (((mz_uint64)(b)) << bits_in); \
3478     bits_in += (l);                              \
3479   }
3480 
3481   flags = 1;
3482   for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end;
3483        flags >>= 1) {
3484     if (flags == 1) flags = *pLZ_codes++ | 0x100;
3485 
3486     if (flags & 1) {
3487       mz_uint s0, s1, n0, n1, sym, num_extra_bits;
3488       mz_uint match_len = pLZ_codes[0],
3489               match_dist = *(const mz_uint16 *)(pLZ_codes + 1);
3490       pLZ_codes += 3;
3491 
3492       MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3493       TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]],
3494                           d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3495       TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]],
3496                           s_tdefl_len_extra[match_len]);
3497 
3498       // This sequence coaxes MSVC into using cmov's vs. jmp's.
3499       s0 = s_tdefl_small_dist_sym[match_dist & 511];
3500       n0 = s_tdefl_small_dist_extra[match_dist & 511];
3501       s1 = s_tdefl_large_dist_sym[match_dist >> 8];
3502       n1 = s_tdefl_large_dist_extra[match_dist >> 8];
3503       sym = (match_dist < 512) ? s0 : s1;
3504       num_extra_bits = (match_dist < 512) ? n0 : n1;
3505 
3506       MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
3507       TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym],
3508                           d->m_huff_code_sizes[1][sym]);
3509       TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits],
3510                           num_extra_bits);
3511     } else {
3512       mz_uint lit = *pLZ_codes++;
3513       MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3514       TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3515                           d->m_huff_code_sizes[0][lit]);
3516 
3517       if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) {
3518         flags >>= 1;
3519         lit = *pLZ_codes++;
3520         MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3521         TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3522                             d->m_huff_code_sizes[0][lit]);
3523 
3524         if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) {
3525           flags >>= 1;
3526           lit = *pLZ_codes++;
3527           MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3528           TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3529                               d->m_huff_code_sizes[0][lit]);
3530         }
3531       }
3532     }
3533 
3534     if (pOutput_buf >= d->m_pOutput_buf_end) return MZ_FALSE;
3535 
3536     *(mz_uint64 *)pOutput_buf = bit_buffer;
3537     pOutput_buf += (bits_in >> 3);
3538     bit_buffer >>= (bits_in & ~7);
3539     bits_in &= 7;
3540   }
3541 
3542 #undef TDEFL_PUT_BITS_FAST
3543 
3544   d->m_pOutput_buf = pOutput_buf;
3545   d->m_bits_in = 0;
3546   d->m_bit_buffer = 0;
3547 
3548   while (bits_in) {
3549     mz_uint32 n = MZ_MIN(bits_in, 16);
3550     TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
3551     bit_buffer >>= n;
3552     bits_in -= n;
3553   }
3554 
3555   TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
3556 
3557   return (d->m_pOutput_buf < d->m_pOutput_buf_end);
3558 }
3559 #else
tdefl_compress_lz_codes(tdefl_compressor * d)3560 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) {
3561   mz_uint flags;
3562   mz_uint8 *pLZ_codes;
3563 
3564   flags = 1;
3565   for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf;
3566        flags >>= 1) {
3567     if (flags == 1) flags = *pLZ_codes++ | 0x100;
3568     if (flags & 1) {
3569       mz_uint sym, num_extra_bits;
3570       mz_uint match_len = pLZ_codes[0],
3571               match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
3572       pLZ_codes += 3;
3573 
3574       MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3575       TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]],
3576                      d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3577       TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]],
3578                      s_tdefl_len_extra[match_len]);
3579 
3580       if (match_dist < 512) {
3581         sym = s_tdefl_small_dist_sym[match_dist];
3582         num_extra_bits = s_tdefl_small_dist_extra[match_dist];
3583       } else {
3584         sym = s_tdefl_large_dist_sym[match_dist >> 8];
3585         num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
3586       }
3587       MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
3588       TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
3589       TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
3590     } else {
3591       mz_uint lit = *pLZ_codes++;
3592       MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3593       TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
3594     }
3595   }
3596 
3597   TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
3598 
3599   return (d->m_pOutput_buf < d->m_pOutput_buf_end);
3600 }
3601 #endif  // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN &&
3602         // MINIZ_HAS_64BIT_REGISTERS
3603 
tdefl_compress_block(tdefl_compressor * d,mz_bool static_block)3604 static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) {
3605   if (static_block)
3606     tdefl_start_static_block(d);
3607   else
3608     tdefl_start_dynamic_block(d);
3609   return tdefl_compress_lz_codes(d);
3610 }
3611 
tdefl_flush_block(tdefl_compressor * d,int flush)3612 static int tdefl_flush_block(tdefl_compressor *d, int flush) {
3613   mz_uint saved_bit_buf, saved_bits_in;
3614   mz_uint8 *pSaved_output_buf;
3615   mz_bool comp_block_succeeded = MZ_FALSE;
3616   int n, use_raw_block =
3617              ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) &&
3618              (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
3619   mz_uint8 *pOutput_buf_start =
3620       ((d->m_pPut_buf_func == NULL) &&
3621        ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE))
3622           ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs)
3623           : d->m_output_buf;
3624 
3625   d->m_pOutput_buf = pOutput_buf_start;
3626   d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
3627 
3628   MZ_ASSERT(!d->m_output_flush_remaining);
3629   d->m_output_flush_ofs = 0;
3630   d->m_output_flush_remaining = 0;
3631 
3632   *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
3633   d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
3634 
3635   if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) {
3636     TDEFL_PUT_BITS(0x78, 8);
3637     TDEFL_PUT_BITS(0x01, 8);
3638   }
3639 
3640   TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
3641 
3642   pSaved_output_buf = d->m_pOutput_buf;
3643   saved_bit_buf = d->m_bit_buffer;
3644   saved_bits_in = d->m_bits_in;
3645 
3646   if (!use_raw_block)
3647     comp_block_succeeded =
3648         tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) ||
3649                                     (d->m_total_lz_bytes < 48));
3650 
3651   // If the block gets expanded, forget the current contents of the output
3652   // buffer and send a raw block instead.
3653   if (((use_raw_block) ||
3654        ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >=
3655                                   d->m_total_lz_bytes))) &&
3656       ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size)) {
3657     mz_uint i;
3658     d->m_pOutput_buf = pSaved_output_buf;
3659     d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
3660     TDEFL_PUT_BITS(0, 2);
3661     if (d->m_bits_in) {
3662       TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3663     }
3664     for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) {
3665       TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
3666     }
3667     for (i = 0; i < d->m_total_lz_bytes; ++i) {
3668       TDEFL_PUT_BITS(
3669           d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK],
3670           8);
3671     }
3672   }
3673   // Check for the extremely unlikely (if not impossible) case of the compressed
3674   // block not fitting into the output buffer when using dynamic codes.
3675   else if (!comp_block_succeeded) {
3676     d->m_pOutput_buf = pSaved_output_buf;
3677     d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
3678     tdefl_compress_block(d, MZ_TRUE);
3679   }
3680 
3681   if (flush) {
3682     if (flush == TDEFL_FINISH) {
3683       if (d->m_bits_in) {
3684         TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3685       }
3686       if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) {
3687         mz_uint i, a = d->m_adler32;
3688         for (i = 0; i < 4; i++) {
3689           TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
3690           a <<= 8;
3691         }
3692       }
3693     } else {
3694       mz_uint i, z = 0;
3695       TDEFL_PUT_BITS(0, 3);
3696       if (d->m_bits_in) {
3697         TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3698       }
3699       for (i = 2; i; --i, z ^= 0xFFFF) {
3700         TDEFL_PUT_BITS(z & 0xFFFF, 16);
3701       }
3702     }
3703   }
3704 
3705   MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
3706 
3707   memset(&d->m_huff_count[0][0], 0,
3708          sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
3709   memset(&d->m_huff_count[1][0], 0,
3710          sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
3711 
3712   d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
3713   d->m_pLZ_flags = d->m_lz_code_buf;
3714   d->m_num_flags_left = 8;
3715   d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;
3716   d->m_total_lz_bytes = 0;
3717   d->m_block_index++;
3718 
3719   if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) {
3720     if (d->m_pPut_buf_func) {
3721       *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
3722       if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
3723         return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
3724     } else if (pOutput_buf_start == d->m_output_buf) {
3725       int bytes_to_copy = (int)MZ_MIN(
3726           (size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
3727       memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf,
3728              bytes_to_copy);
3729       d->m_out_buf_ofs += bytes_to_copy;
3730       if ((n -= bytes_to_copy) != 0) {
3731         d->m_output_flush_ofs = bytes_to_copy;
3732         d->m_output_flush_remaining = n;
3733       }
3734     } else {
3735       d->m_out_buf_ofs += n;
3736     }
3737   }
3738 
3739   return d->m_output_flush_remaining;
3740 }
3741 
3742 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
3743 #define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p)
tdefl_find_match(tdefl_compressor * d,mz_uint lookahead_pos,mz_uint max_dist,mz_uint max_match_len,mz_uint * pMatch_dist,mz_uint * pMatch_len)3744 static MZ_FORCEINLINE void tdefl_find_match(
3745     tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist,
3746     mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) {
3747   mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK,
3748                 match_len = *pMatch_len, probe_pos = pos, next_probe_pos,
3749                 probe_len;
3750   mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
3751   const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;
3752   mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]),
3753             s01 = TDEFL_READ_UNALIGNED_WORD(s);
3754   MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
3755   if (max_match_len <= match_len) return;
3756   for (;;) {
3757     for (;;) {
3758       if (--num_probes_left == 0) return;
3759 #define TDEFL_PROBE                                                            \
3760   next_probe_pos = d->m_next[probe_pos];                                       \
3761   if ((!next_probe_pos) ||                                                     \
3762       ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist))       \
3763     return;                                                                    \
3764   probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                        \
3765   if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \
3766     break;
3767       TDEFL_PROBE;
3768       TDEFL_PROBE;
3769       TDEFL_PROBE;
3770     }
3771     if (!dist) break;
3772     q = (const mz_uint16 *)(d->m_dict + probe_pos);
3773     if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue;
3774     p = s;
3775     probe_len = 32;
3776     do {
3777     } while (
3778         (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
3779         (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
3780         (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
3781         (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
3782         (--probe_len > 0));
3783     if (!probe_len) {
3784       *pMatch_dist = dist;
3785       *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN);
3786       break;
3787     } else if ((probe_len = ((mz_uint)(p - s) * 2) +
3788                             (mz_uint)(*(const mz_uint8 *)p ==
3789                                       *(const mz_uint8 *)q)) > match_len) {
3790       *pMatch_dist = dist;
3791       if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) ==
3792           max_match_len)
3793         break;
3794       c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
3795     }
3796   }
3797 }
3798 #else
tdefl_find_match(tdefl_compressor * d,mz_uint lookahead_pos,mz_uint max_dist,mz_uint max_match_len,mz_uint * pMatch_dist,mz_uint * pMatch_len)3799 static MZ_FORCEINLINE void tdefl_find_match(
3800     tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist,
3801     mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) {
3802   mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK,
3803                 match_len = *pMatch_len, probe_pos = pos, next_probe_pos,
3804                 probe_len;
3805   mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
3806   const mz_uint8 *s = d->m_dict + pos, *p, *q;
3807   mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
3808   MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
3809   if (max_match_len <= match_len) return;
3810   for (;;) {
3811     for (;;) {
3812       if (--num_probes_left == 0) return;
3813 #define TDEFL_PROBE                                                      \
3814   next_probe_pos = d->m_next[probe_pos];                                 \
3815   if ((!next_probe_pos) ||                                               \
3816       ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
3817     return;                                                              \
3818   probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                  \
3819   if ((d->m_dict[probe_pos + match_len] == c0) &&                        \
3820       (d->m_dict[probe_pos + match_len - 1] == c1))                      \
3821     break;
3822       TDEFL_PROBE;
3823       TDEFL_PROBE;
3824       TDEFL_PROBE;
3825     }
3826     if (!dist) break;
3827     p = s;
3828     q = d->m_dict + probe_pos;
3829     for (probe_len = 0; probe_len < max_match_len; probe_len++)
3830       if (*p++ != *q++) break;
3831     if (probe_len > match_len) {
3832       *pMatch_dist = dist;
3833       if ((*pMatch_len = match_len = probe_len) == max_match_len) return;
3834       c0 = d->m_dict[pos + match_len];
3835       c1 = d->m_dict[pos + match_len - 1];
3836     }
3837   }
3838 }
3839 #endif  // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
3840 
3841 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
tdefl_compress_fast(tdefl_compressor * d)3842 static mz_bool tdefl_compress_fast(tdefl_compressor *d) {
3843   // Faster, minimally featured LZRW1-style match+parse loop with better
3844   // register utilization. Intended for applications where raw throughput is
3845   // valued more highly than ratio.
3846   mz_uint lookahead_pos = d->m_lookahead_pos,
3847           lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size,
3848           total_lz_bytes = d->m_total_lz_bytes,
3849           num_flags_left = d->m_num_flags_left;
3850   mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
3851   mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
3852 
3853   while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) {
3854     const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
3855     mz_uint dst_pos =
3856         (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
3857     mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(
3858         d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
3859     d->m_src_buf_left -= num_bytes_to_process;
3860     lookahead_size += num_bytes_to_process;
3861 
3862     while (num_bytes_to_process) {
3863       mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
3864       memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
3865       if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3866         memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc,
3867                MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
3868       d->m_pSrc += n;
3869       dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
3870       num_bytes_to_process -= n;
3871     }
3872 
3873     dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
3874     if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
3875       break;
3876 
3877     while (lookahead_size >= 4) {
3878       mz_uint cur_match_dist, cur_match_len = 1;
3879       mz_uint8 *pCur_dict = d->m_dict + cur_pos;
3880       mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
3881       mz_uint hash =
3882           (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) &
3883           TDEFL_LEVEL1_HASH_SIZE_MASK;
3884       mz_uint probe_pos = d->m_hash[hash];
3885       d->m_hash[hash] = (mz_uint16)lookahead_pos;
3886 
3887       if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <=
3888            dict_size) &&
3889           ((*(const mz_uint32 *)(d->m_dict +
3890                                  (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) &
3891             0xFFFFFF) == first_trigram)) {
3892         const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
3893         const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
3894         mz_uint32 probe_len = 32;
3895         do {
3896         } while ((TDEFL_READ_UNALIGNED_WORD(++p) ==
3897                   TDEFL_READ_UNALIGNED_WORD(++q)) &&
3898                  (TDEFL_READ_UNALIGNED_WORD(++p) ==
3899                   TDEFL_READ_UNALIGNED_WORD(++q)) &&
3900                  (TDEFL_READ_UNALIGNED_WORD(++p) ==
3901                   TDEFL_READ_UNALIGNED_WORD(++q)) &&
3902                  (TDEFL_READ_UNALIGNED_WORD(++p) ==
3903                   TDEFL_READ_UNALIGNED_WORD(++q)) &&
3904                  (--probe_len > 0));
3905         cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) +
3906                         (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
3907         if (!probe_len)
3908           cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
3909 
3910         if ((cur_match_len < TDEFL_MIN_MATCH_LEN) ||
3911             ((cur_match_len == TDEFL_MIN_MATCH_LEN) &&
3912              (cur_match_dist >= 8U * 1024U))) {
3913           cur_match_len = 1;
3914           *pLZ_code_buf++ = (mz_uint8)first_trigram;
3915           *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3916           d->m_huff_count[0][(mz_uint8)first_trigram]++;
3917         } else {
3918           mz_uint32 s0, s1;
3919           cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
3920 
3921           MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) &&
3922                     (cur_match_dist >= 1) &&
3923                     (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
3924 
3925           cur_match_dist--;
3926 
3927           pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
3928           *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
3929           pLZ_code_buf += 3;
3930           *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
3931 
3932           s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
3933           s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
3934           d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
3935 
3936           d->m_huff_count[0][s_tdefl_len_sym[cur_match_len -
3937                                              TDEFL_MIN_MATCH_LEN]]++;
3938         }
3939       } else {
3940         *pLZ_code_buf++ = (mz_uint8)first_trigram;
3941         *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3942         d->m_huff_count[0][(mz_uint8)first_trigram]++;
3943       }
3944 
3945       if (--num_flags_left == 0) {
3946         num_flags_left = 8;
3947         pLZ_flags = pLZ_code_buf++;
3948       }
3949 
3950       total_lz_bytes += cur_match_len;
3951       lookahead_pos += cur_match_len;
3952       dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
3953       cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
3954       MZ_ASSERT(lookahead_size >= cur_match_len);
3955       lookahead_size -= cur_match_len;
3956 
3957       if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) {
3958         int n;
3959         d->m_lookahead_pos = lookahead_pos;
3960         d->m_lookahead_size = lookahead_size;
3961         d->m_dict_size = dict_size;
3962         d->m_total_lz_bytes = total_lz_bytes;
3963         d->m_pLZ_code_buf = pLZ_code_buf;
3964         d->m_pLZ_flags = pLZ_flags;
3965         d->m_num_flags_left = num_flags_left;
3966         if ((n = tdefl_flush_block(d, 0)) != 0)
3967           return (n < 0) ? MZ_FALSE : MZ_TRUE;
3968         total_lz_bytes = d->m_total_lz_bytes;
3969         pLZ_code_buf = d->m_pLZ_code_buf;
3970         pLZ_flags = d->m_pLZ_flags;
3971         num_flags_left = d->m_num_flags_left;
3972       }
3973     }
3974 
3975     while (lookahead_size) {
3976       mz_uint8 lit = d->m_dict[cur_pos];
3977 
3978       total_lz_bytes++;
3979       *pLZ_code_buf++ = lit;
3980       *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3981       if (--num_flags_left == 0) {
3982         num_flags_left = 8;
3983         pLZ_flags = pLZ_code_buf++;
3984       }
3985 
3986       d->m_huff_count[0][lit]++;
3987 
3988       lookahead_pos++;
3989       dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
3990       cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
3991       lookahead_size--;
3992 
3993       if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) {
3994         int n;
3995         d->m_lookahead_pos = lookahead_pos;
3996         d->m_lookahead_size = lookahead_size;
3997         d->m_dict_size = dict_size;
3998         d->m_total_lz_bytes = total_lz_bytes;
3999         d->m_pLZ_code_buf = pLZ_code_buf;
4000         d->m_pLZ_flags = pLZ_flags;
4001         d->m_num_flags_left = num_flags_left;
4002         if ((n = tdefl_flush_block(d, 0)) != 0)
4003           return (n < 0) ? MZ_FALSE : MZ_TRUE;
4004         total_lz_bytes = d->m_total_lz_bytes;
4005         pLZ_code_buf = d->m_pLZ_code_buf;
4006         pLZ_flags = d->m_pLZ_flags;
4007         num_flags_left = d->m_num_flags_left;
4008       }
4009     }
4010   }
4011 
4012   d->m_lookahead_pos = lookahead_pos;
4013   d->m_lookahead_size = lookahead_size;
4014   d->m_dict_size = dict_size;
4015   d->m_total_lz_bytes = total_lz_bytes;
4016   d->m_pLZ_code_buf = pLZ_code_buf;
4017   d->m_pLZ_flags = pLZ_flags;
4018   d->m_num_flags_left = num_flags_left;
4019   return MZ_TRUE;
4020 }
4021 #endif  // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
4022 
tdefl_record_literal(tdefl_compressor * d,mz_uint8 lit)4023 static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d,
4024                                                 mz_uint8 lit) {
4025   d->m_total_lz_bytes++;
4026   *d->m_pLZ_code_buf++ = lit;
4027   *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
4028   if (--d->m_num_flags_left == 0) {
4029     d->m_num_flags_left = 8;
4030     d->m_pLZ_flags = d->m_pLZ_code_buf++;
4031   }
4032   d->m_huff_count[0][lit]++;
4033 }
4034 
tdefl_record_match(tdefl_compressor * d,mz_uint match_len,mz_uint match_dist)4035 static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d,
4036                                               mz_uint match_len,
4037                                               mz_uint match_dist) {
4038   mz_uint32 s0, s1;
4039 
4040   MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) &&
4041             (match_dist <= TDEFL_LZ_DICT_SIZE));
4042 
4043   d->m_total_lz_bytes += match_len;
4044 
4045   d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
4046 
4047   match_dist -= 1;
4048   d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
4049   d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
4050   d->m_pLZ_code_buf += 3;
4051 
4052   *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
4053   if (--d->m_num_flags_left == 0) {
4054     d->m_num_flags_left = 8;
4055     d->m_pLZ_flags = d->m_pLZ_code_buf++;
4056   }
4057 
4058   s0 = s_tdefl_small_dist_sym[match_dist & 511];
4059   s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
4060   d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
4061 
4062   if (match_len >= TDEFL_MIN_MATCH_LEN)
4063     d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
4064 }
4065 
tdefl_compress_normal(tdefl_compressor * d)4066 static mz_bool tdefl_compress_normal(tdefl_compressor *d) {
4067   const mz_uint8 *pSrc = d->m_pSrc;
4068   size_t src_buf_left = d->m_src_buf_left;
4069   tdefl_flush flush = d->m_flush;
4070 
4071   while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) {
4072     mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
4073     // Update dictionary and hash chains. Keeps the lookahead size equal to
4074     // TDEFL_MAX_MATCH_LEN.
4075     if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) {
4076       mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) &
4077                         TDEFL_LZ_DICT_SIZE_MASK,
4078               ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
4079       mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK]
4080                       << TDEFL_LZ_HASH_SHIFT) ^
4081                      d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
4082       mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(
4083           src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
4084       const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
4085       src_buf_left -= num_bytes_to_process;
4086       d->m_lookahead_size += num_bytes_to_process;
4087       while (pSrc != pSrc_end) {
4088         mz_uint8 c = *pSrc++;
4089         d->m_dict[dst_pos] = c;
4090         if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
4091           d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
4092         hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
4093         d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
4094         d->m_hash[hash] = (mz_uint16)(ins_pos);
4095         dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
4096         ins_pos++;
4097       }
4098     } else {
4099       while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) {
4100         mz_uint8 c = *pSrc++;
4101         mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) &
4102                           TDEFL_LZ_DICT_SIZE_MASK;
4103         src_buf_left--;
4104         d->m_dict[dst_pos] = c;
4105         if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
4106           d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
4107         if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) {
4108           mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
4109           mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK]
4110                            << (TDEFL_LZ_HASH_SHIFT * 2)) ^
4111                           (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]
4112                            << TDEFL_LZ_HASH_SHIFT) ^
4113                           c) &
4114                          (TDEFL_LZ_HASH_SIZE - 1);
4115           d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
4116           d->m_hash[hash] = (mz_uint16)(ins_pos);
4117         }
4118       }
4119     }
4120     d->m_dict_size =
4121         MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
4122     if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) break;
4123 
4124     // Simple lazy/greedy parsing state machine.
4125     len_to_move = 1;
4126     cur_match_dist = 0;
4127     cur_match_len =
4128         d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
4129     cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
4130     if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) {
4131       if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) {
4132         mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
4133         cur_match_len = 0;
4134         while (cur_match_len < d->m_lookahead_size) {
4135           if (d->m_dict[cur_pos + cur_match_len] != c) break;
4136           cur_match_len++;
4137         }
4138         if (cur_match_len < TDEFL_MIN_MATCH_LEN)
4139           cur_match_len = 0;
4140         else
4141           cur_match_dist = 1;
4142       }
4143     } else {
4144       tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size,
4145                        d->m_lookahead_size, &cur_match_dist, &cur_match_len);
4146     }
4147     if (((cur_match_len == TDEFL_MIN_MATCH_LEN) &&
4148          (cur_match_dist >= 8U * 1024U)) ||
4149         (cur_pos == cur_match_dist) ||
4150         ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) {
4151       cur_match_dist = cur_match_len = 0;
4152     }
4153     if (d->m_saved_match_len) {
4154       if (cur_match_len > d->m_saved_match_len) {
4155         tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
4156         if (cur_match_len >= 128) {
4157           tdefl_record_match(d, cur_match_len, cur_match_dist);
4158           d->m_saved_match_len = 0;
4159           len_to_move = cur_match_len;
4160         } else {
4161           d->m_saved_lit = d->m_dict[cur_pos];
4162           d->m_saved_match_dist = cur_match_dist;
4163           d->m_saved_match_len = cur_match_len;
4164         }
4165       } else {
4166         tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
4167         len_to_move = d->m_saved_match_len - 1;
4168         d->m_saved_match_len = 0;
4169       }
4170     } else if (!cur_match_dist)
4171       tdefl_record_literal(d,
4172                            d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
4173     else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) ||
4174              (cur_match_len >= 128)) {
4175       tdefl_record_match(d, cur_match_len, cur_match_dist);
4176       len_to_move = cur_match_len;
4177     } else {
4178       d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
4179       d->m_saved_match_dist = cur_match_dist;
4180       d->m_saved_match_len = cur_match_len;
4181     }
4182     // Move the lookahead forward by len_to_move bytes.
4183     d->m_lookahead_pos += len_to_move;
4184     MZ_ASSERT(d->m_lookahead_size >= len_to_move);
4185     d->m_lookahead_size -= len_to_move;
4186     d->m_dict_size =
4187         MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE);
4188     // Check if it's time to flush the current LZ codes to the internal output
4189     // buffer.
4190     if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
4191         ((d->m_total_lz_bytes > 31 * 1024) &&
4192          (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >=
4193            d->m_total_lz_bytes) ||
4194           (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) {
4195       int n;
4196       d->m_pSrc = pSrc;
4197       d->m_src_buf_left = src_buf_left;
4198       if ((n = tdefl_flush_block(d, 0)) != 0)
4199         return (n < 0) ? MZ_FALSE : MZ_TRUE;
4200     }
4201   }
4202 
4203   d->m_pSrc = pSrc;
4204   d->m_src_buf_left = src_buf_left;
4205   return MZ_TRUE;
4206 }
4207 
tdefl_flush_output_buffer(tdefl_compressor * d)4208 static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) {
4209   if (d->m_pIn_buf_size) {
4210     *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
4211   }
4212 
4213   if (d->m_pOut_buf_size) {
4214     size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs,
4215                       d->m_output_flush_remaining);
4216     memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs,
4217            d->m_output_buf + d->m_output_flush_ofs, n);
4218     d->m_output_flush_ofs += (mz_uint)n;
4219     d->m_output_flush_remaining -= (mz_uint)n;
4220     d->m_out_buf_ofs += n;
4221 
4222     *d->m_pOut_buf_size = d->m_out_buf_ofs;
4223   }
4224 
4225   return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE
4226                                                          : TDEFL_STATUS_OKAY;
4227 }
4228 
tdefl_compress(tdefl_compressor * d,const void * pIn_buf,size_t * pIn_buf_size,void * pOut_buf,size_t * pOut_buf_size,tdefl_flush flush)4229 tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf,
4230                             size_t *pIn_buf_size, void *pOut_buf,
4231                             size_t *pOut_buf_size, tdefl_flush flush) {
4232   if (!d) {
4233     if (pIn_buf_size) *pIn_buf_size = 0;
4234     if (pOut_buf_size) *pOut_buf_size = 0;
4235     return TDEFL_STATUS_BAD_PARAM;
4236   }
4237 
4238   d->m_pIn_buf = pIn_buf;
4239   d->m_pIn_buf_size = pIn_buf_size;
4240   d->m_pOut_buf = pOut_buf;
4241   d->m_pOut_buf_size = pOut_buf_size;
4242   d->m_pSrc = (const mz_uint8 *)(pIn_buf);
4243   d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
4244   d->m_out_buf_ofs = 0;
4245   d->m_flush = flush;
4246 
4247   if (((d->m_pPut_buf_func != NULL) ==
4248        ((pOut_buf != NULL) || (pOut_buf_size != NULL))) ||
4249       (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
4250       (d->m_wants_to_finish && (flush != TDEFL_FINISH)) ||
4251       (pIn_buf_size && *pIn_buf_size && !pIn_buf) ||
4252       (pOut_buf_size && *pOut_buf_size && !pOut_buf)) {
4253     if (pIn_buf_size) *pIn_buf_size = 0;
4254     if (pOut_buf_size) *pOut_buf_size = 0;
4255     return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
4256   }
4257   d->m_wants_to_finish |= (flush == TDEFL_FINISH);
4258 
4259   if ((d->m_output_flush_remaining) || (d->m_finished))
4260     return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
4261 
4262 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
4263   if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
4264       ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
4265       ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS |
4266                       TDEFL_RLE_MATCHES)) == 0)) {
4267     if (!tdefl_compress_fast(d)) return d->m_prev_return_status;
4268   } else
4269 #endif  // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
4270   {
4271     if (!tdefl_compress_normal(d)) return d->m_prev_return_status;
4272   }
4273 
4274   if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) &&
4275       (pIn_buf))
4276     d->m_adler32 =
4277         (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf,
4278                               d->m_pSrc - (const mz_uint8 *)pIn_buf);
4279 
4280   if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) &&
4281       (!d->m_output_flush_remaining)) {
4282     if (tdefl_flush_block(d, flush) < 0) return d->m_prev_return_status;
4283     d->m_finished = (flush == TDEFL_FINISH);
4284     if (flush == TDEFL_FULL_FLUSH) {
4285       MZ_CLEAR_OBJ(d->m_hash);
4286       MZ_CLEAR_OBJ(d->m_next);
4287       d->m_dict_size = 0;
4288     }
4289   }
4290 
4291   return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
4292 }
4293 
tdefl_compress_buffer(tdefl_compressor * d,const void * pIn_buf,size_t in_buf_size,tdefl_flush flush)4294 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf,
4295                                    size_t in_buf_size, tdefl_flush flush) {
4296   MZ_ASSERT(d->m_pPut_buf_func);
4297   return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
4298 }
4299 
tdefl_init(tdefl_compressor * d,tdefl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)4300 tdefl_status tdefl_init(tdefl_compressor *d,
4301                         tdefl_put_buf_func_ptr pPut_buf_func,
4302                         void *pPut_buf_user, int flags) {
4303   d->m_pPut_buf_func = pPut_buf_func;
4304   d->m_pPut_buf_user = pPut_buf_user;
4305   d->m_flags = (mz_uint)(flags);
4306   d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
4307   d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
4308   d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
4309   if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash);
4310   d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size =
4311       d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
4312   d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished =
4313       d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
4314   d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
4315   d->m_pLZ_flags = d->m_lz_code_buf;
4316   d->m_num_flags_left = 8;
4317   d->m_pOutput_buf = d->m_output_buf;
4318   d->m_pOutput_buf_end = d->m_output_buf;
4319   d->m_prev_return_status = TDEFL_STATUS_OKAY;
4320   d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
4321   d->m_adler32 = 1;
4322   d->m_pIn_buf = NULL;
4323   d->m_pOut_buf = NULL;
4324   d->m_pIn_buf_size = NULL;
4325   d->m_pOut_buf_size = NULL;
4326   d->m_flush = TDEFL_NO_FLUSH;
4327   d->m_pSrc = NULL;
4328   d->m_src_buf_left = 0;
4329   d->m_out_buf_ofs = 0;
4330   memset(&d->m_huff_count[0][0], 0,
4331          sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
4332   memset(&d->m_huff_count[1][0], 0,
4333          sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
4334   return TDEFL_STATUS_OKAY;
4335 }
4336 
tdefl_get_prev_return_status(tdefl_compressor * d)4337 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) {
4338   return d->m_prev_return_status;
4339 }
4340 
tdefl_get_adler32(tdefl_compressor * d)4341 mz_uint32 tdefl_get_adler32(tdefl_compressor *d) { return d->m_adler32; }
4342 
tdefl_compress_mem_to_output(const void * pBuf,size_t buf_len,tdefl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)4343 mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len,
4344                                      tdefl_put_buf_func_ptr pPut_buf_func,
4345                                      void *pPut_buf_user, int flags) {
4346   tdefl_compressor *pComp;
4347   mz_bool succeeded;
4348   if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE;
4349   pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
4350   if (!pComp) return MZ_FALSE;
4351   succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) ==
4352                TDEFL_STATUS_OKAY);
4353   succeeded =
4354       succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) ==
4355                     TDEFL_STATUS_DONE);
4356   MZ_FREE(pComp);
4357   return succeeded;
4358 }
4359 
4360 typedef struct {
4361   size_t m_size, m_capacity;
4362   mz_uint8 *m_pBuf;
4363   mz_bool m_expandable;
4364 } tdefl_output_buffer;
4365 
tdefl_output_buffer_putter(const void * pBuf,int len,void * pUser)4366 static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len,
4367                                           void *pUser) {
4368   tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
4369   size_t new_size = p->m_size + len;
4370   if (new_size > p->m_capacity) {
4371     size_t new_capacity = p->m_capacity;
4372     mz_uint8 *pNew_buf;
4373     if (!p->m_expandable) return MZ_FALSE;
4374     do {
4375       new_capacity = MZ_MAX(128U, new_capacity << 1U);
4376     } while (new_size > new_capacity);
4377     pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
4378     if (!pNew_buf) return MZ_FALSE;
4379     p->m_pBuf = pNew_buf;
4380     p->m_capacity = new_capacity;
4381   }
4382   memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
4383   p->m_size = new_size;
4384   return MZ_TRUE;
4385 }
4386 
tdefl_compress_mem_to_heap(const void * pSrc_buf,size_t src_buf_len,size_t * pOut_len,int flags)4387 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
4388                                  size_t *pOut_len, int flags) {
4389   tdefl_output_buffer out_buf;
4390   MZ_CLEAR_OBJ(out_buf);
4391   if (!pOut_len)
4392     return MZ_FALSE;
4393   else
4394     *pOut_len = 0;
4395   out_buf.m_expandable = MZ_TRUE;
4396   if (!tdefl_compress_mem_to_output(
4397           pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
4398     return NULL;
4399   *pOut_len = out_buf.m_size;
4400   return out_buf.m_pBuf;
4401 }
4402 
tdefl_compress_mem_to_mem(void * pOut_buf,size_t out_buf_len,const void * pSrc_buf,size_t src_buf_len,int flags)4403 size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
4404                                  const void *pSrc_buf, size_t src_buf_len,
4405                                  int flags) {
4406   tdefl_output_buffer out_buf;
4407   MZ_CLEAR_OBJ(out_buf);
4408   if (!pOut_buf) return 0;
4409   out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
4410   out_buf.m_capacity = out_buf_len;
4411   if (!tdefl_compress_mem_to_output(
4412           pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
4413     return 0;
4414   return out_buf.m_size;
4415 }
4416 
4417 #ifndef MINIZ_NO_ZLIB_APIS
4418 static const mz_uint s_tdefl_num_probes[11] = {0,   1,   6,   32,  16,  32,
4419                                                128, 256, 512, 768, 1500};
4420 
4421 // level may actually range from [0,10] (10 is a "hidden" max level, where we
4422 // want a bit more compression and it's fine if throughput to fall off a cliff
4423 // on some files).
tdefl_create_comp_flags_from_zip_params(int level,int window_bits,int strategy)4424 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
4425                                                 int strategy) {
4426   mz_uint comp_flags =
4427       s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] |
4428       ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
4429   if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
4430 
4431   if (!level)
4432     comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
4433   else if (strategy == MZ_FILTERED)
4434     comp_flags |= TDEFL_FILTER_MATCHES;
4435   else if (strategy == MZ_HUFFMAN_ONLY)
4436     comp_flags &= ~TDEFL_MAX_PROBES_MASK;
4437   else if (strategy == MZ_FIXED)
4438     comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
4439   else if (strategy == MZ_RLE)
4440     comp_flags |= TDEFL_RLE_MATCHES;
4441 
4442   return comp_flags;
4443 }
4444 #endif  // MINIZ_NO_ZLIB_APIS
4445 
4446 #ifdef _MSC_VER
4447 #pragma warning(push)
4448 #pragma warning(disable : 4204)  // nonstandard extension used : non-constant
4449                                  // aggregate initializer (also supported by GNU
4450                                  // C and C99, so no big deal)
4451 #pragma warning(disable : 4244)  // 'initializing': conversion from '__int64' to
4452                                  // 'int', possible loss of data
4453 #pragma warning(disable : 4267)  // 'argument': conversion from '__int64' to
4454                                  // 'int', possible loss of data
4455 #pragma warning(disable : 4996)  // 'strdup': The POSIX name for this item is
4456                                  // deprecated. Instead, use the ISO C and C++
4457                                  // conformant name: _strdup.
4458 #endif
4459 
4460 // Simple PNG writer function by Alex Evans, 2011. Released into the public
4461 // domain: https://gist.github.com/908299, more context at
4462 // http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
4463 // This is actually a modification of Alex's original code so PNG files
4464 // generated by this function pass pngcheck.
tdefl_write_image_to_png_file_in_memory_ex(const void * pImage,int w,int h,int num_chans,size_t * pLen_out,mz_uint level,mz_bool flip)4465 void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w,
4466                                                  int h, int num_chans,
4467                                                  size_t *pLen_out,
4468                                                  mz_uint level, mz_bool flip) {
4469   // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was
4470   // defined.
4471   static const mz_uint s_tdefl_png_num_probes[11] = {
4472       0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500};
4473   tdefl_compressor *pComp =
4474       (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
4475   tdefl_output_buffer out_buf;
4476   int i, bpl = w * num_chans, y, z;
4477   mz_uint32 c;
4478   *pLen_out = 0;
4479   if (!pComp) return NULL;
4480   MZ_CLEAR_OBJ(out_buf);
4481   out_buf.m_expandable = MZ_TRUE;
4482   out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
4483   if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity))) {
4484     MZ_FREE(pComp);
4485     return NULL;
4486   }
4487   // write dummy header
4488   for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf);
4489   // compress image data
4490   tdefl_init(
4491       pComp, tdefl_output_buffer_putter, &out_buf,
4492       s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
4493   for (y = 0; y < h; ++y) {
4494     tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
4495     tdefl_compress_buffer(pComp,
4496                           (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl,
4497                           bpl, TDEFL_NO_FLUSH);
4498   }
4499   if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) !=
4500       TDEFL_STATUS_DONE) {
4501     MZ_FREE(pComp);
4502     MZ_FREE(out_buf.m_pBuf);
4503     return NULL;
4504   }
4505   // write real header
4506   *pLen_out = out_buf.m_size - 41;
4507   {
4508     static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06};
4509     mz_uint8 pnghdr[41] = {0x89,
4510                            0x50,
4511                            0x4e,
4512                            0x47,
4513                            0x0d,
4514                            0x0a,
4515                            0x1a,
4516                            0x0a,
4517                            0x00,
4518                            0x00,
4519                            0x00,
4520                            0x0d,
4521                            0x49,
4522                            0x48,
4523                            0x44,
4524                            0x52,
4525                            0,
4526                            0,
4527                            (mz_uint8)(w >> 8),
4528                            (mz_uint8)w,
4529                            0,
4530                            0,
4531                            (mz_uint8)(h >> 8),
4532                            (mz_uint8)h,
4533                            8,
4534                            chans[num_chans],
4535                            0,
4536                            0,
4537                            0,
4538                            0,
4539                            0,
4540                            0,
4541                            0,
4542                            (mz_uint8)(*pLen_out >> 24),
4543                            (mz_uint8)(*pLen_out >> 16),
4544                            (mz_uint8)(*pLen_out >> 8),
4545                            (mz_uint8)*pLen_out,
4546                            0x49,
4547                            0x44,
4548                            0x41,
4549                            0x54};
4550     c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
4551     for (i = 0; i < 4; ++i, c <<= 8)
4552       ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
4553     memcpy(out_buf.m_pBuf, pnghdr, 41);
4554   }
4555   // write footer (IDAT CRC-32, followed by IEND chunk)
4556   if (!tdefl_output_buffer_putter(
4557           "\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) {
4558     *pLen_out = 0;
4559     MZ_FREE(pComp);
4560     MZ_FREE(out_buf.m_pBuf);
4561     return NULL;
4562   }
4563   c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4,
4564                           *pLen_out + 4);
4565   for (i = 0; i < 4; ++i, c <<= 8)
4566     (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
4567   // compute final size of file, grab compressed data buffer and return
4568   *pLen_out += 57;
4569   MZ_FREE(pComp);
4570   return out_buf.m_pBuf;
4571 }
tdefl_write_image_to_png_file_in_memory(const void * pImage,int w,int h,int num_chans,size_t * pLen_out)4572 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
4573                                               int num_chans, size_t *pLen_out) {
4574   // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we
4575   // can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's
4576   // where #defined out)
4577   return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans,
4578                                                     pLen_out, 6, MZ_FALSE);
4579 }
4580 
4581 // ------------------- .ZIP archive reading
4582 
4583 #ifndef MINIZ_NO_ARCHIVE_APIS
4584 #error "No arvhive APIs"
4585 
4586 #ifdef MINIZ_NO_STDIO
4587 #define MZ_FILE void *
4588 #else
4589 #include <stdio.h>
4590 #include <sys/stat.h>
4591 
4592 #if defined(_MSC_VER) || defined(__MINGW64__)
mz_fopen(const char * pFilename,const char * pMode)4593 static FILE *mz_fopen(const char *pFilename, const char *pMode) {
4594   FILE *pFile = NULL;
4595   fopen_s(&pFile, pFilename, pMode);
4596   return pFile;
4597 }
mz_freopen(const char * pPath,const char * pMode,FILE * pStream)4598 static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
4599   FILE *pFile = NULL;
4600   if (freopen_s(&pFile, pPath, pMode, pStream)) return NULL;
4601   return pFile;
4602 }
4603 #ifndef MINIZ_NO_TIME
4604 #include <sys/utime.h>
4605 #endif
4606 #define MZ_FILE FILE
4607 #define MZ_FOPEN mz_fopen
4608 #define MZ_FCLOSE fclose
4609 #define MZ_FREAD fread
4610 #define MZ_FWRITE fwrite
4611 #define MZ_FTELL64 _ftelli64
4612 #define MZ_FSEEK64 _fseeki64
4613 #define MZ_FILE_STAT_STRUCT _stat
4614 #define MZ_FILE_STAT _stat
4615 #define MZ_FFLUSH fflush
4616 #define MZ_FREOPEN mz_freopen
4617 #define MZ_DELETE_FILE remove
4618 #elif defined(__MINGW32__)
4619 #ifndef MINIZ_NO_TIME
4620 #include <sys/utime.h>
4621 #endif
4622 #define MZ_FILE FILE
4623 #define MZ_FOPEN(f, m) fopen(f, m)
4624 #define MZ_FCLOSE fclose
4625 #define MZ_FREAD fread
4626 #define MZ_FWRITE fwrite
4627 #define MZ_FTELL64 ftello64
4628 #define MZ_FSEEK64 fseeko64
4629 #define MZ_FILE_STAT_STRUCT _stat
4630 #define MZ_FILE_STAT _stat
4631 #define MZ_FFLUSH fflush
4632 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4633 #define MZ_DELETE_FILE remove
4634 #elif defined(__TINYC__)
4635 #ifndef MINIZ_NO_TIME
4636 #include <sys/utime.h>
4637 #endif
4638 #define MZ_FILE FILE
4639 #define MZ_FOPEN(f, m) fopen(f, m)
4640 #define MZ_FCLOSE fclose
4641 #define MZ_FREAD fread
4642 #define MZ_FWRITE fwrite
4643 #define MZ_FTELL64 ftell
4644 #define MZ_FSEEK64 fseek
4645 #define MZ_FILE_STAT_STRUCT stat
4646 #define MZ_FILE_STAT stat
4647 #define MZ_FFLUSH fflush
4648 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4649 #define MZ_DELETE_FILE remove
4650 #elif defined(__GNUC__) && defined(_LARGEFILE64_SOURCE) && _LARGEFILE64_SOURCE
4651 #ifndef MINIZ_NO_TIME
4652 #include <utime.h>
4653 #endif
4654 #define MZ_FILE FILE
4655 #define MZ_FOPEN(f, m) fopen64(f, m)
4656 #define MZ_FCLOSE fclose
4657 #define MZ_FREAD fread
4658 #define MZ_FWRITE fwrite
4659 #define MZ_FTELL64 ftello64
4660 #define MZ_FSEEK64 fseeko64
4661 #define MZ_FILE_STAT_STRUCT stat64
4662 #define MZ_FILE_STAT stat64
4663 #define MZ_FFLUSH fflush
4664 #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
4665 #define MZ_DELETE_FILE remove
4666 #else
4667 #ifndef MINIZ_NO_TIME
4668 #include <utime.h>
4669 #endif
4670 #define MZ_FILE FILE
4671 #define MZ_FOPEN(f, m) fopen(f, m)
4672 #define MZ_FCLOSE fclose
4673 #define MZ_FREAD fread
4674 #define MZ_FWRITE fwrite
4675 #define MZ_FTELL64 ftello
4676 #define MZ_FSEEK64 fseeko
4677 #define MZ_FILE_STAT_STRUCT stat
4678 #define MZ_FILE_STAT stat
4679 #define MZ_FFLUSH fflush
4680 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4681 #define MZ_DELETE_FILE remove
4682 #endif  // #ifdef _MSC_VER
4683 #endif  // #ifdef MINIZ_NO_STDIO
4684 
4685 #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
4686 
4687 // Various ZIP archive enums. To completely avoid cross platform compiler
4688 // alignment and platform endian issues, miniz.c doesn't use structs for any of
4689 // this stuff.
4690 enum {
4691   // ZIP archive identifiers and record sizes
4692   MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
4693   MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
4694   MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
4695   MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
4696   MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
4697   MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
4698   // Central directory header record offsets
4699   MZ_ZIP_CDH_SIG_OFS = 0,
4700   MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
4701   MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
4702   MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
4703   MZ_ZIP_CDH_METHOD_OFS = 10,
4704   MZ_ZIP_CDH_FILE_TIME_OFS = 12,
4705   MZ_ZIP_CDH_FILE_DATE_OFS = 14,
4706   MZ_ZIP_CDH_CRC32_OFS = 16,
4707   MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
4708   MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
4709   MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
4710   MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
4711   MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
4712   MZ_ZIP_CDH_DISK_START_OFS = 34,
4713   MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
4714   MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
4715   MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
4716   // Local directory header offsets
4717   MZ_ZIP_LDH_SIG_OFS = 0,
4718   MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
4719   MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
4720   MZ_ZIP_LDH_METHOD_OFS = 8,
4721   MZ_ZIP_LDH_FILE_TIME_OFS = 10,
4722   MZ_ZIP_LDH_FILE_DATE_OFS = 12,
4723   MZ_ZIP_LDH_CRC32_OFS = 14,
4724   MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
4725   MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
4726   MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
4727   MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
4728   // End of central directory offsets
4729   MZ_ZIP_ECDH_SIG_OFS = 0,
4730   MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
4731   MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
4732   MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
4733   MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
4734   MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
4735   MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
4736   MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
4737 };
4738 
4739 typedef struct {
4740   void *m_p;
4741   size_t m_size, m_capacity;
4742   mz_uint m_element_size;
4743 } mz_zip_array;
4744 
4745 struct mz_zip_internal_state_tag {
4746   mz_zip_array m_central_dir;
4747   mz_zip_array m_central_dir_offsets;
4748   mz_zip_array m_sorted_central_dir_offsets;
4749   MZ_FILE *m_pFile;
4750   void *m_pMem;
4751   size_t m_mem_size;
4752   size_t m_mem_capacity;
4753 };
4754 
4755 #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) \
4756   (array_ptr)->m_element_size = element_size
4757 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) \
4758   ((element_type *)((array_ptr)->m_p))[index]
4759 
mz_zip_array_clear(mz_zip_archive * pZip,mz_zip_array * pArray)4760 static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip,
4761                                               mz_zip_array *pArray) {
4762   pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
4763   memset(pArray, 0, sizeof(mz_zip_array));
4764 }
4765 
mz_zip_array_ensure_capacity(mz_zip_archive * pZip,mz_zip_array * pArray,size_t min_new_capacity,mz_uint growing)4766 static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip,
4767                                             mz_zip_array *pArray,
4768                                             size_t min_new_capacity,
4769                                             mz_uint growing) {
4770   void *pNew_p;
4771   size_t new_capacity = min_new_capacity;
4772   MZ_ASSERT(pArray->m_element_size);
4773   if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE;
4774   if (growing) {
4775     new_capacity = MZ_MAX(1, pArray->m_capacity);
4776     while (new_capacity < min_new_capacity) new_capacity *= 2;
4777   }
4778   if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p,
4779                                          pArray->m_element_size, new_capacity)))
4780     return MZ_FALSE;
4781   pArray->m_p = pNew_p;
4782   pArray->m_capacity = new_capacity;
4783   return MZ_TRUE;
4784 }
4785 
mz_zip_array_reserve(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_capacity,mz_uint growing)4786 static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip,
4787                                                    mz_zip_array *pArray,
4788                                                    size_t new_capacity,
4789                                                    mz_uint growing) {
4790   if (new_capacity > pArray->m_capacity) {
4791     if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
4792       return MZ_FALSE;
4793   }
4794   return MZ_TRUE;
4795 }
4796 
mz_zip_array_resize(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_size,mz_uint growing)4797 static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip,
4798                                                   mz_zip_array *pArray,
4799                                                   size_t new_size,
4800                                                   mz_uint growing) {
4801   if (new_size > pArray->m_capacity) {
4802     if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
4803       return MZ_FALSE;
4804   }
4805   pArray->m_size = new_size;
4806   return MZ_TRUE;
4807 }
4808 
mz_zip_array_ensure_room(mz_zip_archive * pZip,mz_zip_array * pArray,size_t n)4809 static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip,
4810                                                        mz_zip_array *pArray,
4811                                                        size_t n) {
4812   return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
4813 }
4814 
mz_zip_array_push_back(mz_zip_archive * pZip,mz_zip_array * pArray,const void * pElements,size_t n)4815 static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip,
4816                                                      mz_zip_array *pArray,
4817                                                      const void *pElements,
4818                                                      size_t n) {
4819   size_t orig_size = pArray->m_size;
4820   if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
4821     return MZ_FALSE;
4822   memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size,
4823          pElements, n * pArray->m_element_size);
4824   return MZ_TRUE;
4825 }
4826 
4827 #ifndef MINIZ_NO_TIME
mz_zip_dos_to_time_t(int dos_time,int dos_date)4828 static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) {
4829   struct tm tm;
4830   memset(&tm, 0, sizeof(tm));
4831   tm.tm_isdst = -1;
4832   tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
4833   tm.tm_mon = ((dos_date >> 5) & 15) - 1;
4834   tm.tm_mday = dos_date & 31;
4835   tm.tm_hour = (dos_time >> 11) & 31;
4836   tm.tm_min = (dos_time >> 5) & 63;
4837   tm.tm_sec = (dos_time << 1) & 62;
4838   return mktime(&tm);
4839 }
4840 
mz_zip_time_to_dos_time(time_t time,mz_uint16 * pDOS_time,mz_uint16 * pDOS_date)4841 static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time,
4842                                     mz_uint16 *pDOS_date) {
4843 #ifdef _MSC_VER
4844   struct tm tm_struct;
4845   struct tm *tm = &tm_struct;
4846   errno_t err = localtime_s(tm, &time);
4847   if (err) {
4848     *pDOS_date = 0;
4849     *pDOS_time = 0;
4850     return;
4851   }
4852 #else
4853   struct tm *tm = localtime(&time);
4854 #endif
4855   *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) +
4856                            ((tm->tm_sec) >> 1));
4857   *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) +
4858                            ((tm->tm_mon + 1) << 5) + tm->tm_mday);
4859 }
4860 #endif
4861 
4862 #ifndef MINIZ_NO_STDIO
mz_zip_get_file_modified_time(const char * pFilename,mz_uint16 * pDOS_time,mz_uint16 * pDOS_date)4863 static mz_bool mz_zip_get_file_modified_time(const char *pFilename,
4864                                              mz_uint16 *pDOS_time,
4865                                              mz_uint16 *pDOS_date) {
4866 #ifdef MINIZ_NO_TIME
4867   (void)pFilename;
4868   *pDOS_date = *pDOS_time = 0;
4869 #else
4870   struct MZ_FILE_STAT_STRUCT file_stat;
4871   // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000
4872   // bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh.
4873   if (MZ_FILE_STAT(pFilename, &file_stat) != 0) return MZ_FALSE;
4874   mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date);
4875 #endif  // #ifdef MINIZ_NO_TIME
4876   return MZ_TRUE;
4877 }
4878 
4879 #ifndef MINIZ_NO_TIME
mz_zip_set_file_times(const char * pFilename,time_t access_time,time_t modified_time)4880 static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time,
4881                                      time_t modified_time) {
4882   struct utimbuf t;
4883   t.actime = access_time;
4884   t.modtime = modified_time;
4885   return !utime(pFilename, &t);
4886 }
4887 #endif  // #ifndef MINIZ_NO_TIME
4888 #endif  // #ifndef MINIZ_NO_STDIO
4889 
mz_zip_reader_init_internal(mz_zip_archive * pZip,mz_uint32 flags)4890 static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip,
4891                                            mz_uint32 flags) {
4892   (void)flags;
4893   if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
4894     return MZ_FALSE;
4895 
4896   if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
4897   if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
4898   if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
4899 
4900   pZip->m_zip_mode = MZ_ZIP_MODE_READING;
4901   pZip->m_archive_size = 0;
4902   pZip->m_central_directory_file_ofs = 0;
4903   pZip->m_total_files = 0;
4904 
4905   if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
4906                    pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
4907     return MZ_FALSE;
4908   memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
4909   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
4910                                 sizeof(mz_uint8));
4911   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
4912                                 sizeof(mz_uint32));
4913   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
4914                                 sizeof(mz_uint32));
4915   return MZ_TRUE;
4916 }
4917 
4918 static MZ_FORCEINLINE mz_bool
mz_zip_reader_filename_less(const mz_zip_array * pCentral_dir_array,const mz_zip_array * pCentral_dir_offsets,mz_uint l_index,mz_uint r_index)4919 mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array,
4920                             const mz_zip_array *pCentral_dir_offsets,
4921                             mz_uint l_index, mz_uint r_index) {
4922   const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
4923                      pCentral_dir_array, mz_uint8,
4924                      MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
4925                                           l_index)),
4926                  *pE;
4927   const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(
4928       pCentral_dir_array, mz_uint8,
4929       MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
4930   mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS),
4931           r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4932   mz_uint8 l = 0, r = 0;
4933   pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4934   pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4935   pE = pL + MZ_MIN(l_len, r_len);
4936   while (pL < pE) {
4937     if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) break;
4938     pL++;
4939     pR++;
4940   }
4941   return (pL == pE) ? (l_len < r_len) : (l < r);
4942 }
4943 
4944 #define MZ_SWAP_UINT32(a, b) \
4945   do {                       \
4946     mz_uint32 t = a;         \
4947     a = b;                   \
4948     b = t;                   \
4949   }                          \
4950   MZ_MACRO_END
4951 
4952 // Heap sort of lowercased filenames, used to help accelerate plain central
4953 // directory searches by mz_zip_reader_locate_file(). (Could also use qsort(),
4954 // but it could allocate memory.)
mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive * pZip)4955 static void mz_zip_reader_sort_central_dir_offsets_by_filename(
4956     mz_zip_archive *pZip) {
4957   mz_zip_internal_state *pState = pZip->m_pState;
4958   const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4959   const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4960   mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(
4961       &pState->m_sorted_central_dir_offsets, mz_uint32, 0);
4962   const int size = pZip->m_total_files;
4963   int start = (size - 2) >> 1, end;
4964   while (start >= 0) {
4965     int child, root = start;
4966     for (;;) {
4967       if ((child = (root << 1) + 1) >= size) break;
4968       child +=
4969           (((child + 1) < size) &&
4970            (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4971                                         pIndices[child], pIndices[child + 1])));
4972       if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4973                                        pIndices[root], pIndices[child]))
4974         break;
4975       MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
4976       root = child;
4977     }
4978     start--;
4979   }
4980 
4981   end = size - 1;
4982   while (end > 0) {
4983     int child, root = 0;
4984     MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
4985     for (;;) {
4986       if ((child = (root << 1) + 1) >= end) break;
4987       child +=
4988           (((child + 1) < end) &&
4989            mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4990                                        pIndices[child], pIndices[child + 1]));
4991       if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4992                                        pIndices[root], pIndices[child]))
4993         break;
4994       MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
4995       root = child;
4996     }
4997     end--;
4998   }
4999 }
5000 
mz_zip_reader_read_central_dir(mz_zip_archive * pZip,mz_uint32 flags)5001 static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip,
5002                                               mz_uint32 flags) {
5003   mz_uint cdir_size, num_this_disk, cdir_disk_index;
5004   mz_uint64 cdir_ofs;
5005   mz_int64 cur_file_ofs;
5006   const mz_uint8 *p;
5007   mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
5008   mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
5009   mz_bool sort_central_dir =
5010       ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
5011   // Basic sanity checks - reject files which are too small, and check the first
5012   // 4 bytes of the file to make sure a local header is there.
5013   if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
5014     return MZ_FALSE;
5015   // Find the end of central directory record by scanning the file from the end
5016   // towards the beginning.
5017   cur_file_ofs =
5018       MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
5019   for (;;) {
5020     int i,
5021         n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
5022     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
5023       return MZ_FALSE;
5024     for (i = n - 4; i >= 0; --i)
5025       if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) break;
5026     if (i >= 0) {
5027       cur_file_ofs += i;
5028       break;
5029     }
5030     if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >=
5031                             (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
5032       return MZ_FALSE;
5033     cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
5034   }
5035   // Read and verify the end of central directory record.
5036   if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
5037                     MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) !=
5038       MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
5039     return MZ_FALSE;
5040   if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) !=
5041        MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) ||
5042       ((pZip->m_total_files =
5043             MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) !=
5044        MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS)))
5045     return MZ_FALSE;
5046 
5047   num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
5048   cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
5049   if (((num_this_disk | cdir_disk_index) != 0) &&
5050       ((num_this_disk != 1) || (cdir_disk_index != 1)))
5051     return MZ_FALSE;
5052 
5053   if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) <
5054       pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
5055     return MZ_FALSE;
5056 
5057   cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
5058   if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) return MZ_FALSE;
5059 
5060   pZip->m_central_directory_file_ofs = cdir_ofs;
5061 
5062   if (pZip->m_total_files) {
5063     mz_uint i, n;
5064 
5065     // Read the entire central directory into a heap block, and allocate another
5066     // heap block to hold the unsorted central dir file record offsets, and
5067     // another to hold the sorted indices.
5068     if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size,
5069                               MZ_FALSE)) ||
5070         (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets,
5071                               pZip->m_total_files, MZ_FALSE)))
5072       return MZ_FALSE;
5073 
5074     if (sort_central_dir) {
5075       if (!mz_zip_array_resize(pZip,
5076                                &pZip->m_pState->m_sorted_central_dir_offsets,
5077                                pZip->m_total_files, MZ_FALSE))
5078         return MZ_FALSE;
5079     }
5080 
5081     if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs,
5082                       pZip->m_pState->m_central_dir.m_p,
5083                       cdir_size) != cdir_size)
5084       return MZ_FALSE;
5085 
5086     // Now create an index into the central directory file records, do some
5087     // basic sanity checking on each record, and check for zip64 entries (which
5088     // are not yet supported).
5089     p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
5090     for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) {
5091       mz_uint total_header_size, comp_size, decomp_size, disk_index;
5092       if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) ||
5093           (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
5094         return MZ_FALSE;
5095       MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5096                            i) =
5097           (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
5098       if (sort_central_dir)
5099         MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets,
5100                              mz_uint32, i) = i;
5101       comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5102       decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5103       if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) &&
5104            (decomp_size != comp_size)) ||
5105           (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) ||
5106           (comp_size == 0xFFFFFFFF))
5107         return MZ_FALSE;
5108       disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
5109       if ((disk_index != num_this_disk) && (disk_index != 1)) return MZ_FALSE;
5110       if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) +
5111            MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
5112         return MZ_FALSE;
5113       if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5114                                MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
5115                                MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
5116                                MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) >
5117           n)
5118         return MZ_FALSE;
5119       n -= total_header_size;
5120       p += total_header_size;
5121     }
5122   }
5123 
5124   if (sort_central_dir)
5125     mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
5126 
5127   return MZ_TRUE;
5128 }
5129 
mz_zip_reader_init(mz_zip_archive * pZip,mz_uint64 size,mz_uint32 flags)5130 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
5131                            mz_uint32 flags) {
5132   if ((!pZip) || (!pZip->m_pRead)) return MZ_FALSE;
5133   if (!mz_zip_reader_init_internal(pZip, flags)) return MZ_FALSE;
5134   pZip->m_archive_size = size;
5135   if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5136     mz_zip_reader_end(pZip);
5137     return MZ_FALSE;
5138   }
5139   return MZ_TRUE;
5140 }
5141 
mz_zip_mem_read_func(void * pOpaque,mz_uint64 file_ofs,void * pBuf,size_t n)5142 static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs,
5143                                    void *pBuf, size_t n) {
5144   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5145   size_t s = (file_ofs >= pZip->m_archive_size)
5146                  ? 0
5147                  : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
5148   memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
5149   return s;
5150 }
5151 
mz_zip_reader_init_mem(mz_zip_archive * pZip,const void * pMem,size_t size,mz_uint32 flags)5152 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem,
5153                                size_t size, mz_uint32 flags) {
5154   if (!mz_zip_reader_init_internal(pZip, flags)) return MZ_FALSE;
5155   pZip->m_archive_size = size;
5156   pZip->m_pRead = mz_zip_mem_read_func;
5157   pZip->m_pIO_opaque = pZip;
5158 #ifdef __cplusplus
5159   pZip->m_pState->m_pMem = const_cast<void *>(pMem);
5160 #else
5161   pZip->m_pState->m_pMem = (void *)pMem;
5162 #endif
5163   pZip->m_pState->m_mem_size = size;
5164   if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5165     mz_zip_reader_end(pZip);
5166     return MZ_FALSE;
5167   }
5168   return MZ_TRUE;
5169 }
5170 
5171 #ifndef MINIZ_NO_STDIO
mz_zip_file_read_func(void * pOpaque,mz_uint64 file_ofs,void * pBuf,size_t n)5172 static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs,
5173                                     void *pBuf, size_t n) {
5174   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5175   mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5176   if (((mz_int64)file_ofs < 0) ||
5177       (((cur_ofs != (mz_int64)file_ofs)) &&
5178        (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5179     return 0;
5180   return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
5181 }
5182 
mz_zip_reader_init_file(mz_zip_archive * pZip,const char * pFilename,mz_uint32 flags)5183 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename,
5184                                 mz_uint32 flags) {
5185   mz_uint64 file_size;
5186   MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb");
5187   if (!pFile) return MZ_FALSE;
5188   if (MZ_FSEEK64(pFile, 0, SEEK_END)) {
5189     MZ_FCLOSE(pFile);
5190     return MZ_FALSE;
5191   }
5192   file_size = MZ_FTELL64(pFile);
5193   if (!mz_zip_reader_init_internal(pZip, flags)) {
5194     MZ_FCLOSE(pFile);
5195     return MZ_FALSE;
5196   }
5197   pZip->m_pRead = mz_zip_file_read_func;
5198   pZip->m_pIO_opaque = pZip;
5199   pZip->m_pState->m_pFile = pFile;
5200   pZip->m_archive_size = file_size;
5201   if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5202     mz_zip_reader_end(pZip);
5203     return MZ_FALSE;
5204   }
5205   return MZ_TRUE;
5206 }
5207 #endif  // #ifndef MINIZ_NO_STDIO
5208 
mz_zip_reader_get_num_files(mz_zip_archive * pZip)5209 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) {
5210   return pZip ? pZip->m_total_files : 0;
5211 }
5212 
mz_zip_reader_get_cdh(mz_zip_archive * pZip,mz_uint file_index)5213 static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(
5214     mz_zip_archive *pZip, mz_uint file_index) {
5215   if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) ||
5216       (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5217     return NULL;
5218   return &MZ_ZIP_ARRAY_ELEMENT(
5219       &pZip->m_pState->m_central_dir, mz_uint8,
5220       MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5221                            file_index));
5222 }
5223 
mz_zip_reader_is_file_encrypted(mz_zip_archive * pZip,mz_uint file_index)5224 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip,
5225                                         mz_uint file_index) {
5226   mz_uint m_bit_flag;
5227   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5228   if (!p) return MZ_FALSE;
5229   m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
5230   return (m_bit_flag & 1);
5231 }
5232 
mz_zip_reader_is_file_a_directory(mz_zip_archive * pZip,mz_uint file_index)5233 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
5234                                           mz_uint file_index) {
5235   mz_uint filename_len, external_attr;
5236   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5237   if (!p) return MZ_FALSE;
5238 
5239   // First see if the filename ends with a '/' character.
5240   filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5241   if (filename_len) {
5242     if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
5243       return MZ_TRUE;
5244   }
5245 
5246   // Bugfix: This code was also checking if the internal attribute was non-zero,
5247   // which wasn't correct.
5248   // Most/all zip writers (hopefully) set DOS file/directory attributes in the
5249   // low 16-bits, so check for the DOS directory flag and ignore the source OS
5250   // ID in the created by field.
5251   // FIXME: Remove this check? Is it necessary - we already check the filename.
5252   external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
5253   if ((external_attr & 0x10) != 0) return MZ_TRUE;
5254 
5255   return MZ_FALSE;
5256 }
5257 
mz_zip_reader_file_stat(mz_zip_archive * pZip,mz_uint file_index,mz_zip_archive_file_stat * pStat)5258 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
5259                                 mz_zip_archive_file_stat *pStat) {
5260   mz_uint n;
5261   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5262   if ((!p) || (!pStat)) return MZ_FALSE;
5263 
5264   // Unpack the central directory record.
5265   pStat->m_file_index = file_index;
5266   pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(
5267       &pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
5268   pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
5269   pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
5270   pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
5271   pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
5272 #ifndef MINIZ_NO_TIME
5273   pStat->m_time =
5274       mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS),
5275                            MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
5276 #endif
5277   pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
5278   pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5279   pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5280   pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
5281   pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
5282   pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
5283 
5284   // Copy as much of the filename and comment as possible.
5285   n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5286   n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
5287   memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
5288   pStat->m_filename[n] = '\0';
5289 
5290   n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
5291   n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
5292   pStat->m_comment_size = n;
5293   memcpy(pStat->m_comment,
5294          p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5295              MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
5296              MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
5297          n);
5298   pStat->m_comment[n] = '\0';
5299 
5300   return MZ_TRUE;
5301 }
5302 
mz_zip_reader_get_filename(mz_zip_archive * pZip,mz_uint file_index,char * pFilename,mz_uint filename_buf_size)5303 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index,
5304                                    char *pFilename, mz_uint filename_buf_size) {
5305   mz_uint n;
5306   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5307   if (!p) {
5308     if (filename_buf_size) pFilename[0] = '\0';
5309     return 0;
5310   }
5311   n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5312   if (filename_buf_size) {
5313     n = MZ_MIN(n, filename_buf_size - 1);
5314     memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
5315     pFilename[n] = '\0';
5316   }
5317   return n + 1;
5318 }
5319 
mz_zip_reader_string_equal(const char * pA,const char * pB,mz_uint len,mz_uint flags)5320 static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA,
5321                                                          const char *pB,
5322                                                          mz_uint len,
5323                                                          mz_uint flags) {
5324   mz_uint i;
5325   if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) return 0 == memcmp(pA, pB, len);
5326   for (i = 0; i < len; ++i)
5327     if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) return MZ_FALSE;
5328   return MZ_TRUE;
5329 }
5330 
mz_zip_reader_filename_compare(const mz_zip_array * pCentral_dir_array,const mz_zip_array * pCentral_dir_offsets,mz_uint l_index,const char * pR,mz_uint r_len)5331 static MZ_FORCEINLINE int mz_zip_reader_filename_compare(
5332     const mz_zip_array *pCentral_dir_array,
5333     const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR,
5334     mz_uint r_len) {
5335   const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
5336                      pCentral_dir_array, mz_uint8,
5337                      MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
5338                                           l_index)),
5339                  *pE;
5340   mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5341   mz_uint8 l = 0, r = 0;
5342   pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5343   pE = pL + MZ_MIN(l_len, r_len);
5344   while (pL < pE) {
5345     if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) break;
5346     pL++;
5347     pR++;
5348   }
5349   return (pL == pE) ? (int)(l_len - r_len) : (l - r);
5350 }
5351 
mz_zip_reader_locate_file_binary_search(mz_zip_archive * pZip,const char * pFilename)5352 static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip,
5353                                                    const char *pFilename) {
5354   mz_zip_internal_state *pState = pZip->m_pState;
5355   const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
5356   const mz_zip_array *pCentral_dir = &pState->m_central_dir;
5357   mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(
5358       &pState->m_sorted_central_dir_offsets, mz_uint32, 0);
5359   const int size = pZip->m_total_files;
5360   const mz_uint filename_len = (mz_uint)strlen(pFilename);
5361   int l = 0, h = size - 1;
5362   while (l <= h) {
5363     int m = (l + h) >> 1, file_index = pIndices[m],
5364         comp =
5365             mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets,
5366                                            file_index, pFilename, filename_len);
5367     if (!comp)
5368       return file_index;
5369     else if (comp < 0)
5370       l = m + 1;
5371     else
5372       h = m - 1;
5373   }
5374   return -1;
5375 }
5376 
mz_zip_reader_locate_file(mz_zip_archive * pZip,const char * pName,const char * pComment,mz_uint flags)5377 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
5378                               const char *pComment, mz_uint flags) {
5379   mz_uint file_index;
5380   size_t name_len, comment_len;
5381   if ((!pZip) || (!pZip->m_pState) || (!pName) ||
5382       (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5383     return -1;
5384   if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) &&
5385       (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
5386     return mz_zip_reader_locate_file_binary_search(pZip, pName);
5387   name_len = strlen(pName);
5388   if (name_len > 0xFFFF) return -1;
5389   comment_len = pComment ? strlen(pComment) : 0;
5390   if (comment_len > 0xFFFF) return -1;
5391   for (file_index = 0; file_index < pZip->m_total_files; file_index++) {
5392     const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(
5393         &pZip->m_pState->m_central_dir, mz_uint8,
5394         MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5395                              file_index));
5396     mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5397     const char *pFilename =
5398         (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5399     if (filename_len < name_len) continue;
5400     if (comment_len) {
5401       mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS),
5402               file_comment_len =
5403                   MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
5404       const char *pFile_comment = pFilename + filename_len + file_extra_len;
5405       if ((file_comment_len != comment_len) ||
5406           (!mz_zip_reader_string_equal(pComment, pFile_comment,
5407                                        file_comment_len, flags)))
5408         continue;
5409     }
5410     if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) {
5411       int ofs = filename_len - 1;
5412       do {
5413         if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') ||
5414             (pFilename[ofs] == ':'))
5415           break;
5416       } while (--ofs >= 0);
5417       ofs++;
5418       pFilename += ofs;
5419       filename_len -= ofs;
5420     }
5421     if ((filename_len == name_len) &&
5422         (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags)))
5423       return file_index;
5424   }
5425   return -1;
5426 }
5427 
mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive * pZip,mz_uint file_index,void * pBuf,size_t buf_size,mz_uint flags,void * pUser_read_buf,size_t user_read_buf_size)5428 mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
5429                                               mz_uint file_index, void *pBuf,
5430                                               size_t buf_size, mz_uint flags,
5431                                               void *pUser_read_buf,
5432                                               size_t user_read_buf_size) {
5433   int status = TINFL_STATUS_DONE;
5434   mz_uint64 needed_size, cur_file_ofs, comp_remaining,
5435       out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
5436   mz_zip_archive_file_stat file_stat;
5437   void *pRead_buf;
5438   mz_uint32
5439       local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
5440                        sizeof(mz_uint32)];
5441   mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5442   tinfl_decompressor inflator;
5443 
5444   if ((buf_size) && (!pBuf)) return MZ_FALSE;
5445 
5446   if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE;
5447 
5448   // Empty file, or a directory (but not always a directory - I've seen odd zips
5449   // with directories that have compressed data which inflates to 0 bytes)
5450   if (!file_stat.m_comp_size) return MZ_TRUE;
5451 
5452   // Entry is a subdirectory (I've seen old zips with dir entries which have
5453   // compressed deflate data which inflates to 0 bytes, but these entries claim
5454   // to uncompress to 512 bytes in the headers).
5455   // I'm torn how to handle this case - should it fail instead?
5456   if (mz_zip_reader_is_file_a_directory(pZip, file_index)) return MZ_TRUE;
5457 
5458   // Encryption and patch files are not supported.
5459   if (file_stat.m_bit_flag & (1 | 32)) return MZ_FALSE;
5460 
5461   // This function only supports stored and deflate.
5462   if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
5463       (file_stat.m_method != MZ_DEFLATED))
5464     return MZ_FALSE;
5465 
5466   // Ensure supplied output buffer is large enough.
5467   needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size
5468                                                       : file_stat.m_uncomp_size;
5469   if (buf_size < needed_size) return MZ_FALSE;
5470 
5471   // Read and parse the local directory entry.
5472   cur_file_ofs = file_stat.m_local_header_ofs;
5473   if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
5474                     MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
5475       MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5476     return MZ_FALSE;
5477   if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5478     return MZ_FALSE;
5479 
5480   cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
5481                   MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
5482                   MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5483   if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
5484     return MZ_FALSE;
5485 
5486   if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
5487     // The file is stored or the caller has requested the compressed data.
5488     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
5489                       (size_t)needed_size) != needed_size)
5490       return MZ_FALSE;
5491     return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) ||
5492            (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
5493                      (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32);
5494   }
5495 
5496   // Decompress the file either directly from memory or from a file input
5497   // buffer.
5498   tinfl_init(&inflator);
5499 
5500   if (pZip->m_pState->m_pMem) {
5501     // Read directly from the archive in memory.
5502     pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
5503     read_buf_size = read_buf_avail = file_stat.m_comp_size;
5504     comp_remaining = 0;
5505   } else if (pUser_read_buf) {
5506     // Use a user provided read buffer.
5507     if (!user_read_buf_size) return MZ_FALSE;
5508     pRead_buf = (mz_uint8 *)pUser_read_buf;
5509     read_buf_size = user_read_buf_size;
5510     read_buf_avail = 0;
5511     comp_remaining = file_stat.m_comp_size;
5512   } else {
5513     // Temporarily allocate a read buffer.
5514     read_buf_size =
5515         MZ_MIN(file_stat.m_comp_size, (mz_uint)MZ_ZIP_MAX_IO_BUF_SIZE);
5516 #ifdef _MSC_VER
5517     if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
5518         (read_buf_size > 0x7FFFFFFF))
5519 #else
5520     if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
5521 #endif
5522       return MZ_FALSE;
5523     if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5524                                             (size_t)read_buf_size)))
5525       return MZ_FALSE;
5526     read_buf_avail = 0;
5527     comp_remaining = file_stat.m_comp_size;
5528   }
5529 
5530   do {
5531     size_t in_buf_size,
5532         out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
5533     if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
5534       read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5535       if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5536                         (size_t)read_buf_avail) != read_buf_avail) {
5537         status = TINFL_STATUS_FAILED;
5538         break;
5539       }
5540       cur_file_ofs += read_buf_avail;
5541       comp_remaining -= read_buf_avail;
5542       read_buf_ofs = 0;
5543     }
5544     in_buf_size = (size_t)read_buf_avail;
5545     status = tinfl_decompress(
5546         &inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
5547         (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size,
5548         TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF |
5549             (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
5550     read_buf_avail -= in_buf_size;
5551     read_buf_ofs += in_buf_size;
5552     out_buf_ofs += out_buf_size;
5553   } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
5554 
5555   if (status == TINFL_STATUS_DONE) {
5556     // Make sure the entire file was decompressed, and check its CRC.
5557     if ((out_buf_ofs != file_stat.m_uncomp_size) ||
5558         (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
5559                   (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32))
5560       status = TINFL_STATUS_FAILED;
5561   }
5562 
5563   if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
5564     pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
5565 
5566   return status == TINFL_STATUS_DONE;
5567 }
5568 
mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive * pZip,const char * pFilename,void * pBuf,size_t buf_size,mz_uint flags,void * pUser_read_buf,size_t user_read_buf_size)5569 mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(
5570     mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size,
5571     mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) {
5572   int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5573   if (file_index < 0) return MZ_FALSE;
5574   return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
5575                                                flags, pUser_read_buf,
5576                                                user_read_buf_size);
5577 }
5578 
mz_zip_reader_extract_to_mem(mz_zip_archive * pZip,mz_uint file_index,void * pBuf,size_t buf_size,mz_uint flags)5579 mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index,
5580                                      void *pBuf, size_t buf_size,
5581                                      mz_uint flags) {
5582   return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
5583                                                flags, NULL, 0);
5584 }
5585 
mz_zip_reader_extract_file_to_mem(mz_zip_archive * pZip,const char * pFilename,void * pBuf,size_t buf_size,mz_uint flags)5586 mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip,
5587                                           const char *pFilename, void *pBuf,
5588                                           size_t buf_size, mz_uint flags) {
5589   return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf,
5590                                                     buf_size, flags, NULL, 0);
5591 }
5592 
mz_zip_reader_extract_to_heap(mz_zip_archive * pZip,mz_uint file_index,size_t * pSize,mz_uint flags)5593 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
5594                                     size_t *pSize, mz_uint flags) {
5595   mz_uint64 comp_size, uncomp_size, alloc_size;
5596   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5597   void *pBuf;
5598 
5599   if (pSize) *pSize = 0;
5600   if (!p) return NULL;
5601 
5602   comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5603   uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5604 
5605   alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
5606 #ifdef _MSC_VER
5607   if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
5608 #else
5609   if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
5610 #endif
5611     return NULL;
5612   if (NULL ==
5613       (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
5614     return NULL;
5615 
5616   if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size,
5617                                     flags)) {
5618     pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
5619     return NULL;
5620   }
5621 
5622   if (pSize) *pSize = (size_t)alloc_size;
5623   return pBuf;
5624 }
5625 
mz_zip_reader_extract_file_to_heap(mz_zip_archive * pZip,const char * pFilename,size_t * pSize,mz_uint flags)5626 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip,
5627                                          const char *pFilename, size_t *pSize,
5628                                          mz_uint flags) {
5629   int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5630   if (file_index < 0) {
5631     if (pSize) *pSize = 0;
5632     return MZ_FALSE;
5633   }
5634   return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
5635 }
5636 
mz_zip_reader_extract_to_callback(mz_zip_archive * pZip,mz_uint file_index,mz_file_write_func pCallback,void * pOpaque,mz_uint flags)5637 mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
5638                                           mz_uint file_index,
5639                                           mz_file_write_func pCallback,
5640                                           void *pOpaque, mz_uint flags) {
5641   int status = TINFL_STATUS_DONE;
5642   mz_uint file_crc32 = MZ_CRC32_INIT;
5643   mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining,
5644                            out_buf_ofs = 0, cur_file_ofs;
5645   mz_zip_archive_file_stat file_stat;
5646   void *pRead_buf = NULL;
5647   void *pWrite_buf = NULL;
5648   mz_uint32
5649       local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
5650                        sizeof(mz_uint32)];
5651   mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5652 
5653   if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE;
5654 
5655   // Empty file, or a directory (but not always a directory - I've seen odd zips
5656   // with directories that have compressed data which inflates to 0 bytes)
5657   if (!file_stat.m_comp_size) return MZ_TRUE;
5658 
5659   // Entry is a subdirectory (I've seen old zips with dir entries which have
5660   // compressed deflate data which inflates to 0 bytes, but these entries claim
5661   // to uncompress to 512 bytes in the headers).
5662   // I'm torn how to handle this case - should it fail instead?
5663   if (mz_zip_reader_is_file_a_directory(pZip, file_index)) return MZ_TRUE;
5664 
5665   // Encryption and patch files are not supported.
5666   if (file_stat.m_bit_flag & (1 | 32)) return MZ_FALSE;
5667 
5668   // This function only supports stored and deflate.
5669   if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
5670       (file_stat.m_method != MZ_DEFLATED))
5671     return MZ_FALSE;
5672 
5673   // Read and parse the local directory entry.
5674   cur_file_ofs = file_stat.m_local_header_ofs;
5675   if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
5676                     MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
5677       MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5678     return MZ_FALSE;
5679   if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5680     return MZ_FALSE;
5681 
5682   cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
5683                   MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
5684                   MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5685   if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
5686     return MZ_FALSE;
5687 
5688   // Decompress the file either directly from memory or from a file input
5689   // buffer.
5690   if (pZip->m_pState->m_pMem) {
5691     pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
5692     read_buf_size = read_buf_avail = file_stat.m_comp_size;
5693     comp_remaining = 0;
5694   } else {
5695     read_buf_size =
5696         MZ_MIN(file_stat.m_comp_size, (mz_uint)MZ_ZIP_MAX_IO_BUF_SIZE);
5697     if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5698                                             (size_t)read_buf_size)))
5699       return MZ_FALSE;
5700     read_buf_avail = 0;
5701     comp_remaining = file_stat.m_comp_size;
5702   }
5703 
5704   if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
5705     // The file is stored or the caller has requested the compressed data.
5706     if (pZip->m_pState->m_pMem) {
5707 #ifdef _MSC_VER
5708       if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
5709           (file_stat.m_comp_size > 0xFFFFFFFF))
5710 #else
5711       if (((sizeof(size_t) == sizeof(mz_uint32))) &&
5712           (file_stat.m_comp_size > 0xFFFFFFFF))
5713 #endif
5714         return MZ_FALSE;
5715       if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
5716                     (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
5717         status = TINFL_STATUS_FAILED;
5718       else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5719         file_crc32 =
5720             (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf,
5721                                 (size_t)file_stat.m_comp_size);
5722       cur_file_ofs += file_stat.m_comp_size;
5723       out_buf_ofs += file_stat.m_comp_size;
5724       comp_remaining = 0;
5725     } else {
5726       while (comp_remaining) {
5727         read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5728         if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5729                           (size_t)read_buf_avail) != read_buf_avail) {
5730           status = TINFL_STATUS_FAILED;
5731           break;
5732         }
5733 
5734         if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5735           file_crc32 = (mz_uint32)mz_crc32(
5736               file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
5737 
5738         if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
5739                       (size_t)read_buf_avail) != read_buf_avail) {
5740           status = TINFL_STATUS_FAILED;
5741           break;
5742         }
5743         cur_file_ofs += read_buf_avail;
5744         out_buf_ofs += read_buf_avail;
5745         comp_remaining -= read_buf_avail;
5746       }
5747     }
5748   } else {
5749     tinfl_decompressor inflator;
5750     tinfl_init(&inflator);
5751 
5752     if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5753                                              TINFL_LZ_DICT_SIZE)))
5754       status = TINFL_STATUS_FAILED;
5755     else {
5756       do {
5757         mz_uint8 *pWrite_buf_cur =
5758             (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5759         size_t in_buf_size,
5760             out_buf_size =
5761                 TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5762         if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
5763           read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5764           if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5765                             (size_t)read_buf_avail) != read_buf_avail) {
5766             status = TINFL_STATUS_FAILED;
5767             break;
5768           }
5769           cur_file_ofs += read_buf_avail;
5770           comp_remaining -= read_buf_avail;
5771           read_buf_ofs = 0;
5772         }
5773 
5774         in_buf_size = (size_t)read_buf_avail;
5775         status = tinfl_decompress(
5776             &inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
5777             (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size,
5778             comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
5779         read_buf_avail -= in_buf_size;
5780         read_buf_ofs += in_buf_size;
5781 
5782         if (out_buf_size) {
5783           if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) !=
5784               out_buf_size) {
5785             status = TINFL_STATUS_FAILED;
5786             break;
5787           }
5788           file_crc32 =
5789               (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
5790           if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) {
5791             status = TINFL_STATUS_FAILED;
5792             break;
5793           }
5794         }
5795       } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) ||
5796                (status == TINFL_STATUS_HAS_MORE_OUTPUT));
5797     }
5798   }
5799 
5800   if ((status == TINFL_STATUS_DONE) &&
5801       (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) {
5802     // Make sure the entire file was decompressed, and check its CRC.
5803     if ((out_buf_ofs != file_stat.m_uncomp_size) ||
5804         (file_crc32 != file_stat.m_crc32))
5805       status = TINFL_STATUS_FAILED;
5806   }
5807 
5808   if (!pZip->m_pState->m_pMem) pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
5809   if (pWrite_buf) pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
5810 
5811   return status == TINFL_STATUS_DONE;
5812 }
5813 
mz_zip_reader_extract_file_to_callback(mz_zip_archive * pZip,const char * pFilename,mz_file_write_func pCallback,void * pOpaque,mz_uint flags)5814 mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip,
5815                                                const char *pFilename,
5816                                                mz_file_write_func pCallback,
5817                                                void *pOpaque, mz_uint flags) {
5818   int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5819   if (file_index < 0) return MZ_FALSE;
5820   return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque,
5821                                            flags);
5822 }
5823 
5824 #ifndef MINIZ_NO_STDIO
mz_zip_file_write_callback(void * pOpaque,mz_uint64 ofs,const void * pBuf,size_t n)5825 static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs,
5826                                          const void *pBuf, size_t n) {
5827   (void)ofs;
5828   return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5829 }
5830 
mz_zip_reader_extract_to_file(mz_zip_archive * pZip,mz_uint file_index,const char * pDst_filename,mz_uint flags)5831 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
5832                                       const char *pDst_filename,
5833                                       mz_uint flags) {
5834   mz_bool status;
5835   mz_zip_archive_file_stat file_stat;
5836   MZ_FILE *pFile;
5837   if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE;
5838   pFile = MZ_FOPEN(pDst_filename, "wb");
5839   if (!pFile) return MZ_FALSE;
5840   status = mz_zip_reader_extract_to_callback(
5841       pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5842   if (MZ_FCLOSE(pFile) == EOF) return MZ_FALSE;
5843 #ifndef MINIZ_NO_TIME
5844   if (status)
5845     mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5846 #endif
5847   return status;
5848 }
5849 #endif  // #ifndef MINIZ_NO_STDIO
5850 
mz_zip_reader_end(mz_zip_archive * pZip)5851 mz_bool mz_zip_reader_end(mz_zip_archive *pZip) {
5852   if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
5853       (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5854     return MZ_FALSE;
5855 
5856   if (pZip->m_pState) {
5857     mz_zip_internal_state *pState = pZip->m_pState;
5858     pZip->m_pState = NULL;
5859     mz_zip_array_clear(pZip, &pState->m_central_dir);
5860     mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5861     mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5862 
5863 #ifndef MINIZ_NO_STDIO
5864     if (pState->m_pFile) {
5865       MZ_FCLOSE(pState->m_pFile);
5866       pState->m_pFile = NULL;
5867     }
5868 #endif  // #ifndef MINIZ_NO_STDIO
5869 
5870     pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5871   }
5872   pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5873 
5874   return MZ_TRUE;
5875 }
5876 
5877 #ifndef MINIZ_NO_STDIO
mz_zip_reader_extract_file_to_file(mz_zip_archive * pZip,const char * pArchive_filename,const char * pDst_filename,mz_uint flags)5878 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip,
5879                                            const char *pArchive_filename,
5880                                            const char *pDst_filename,
5881                                            mz_uint flags) {
5882   int file_index =
5883       mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags);
5884   if (file_index < 0) return MZ_FALSE;
5885   return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5886 }
5887 #endif
5888 
5889 // ------------------- .ZIP archive writing
5890 
5891 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5892 
mz_write_le16(mz_uint8 * p,mz_uint16 v)5893 static void mz_write_le16(mz_uint8 *p, mz_uint16 v) {
5894   p[0] = (mz_uint8)v;
5895   p[1] = (mz_uint8)(v >> 8);
5896 }
mz_write_le32(mz_uint8 * p,mz_uint32 v)5897 static void mz_write_le32(mz_uint8 *p, mz_uint32 v) {
5898   p[0] = (mz_uint8)v;
5899   p[1] = (mz_uint8)(v >> 8);
5900   p[2] = (mz_uint8)(v >> 16);
5901   p[3] = (mz_uint8)(v >> 24);
5902 }
5903 #define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5904 #define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5905 
mz_zip_writer_init(mz_zip_archive * pZip,mz_uint64 existing_size)5906 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) {
5907   if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) ||
5908       (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5909     return MZ_FALSE;
5910 
5911   if (pZip->m_file_offset_alignment) {
5912     // Ensure user specified file offset alignment is a power of 2.
5913     if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5914       return MZ_FALSE;
5915   }
5916 
5917   if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
5918   if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
5919   if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
5920 
5921   pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5922   pZip->m_archive_size = existing_size;
5923   pZip->m_central_directory_file_ofs = 0;
5924   pZip->m_total_files = 0;
5925 
5926   if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
5927                    pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5928     return MZ_FALSE;
5929   memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5930   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
5931                                 sizeof(mz_uint8));
5932   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
5933                                 sizeof(mz_uint32));
5934   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
5935                                 sizeof(mz_uint32));
5936   return MZ_TRUE;
5937 }
5938 
mz_zip_heap_write_func(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)5939 static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs,
5940                                      const void *pBuf, size_t n) {
5941   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5942   mz_zip_internal_state *pState = pZip->m_pState;
5943   mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5944 #ifdef _MSC_VER
5945   if ((!n) ||
5946       ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
5947 #else
5948   if ((!n) ||
5949       ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
5950 #endif
5951     return 0;
5952   if (new_size > pState->m_mem_capacity) {
5953     void *pNew_block;
5954     size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5955     while (new_capacity < new_size) new_capacity *= 2;
5956     if (NULL == (pNew_block = pZip->m_pRealloc(
5957                      pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5958       return 0;
5959     pState->m_pMem = pNew_block;
5960     pState->m_mem_capacity = new_capacity;
5961   }
5962   memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5963   pState->m_mem_size = (size_t)new_size;
5964   return n;
5965 }
5966 
mz_zip_writer_init_heap(mz_zip_archive * pZip,size_t size_to_reserve_at_beginning,size_t initial_allocation_size)5967 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip,
5968                                 size_t size_to_reserve_at_beginning,
5969                                 size_t initial_allocation_size) {
5970   pZip->m_pWrite = mz_zip_heap_write_func;
5971   pZip->m_pIO_opaque = pZip;
5972   if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) return MZ_FALSE;
5973   if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size,
5974                                              size_to_reserve_at_beginning))) {
5975     if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(
5976                      pZip->m_pAlloc_opaque, 1, initial_allocation_size))) {
5977       mz_zip_writer_end(pZip);
5978       return MZ_FALSE;
5979     }
5980     pZip->m_pState->m_mem_capacity = initial_allocation_size;
5981   }
5982   return MZ_TRUE;
5983 }
5984 
5985 #ifndef MINIZ_NO_STDIO
mz_zip_file_write_func(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)5986 static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs,
5987                                      const void *pBuf, size_t n) {
5988   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5989   mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5990   if (((mz_int64)file_ofs < 0) ||
5991       (((cur_ofs != (mz_int64)file_ofs)) &&
5992        (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5993     return 0;
5994   return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5995 }
5996 
mz_zip_writer_init_file(mz_zip_archive * pZip,const char * pFilename,mz_uint64 size_to_reserve_at_beginning)5997 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename,
5998                                 mz_uint64 size_to_reserve_at_beginning) {
5999   MZ_FILE *pFile;
6000   pZip->m_pWrite = mz_zip_file_write_func;
6001   pZip->m_pIO_opaque = pZip;
6002   if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) return MZ_FALSE;
6003   if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) {
6004     mz_zip_writer_end(pZip);
6005     return MZ_FALSE;
6006   }
6007   pZip->m_pState->m_pFile = pFile;
6008   if (size_to_reserve_at_beginning) {
6009     mz_uint64 cur_ofs = 0;
6010     char buf[4096];
6011     MZ_CLEAR_OBJ(buf);
6012     do {
6013       size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
6014       if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) {
6015         mz_zip_writer_end(pZip);
6016         return MZ_FALSE;
6017       }
6018       cur_ofs += n;
6019       size_to_reserve_at_beginning -= n;
6020     } while (size_to_reserve_at_beginning);
6021   }
6022   return MZ_TRUE;
6023 }
6024 #endif  // #ifndef MINIZ_NO_STDIO
6025 
mz_zip_writer_init_from_reader(mz_zip_archive * pZip,const char * pFilename)6026 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip,
6027                                        const char *pFilename) {
6028   mz_zip_internal_state *pState;
6029   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
6030     return MZ_FALSE;
6031   // No sense in trying to write to an archive that's already at the support max
6032   // size
6033   if ((pZip->m_total_files == 0xFFFF) ||
6034       ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6035         MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
6036     return MZ_FALSE;
6037 
6038   pState = pZip->m_pState;
6039 
6040   if (pState->m_pFile) {
6041 #ifdef MINIZ_NO_STDIO
6042     pFilename;
6043     return MZ_FALSE;
6044 #else
6045     // Archive is being read from stdio - try to reopen as writable.
6046     if (pZip->m_pIO_opaque != pZip) return MZ_FALSE;
6047     if (!pFilename) return MZ_FALSE;
6048     pZip->m_pWrite = mz_zip_file_write_func;
6049     if (NULL ==
6050         (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) {
6051       // The mz_zip_archive is now in a bogus state because pState->m_pFile is
6052       // NULL, so just close it.
6053       mz_zip_reader_end(pZip);
6054       return MZ_FALSE;
6055     }
6056 #endif  // #ifdef MINIZ_NO_STDIO
6057   } else if (pState->m_pMem) {
6058     // Archive lives in a memory block. Assume it's from the heap that we can
6059     // resize using the realloc callback.
6060     if (pZip->m_pIO_opaque != pZip) return MZ_FALSE;
6061     pState->m_mem_capacity = pState->m_mem_size;
6062     pZip->m_pWrite = mz_zip_heap_write_func;
6063   }
6064   // Archive is being read via a user provided read function - make sure the
6065   // user has specified a write function too.
6066   else if (!pZip->m_pWrite)
6067     return MZ_FALSE;
6068 
6069   // Start writing new files at the archive's current central directory
6070   // location.
6071   pZip->m_archive_size = pZip->m_central_directory_file_ofs;
6072   pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
6073   pZip->m_central_directory_file_ofs = 0;
6074 
6075   return MZ_TRUE;
6076 }
6077 
mz_zip_writer_add_mem(mz_zip_archive * pZip,const char * pArchive_name,const void * pBuf,size_t buf_size,mz_uint level_and_flags)6078 mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name,
6079                               const void *pBuf, size_t buf_size,
6080                               mz_uint level_and_flags) {
6081   return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0,
6082                                   level_and_flags, 0, 0);
6083 }
6084 
6085 typedef struct {
6086   mz_zip_archive *m_pZip;
6087   mz_uint64 m_cur_archive_file_ofs;
6088   mz_uint64 m_comp_size;
6089 } mz_zip_writer_add_state;
6090 
mz_zip_writer_add_put_buf_callback(const void * pBuf,int len,void * pUser)6091 static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len,
6092                                                   void *pUser) {
6093   mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
6094   if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque,
6095                                     pState->m_cur_archive_file_ofs, pBuf,
6096                                     len) != len)
6097     return MZ_FALSE;
6098   pState->m_cur_archive_file_ofs += len;
6099   pState->m_comp_size += len;
6100   return MZ_TRUE;
6101 }
6102 
mz_zip_writer_create_local_dir_header(mz_zip_archive * pZip,mz_uint8 * pDst,mz_uint16 filename_size,mz_uint16 extra_size,mz_uint64 uncomp_size,mz_uint64 comp_size,mz_uint32 uncomp_crc32,mz_uint16 method,mz_uint16 bit_flags,mz_uint16 dos_time,mz_uint16 dos_date)6103 static mz_bool mz_zip_writer_create_local_dir_header(
6104     mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
6105     mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
6106     mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
6107     mz_uint16 dos_time, mz_uint16 dos_date) {
6108   (void)pZip;
6109   memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
6110   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
6111   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6112   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
6113   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
6114   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
6115   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
6116   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
6117   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size);
6118   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
6119   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
6120   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
6121   return MZ_TRUE;
6122 }
6123 
mz_zip_writer_create_central_dir_header(mz_zip_archive * pZip,mz_uint8 * pDst,mz_uint16 filename_size,mz_uint16 extra_size,mz_uint16 comment_size,mz_uint64 uncomp_size,mz_uint64 comp_size,mz_uint32 uncomp_crc32,mz_uint16 method,mz_uint16 bit_flags,mz_uint16 dos_time,mz_uint16 dos_date,mz_uint64 local_header_ofs,mz_uint32 ext_attributes)6124 static mz_bool mz_zip_writer_create_central_dir_header(
6125     mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
6126     mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size,
6127     mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method,
6128     mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6129     mz_uint64 local_header_ofs, mz_uint32 ext_attributes) {
6130   (void)pZip;
6131   memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6132   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
6133   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6134   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
6135   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
6136   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
6137   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
6138   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
6139   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size);
6140   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
6141   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
6142   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
6143   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
6144   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
6145   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs);
6146   return MZ_TRUE;
6147 }
6148 
mz_zip_writer_add_to_central_dir(mz_zip_archive * pZip,const char * pFilename,mz_uint16 filename_size,const void * pExtra,mz_uint16 extra_size,const void * pComment,mz_uint16 comment_size,mz_uint64 uncomp_size,mz_uint64 comp_size,mz_uint32 uncomp_crc32,mz_uint16 method,mz_uint16 bit_flags,mz_uint16 dos_time,mz_uint16 dos_date,mz_uint64 local_header_ofs,mz_uint32 ext_attributes)6149 static mz_bool mz_zip_writer_add_to_central_dir(
6150     mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
6151     const void *pExtra, mz_uint16 extra_size, const void *pComment,
6152     mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
6153     mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
6154     mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs,
6155     mz_uint32 ext_attributes) {
6156   mz_zip_internal_state *pState = pZip->m_pState;
6157   mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
6158   size_t orig_central_dir_size = pState->m_central_dir.m_size;
6159   mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6160 
6161   // No zip64 support yet
6162   if ((local_header_ofs > 0xFFFFFFFF) ||
6163       (((mz_uint64)pState->m_central_dir.m_size +
6164         MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size +
6165         comment_size) > 0xFFFFFFFF))
6166     return MZ_FALSE;
6167 
6168   if (!mz_zip_writer_create_central_dir_header(
6169           pZip, central_dir_header, filename_size, extra_size, comment_size,
6170           uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time,
6171           dos_date, local_header_ofs, ext_attributes))
6172     return MZ_FALSE;
6173 
6174   if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header,
6175                                MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
6176       (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename,
6177                                filename_size)) ||
6178       (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra,
6179                                extra_size)) ||
6180       (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment,
6181                                comment_size)) ||
6182       (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets,
6183                                &central_dir_ofs, 1))) {
6184     // Try to push the central directory array back into its original state.
6185     mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6186                         MZ_FALSE);
6187     return MZ_FALSE;
6188   }
6189 
6190   return MZ_TRUE;
6191 }
6192 
mz_zip_writer_validate_archive_name(const char * pArchive_name)6193 static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) {
6194   // Basic ZIP archive filename validity checks: Valid filenames cannot start
6195   // with a forward slash, cannot contain a drive letter, and cannot use
6196   // DOS-style backward slashes.
6197   if (*pArchive_name == '/') return MZ_FALSE;
6198   while (*pArchive_name) {
6199     if ((*pArchive_name == '\\') || (*pArchive_name == ':')) return MZ_FALSE;
6200     pArchive_name++;
6201   }
6202   return MZ_TRUE;
6203 }
6204 
mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive * pZip)6205 static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(
6206     mz_zip_archive *pZip) {
6207   mz_uint32 n;
6208   if (!pZip->m_file_offset_alignment) return 0;
6209   n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
6210   return (pZip->m_file_offset_alignment - n) &
6211          (pZip->m_file_offset_alignment - 1);
6212 }
6213 
mz_zip_writer_write_zeros(mz_zip_archive * pZip,mz_uint64 cur_file_ofs,mz_uint32 n)6214 static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip,
6215                                          mz_uint64 cur_file_ofs, mz_uint32 n) {
6216   char buf[4096];
6217   memset(buf, 0, MZ_MIN(sizeof(buf), n));
6218   while (n) {
6219     mz_uint32 s = MZ_MIN(sizeof(buf), n);
6220     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6221       return MZ_FALSE;
6222     cur_file_ofs += s;
6223     n -= s;
6224   }
6225   return MZ_TRUE;
6226 }
6227 
mz_zip_writer_add_mem_ex(mz_zip_archive * pZip,const char * pArchive_name,const void * pBuf,size_t buf_size,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags,mz_uint64 uncomp_size,mz_uint32 uncomp_crc32)6228 mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
6229                                  const char *pArchive_name, const void *pBuf,
6230                                  size_t buf_size, const void *pComment,
6231                                  mz_uint16 comment_size,
6232                                  mz_uint level_and_flags, mz_uint64 uncomp_size,
6233                                  mz_uint32 uncomp_crc32) {
6234   mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6235   mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
6236   mz_uint64 local_dir_header_ofs = pZip->m_archive_size,
6237             cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
6238   size_t archive_name_size;
6239   mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6240   tdefl_compressor *pComp = NULL;
6241   mz_bool store_data_uncompressed;
6242   mz_zip_internal_state *pState;
6243 
6244   if ((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL;
6245   level = level_and_flags & 0xF;
6246   store_data_uncompressed =
6247       ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6248 
6249   if ((!pZip) || (!pZip->m_pState) ||
6250       (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) ||
6251       (!pArchive_name) || ((comment_size) && (!pComment)) ||
6252       (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
6253     return MZ_FALSE;
6254 
6255   pState = pZip->m_pState;
6256 
6257   if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6258     return MZ_FALSE;
6259   // No zip64 support yet
6260   if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) return MZ_FALSE;
6261   if (!mz_zip_writer_validate_archive_name(pArchive_name)) return MZ_FALSE;
6262 
6263 #ifndef MINIZ_NO_TIME
6264   {
6265     time_t cur_time;
6266     time(&cur_time);
6267     mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date);
6268   }
6269 #endif  // #ifndef MINIZ_NO_TIME
6270 
6271   archive_name_size = strlen(pArchive_name);
6272   if (archive_name_size > 0xFFFF) return MZ_FALSE;
6273 
6274   num_alignment_padding_bytes =
6275       mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6276 
6277   // no zip64 support yet
6278   if ((pZip->m_total_files == 0xFFFF) ||
6279       ((pZip->m_archive_size + num_alignment_padding_bytes +
6280         MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6281         comment_size + archive_name_size) > 0xFFFFFFFF))
6282     return MZ_FALSE;
6283 
6284   if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) {
6285     // Set DOS Subdirectory attribute bit.
6286     ext_attributes |= 0x10;
6287     // Subdirectories cannot contain data.
6288     if ((buf_size) || (uncomp_size)) return MZ_FALSE;
6289   }
6290 
6291   // Try to do any allocations before writing to the archive, so if an
6292   // allocation fails the file remains unmodified. (A good idea if we're doing
6293   // an in-place modification.)
6294   if ((!mz_zip_array_ensure_room(
6295           pZip, &pState->m_central_dir,
6296           MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) ||
6297       (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
6298     return MZ_FALSE;
6299 
6300   if ((!store_data_uncompressed) && (buf_size)) {
6301     if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(
6302                      pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
6303       return MZ_FALSE;
6304   }
6305 
6306   if (!mz_zip_writer_write_zeros(
6307           pZip, cur_archive_file_ofs,
6308           num_alignment_padding_bytes + sizeof(local_dir_header))) {
6309     pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6310     return MZ_FALSE;
6311   }
6312   local_dir_header_ofs += num_alignment_padding_bytes;
6313   if (pZip->m_file_offset_alignment) {
6314     MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6315               0);
6316   }
6317   cur_archive_file_ofs +=
6318       num_alignment_padding_bytes + sizeof(local_dir_header);
6319 
6320   MZ_CLEAR_OBJ(local_dir_header);
6321   if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
6322                      archive_name_size) != archive_name_size) {
6323     pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6324     return MZ_FALSE;
6325   }
6326   cur_archive_file_ofs += archive_name_size;
6327 
6328   if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) {
6329     uncomp_crc32 =
6330         (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
6331     uncomp_size = buf_size;
6332     if (uncomp_size <= 3) {
6333       level = 0;
6334       store_data_uncompressed = MZ_TRUE;
6335     }
6336   }
6337 
6338   if (store_data_uncompressed) {
6339     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf,
6340                        buf_size) != buf_size) {
6341       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6342       return MZ_FALSE;
6343     }
6344 
6345     cur_archive_file_ofs += buf_size;
6346     comp_size = buf_size;
6347 
6348     if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) method = MZ_DEFLATED;
6349   } else if (buf_size) {
6350     mz_zip_writer_add_state state;
6351 
6352     state.m_pZip = pZip;
6353     state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6354     state.m_comp_size = 0;
6355 
6356     if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
6357                     tdefl_create_comp_flags_from_zip_params(
6358                         level, -15, MZ_DEFAULT_STRATEGY)) !=
6359          TDEFL_STATUS_OKAY) ||
6360         (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) !=
6361          TDEFL_STATUS_DONE)) {
6362       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6363       return MZ_FALSE;
6364     }
6365 
6366     comp_size = state.m_comp_size;
6367     cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6368 
6369     method = MZ_DEFLATED;
6370   }
6371 
6372   pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6373   pComp = NULL;
6374 
6375   // no zip64 support yet
6376   if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
6377     return MZ_FALSE;
6378 
6379   if (!mz_zip_writer_create_local_dir_header(
6380           pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size,
6381           comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
6382     return MZ_FALSE;
6383 
6384   if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
6385                      sizeof(local_dir_header)) != sizeof(local_dir_header))
6386     return MZ_FALSE;
6387 
6388   if (!mz_zip_writer_add_to_central_dir(
6389           pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment,
6390           comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0,
6391           dos_time, dos_date, local_dir_header_ofs, ext_attributes))
6392     return MZ_FALSE;
6393 
6394   pZip->m_total_files++;
6395   pZip->m_archive_size = cur_archive_file_ofs;
6396 
6397   return MZ_TRUE;
6398 }
6399 
6400 #ifndef MINIZ_NO_STDIO
mz_zip_writer_add_file(mz_zip_archive * pZip,const char * pArchive_name,const char * pSrc_filename,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags)6401 mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
6402                                const char *pSrc_filename, const void *pComment,
6403                                mz_uint16 comment_size,
6404                                mz_uint level_and_flags) {
6405   mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6406   mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
6407   mz_uint64 local_dir_header_ofs = pZip->m_archive_size,
6408             cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0,
6409             comp_size = 0;
6410   size_t archive_name_size;
6411   mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6412   MZ_FILE *pSrc_file = NULL;
6413 
6414   if ((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL;
6415   level = level_and_flags & 0xF;
6416 
6417   if ((!pZip) || (!pZip->m_pState) ||
6418       (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) ||
6419       ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6420     return MZ_FALSE;
6421   if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) return MZ_FALSE;
6422   if (!mz_zip_writer_validate_archive_name(pArchive_name)) return MZ_FALSE;
6423 
6424   archive_name_size = strlen(pArchive_name);
6425   if (archive_name_size > 0xFFFF) return MZ_FALSE;
6426 
6427   num_alignment_padding_bytes =
6428       mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6429 
6430   // no zip64 support yet
6431   if ((pZip->m_total_files == 0xFFFF) ||
6432       ((pZip->m_archive_size + num_alignment_padding_bytes +
6433         MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6434         comment_size + archive_name_size) > 0xFFFFFFFF))
6435     return MZ_FALSE;
6436 
6437   if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date))
6438     return MZ_FALSE;
6439 
6440   pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6441   if (!pSrc_file) return MZ_FALSE;
6442   MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6443   uncomp_size = MZ_FTELL64(pSrc_file);
6444   MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6445 
6446   if (uncomp_size > 0xFFFFFFFF) {
6447     // No zip64 support yet
6448     MZ_FCLOSE(pSrc_file);
6449     return MZ_FALSE;
6450   }
6451   if (uncomp_size <= 3) level = 0;
6452 
6453   if (!mz_zip_writer_write_zeros(
6454           pZip, cur_archive_file_ofs,
6455           num_alignment_padding_bytes + sizeof(local_dir_header))) {
6456     MZ_FCLOSE(pSrc_file);
6457     return MZ_FALSE;
6458   }
6459   local_dir_header_ofs += num_alignment_padding_bytes;
6460   if (pZip->m_file_offset_alignment) {
6461     MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6462               0);
6463   }
6464   cur_archive_file_ofs +=
6465       num_alignment_padding_bytes + sizeof(local_dir_header);
6466 
6467   MZ_CLEAR_OBJ(local_dir_header);
6468   if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
6469                      archive_name_size) != archive_name_size) {
6470     MZ_FCLOSE(pSrc_file);
6471     return MZ_FALSE;
6472   }
6473   cur_archive_file_ofs += archive_name_size;
6474 
6475   if (uncomp_size) {
6476     mz_uint64 uncomp_remaining = uncomp_size;
6477     void *pRead_buf =
6478         pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6479     if (!pRead_buf) {
6480       MZ_FCLOSE(pSrc_file);
6481       return MZ_FALSE;
6482     }
6483 
6484     if (!level) {
6485       while (uncomp_remaining) {
6486         mz_uint n =
6487             (mz_uint)MZ_MIN((mz_uint)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
6488         if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) ||
6489             (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf,
6490                             n) != n)) {
6491           pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6492           MZ_FCLOSE(pSrc_file);
6493           return MZ_FALSE;
6494         }
6495         uncomp_crc32 =
6496             (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6497         uncomp_remaining -= n;
6498         cur_archive_file_ofs += n;
6499       }
6500       comp_size = uncomp_size;
6501     } else {
6502       mz_bool result = MZ_FALSE;
6503       mz_zip_writer_add_state state;
6504       tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(
6505           pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6506       if (!pComp) {
6507         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6508         MZ_FCLOSE(pSrc_file);
6509         return MZ_FALSE;
6510       }
6511 
6512       state.m_pZip = pZip;
6513       state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6514       state.m_comp_size = 0;
6515 
6516       if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
6517                      tdefl_create_comp_flags_from_zip_params(
6518                          level, -15, MZ_DEFAULT_STRATEGY)) !=
6519           TDEFL_STATUS_OKAY) {
6520         pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6521         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6522         MZ_FCLOSE(pSrc_file);
6523         return MZ_FALSE;
6524       }
6525 
6526       for (;;) {
6527         size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining,
6528                                                (mz_uint)MZ_ZIP_MAX_IO_BUF_SIZE);
6529         tdefl_status status;
6530 
6531         if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
6532           break;
6533 
6534         uncomp_crc32 = (mz_uint32)mz_crc32(
6535             uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
6536         uncomp_remaining -= in_buf_size;
6537 
6538         status = tdefl_compress_buffer(
6539             pComp, pRead_buf, in_buf_size,
6540             uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH);
6541         if (status == TDEFL_STATUS_DONE) {
6542           result = MZ_TRUE;
6543           break;
6544         } else if (status != TDEFL_STATUS_OKAY)
6545           break;
6546       }
6547 
6548       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6549 
6550       if (!result) {
6551         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6552         MZ_FCLOSE(pSrc_file);
6553         return MZ_FALSE;
6554       }
6555 
6556       comp_size = state.m_comp_size;
6557       cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6558 
6559       method = MZ_DEFLATED;
6560     }
6561 
6562     pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6563   }
6564 
6565   MZ_FCLOSE(pSrc_file);
6566   pSrc_file = NULL;
6567 
6568   // no zip64 support yet
6569   if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
6570     return MZ_FALSE;
6571 
6572   if (!mz_zip_writer_create_local_dir_header(
6573           pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size,
6574           comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
6575     return MZ_FALSE;
6576 
6577   if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
6578                      sizeof(local_dir_header)) != sizeof(local_dir_header))
6579     return MZ_FALSE;
6580 
6581   if (!mz_zip_writer_add_to_central_dir(
6582           pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment,
6583           comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0,
6584           dos_time, dos_date, local_dir_header_ofs, ext_attributes))
6585     return MZ_FALSE;
6586 
6587   pZip->m_total_files++;
6588   pZip->m_archive_size = cur_archive_file_ofs;
6589 
6590   return MZ_TRUE;
6591 }
6592 #endif  // #ifndef MINIZ_NO_STDIO
6593 
mz_zip_writer_add_from_zip_reader(mz_zip_archive * pZip,mz_zip_archive * pSource_zip,mz_uint file_index)6594 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip,
6595                                           mz_zip_archive *pSource_zip,
6596                                           mz_uint file_index) {
6597   mz_uint n, bit_flags, num_alignment_padding_bytes;
6598   mz_uint64 comp_bytes_remaining, local_dir_header_ofs;
6599   mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
6600   mz_uint32
6601       local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
6602                        sizeof(mz_uint32)];
6603   mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6604   mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6605   size_t orig_central_dir_size;
6606   mz_zip_internal_state *pState;
6607   void *pBuf;
6608   const mz_uint8 *pSrc_central_header;
6609 
6610   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
6611     return MZ_FALSE;
6612   if (NULL ==
6613       (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index)))
6614     return MZ_FALSE;
6615   pState = pZip->m_pState;
6616 
6617   num_alignment_padding_bytes =
6618       mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6619 
6620   // no zip64 support yet
6621   if ((pZip->m_total_files == 0xFFFF) ||
6622       ((pZip->m_archive_size + num_alignment_padding_bytes +
6623         MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) >
6624        0xFFFFFFFF))
6625     return MZ_FALSE;
6626 
6627   cur_src_file_ofs =
6628       MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
6629   cur_dst_file_ofs = pZip->m_archive_size;
6630 
6631   if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs,
6632                            pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6633       MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6634     return MZ_FALSE;
6635   if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
6636     return MZ_FALSE;
6637   cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6638 
6639   if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs,
6640                                  num_alignment_padding_bytes))
6641     return MZ_FALSE;
6642   cur_dst_file_ofs += num_alignment_padding_bytes;
6643   local_dir_header_ofs = cur_dst_file_ofs;
6644   if (pZip->m_file_offset_alignment) {
6645     MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6646               0);
6647   }
6648 
6649   if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header,
6650                      MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6651       MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6652     return MZ_FALSE;
6653   cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6654 
6655   n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
6656       MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6657   comp_bytes_remaining =
6658       n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
6659 
6660   if (NULL == (pBuf = pZip->m_pAlloc(
6661                    pZip->m_pAlloc_opaque, 1,
6662                    (size_t)MZ_MAX(sizeof(mz_uint32) * 4,
6663                                   MZ_MIN((mz_uint)MZ_ZIP_MAX_IO_BUF_SIZE,
6664                                          comp_bytes_remaining)))))
6665     return MZ_FALSE;
6666 
6667   while (comp_bytes_remaining) {
6668     n = (mz_uint)MZ_MIN((mz_uint)MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining);
6669     if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
6670                              n) != n) {
6671       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6672       return MZ_FALSE;
6673     }
6674     cur_src_file_ofs += n;
6675 
6676     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
6677       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6678       return MZ_FALSE;
6679     }
6680     cur_dst_file_ofs += n;
6681 
6682     comp_bytes_remaining -= n;
6683   }
6684 
6685   bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
6686   if (bit_flags & 8) {
6687     // Copy data descriptor
6688     if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
6689                              sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) {
6690       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6691       return MZ_FALSE;
6692     }
6693 
6694     n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3);
6695     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
6696       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6697       return MZ_FALSE;
6698     }
6699 
6700     cur_src_file_ofs += n;
6701     cur_dst_file_ofs += n;
6702   }
6703   pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6704 
6705   // no zip64 support yet
6706   if (cur_dst_file_ofs > 0xFFFFFFFF) return MZ_FALSE;
6707 
6708   orig_central_dir_size = pState->m_central_dir.m_size;
6709 
6710   memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6711   MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS,
6712                 local_dir_header_ofs);
6713   if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header,
6714                               MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
6715     return MZ_FALSE;
6716 
6717   n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
6718       MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
6719       MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
6720   if (!mz_zip_array_push_back(
6721           pZip, &pState->m_central_dir,
6722           pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) {
6723     mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6724                         MZ_FALSE);
6725     return MZ_FALSE;
6726   }
6727 
6728   if (pState->m_central_dir.m_size > 0xFFFFFFFF) return MZ_FALSE;
6729   n = (mz_uint32)orig_central_dir_size;
6730   if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) {
6731     mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6732                         MZ_FALSE);
6733     return MZ_FALSE;
6734   }
6735 
6736   pZip->m_total_files++;
6737   pZip->m_archive_size = cur_dst_file_ofs;
6738 
6739   return MZ_TRUE;
6740 }
6741 
mz_zip_writer_finalize_archive(mz_zip_archive * pZip)6742 mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) {
6743   mz_zip_internal_state *pState;
6744   mz_uint64 central_dir_ofs, central_dir_size;
6745   mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE];
6746 
6747   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
6748     return MZ_FALSE;
6749 
6750   pState = pZip->m_pState;
6751 
6752   // no zip64 support yet
6753   if ((pZip->m_total_files > 0xFFFF) ||
6754       ((pZip->m_archive_size + pState->m_central_dir.m_size +
6755         MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
6756     return MZ_FALSE;
6757 
6758   central_dir_ofs = 0;
6759   central_dir_size = 0;
6760   if (pZip->m_total_files) {
6761     // Write central directory
6762     central_dir_ofs = pZip->m_archive_size;
6763     central_dir_size = pState->m_central_dir.m_size;
6764     pZip->m_central_directory_file_ofs = central_dir_ofs;
6765     if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs,
6766                        pState->m_central_dir.m_p,
6767                        (size_t)central_dir_size) != central_dir_size)
6768       return MZ_FALSE;
6769     pZip->m_archive_size += central_dir_size;
6770   }
6771 
6772   // Write end of central directory record
6773   MZ_CLEAR_OBJ(hdr);
6774   MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS,
6775                 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
6776   MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS,
6777                 pZip->m_total_files);
6778   MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
6779   MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size);
6780   MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs);
6781 
6782   if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr,
6783                      sizeof(hdr)) != sizeof(hdr))
6784     return MZ_FALSE;
6785 #ifndef MINIZ_NO_STDIO
6786   if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) return MZ_FALSE;
6787 #endif  // #ifndef MINIZ_NO_STDIO
6788 
6789   pZip->m_archive_size += sizeof(hdr);
6790 
6791   pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
6792   return MZ_TRUE;
6793 }
6794 
mz_zip_writer_finalize_heap_archive(mz_zip_archive * pZip,void ** pBuf,size_t * pSize)6795 mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf,
6796                                             size_t *pSize) {
6797   if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize)) return MZ_FALSE;
6798   if (pZip->m_pWrite != mz_zip_heap_write_func) return MZ_FALSE;
6799   if (!mz_zip_writer_finalize_archive(pZip)) return MZ_FALSE;
6800 
6801   *pBuf = pZip->m_pState->m_pMem;
6802   *pSize = pZip->m_pState->m_mem_size;
6803   pZip->m_pState->m_pMem = NULL;
6804   pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
6805   return MZ_TRUE;
6806 }
6807 
mz_zip_writer_end(mz_zip_archive * pZip)6808 mz_bool mz_zip_writer_end(mz_zip_archive *pZip) {
6809   mz_zip_internal_state *pState;
6810   mz_bool status = MZ_TRUE;
6811   if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
6812       ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) &&
6813        (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
6814     return MZ_FALSE;
6815 
6816   pState = pZip->m_pState;
6817   pZip->m_pState = NULL;
6818   mz_zip_array_clear(pZip, &pState->m_central_dir);
6819   mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
6820   mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
6821 
6822 #ifndef MINIZ_NO_STDIO
6823   if (pState->m_pFile) {
6824     MZ_FCLOSE(pState->m_pFile);
6825     pState->m_pFile = NULL;
6826   }
6827 #endif  // #ifndef MINIZ_NO_STDIO
6828 
6829   if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) {
6830     pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
6831     pState->m_pMem = NULL;
6832   }
6833 
6834   pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6835   pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
6836   return status;
6837 }
6838 
6839 #ifndef MINIZ_NO_STDIO
mz_zip_add_mem_to_archive_file_in_place(const char * pZip_filename,const char * pArchive_name,const void * pBuf,size_t buf_size,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags)6840 mz_bool mz_zip_add_mem_to_archive_file_in_place(
6841     const char *pZip_filename, const char *pArchive_name, const void *pBuf,
6842     size_t buf_size, const void *pComment, mz_uint16 comment_size,
6843     mz_uint level_and_flags) {
6844   mz_bool status, created_new_archive = MZ_FALSE;
6845   mz_zip_archive zip_archive;
6846   struct MZ_FILE_STAT_STRUCT file_stat;
6847   MZ_CLEAR_OBJ(zip_archive);
6848   if ((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL;
6849   if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) ||
6850       ((comment_size) && (!pComment)) ||
6851       ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
6852     return MZ_FALSE;
6853   if (!mz_zip_writer_validate_archive_name(pArchive_name)) return MZ_FALSE;
6854   if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) {
6855     // Create a new archive.
6856     if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
6857       return MZ_FALSE;
6858     created_new_archive = MZ_TRUE;
6859   } else {
6860     // Append to an existing archive.
6861     if (!mz_zip_reader_init_file(
6862             &zip_archive, pZip_filename,
6863             level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
6864       return MZ_FALSE;
6865     if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) {
6866       mz_zip_reader_end(&zip_archive);
6867       return MZ_FALSE;
6868     }
6869   }
6870   status =
6871       mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size,
6872                                pComment, comment_size, level_and_flags, 0, 0);
6873   // Always finalize, even if adding failed for some reason, so we have a valid
6874   // central directory. (This may not always succeed, but we can try.)
6875   if (!mz_zip_writer_finalize_archive(&zip_archive)) status = MZ_FALSE;
6876   if (!mz_zip_writer_end(&zip_archive)) status = MZ_FALSE;
6877   if ((!status) && (created_new_archive)) {
6878     // It's a new archive and something went wrong, so just delete it.
6879     int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
6880     (void)ignoredStatus;
6881   }
6882   return status;
6883 }
6884 
mz_zip_extract_archive_file_to_heap(const char * pZip_filename,const char * pArchive_name,size_t * pSize,mz_uint flags)6885 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
6886                                           const char *pArchive_name,
6887                                           size_t *pSize, mz_uint flags) {
6888   int file_index;
6889   mz_zip_archive zip_archive;
6890   void *p = NULL;
6891 
6892   if (pSize) *pSize = 0;
6893 
6894   if ((!pZip_filename) || (!pArchive_name)) return NULL;
6895 
6896   MZ_CLEAR_OBJ(zip_archive);
6897   if (!mz_zip_reader_init_file(
6898           &zip_archive, pZip_filename,
6899           flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
6900     return NULL;
6901 
6902   if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL,
6903                                               flags)) >= 0)
6904     p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
6905 
6906   mz_zip_reader_end(&zip_archive);
6907   return p;
6908 }
6909 
6910 #endif  // #ifndef MINIZ_NO_STDIO
6911 
6912 #endif  // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
6913 
6914 #endif  // #ifndef MINIZ_NO_ARCHIVE_APIS
6915 
6916 #ifdef __cplusplus
6917 }
6918 #endif
6919 
6920 #endif  // MINIZ_HEADER_FILE_ONLY
6921 
6922 /*
6923   This is free and unencumbered software released into the public domain.
6924 
6925   Anyone is free to copy, modify, publish, use, compile, sell, or
6926   distribute this software, either in source code form or as a compiled
6927   binary, for any purpose, commercial or non-commercial, and by any
6928   means.
6929 
6930   In jurisdictions that recognize copyright laws, the author or authors
6931   of this software dedicate any and all copyright interest in the
6932   software to the public domain. We make this dedication for the benefit
6933   of the public at large and to the detriment of our heirs and
6934   successors. We intend this dedication to be an overt act of
6935   relinquishment in perpetuity of all present and future rights to this
6936   software under copyright law.
6937 
6938   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
6939   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6940   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6941   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
6942   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6943   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6944   OTHER DEALINGS IN THE SOFTWARE.
6945 
6946   For more information, please refer to <http://unlicense.org/>
6947 */
6948 
6949 // ---------------------- end of miniz ----------------------------------------
6950 
6951 #ifdef __clang__
6952 #pragma clang diagnostic pop
6953 #endif
6954 
6955 #ifdef _MSC_VER
6956 #pragma warning(pop)
6957 #endif
6958 }  // namespace miniz
6959 #else
6960 
6961 // Reuse MINIZ_LITTE_ENDIAN macro
6962 
6963 #if defined(__sparcv9)
6964 // Big endian
6965 #else
6966 #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
6967 // Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
6968 #define MINIZ_LITTLE_ENDIAN 1
6969 #endif
6970 #endif
6971 
6972 #endif  // TINYEXR_USE_MINIZ
6973 
6974 // static bool IsBigEndian(void) {
6975 //  union {
6976 //    unsigned int i;
6977 //    char c[4];
6978 //  } bint = {0x01020304};
6979 //
6980 //  return bint.c[0] == 1;
6981 //}
6982 
SetErrorMessage(const std::string & msg,const char ** err)6983 static void SetErrorMessage(const std::string &msg, const char **err) {
6984   if (err) {
6985 #ifdef _WIN32
6986     (*err) = _strdup(msg.c_str());
6987 #else
6988     (*err) = strdup(msg.c_str());
6989 #endif
6990   }
6991 }
6992 
6993 static const int kEXRVersionSize = 8;
6994 
cpy2(unsigned short * dst_val,const unsigned short * src_val)6995 static void cpy2(unsigned short *dst_val, const unsigned short *src_val) {
6996   unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
6997   const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
6998 
6999   dst[0] = src[0];
7000   dst[1] = src[1];
7001 }
7002 
swap2(unsigned short * val)7003 static void swap2(unsigned short *val) {
7004 #ifdef MINIZ_LITTLE_ENDIAN
7005   (void)val;
7006 #else
7007   unsigned short tmp = *val;
7008   unsigned char *dst = reinterpret_cast<unsigned char *>(val);
7009   unsigned char *src = reinterpret_cast<unsigned char *>(&tmp);
7010 
7011   dst[0] = src[1];
7012   dst[1] = src[0];
7013 #endif
7014 }
7015 
7016 #ifdef __clang__
7017 #pragma clang diagnostic push
7018 #pragma clang diagnostic ignored "-Wunused-function"
7019 #endif
7020 
7021 #ifdef __GNUC__
7022 #pragma GCC diagnostic push
7023 #pragma GCC diagnostic ignored "-Wunused-function"
7024 #endif
cpy4(int * dst_val,const int * src_val)7025 static void cpy4(int *dst_val, const int *src_val) {
7026   unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
7027   const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
7028 
7029   dst[0] = src[0];
7030   dst[1] = src[1];
7031   dst[2] = src[2];
7032   dst[3] = src[3];
7033 }
7034 
cpy4(unsigned int * dst_val,const unsigned int * src_val)7035 static void cpy4(unsigned int *dst_val, const unsigned int *src_val) {
7036   unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
7037   const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
7038 
7039   dst[0] = src[0];
7040   dst[1] = src[1];
7041   dst[2] = src[2];
7042   dst[3] = src[3];
7043 }
7044 
cpy4(float * dst_val,const float * src_val)7045 static void cpy4(float *dst_val, const float *src_val) {
7046   unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
7047   const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
7048 
7049   dst[0] = src[0];
7050   dst[1] = src[1];
7051   dst[2] = src[2];
7052   dst[3] = src[3];
7053 }
7054 #ifdef __clang__
7055 #pragma clang diagnostic pop
7056 #endif
7057 
7058 #ifdef __GNUC__
7059 #pragma GCC diagnostic pop
7060 #endif
7061 
swap4(unsigned int * val)7062 static void swap4(unsigned int *val) {
7063 #ifdef MINIZ_LITTLE_ENDIAN
7064   (void)val;
7065 #else
7066   unsigned int tmp = *val;
7067   unsigned char *dst = reinterpret_cast<unsigned char *>(val);
7068   unsigned char *src = reinterpret_cast<unsigned char *>(&tmp);
7069 
7070   dst[0] = src[3];
7071   dst[1] = src[2];
7072   dst[2] = src[1];
7073   dst[3] = src[0];
7074 #endif
7075 }
7076 
7077 #if 0
7078 static void cpy8(tinyexr::tinyexr_uint64 *dst_val, const tinyexr::tinyexr_uint64 *src_val) {
7079   unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
7080   const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
7081 
7082   dst[0] = src[0];
7083   dst[1] = src[1];
7084   dst[2] = src[2];
7085   dst[3] = src[3];
7086   dst[4] = src[4];
7087   dst[5] = src[5];
7088   dst[6] = src[6];
7089   dst[7] = src[7];
7090 }
7091 #endif
7092 
swap8(tinyexr::tinyexr_uint64 * val)7093 static void swap8(tinyexr::tinyexr_uint64 *val) {
7094 #ifdef MINIZ_LITTLE_ENDIAN
7095   (void)val;
7096 #else
7097   tinyexr::tinyexr_uint64 tmp = (*val);
7098   unsigned char *dst = reinterpret_cast<unsigned char *>(val);
7099   unsigned char *src = reinterpret_cast<unsigned char *>(&tmp);
7100 
7101   dst[0] = src[7];
7102   dst[1] = src[6];
7103   dst[2] = src[5];
7104   dst[3] = src[4];
7105   dst[4] = src[3];
7106   dst[5] = src[2];
7107   dst[6] = src[1];
7108   dst[7] = src[0];
7109 #endif
7110 }
7111 
7112 // https://gist.github.com/rygorous/2156668
7113 // Reuse MINIZ_LITTLE_ENDIAN flag from miniz.
7114 union FP32 {
7115   unsigned int u;
7116   float f;
7117   struct {
7118 #if MINIZ_LITTLE_ENDIAN
7119     unsigned int Mantissa : 23;
7120     unsigned int Exponent : 8;
7121     unsigned int Sign : 1;
7122 #else
7123     unsigned int Sign : 1;
7124     unsigned int Exponent : 8;
7125     unsigned int Mantissa : 23;
7126 #endif
7127   } s;
7128 };
7129 
7130 #ifdef __clang__
7131 #pragma clang diagnostic push
7132 #pragma clang diagnostic ignored "-Wpadded"
7133 #endif
7134 
7135 union FP16 {
7136   unsigned short u;
7137   struct {
7138 #if MINIZ_LITTLE_ENDIAN
7139     unsigned int Mantissa : 10;
7140     unsigned int Exponent : 5;
7141     unsigned int Sign : 1;
7142 #else
7143     unsigned int Sign : 1;
7144     unsigned int Exponent : 5;
7145     unsigned int Mantissa : 10;
7146 #endif
7147   } s;
7148 };
7149 
7150 #ifdef __clang__
7151 #pragma clang diagnostic pop
7152 #endif
7153 
half_to_float(FP16 h)7154 static FP32 half_to_float(FP16 h) {
7155   static const FP32 magic = {113 << 23};
7156   static const unsigned int shifted_exp = 0x7c00
7157                                           << 13;  // exponent mask after shift
7158   FP32 o;
7159 
7160   o.u = (h.u & 0x7fffU) << 13U;           // exponent/mantissa bits
7161   unsigned int exp_ = shifted_exp & o.u;  // just the exponent
7162   o.u += (127 - 15) << 23;                // exponent adjust
7163 
7164   // handle exponent special cases
7165   if (exp_ == shifted_exp)    // Inf/NaN?
7166     o.u += (128 - 16) << 23;  // extra exp adjust
7167   else if (exp_ == 0)         // Zero/Denormal?
7168   {
7169     o.u += 1 << 23;  // extra exp adjust
7170     o.f -= magic.f;  // renormalize
7171   }
7172 
7173   o.u |= (h.u & 0x8000U) << 16U;  // sign bit
7174   return o;
7175 }
7176 
float_to_half_full(FP32 f)7177 static FP16 float_to_half_full(FP32 f) {
7178   FP16 o = {0};
7179 
7180   // Based on ISPC reference code (with minor modifications)
7181   if (f.s.Exponent == 0)  // Signed zero/denormal (which will underflow)
7182     o.s.Exponent = 0;
7183   else if (f.s.Exponent == 255)  // Inf or NaN (all exponent bits set)
7184   {
7185     o.s.Exponent = 31;
7186     o.s.Mantissa = f.s.Mantissa ? 0x200 : 0;  // NaN->qNaN and Inf->Inf
7187   } else                                      // Normalized number
7188   {
7189     // Exponent unbias the single, then bias the halfp
7190     int newexp = f.s.Exponent - 127 + 15;
7191     if (newexp >= 31)  // Overflow, return signed infinity
7192       o.s.Exponent = 31;
7193     else if (newexp <= 0)  // Underflow
7194     {
7195       if ((14 - newexp) <= 24)  // Mantissa might be non-zero
7196       {
7197         unsigned int mant = f.s.Mantissa | 0x800000;  // Hidden 1 bit
7198         o.s.Mantissa = mant >> (14 - newexp);
7199         if ((mant >> (13 - newexp)) & 1)  // Check for rounding
7200           o.u++;  // Round, might overflow into exp bit, but this is OK
7201       }
7202     } else {
7203       o.s.Exponent = static_cast<unsigned int>(newexp);
7204       o.s.Mantissa = f.s.Mantissa >> 13;
7205       if (f.s.Mantissa & 0x1000)  // Check for rounding
7206         o.u++;                    // Round, might overflow to inf, this is OK
7207     }
7208   }
7209 
7210   o.s.Sign = f.s.Sign;
7211   return o;
7212 }
7213 
7214 // NOTE: From OpenEXR code
7215 // #define IMF_INCREASING_Y  0
7216 // #define IMF_DECREASING_Y  1
7217 // #define IMF_RAMDOM_Y    2
7218 //
7219 // #define IMF_NO_COMPRESSION  0
7220 // #define IMF_RLE_COMPRESSION 1
7221 // #define IMF_ZIPS_COMPRESSION  2
7222 // #define IMF_ZIP_COMPRESSION 3
7223 // #define IMF_PIZ_COMPRESSION 4
7224 // #define IMF_PXR24_COMPRESSION 5
7225 // #define IMF_B44_COMPRESSION 6
7226 // #define IMF_B44A_COMPRESSION  7
7227 
7228 #ifdef __clang__
7229 #pragma clang diagnostic push
7230 
7231 #if __has_warning("-Wzero-as-null-pointer-constant")
7232 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
7233 #endif
7234 
7235 #endif
7236 
ReadString(std::string * s,const char * ptr,size_t len)7237 static const char *ReadString(std::string *s, const char *ptr, size_t len) {
7238   // Read untile NULL(\0).
7239   const char *p = ptr;
7240   const char *q = ptr;
7241   while ((size_t(q - ptr) < len) && (*q) != 0) {
7242     q++;
7243   }
7244 
7245   if (size_t(q - ptr) >= len) {
7246     (*s) = std::string();
7247     return NULL;
7248   }
7249 
7250   (*s) = std::string(p, q);
7251 
7252   return q + 1;  // skip '\0'
7253 }
7254 
ReadAttribute(std::string * name,std::string * type,std::vector<unsigned char> * data,size_t * marker_size,const char * marker,size_t size)7255 static bool ReadAttribute(std::string *name, std::string *type,
7256                           std::vector<unsigned char> *data, size_t *marker_size,
7257                           const char *marker, size_t size) {
7258   size_t name_len = strnlen(marker, size);
7259   if (name_len == size) {
7260     // String does not have a terminating character.
7261     return false;
7262   }
7263   *name = std::string(marker, name_len);
7264 
7265   marker += name_len + 1;
7266   size -= name_len + 1;
7267 
7268   size_t type_len = strnlen(marker, size);
7269   if (type_len == size) {
7270     return false;
7271   }
7272   *type = std::string(marker, type_len);
7273 
7274   marker += type_len + 1;
7275   size -= type_len + 1;
7276 
7277   if (size < sizeof(uint32_t)) {
7278     return false;
7279   }
7280 
7281   uint32_t data_len;
7282   memcpy(&data_len, marker, sizeof(uint32_t));
7283   tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
7284 
7285   if (data_len == 0) {
7286     if ((*type).compare("string") == 0) {
7287       // Accept empty string attribute.
7288 
7289       marker += sizeof(uint32_t);
7290       size -= sizeof(uint32_t);
7291 
7292       *marker_size = name_len + 1 + type_len + 1 + sizeof(uint32_t);
7293 
7294       data->resize(1);
7295       (*data)[0] = '\0';
7296 
7297       return true;
7298     } else {
7299       return false;
7300     }
7301   }
7302 
7303   marker += sizeof(uint32_t);
7304   size -= sizeof(uint32_t);
7305 
7306   if (size < data_len) {
7307     return false;
7308   }
7309 
7310   data->resize(static_cast<size_t>(data_len));
7311   memcpy(&data->at(0), marker, static_cast<size_t>(data_len));
7312 
7313   *marker_size = name_len + 1 + type_len + 1 + sizeof(uint32_t) + data_len;
7314   return true;
7315 }
7316 
WriteAttributeToMemory(std::vector<unsigned char> * out,const char * name,const char * type,const unsigned char * data,int len)7317 static void WriteAttributeToMemory(std::vector<unsigned char> *out,
7318                                    const char *name, const char *type,
7319                                    const unsigned char *data, int len) {
7320   out->insert(out->end(), name, name + strlen(name) + 1);
7321   out->insert(out->end(), type, type + strlen(type) + 1);
7322 
7323   int outLen = len;
7324   tinyexr::swap4(reinterpret_cast<unsigned int *>(&outLen));
7325   out->insert(out->end(), reinterpret_cast<unsigned char *>(&outLen),
7326               reinterpret_cast<unsigned char *>(&outLen) + sizeof(int));
7327   out->insert(out->end(), data, data + len);
7328 }
7329 
7330 typedef struct {
7331   std::string name;  // less than 255 bytes long
7332   int pixel_type;
7333   int x_sampling;
7334   int y_sampling;
7335   unsigned char p_linear;
7336   unsigned char pad[3];
7337 } ChannelInfo;
7338 
7339 typedef struct {
7340   std::vector<tinyexr::ChannelInfo> channels;
7341   std::vector<EXRAttribute> attributes;
7342 
7343   int data_window[4];
7344   int line_order;
7345   int display_window[4];
7346   float screen_window_center[2];
7347   float screen_window_width;
7348   float pixel_aspect_ratio;
7349 
7350   int chunk_count;
7351 
7352   // Tiled format
7353   int tile_size_x;
7354   int tile_size_y;
7355   int tile_level_mode;
7356   int tile_rounding_mode;
7357 
7358   unsigned int header_len;
7359 
7360   int compression_type;
7361 
clear__anon3809bf2420087362   void clear() {
7363     channels.clear();
7364     attributes.clear();
7365 
7366     data_window[0] = 0;
7367     data_window[1] = 0;
7368     data_window[2] = 0;
7369     data_window[3] = 0;
7370     line_order = 0;
7371     display_window[0] = 0;
7372     display_window[1] = 0;
7373     display_window[2] = 0;
7374     display_window[3] = 0;
7375     screen_window_center[0] = 0.0f;
7376     screen_window_center[1] = 0.0f;
7377     screen_window_width = 0.0f;
7378     pixel_aspect_ratio = 0.0f;
7379 
7380     chunk_count = 0;
7381 
7382     // Tiled format
7383     tile_size_x = 0;
7384     tile_size_y = 0;
7385     tile_level_mode = 0;
7386     tile_rounding_mode = 0;
7387 
7388     header_len = 0;
7389     compression_type = 0;
7390   }
7391 } HeaderInfo;
7392 
ReadChannelInfo(std::vector<ChannelInfo> & channels,const std::vector<unsigned char> & data)7393 static bool ReadChannelInfo(std::vector<ChannelInfo> &channels,
7394                             const std::vector<unsigned char> &data) {
7395   const char *p = reinterpret_cast<const char *>(&data.at(0));
7396 
7397   for (;;) {
7398     if ((*p) == 0) {
7399       break;
7400     }
7401     ChannelInfo info;
7402 
7403     tinyexr_int64 data_len = static_cast<tinyexr_int64>(data.size()) -
7404                              (p - reinterpret_cast<const char *>(data.data()));
7405     if (data_len < 0) {
7406       return false;
7407     }
7408 
7409     p = ReadString(&info.name, p, size_t(data_len));
7410     if ((p == NULL) && (info.name.empty())) {
7411       // Buffer overrun. Issue #51.
7412       return false;
7413     }
7414 
7415     const unsigned char *data_end =
7416         reinterpret_cast<const unsigned char *>(p) + 16;
7417     if (data_end >= (data.data() + data.size())) {
7418       return false;
7419     }
7420 
7421     memcpy(&info.pixel_type, p, sizeof(int));
7422     p += 4;
7423     info.p_linear = static_cast<unsigned char>(p[0]);  // uchar
7424     p += 1 + 3;                                        // reserved: uchar[3]
7425     memcpy(&info.x_sampling, p, sizeof(int));          // int
7426     p += 4;
7427     memcpy(&info.y_sampling, p, sizeof(int));  // int
7428     p += 4;
7429 
7430     tinyexr::swap4(reinterpret_cast<unsigned int *>(&info.pixel_type));
7431     tinyexr::swap4(reinterpret_cast<unsigned int *>(&info.x_sampling));
7432     tinyexr::swap4(reinterpret_cast<unsigned int *>(&info.y_sampling));
7433 
7434     channels.push_back(info);
7435   }
7436 
7437   return true;
7438 }
7439 
WriteChannelInfo(std::vector<unsigned char> & data,const std::vector<ChannelInfo> & channels)7440 static void WriteChannelInfo(std::vector<unsigned char> &data,
7441                              const std::vector<ChannelInfo> &channels) {
7442   size_t sz = 0;
7443 
7444   // Calculate total size.
7445   for (size_t c = 0; c < channels.size(); c++) {
7446     sz += strlen(channels[c].name.c_str()) + 1;  // +1 for \0
7447     sz += 16;                                    // 4 * int
7448   }
7449   data.resize(sz + 1);
7450 
7451   unsigned char *p = &data.at(0);
7452 
7453   for (size_t c = 0; c < channels.size(); c++) {
7454     memcpy(p, channels[c].name.c_str(), strlen(channels[c].name.c_str()));
7455     p += strlen(channels[c].name.c_str());
7456     (*p) = '\0';
7457     p++;
7458 
7459     int pixel_type = channels[c].pixel_type;
7460     int x_sampling = channels[c].x_sampling;
7461     int y_sampling = channels[c].y_sampling;
7462     tinyexr::swap4(reinterpret_cast<unsigned int *>(&pixel_type));
7463     tinyexr::swap4(reinterpret_cast<unsigned int *>(&x_sampling));
7464     tinyexr::swap4(reinterpret_cast<unsigned int *>(&y_sampling));
7465 
7466     memcpy(p, &pixel_type, sizeof(int));
7467     p += sizeof(int);
7468 
7469     (*p) = channels[c].p_linear;
7470     p += 4;
7471 
7472     memcpy(p, &x_sampling, sizeof(int));
7473     p += sizeof(int);
7474 
7475     memcpy(p, &y_sampling, sizeof(int));
7476     p += sizeof(int);
7477   }
7478 
7479   (*p) = '\0';
7480 }
7481 
CompressZip(unsigned char * dst,tinyexr::tinyexr_uint64 & compressedSize,const unsigned char * src,unsigned long src_size)7482 static void CompressZip(unsigned char *dst,
7483                         tinyexr::tinyexr_uint64 &compressedSize,
7484                         const unsigned char *src, unsigned long src_size) {
7485   std::vector<unsigned char> tmpBuf(src_size);
7486 
7487   //
7488   // Apply EXR-specific? postprocess. Grabbed from OpenEXR's
7489   // ImfZipCompressor.cpp
7490   //
7491 
7492   //
7493   // Reorder the pixel data.
7494   //
7495 
7496   const char *srcPtr = reinterpret_cast<const char *>(src);
7497 
7498   {
7499     char *t1 = reinterpret_cast<char *>(&tmpBuf.at(0));
7500     char *t2 = reinterpret_cast<char *>(&tmpBuf.at(0)) + (src_size + 1) / 2;
7501     const char *stop = srcPtr + src_size;
7502 
7503     for (;;) {
7504       if (srcPtr < stop)
7505         *(t1++) = *(srcPtr++);
7506       else
7507         break;
7508 
7509       if (srcPtr < stop)
7510         *(t2++) = *(srcPtr++);
7511       else
7512         break;
7513     }
7514   }
7515 
7516   //
7517   // Predictor.
7518   //
7519 
7520   {
7521     unsigned char *t = &tmpBuf.at(0) + 1;
7522     unsigned char *stop = &tmpBuf.at(0) + src_size;
7523     int p = t[-1];
7524 
7525     while (t < stop) {
7526       int d = int(t[0]) - p + (128 + 256);
7527       p = t[0];
7528       t[0] = static_cast<unsigned char>(d);
7529       ++t;
7530     }
7531   }
7532 
7533 #if TINYEXR_USE_MINIZ
7534   //
7535   // Compress the data using miniz
7536   //
7537 
7538   miniz::mz_ulong outSize = miniz::mz_compressBound(src_size);
7539   int ret = miniz::mz_compress(
7540       dst, &outSize, static_cast<const unsigned char *>(&tmpBuf.at(0)),
7541       src_size);
7542   assert(ret == miniz::MZ_OK);
7543   (void)ret;
7544 
7545   compressedSize = outSize;
7546 #else
7547   uLong outSize = compressBound(static_cast<uLong>(src_size));
7548   int ret = compress(dst, &outSize, static_cast<const Bytef *>(&tmpBuf.at(0)),
7549                      src_size);
7550   assert(ret == Z_OK);
7551 
7552   compressedSize = outSize;
7553 #endif
7554 
7555   // Use uncompressed data when compressed data is larger than uncompressed.
7556   // (Issue 40)
7557   if (compressedSize >= src_size) {
7558     compressedSize = src_size;
7559     memcpy(dst, src, src_size);
7560   }
7561 }
7562 
DecompressZip(unsigned char * dst,unsigned long * uncompressed_size,const unsigned char * src,unsigned long src_size)7563 static bool DecompressZip(unsigned char *dst,
7564                           unsigned long *uncompressed_size /* inout */,
7565                           const unsigned char *src, unsigned long src_size) {
7566   if ((*uncompressed_size) == src_size) {
7567     // Data is not compressed(Issue 40).
7568     memcpy(dst, src, src_size);
7569     return true;
7570   }
7571   std::vector<unsigned char> tmpBuf(*uncompressed_size);
7572 
7573 #if TINYEXR_USE_MINIZ
7574   int ret =
7575       miniz::mz_uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size);
7576   if (miniz::MZ_OK != ret) {
7577     return false;
7578   }
7579 #else
7580   int ret = uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size);
7581   if (Z_OK != ret) {
7582     return false;
7583   }
7584 #endif
7585 
7586   //
7587   // Apply EXR-specific? postprocess. Grabbed from OpenEXR's
7588   // ImfZipCompressor.cpp
7589   //
7590 
7591   // Predictor.
7592   {
7593     unsigned char *t = &tmpBuf.at(0) + 1;
7594     unsigned char *stop = &tmpBuf.at(0) + (*uncompressed_size);
7595 
7596     while (t < stop) {
7597       int d = int(t[-1]) + int(t[0]) - 128;
7598       t[0] = static_cast<unsigned char>(d);
7599       ++t;
7600     }
7601   }
7602 
7603   // Reorder the pixel data.
7604   {
7605     const char *t1 = reinterpret_cast<const char *>(&tmpBuf.at(0));
7606     const char *t2 = reinterpret_cast<const char *>(&tmpBuf.at(0)) +
7607                      (*uncompressed_size + 1) / 2;
7608     char *s = reinterpret_cast<char *>(dst);
7609     char *stop = s + (*uncompressed_size);
7610 
7611     for (;;) {
7612       if (s < stop)
7613         *(s++) = *(t1++);
7614       else
7615         break;
7616 
7617       if (s < stop)
7618         *(s++) = *(t2++);
7619       else
7620         break;
7621     }
7622   }
7623 
7624   return true;
7625 }
7626 
7627 // RLE code from OpenEXR --------------------------------------
7628 
7629 #ifdef __clang__
7630 #pragma clang diagnostic push
7631 #pragma clang diagnostic ignored "-Wsign-conversion"
7632 #if __has_warning("-Wextra-semi-stmt")
7633 #pragma clang diagnostic ignored "-Wextra-semi-stmt"
7634 #endif
7635 #endif
7636 
7637 #ifdef _MSC_VER
7638 #pragma warning(push)
7639 #pragma warning(disable : 4204)  // nonstandard extension used : non-constant
7640                                  // aggregate initializer (also supported by GNU
7641                                  // C and C99, so no big deal)
7642 #pragma warning(disable : 4244)  // 'initializing': conversion from '__int64' to
7643                                  // 'int', possible loss of data
7644 #pragma warning(disable : 4267)  // 'argument': conversion from '__int64' to
7645                                  // 'int', possible loss of data
7646 #pragma warning(disable : 4996)  // 'strdup': The POSIX name for this item is
7647                                  // deprecated. Instead, use the ISO C and C++
7648                                  // conformant name: _strdup.
7649 #endif
7650 
7651 const int MIN_RUN_LENGTH = 3;
7652 const int MAX_RUN_LENGTH = 127;
7653 
7654 //
7655 // Compress an array of bytes, using run-length encoding,
7656 // and return the length of the compressed data.
7657 //
7658 
rleCompress(int inLength,const char in[],signed char out[])7659 static int rleCompress(int inLength, const char in[], signed char out[]) {
7660   const char *inEnd = in + inLength;
7661   const char *runStart = in;
7662   const char *runEnd = in + 1;
7663   signed char *outWrite = out;
7664 
7665   while (runStart < inEnd) {
7666     while (runEnd < inEnd && *runStart == *runEnd &&
7667            runEnd - runStart - 1 < MAX_RUN_LENGTH) {
7668       ++runEnd;
7669     }
7670 
7671     if (runEnd - runStart >= MIN_RUN_LENGTH) {
7672       //
7673       // Compressable run
7674       //
7675 
7676       *outWrite++ = static_cast<char>(runEnd - runStart) - 1;
7677       *outWrite++ = *(reinterpret_cast<const signed char *>(runStart));
7678       runStart = runEnd;
7679     } else {
7680       //
7681       // Uncompressable run
7682       //
7683 
7684       while (runEnd < inEnd &&
7685              ((runEnd + 1 >= inEnd || *runEnd != *(runEnd + 1)) ||
7686               (runEnd + 2 >= inEnd || *(runEnd + 1) != *(runEnd + 2))) &&
7687              runEnd - runStart < MAX_RUN_LENGTH) {
7688         ++runEnd;
7689       }
7690 
7691       *outWrite++ = static_cast<char>(runStart - runEnd);
7692 
7693       while (runStart < runEnd) {
7694         *outWrite++ = *(reinterpret_cast<const signed char *>(runStart++));
7695       }
7696     }
7697 
7698     ++runEnd;
7699   }
7700 
7701   return static_cast<int>(outWrite - out);
7702 }
7703 
7704 //
7705 // Uncompress an array of bytes compressed with rleCompress().
7706 // Returns the length of the oncompressed data, or 0 if the
7707 // length of the uncompressed data would be more than maxLength.
7708 //
7709 
rleUncompress(int inLength,int maxLength,const signed char in[],char out[])7710 static int rleUncompress(int inLength, int maxLength, const signed char in[],
7711                          char out[]) {
7712   char *outStart = out;
7713 
7714   while (inLength > 0) {
7715     if (*in < 0) {
7716       int count = -(static_cast<int>(*in++));
7717       inLength -= count + 1;
7718 
7719       // Fixes #116: Add bounds check to in buffer.
7720       if ((0 > (maxLength -= count)) || (inLength < 0)) return 0;
7721 
7722       memcpy(out, in, count);
7723       out += count;
7724       in += count;
7725     } else {
7726       int count = *in++;
7727       inLength -= 2;
7728 
7729       if (0 > (maxLength -= count + 1)) return 0;
7730 
7731       memset(out, *reinterpret_cast<const char *>(in), count + 1);
7732       out += count + 1;
7733 
7734       in++;
7735     }
7736   }
7737 
7738   return static_cast<int>(out - outStart);
7739 }
7740 
7741 #ifdef __clang__
7742 #pragma clang diagnostic pop
7743 #endif
7744 
7745 // End of RLE code from OpenEXR -----------------------------------
7746 
CompressRle(unsigned char * dst,tinyexr::tinyexr_uint64 & compressedSize,const unsigned char * src,unsigned long src_size)7747 static void CompressRle(unsigned char *dst,
7748                         tinyexr::tinyexr_uint64 &compressedSize,
7749                         const unsigned char *src, unsigned long src_size) {
7750   std::vector<unsigned char> tmpBuf(src_size);
7751 
7752   //
7753   // Apply EXR-specific? postprocess. Grabbed from OpenEXR's
7754   // ImfRleCompressor.cpp
7755   //
7756 
7757   //
7758   // Reorder the pixel data.
7759   //
7760 
7761   const char *srcPtr = reinterpret_cast<const char *>(src);
7762 
7763   {
7764     char *t1 = reinterpret_cast<char *>(&tmpBuf.at(0));
7765     char *t2 = reinterpret_cast<char *>(&tmpBuf.at(0)) + (src_size + 1) / 2;
7766     const char *stop = srcPtr + src_size;
7767 
7768     for (;;) {
7769       if (srcPtr < stop)
7770         *(t1++) = *(srcPtr++);
7771       else
7772         break;
7773 
7774       if (srcPtr < stop)
7775         *(t2++) = *(srcPtr++);
7776       else
7777         break;
7778     }
7779   }
7780 
7781   //
7782   // Predictor.
7783   //
7784 
7785   {
7786     unsigned char *t = &tmpBuf.at(0) + 1;
7787     unsigned char *stop = &tmpBuf.at(0) + src_size;
7788     int p = t[-1];
7789 
7790     while (t < stop) {
7791       int d = int(t[0]) - p + (128 + 256);
7792       p = t[0];
7793       t[0] = static_cast<unsigned char>(d);
7794       ++t;
7795     }
7796   }
7797 
7798   // outSize will be (srcSiz * 3) / 2 at max.
7799   int outSize = rleCompress(static_cast<int>(src_size),
7800                             reinterpret_cast<const char *>(&tmpBuf.at(0)),
7801                             reinterpret_cast<signed char *>(dst));
7802   assert(outSize > 0);
7803 
7804   compressedSize = static_cast<tinyexr::tinyexr_uint64>(outSize);
7805 
7806   // Use uncompressed data when compressed data is larger than uncompressed.
7807   // (Issue 40)
7808   if (compressedSize >= src_size) {
7809     compressedSize = src_size;
7810     memcpy(dst, src, src_size);
7811   }
7812 }
7813 
DecompressRle(unsigned char * dst,const unsigned long uncompressed_size,const unsigned char * src,unsigned long src_size)7814 static bool DecompressRle(unsigned char *dst,
7815                           const unsigned long uncompressed_size,
7816                           const unsigned char *src, unsigned long src_size) {
7817   if (uncompressed_size == src_size) {
7818     // Data is not compressed(Issue 40).
7819     memcpy(dst, src, src_size);
7820     return true;
7821   }
7822 
7823   // Workaround for issue #112.
7824   // TODO(syoyo): Add more robust out-of-bounds check in `rleUncompress`.
7825   if (src_size <= 2) {
7826     return false;
7827   }
7828 
7829   std::vector<unsigned char> tmpBuf(uncompressed_size);
7830 
7831   int ret = rleUncompress(static_cast<int>(src_size),
7832                           static_cast<int>(uncompressed_size),
7833                           reinterpret_cast<const signed char *>(src),
7834                           reinterpret_cast<char *>(&tmpBuf.at(0)));
7835   if (ret != static_cast<int>(uncompressed_size)) {
7836     return false;
7837   }
7838 
7839   //
7840   // Apply EXR-specific? postprocess. Grabbed from OpenEXR's
7841   // ImfRleCompressor.cpp
7842   //
7843 
7844   // Predictor.
7845   {
7846     unsigned char *t = &tmpBuf.at(0) + 1;
7847     unsigned char *stop = &tmpBuf.at(0) + uncompressed_size;
7848 
7849     while (t < stop) {
7850       int d = int(t[-1]) + int(t[0]) - 128;
7851       t[0] = static_cast<unsigned char>(d);
7852       ++t;
7853     }
7854   }
7855 
7856   // Reorder the pixel data.
7857   {
7858     const char *t1 = reinterpret_cast<const char *>(&tmpBuf.at(0));
7859     const char *t2 = reinterpret_cast<const char *>(&tmpBuf.at(0)) +
7860                      (uncompressed_size + 1) / 2;
7861     char *s = reinterpret_cast<char *>(dst);
7862     char *stop = s + uncompressed_size;
7863 
7864     for (;;) {
7865       if (s < stop)
7866         *(s++) = *(t1++);
7867       else
7868         break;
7869 
7870       if (s < stop)
7871         *(s++) = *(t2++);
7872       else
7873         break;
7874     }
7875   }
7876 
7877   return true;
7878 }
7879 
7880 #if TINYEXR_USE_PIZ
7881 
7882 #ifdef __clang__
7883 #pragma clang diagnostic push
7884 #pragma clang diagnostic ignored "-Wc++11-long-long"
7885 #pragma clang diagnostic ignored "-Wold-style-cast"
7886 #pragma clang diagnostic ignored "-Wpadded"
7887 #pragma clang diagnostic ignored "-Wsign-conversion"
7888 #pragma clang diagnostic ignored "-Wc++11-extensions"
7889 #pragma clang diagnostic ignored "-Wconversion"
7890 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
7891 
7892 #if __has_warning("-Wcast-qual")
7893 #pragma clang diagnostic ignored "-Wcast-qual"
7894 #endif
7895 
7896 #if __has_warning("-Wextra-semi-stmt")
7897 #pragma clang diagnostic ignored "-Wextra-semi-stmt"
7898 #endif
7899 
7900 #endif
7901 
7902 //
7903 // PIZ compress/uncompress, based on OpenEXR's ImfPizCompressor.cpp
7904 //
7905 // -----------------------------------------------------------------
7906 // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
7907 // Digital Ltd. LLC)
7908 // (3 clause BSD license)
7909 //
7910 
7911 struct PIZChannelData {
7912   unsigned short *start;
7913   unsigned short *end;
7914   int nx;
7915   int ny;
7916   int ys;
7917   int size;
7918 };
7919 
7920 //-----------------------------------------------------------------------------
7921 //
7922 //  16-bit Haar Wavelet encoding and decoding
7923 //
7924 //  The source code in this file is derived from the encoding
7925 //  and decoding routines written by Christian Rouet for his
7926 //  PIZ image file format.
7927 //
7928 //-----------------------------------------------------------------------------
7929 
7930 //
7931 // Wavelet basis functions without modulo arithmetic; they produce
7932 // the best compression ratios when the wavelet-transformed data are
7933 // Huffman-encoded, but the wavelet transform works only for 14-bit
7934 // data (untransformed data values must be less than (1 << 14)).
7935 //
7936 
wenc14(unsigned short a,unsigned short b,unsigned short & l,unsigned short & h)7937 inline void wenc14(unsigned short a, unsigned short b, unsigned short &l,
7938                    unsigned short &h) {
7939   short as = static_cast<short>(a);
7940   short bs = static_cast<short>(b);
7941 
7942   short ms = (as + bs) >> 1;
7943   short ds = as - bs;
7944 
7945   l = static_cast<unsigned short>(ms);
7946   h = static_cast<unsigned short>(ds);
7947 }
7948 
wdec14(unsigned short l,unsigned short h,unsigned short & a,unsigned short & b)7949 inline void wdec14(unsigned short l, unsigned short h, unsigned short &a,
7950                    unsigned short &b) {
7951   short ls = static_cast<short>(l);
7952   short hs = static_cast<short>(h);
7953 
7954   int hi = hs;
7955   int ai = ls + (hi & 1) + (hi >> 1);
7956 
7957   short as = static_cast<short>(ai);
7958   short bs = static_cast<short>(ai - hi);
7959 
7960   a = static_cast<unsigned short>(as);
7961   b = static_cast<unsigned short>(bs);
7962 }
7963 
7964 //
7965 // Wavelet basis functions with modulo arithmetic; they work with full
7966 // 16-bit data, but Huffman-encoding the wavelet-transformed data doesn't
7967 // compress the data quite as well.
7968 //
7969 
7970 const int NBITS = 16;
7971 const int A_OFFSET = 1 << (NBITS - 1);
7972 const int M_OFFSET = 1 << (NBITS - 1);
7973 const int MOD_MASK = (1 << NBITS) - 1;
7974 
wenc16(unsigned short a,unsigned short b,unsigned short & l,unsigned short & h)7975 inline void wenc16(unsigned short a, unsigned short b, unsigned short &l,
7976                    unsigned short &h) {
7977   int ao = (a + A_OFFSET) & MOD_MASK;
7978   int m = ((ao + b) >> 1);
7979   int d = ao - b;
7980 
7981   if (d < 0) m = (m + M_OFFSET) & MOD_MASK;
7982 
7983   d &= MOD_MASK;
7984 
7985   l = static_cast<unsigned short>(m);
7986   h = static_cast<unsigned short>(d);
7987 }
7988 
wdec16(unsigned short l,unsigned short h,unsigned short & a,unsigned short & b)7989 inline void wdec16(unsigned short l, unsigned short h, unsigned short &a,
7990                    unsigned short &b) {
7991   int m = l;
7992   int d = h;
7993   int bb = (m - (d >> 1)) & MOD_MASK;
7994   int aa = (d + bb - A_OFFSET) & MOD_MASK;
7995   b = static_cast<unsigned short>(bb);
7996   a = static_cast<unsigned short>(aa);
7997 }
7998 
7999 //
8000 // 2D Wavelet encoding:
8001 //
8002 
wav2Encode(unsigned short * in,int nx,int ox,int ny,int oy,unsigned short mx)8003 static void wav2Encode(
8004     unsigned short *in,  // io: values are transformed in place
8005     int nx,              // i : x size
8006     int ox,              // i : x offset
8007     int ny,              // i : y size
8008     int oy,              // i : y offset
8009     unsigned short mx)   // i : maximum in[x][y] value
8010 {
8011   bool w14 = (mx < (1 << 14));
8012   int n = (nx > ny) ? ny : nx;
8013   int p = 1;   // == 1 <<  level
8014   int p2 = 2;  // == 1 << (level+1)
8015 
8016   //
8017   // Hierachical loop on smaller dimension n
8018   //
8019 
8020   while (p2 <= n) {
8021     unsigned short *py = in;
8022     unsigned short *ey = in + oy * (ny - p2);
8023     int oy1 = oy * p;
8024     int oy2 = oy * p2;
8025     int ox1 = ox * p;
8026     int ox2 = ox * p2;
8027     unsigned short i00, i01, i10, i11;
8028 
8029     //
8030     // Y loop
8031     //
8032 
8033     for (; py <= ey; py += oy2) {
8034       unsigned short *px = py;
8035       unsigned short *ex = py + ox * (nx - p2);
8036 
8037       //
8038       // X loop
8039       //
8040 
8041       for (; px <= ex; px += ox2) {
8042         unsigned short *p01 = px + ox1;
8043         unsigned short *p10 = px + oy1;
8044         unsigned short *p11 = p10 + ox1;
8045 
8046         //
8047         // 2D wavelet encoding
8048         //
8049 
8050         if (w14) {
8051           wenc14(*px, *p01, i00, i01);
8052           wenc14(*p10, *p11, i10, i11);
8053           wenc14(i00, i10, *px, *p10);
8054           wenc14(i01, i11, *p01, *p11);
8055         } else {
8056           wenc16(*px, *p01, i00, i01);
8057           wenc16(*p10, *p11, i10, i11);
8058           wenc16(i00, i10, *px, *p10);
8059           wenc16(i01, i11, *p01, *p11);
8060         }
8061       }
8062 
8063       //
8064       // Encode (1D) odd column (still in Y loop)
8065       //
8066 
8067       if (nx & p) {
8068         unsigned short *p10 = px + oy1;
8069 
8070         if (w14)
8071           wenc14(*px, *p10, i00, *p10);
8072         else
8073           wenc16(*px, *p10, i00, *p10);
8074 
8075         *px = i00;
8076       }
8077     }
8078 
8079     //
8080     // Encode (1D) odd line (must loop in X)
8081     //
8082 
8083     if (ny & p) {
8084       unsigned short *px = py;
8085       unsigned short *ex = py + ox * (nx - p2);
8086 
8087       for (; px <= ex; px += ox2) {
8088         unsigned short *p01 = px + ox1;
8089 
8090         if (w14)
8091           wenc14(*px, *p01, i00, *p01);
8092         else
8093           wenc16(*px, *p01, i00, *p01);
8094 
8095         *px = i00;
8096       }
8097     }
8098 
8099     //
8100     // Next level
8101     //
8102 
8103     p = p2;
8104     p2 <<= 1;
8105   }
8106 }
8107 
8108 //
8109 // 2D Wavelet decoding:
8110 //
8111 
wav2Decode(unsigned short * in,int nx,int ox,int ny,int oy,unsigned short mx)8112 static void wav2Decode(
8113     unsigned short *in,  // io: values are transformed in place
8114     int nx,              // i : x size
8115     int ox,              // i : x offset
8116     int ny,              // i : y size
8117     int oy,              // i : y offset
8118     unsigned short mx)   // i : maximum in[x][y] value
8119 {
8120   bool w14 = (mx < (1 << 14));
8121   int n = (nx > ny) ? ny : nx;
8122   int p = 1;
8123   int p2;
8124 
8125   //
8126   // Search max level
8127   //
8128 
8129   while (p <= n) p <<= 1;
8130 
8131   p >>= 1;
8132   p2 = p;
8133   p >>= 1;
8134 
8135   //
8136   // Hierarchical loop on smaller dimension n
8137   //
8138 
8139   while (p >= 1) {
8140     unsigned short *py = in;
8141     unsigned short *ey = in + oy * (ny - p2);
8142     int oy1 = oy * p;
8143     int oy2 = oy * p2;
8144     int ox1 = ox * p;
8145     int ox2 = ox * p2;
8146     unsigned short i00, i01, i10, i11;
8147 
8148     //
8149     // Y loop
8150     //
8151 
8152     for (; py <= ey; py += oy2) {
8153       unsigned short *px = py;
8154       unsigned short *ex = py + ox * (nx - p2);
8155 
8156       //
8157       // X loop
8158       //
8159 
8160       for (; px <= ex; px += ox2) {
8161         unsigned short *p01 = px + ox1;
8162         unsigned short *p10 = px + oy1;
8163         unsigned short *p11 = p10 + ox1;
8164 
8165         //
8166         // 2D wavelet decoding
8167         //
8168 
8169         if (w14) {
8170           wdec14(*px, *p10, i00, i10);
8171           wdec14(*p01, *p11, i01, i11);
8172           wdec14(i00, i01, *px, *p01);
8173           wdec14(i10, i11, *p10, *p11);
8174         } else {
8175           wdec16(*px, *p10, i00, i10);
8176           wdec16(*p01, *p11, i01, i11);
8177           wdec16(i00, i01, *px, *p01);
8178           wdec16(i10, i11, *p10, *p11);
8179         }
8180       }
8181 
8182       //
8183       // Decode (1D) odd column (still in Y loop)
8184       //
8185 
8186       if (nx & p) {
8187         unsigned short *p10 = px + oy1;
8188 
8189         if (w14)
8190           wdec14(*px, *p10, i00, *p10);
8191         else
8192           wdec16(*px, *p10, i00, *p10);
8193 
8194         *px = i00;
8195       }
8196     }
8197 
8198     //
8199     // Decode (1D) odd line (must loop in X)
8200     //
8201 
8202     if (ny & p) {
8203       unsigned short *px = py;
8204       unsigned short *ex = py + ox * (nx - p2);
8205 
8206       for (; px <= ex; px += ox2) {
8207         unsigned short *p01 = px + ox1;
8208 
8209         if (w14)
8210           wdec14(*px, *p01, i00, *p01);
8211         else
8212           wdec16(*px, *p01, i00, *p01);
8213 
8214         *px = i00;
8215       }
8216     }
8217 
8218     //
8219     // Next level
8220     //
8221 
8222     p2 = p;
8223     p >>= 1;
8224   }
8225 }
8226 
8227 //-----------------------------------------------------------------------------
8228 //
8229 //  16-bit Huffman compression and decompression.
8230 //
8231 //  The source code in this file is derived from the 8-bit
8232 //  Huffman compression and decompression routines written
8233 //  by Christian Rouet for his PIZ image file format.
8234 //
8235 //-----------------------------------------------------------------------------
8236 
8237 // Adds some modification for tinyexr.
8238 
8239 const int HUF_ENCBITS = 16;  // literal (value) bit length
8240 const int HUF_DECBITS = 14;  // decoding bit size (>= 8)
8241 
8242 const int HUF_ENCSIZE = (1 << HUF_ENCBITS) + 1;  // encoding table size
8243 const int HUF_DECSIZE = 1 << HUF_DECBITS;        // decoding table size
8244 const int HUF_DECMASK = HUF_DECSIZE - 1;
8245 
8246 struct HufDec {  // short code    long code
8247   //-------------------------------
8248   int len : 8;   // code length    0
8249   int lit : 24;  // lit      p size
8250   int *p;        // 0      lits
8251 };
8252 
hufLength(long long code)8253 inline long long hufLength(long long code) { return code & 63; }
8254 
hufCode(long long code)8255 inline long long hufCode(long long code) { return code >> 6; }
8256 
outputBits(int nBits,long long bits,long long & c,int & lc,char * & out)8257 inline void outputBits(int nBits, long long bits, long long &c, int &lc,
8258                        char *&out) {
8259   c <<= nBits;
8260   lc += nBits;
8261 
8262   c |= bits;
8263 
8264   while (lc >= 8) *out++ = static_cast<char>((c >> (lc -= 8)));
8265 }
8266 
getBits(int nBits,long long & c,int & lc,const char * & in)8267 inline long long getBits(int nBits, long long &c, int &lc, const char *&in) {
8268   while (lc < nBits) {
8269     c = (c << 8) | *(reinterpret_cast<const unsigned char *>(in++));
8270     lc += 8;
8271   }
8272 
8273   lc -= nBits;
8274   return (c >> lc) & ((1 << nBits) - 1);
8275 }
8276 
8277 //
8278 // ENCODING TABLE BUILDING & (UN)PACKING
8279 //
8280 
8281 //
8282 // Build a "canonical" Huffman code table:
8283 //  - for each (uncompressed) symbol, hcode contains the length
8284 //    of the corresponding code (in the compressed data)
8285 //  - canonical codes are computed and stored in hcode
8286 //  - the rules for constructing canonical codes are as follows:
8287 //    * shorter codes (if filled with zeroes to the right)
8288 //      have a numerically higher value than longer codes
8289 //    * for codes with the same length, numerical values
8290 //      increase with numerical symbol values
8291 //  - because the canonical code table can be constructed from
8292 //    symbol lengths alone, the code table can be transmitted
8293 //    without sending the actual code values
8294 //  - see http://www.compressconsult.com/huffman/
8295 //
8296 
hufCanonicalCodeTable(long long hcode[HUF_ENCSIZE])8297 static void hufCanonicalCodeTable(long long hcode[HUF_ENCSIZE]) {
8298   long long n[59];
8299 
8300   //
8301   // For each i from 0 through 58, count the
8302   // number of different codes of length i, and
8303   // store the count in n[i].
8304   //
8305 
8306   for (int i = 0; i <= 58; ++i) n[i] = 0;
8307 
8308   for (int i = 0; i < HUF_ENCSIZE; ++i) n[hcode[i]] += 1;
8309 
8310   //
8311   // For each i from 58 through 1, compute the
8312   // numerically lowest code with length i, and
8313   // store that code in n[i].
8314   //
8315 
8316   long long c = 0;
8317 
8318   for (int i = 58; i > 0; --i) {
8319     long long nc = ((c + n[i]) >> 1);
8320     n[i] = c;
8321     c = nc;
8322   }
8323 
8324   //
8325   // hcode[i] contains the length, l, of the
8326   // code for symbol i.  Assign the next available
8327   // code of length l to the symbol and store both
8328   // l and the code in hcode[i].
8329   //
8330 
8331   for (int i = 0; i < HUF_ENCSIZE; ++i) {
8332     int l = static_cast<int>(hcode[i]);
8333 
8334     if (l > 0) hcode[i] = l | (n[l]++ << 6);
8335   }
8336 }
8337 
8338 //
8339 // Compute Huffman codes (based on frq input) and store them in frq:
8340 //  - code structure is : [63:lsb - 6:msb] | [5-0: bit length];
8341 //  - max code length is 58 bits;
8342 //  - codes outside the range [im-iM] have a null length (unused values);
8343 //  - original frequencies are destroyed;
8344 //  - encoding tables are used by hufEncode() and hufBuildDecTable();
8345 //
8346 
8347 struct FHeapCompare {
operatorFHeapCompare8348   bool operator()(long long *a, long long *b) { return *a > *b; }
8349 };
8350 
hufBuildEncTable(long long * frq,int * im,int * iM)8351 static void hufBuildEncTable(
8352     long long *frq,  // io: input frequencies [HUF_ENCSIZE], output table
8353     int *im,         //  o: min frq index
8354     int *iM)         //  o: max frq index
8355 {
8356   //
8357   // This function assumes that when it is called, array frq
8358   // indicates the frequency of all possible symbols in the data
8359   // that are to be Huffman-encoded.  (frq[i] contains the number
8360   // of occurrences of symbol i in the data.)
8361   //
8362   // The loop below does three things:
8363   //
8364   // 1) Finds the minimum and maximum indices that point
8365   //    to non-zero entries in frq:
8366   //
8367   //     frq[im] != 0, and frq[i] == 0 for all i < im
8368   //     frq[iM] != 0, and frq[i] == 0 for all i > iM
8369   //
8370   // 2) Fills array fHeap with pointers to all non-zero
8371   //    entries in frq.
8372   //
8373   // 3) Initializes array hlink such that hlink[i] == i
8374   //    for all array entries.
8375   //
8376 
8377   std::vector<int> hlink(HUF_ENCSIZE);
8378   std::vector<long long *> fHeap(HUF_ENCSIZE);
8379 
8380   *im = 0;
8381 
8382   while (!frq[*im]) (*im)++;
8383 
8384   int nf = 0;
8385 
8386   for (int i = *im; i < HUF_ENCSIZE; i++) {
8387     hlink[i] = i;
8388 
8389     if (frq[i]) {
8390       fHeap[nf] = &frq[i];
8391       nf++;
8392       *iM = i;
8393     }
8394   }
8395 
8396   //
8397   // Add a pseudo-symbol, with a frequency count of 1, to frq;
8398   // adjust the fHeap and hlink array accordingly.  Function
8399   // hufEncode() uses the pseudo-symbol for run-length encoding.
8400   //
8401 
8402   (*iM)++;
8403   frq[*iM] = 1;
8404   fHeap[nf] = &frq[*iM];
8405   nf++;
8406 
8407   //
8408   // Build an array, scode, such that scode[i] contains the number
8409   // of bits assigned to symbol i.  Conceptually this is done by
8410   // constructing a tree whose leaves are the symbols with non-zero
8411   // frequency:
8412   //
8413   //     Make a heap that contains all symbols with a non-zero frequency,
8414   //     with the least frequent symbol on top.
8415   //
8416   //     Repeat until only one symbol is left on the heap:
8417   //
8418   //         Take the two least frequent symbols off the top of the heap.
8419   //         Create a new node that has first two nodes as children, and
8420   //         whose frequency is the sum of the frequencies of the first
8421   //         two nodes.  Put the new node back into the heap.
8422   //
8423   // The last node left on the heap is the root of the tree.  For each
8424   // leaf node, the distance between the root and the leaf is the length
8425   // of the code for the corresponding symbol.
8426   //
8427   // The loop below doesn't actually build the tree; instead we compute
8428   // the distances of the leaves from the root on the fly.  When a new
8429   // node is added to the heap, then that node's descendants are linked
8430   // into a single linear list that starts at the new node, and the code
8431   // lengths of the descendants (that is, their distance from the root
8432   // of the tree) are incremented by one.
8433   //
8434 
8435   std::make_heap(&fHeap[0], &fHeap[nf], FHeapCompare());
8436 
8437   std::vector<long long> scode(HUF_ENCSIZE);
8438   memset(scode.data(), 0, sizeof(long long) * HUF_ENCSIZE);
8439 
8440   while (nf > 1) {
8441     //
8442     // Find the indices, mm and m, of the two smallest non-zero frq
8443     // values in fHeap, add the smallest frq to the second-smallest
8444     // frq, and remove the smallest frq value from fHeap.
8445     //
8446 
8447     int mm = fHeap[0] - frq;
8448     std::pop_heap(&fHeap[0], &fHeap[nf], FHeapCompare());
8449     --nf;
8450 
8451     int m = fHeap[0] - frq;
8452     std::pop_heap(&fHeap[0], &fHeap[nf], FHeapCompare());
8453 
8454     frq[m] += frq[mm];
8455     std::push_heap(&fHeap[0], &fHeap[nf], FHeapCompare());
8456 
8457     //
8458     // The entries in scode are linked into lists with the
8459     // entries in hlink serving as "next" pointers and with
8460     // the end of a list marked by hlink[j] == j.
8461     //
8462     // Traverse the lists that start at scode[m] and scode[mm].
8463     // For each element visited, increment the length of the
8464     // corresponding code by one bit. (If we visit scode[j]
8465     // during the traversal, then the code for symbol j becomes
8466     // one bit longer.)
8467     //
8468     // Merge the lists that start at scode[m] and scode[mm]
8469     // into a single list that starts at scode[m].
8470     //
8471 
8472     //
8473     // Add a bit to all codes in the first list.
8474     //
8475 
8476     for (int j = m;; j = hlink[j]) {
8477       scode[j]++;
8478 
8479       assert(scode[j] <= 58);
8480 
8481       if (hlink[j] == j) {
8482         //
8483         // Merge the two lists.
8484         //
8485 
8486         hlink[j] = mm;
8487         break;
8488       }
8489     }
8490 
8491     //
8492     // Add a bit to all codes in the second list
8493     //
8494 
8495     for (int j = mm;; j = hlink[j]) {
8496       scode[j]++;
8497 
8498       assert(scode[j] <= 58);
8499 
8500       if (hlink[j] == j) break;
8501     }
8502   }
8503 
8504   //
8505   // Build a canonical Huffman code table, replacing the code
8506   // lengths in scode with (code, code length) pairs.  Copy the
8507   // code table from scode into frq.
8508   //
8509 
8510   hufCanonicalCodeTable(scode.data());
8511   memcpy(frq, scode.data(), sizeof(long long) * HUF_ENCSIZE);
8512 }
8513 
8514 //
8515 // Pack an encoding table:
8516 //  - only code lengths, not actual codes, are stored
8517 //  - runs of zeroes are compressed as follows:
8518 //
8519 //    unpacked    packed
8520 //    --------------------------------
8521 //    1 zero    0  (6 bits)
8522 //    2 zeroes    59
8523 //    3 zeroes    60
8524 //    4 zeroes    61
8525 //    5 zeroes    62
8526 //    n zeroes (6 or more)  63 n-6  (6 + 8 bits)
8527 //
8528 
8529 const int SHORT_ZEROCODE_RUN = 59;
8530 const int LONG_ZEROCODE_RUN = 63;
8531 const int SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN;
8532 const int LONGEST_LONG_RUN = 255 + SHORTEST_LONG_RUN;
8533 
hufPackEncTable(const long long * hcode,int im,int iM,char ** pcode)8534 static void hufPackEncTable(
8535     const long long *hcode,  // i : encoding table [HUF_ENCSIZE]
8536     int im,                  // i : min hcode index
8537     int iM,                  // i : max hcode index
8538     char **pcode)            //  o: ptr to packed table (updated)
8539 {
8540   char *p = *pcode;
8541   long long c = 0;
8542   int lc = 0;
8543 
8544   for (; im <= iM; im++) {
8545     int l = hufLength(hcode[im]);
8546 
8547     if (l == 0) {
8548       int zerun = 1;
8549 
8550       while ((im < iM) && (zerun < LONGEST_LONG_RUN)) {
8551         if (hufLength(hcode[im + 1]) > 0) break;
8552         im++;
8553         zerun++;
8554       }
8555 
8556       if (zerun >= 2) {
8557         if (zerun >= SHORTEST_LONG_RUN) {
8558           outputBits(6, LONG_ZEROCODE_RUN, c, lc, p);
8559           outputBits(8, zerun - SHORTEST_LONG_RUN, c, lc, p);
8560         } else {
8561           outputBits(6, SHORT_ZEROCODE_RUN + zerun - 2, c, lc, p);
8562         }
8563         continue;
8564       }
8565     }
8566 
8567     outputBits(6, l, c, lc, p);
8568   }
8569 
8570   if (lc > 0) *p++ = (unsigned char)(c << (8 - lc));
8571 
8572   *pcode = p;
8573 }
8574 
8575 //
8576 // Unpack an encoding table packed by hufPackEncTable():
8577 //
8578 
hufUnpackEncTable(const char ** pcode,int ni,int im,int iM,long long * hcode)8579 static bool hufUnpackEncTable(
8580     const char **pcode,  // io: ptr to packed table (updated)
8581     int ni,              // i : input size (in bytes)
8582     int im,              // i : min hcode index
8583     int iM,              // i : max hcode index
8584     long long *hcode)    //  o: encoding table [HUF_ENCSIZE]
8585 {
8586   memset(hcode, 0, sizeof(long long) * HUF_ENCSIZE);
8587 
8588   const char *p = *pcode;
8589   long long c = 0;
8590   int lc = 0;
8591 
8592   for (; im <= iM; im++) {
8593     if (p - *pcode >= ni) {
8594       return false;
8595     }
8596 
8597     long long l = hcode[im] = getBits(6, c, lc, p);  // code length
8598 
8599     if (l == (long long)LONG_ZEROCODE_RUN) {
8600       if (p - *pcode > ni) {
8601         return false;
8602       }
8603 
8604       int zerun = getBits(8, c, lc, p) + SHORTEST_LONG_RUN;
8605 
8606       if (im + zerun > iM + 1) {
8607         return false;
8608       }
8609 
8610       while (zerun--) hcode[im++] = 0;
8611 
8612       im--;
8613     } else if (l >= (long long)SHORT_ZEROCODE_RUN) {
8614       int zerun = l - SHORT_ZEROCODE_RUN + 2;
8615 
8616       if (im + zerun > iM + 1) {
8617         return false;
8618       }
8619 
8620       while (zerun--) hcode[im++] = 0;
8621 
8622       im--;
8623     }
8624   }
8625 
8626   *pcode = const_cast<char *>(p);
8627 
8628   hufCanonicalCodeTable(hcode);
8629 
8630   return true;
8631 }
8632 
8633 //
8634 // DECODING TABLE BUILDING
8635 //
8636 
8637 //
8638 // Clear a newly allocated decoding table so that it contains only zeroes.
8639 //
8640 
hufClearDecTable(HufDec * hdecod)8641 static void hufClearDecTable(HufDec *hdecod)  // io: (allocated by caller)
8642 //     decoding table [HUF_DECSIZE]
8643 {
8644   for (int i = 0; i < HUF_DECSIZE; i++) {
8645     hdecod[i].len = 0;
8646     hdecod[i].lit = 0;
8647     hdecod[i].p = NULL;
8648   }
8649   // memset(hdecod, 0, sizeof(HufDec) * HUF_DECSIZE);
8650 }
8651 
8652 //
8653 // Build a decoding hash table based on the encoding table hcode:
8654 //  - short codes (<= HUF_DECBITS) are resolved with a single table access;
8655 //  - long code entry allocations are not optimized, because long codes are
8656 //    unfrequent;
8657 //  - decoding tables are used by hufDecode();
8658 //
8659 
hufBuildDecTable(const long long * hcode,int im,int iM,HufDec * hdecod)8660 static bool hufBuildDecTable(const long long *hcode,  // i : encoding table
8661                              int im,                  // i : min index in hcode
8662                              int iM,                  // i : max index in hcode
8663                              HufDec *hdecod)  //  o: (allocated by caller)
8664 //     decoding table [HUF_DECSIZE]
8665 {
8666   //
8667   // Init hashtable & loop on all codes.
8668   // Assumes that hufClearDecTable(hdecod) has already been called.
8669   //
8670 
8671   for (; im <= iM; im++) {
8672     long long c = hufCode(hcode[im]);
8673     int l = hufLength(hcode[im]);
8674 
8675     if (c >> l) {
8676       //
8677       // Error: c is supposed to be an l-bit code,
8678       // but c contains a value that is greater
8679       // than the largest l-bit number.
8680       //
8681 
8682       // invalidTableEntry();
8683       return false;
8684     }
8685 
8686     if (l > HUF_DECBITS) {
8687       //
8688       // Long code: add a secondary entry
8689       //
8690 
8691       HufDec *pl = hdecod + (c >> (l - HUF_DECBITS));
8692 
8693       if (pl->len) {
8694         //
8695         // Error: a short code has already
8696         // been stored in table entry *pl.
8697         //
8698 
8699         // invalidTableEntry();
8700         return false;
8701       }
8702 
8703       pl->lit++;
8704 
8705       if (pl->p) {
8706         int *p = pl->p;
8707         pl->p = new int[pl->lit];
8708 
8709         for (int i = 0; i < pl->lit - 1; ++i) pl->p[i] = p[i];
8710 
8711         delete[] p;
8712       } else {
8713         pl->p = new int[1];
8714       }
8715 
8716       pl->p[pl->lit - 1] = im;
8717     } else if (l) {
8718       //
8719       // Short code: init all primary entries
8720       //
8721 
8722       HufDec *pl = hdecod + (c << (HUF_DECBITS - l));
8723 
8724       for (long long i = 1ULL << (HUF_DECBITS - l); i > 0; i--, pl++) {
8725         if (pl->len || pl->p) {
8726           //
8727           // Error: a short code or a long code has
8728           // already been stored in table entry *pl.
8729           //
8730 
8731           // invalidTableEntry();
8732           return false;
8733         }
8734 
8735         pl->len = l;
8736         pl->lit = im;
8737       }
8738     }
8739   }
8740 
8741   return true;
8742 }
8743 
8744 //
8745 // Free the long code entries of a decoding table built by hufBuildDecTable()
8746 //
8747 
hufFreeDecTable(HufDec * hdecod)8748 static void hufFreeDecTable(HufDec *hdecod)  // io: Decoding table
8749 {
8750   for (int i = 0; i < HUF_DECSIZE; i++) {
8751     if (hdecod[i].p) {
8752       delete[] hdecod[i].p;
8753       hdecod[i].p = 0;
8754     }
8755   }
8756 }
8757 
8758 //
8759 // ENCODING
8760 //
8761 
outputCode(long long code,long long & c,int & lc,char * & out)8762 inline void outputCode(long long code, long long &c, int &lc, char *&out) {
8763   outputBits(hufLength(code), hufCode(code), c, lc, out);
8764 }
8765 
sendCode(long long sCode,int runCount,long long runCode,long long & c,int & lc,char * & out)8766 inline void sendCode(long long sCode, int runCount, long long runCode,
8767                      long long &c, int &lc, char *&out) {
8768   //
8769   // Output a run of runCount instances of the symbol sCount.
8770   // Output the symbols explicitly, or if that is shorter, output
8771   // the sCode symbol once followed by a runCode symbol and runCount
8772   // expressed as an 8-bit number.
8773   //
8774 
8775   if (hufLength(sCode) + hufLength(runCode) + 8 < hufLength(sCode) * runCount) {
8776     outputCode(sCode, c, lc, out);
8777     outputCode(runCode, c, lc, out);
8778     outputBits(8, runCount, c, lc, out);
8779   } else {
8780     while (runCount-- >= 0) outputCode(sCode, c, lc, out);
8781   }
8782 }
8783 
8784 //
8785 // Encode (compress) ni values based on the Huffman encoding table hcode:
8786 //
8787 
hufEncode(const long long * hcode,const unsigned short * in,const int ni,int rlc,char * out)8788 static int hufEncode            // return: output size (in bits)
8789     (const long long *hcode,    // i : encoding table
8790      const unsigned short *in,  // i : uncompressed input buffer
8791      const int ni,              // i : input buffer size (in bytes)
8792      int rlc,                   // i : rl code
8793      char *out)                 //  o: compressed output buffer
8794 {
8795   char *outStart = out;
8796   long long c = 0;  // bits not yet written to out
8797   int lc = 0;       // number of valid bits in c (LSB)
8798   int s = in[0];
8799   int cs = 0;
8800 
8801   //
8802   // Loop on input values
8803   //
8804 
8805   for (int i = 1; i < ni; i++) {
8806     //
8807     // Count same values or send code
8808     //
8809 
8810     if (s == in[i] && cs < 255) {
8811       cs++;
8812     } else {
8813       sendCode(hcode[s], cs, hcode[rlc], c, lc, out);
8814       cs = 0;
8815     }
8816 
8817     s = in[i];
8818   }
8819 
8820   //
8821   // Send remaining code
8822   //
8823 
8824   sendCode(hcode[s], cs, hcode[rlc], c, lc, out);
8825 
8826   if (lc) *out = (c << (8 - lc)) & 0xff;
8827 
8828   return (out - outStart) * 8 + lc;
8829 }
8830 
8831 //
8832 // DECODING
8833 //
8834 
8835 //
8836 // In order to force the compiler to inline them,
8837 // getChar() and getCode() are implemented as macros
8838 // instead of "inline" functions.
8839 //
8840 
8841 #define getChar(c, lc, in)                   \
8842   {                                          \
8843     c = (c << 8) | *(unsigned char *)(in++); \
8844     lc += 8;                                 \
8845   }
8846 
8847 #if 0
8848 #define getCode(po, rlc, c, lc, in, out, ob, oe) \
8849   {                                              \
8850     if (po == rlc) {                             \
8851       if (lc < 8) getChar(c, lc, in);            \
8852                                                  \
8853       lc -= 8;                                   \
8854                                                  \
8855       unsigned char cs = (c >> lc);              \
8856                                                  \
8857       if (out + cs > oe) return false;           \
8858                                                  \
8859       /* TinyEXR issue 78 */                     \
8860       unsigned short s = out[-1];                \
8861                                                  \
8862       while (cs-- > 0) *out++ = s;               \
8863     } else if (out < oe) {                       \
8864       *out++ = po;                               \
8865     } else {                                     \
8866       return false;                              \
8867     }                                            \
8868   }
8869 #else
getCode(int po,int rlc,long long & c,int & lc,const char * & in,const char * in_end,unsigned short * & out,const unsigned short * ob,const unsigned short * oe)8870 static bool getCode(int po, int rlc, long long &c, int &lc, const char *&in,
8871                     const char *in_end, unsigned short *&out,
8872                     const unsigned short *ob, const unsigned short *oe) {
8873   (void)ob;
8874   if (po == rlc) {
8875     if (lc < 8) {
8876       /* TinyEXR issue 78 */
8877       if ((in + 1) >= in_end) {
8878         return false;
8879       }
8880 
8881       getChar(c, lc, in);
8882     }
8883 
8884     lc -= 8;
8885 
8886     unsigned char cs = (c >> lc);
8887 
8888     if (out + cs > oe) return false;
8889 
8890     // Bounds check for safety
8891     // Issue 100.
8892     if ((out - 1) < ob) return false;
8893     unsigned short s = out[-1];
8894 
8895     while (cs-- > 0) *out++ = s;
8896   } else if (out < oe) {
8897     *out++ = po;
8898   } else {
8899     return false;
8900   }
8901   return true;
8902 }
8903 #endif
8904 
8905 //
8906 // Decode (uncompress) ni bits based on encoding & decoding tables:
8907 //
8908 
hufDecode(const long long * hcode,const HufDec * hdecod,const char * in,int ni,int rlc,int no,unsigned short * out)8909 static bool hufDecode(const long long *hcode,  // i : encoding table
8910                       const HufDec *hdecod,    // i : decoding table
8911                       const char *in,          // i : compressed input buffer
8912                       int ni,                  // i : input size (in bits)
8913                       int rlc,                 // i : run-length code
8914                       int no,  // i : expected output size (in bytes)
8915                       unsigned short *out)  //  o: uncompressed output buffer
8916 {
8917   long long c = 0;
8918   int lc = 0;
8919   unsigned short *outb = out;          // begin
8920   unsigned short *oe = out + no;       // end
8921   const char *ie = in + (ni + 7) / 8;  // input byte size
8922 
8923   //
8924   // Loop on input bytes
8925   //
8926 
8927   while (in < ie) {
8928     getChar(c, lc, in);
8929 
8930     //
8931     // Access decoding table
8932     //
8933 
8934     while (lc >= HUF_DECBITS) {
8935       const HufDec pl = hdecod[(c >> (lc - HUF_DECBITS)) & HUF_DECMASK];
8936 
8937       if (pl.len) {
8938         //
8939         // Get short code
8940         //
8941 
8942         lc -= pl.len;
8943         // std::cout << "lit = " << pl.lit << std::endl;
8944         // std::cout << "rlc = " << rlc << std::endl;
8945         // std::cout << "c = " << c << std::endl;
8946         // std::cout << "lc = " << lc << std::endl;
8947         // std::cout << "in = " << in << std::endl;
8948         // std::cout << "out = " << out << std::endl;
8949         // std::cout << "oe = " << oe << std::endl;
8950         if (!getCode(pl.lit, rlc, c, lc, in, ie, out, outb, oe)) {
8951           return false;
8952         }
8953       } else {
8954         if (!pl.p) {
8955           return false;
8956         }
8957         // invalidCode(); // wrong code
8958 
8959         //
8960         // Search long code
8961         //
8962 
8963         int j;
8964 
8965         for (j = 0; j < pl.lit; j++) {
8966           int l = hufLength(hcode[pl.p[j]]);
8967 
8968           while (lc < l && in < ie)  // get more bits
8969             getChar(c, lc, in);
8970 
8971           if (lc >= l) {
8972             if (hufCode(hcode[pl.p[j]]) ==
8973                 ((c >> (lc - l)) & (((long long)(1) << l) - 1))) {
8974               //
8975               // Found : get long code
8976               //
8977 
8978               lc -= l;
8979               if (!getCode(pl.p[j], rlc, c, lc, in, ie, out, outb, oe)) {
8980                 return false;
8981               }
8982               break;
8983             }
8984           }
8985         }
8986 
8987         if (j == pl.lit) {
8988           return false;
8989           // invalidCode(); // Not found
8990         }
8991       }
8992     }
8993   }
8994 
8995   //
8996   // Get remaining (short) codes
8997   //
8998 
8999   int i = (8 - ni) & 7;
9000   c >>= i;
9001   lc -= i;
9002 
9003   while (lc > 0) {
9004     const HufDec pl = hdecod[(c << (HUF_DECBITS - lc)) & HUF_DECMASK];
9005 
9006     if (pl.len) {
9007       lc -= pl.len;
9008       if (!getCode(pl.lit, rlc, c, lc, in, ie, out, outb, oe)) {
9009         return false;
9010       }
9011     } else {
9012       return false;
9013       // invalidCode(); // wrong (long) code
9014     }
9015   }
9016 
9017   if (out - outb != no) {
9018     return false;
9019   }
9020   // notEnoughData ();
9021 
9022   return true;
9023 }
9024 
countFrequencies(std::vector<long long> & freq,const unsigned short data[],int n)9025 static void countFrequencies(std::vector<long long> &freq,
9026                              const unsigned short data[/*n*/], int n) {
9027   for (int i = 0; i < HUF_ENCSIZE; ++i) freq[i] = 0;
9028 
9029   for (int i = 0; i < n; ++i) ++freq[data[i]];
9030 }
9031 
writeUInt(char buf[4],unsigned int i)9032 static void writeUInt(char buf[4], unsigned int i) {
9033   unsigned char *b = (unsigned char *)buf;
9034 
9035   b[0] = i;
9036   b[1] = i >> 8;
9037   b[2] = i >> 16;
9038   b[3] = i >> 24;
9039 }
9040 
readUInt(const char buf[4])9041 static unsigned int readUInt(const char buf[4]) {
9042   const unsigned char *b = (const unsigned char *)buf;
9043 
9044   return (b[0] & 0x000000ff) | ((b[1] << 8) & 0x0000ff00) |
9045          ((b[2] << 16) & 0x00ff0000) | ((b[3] << 24) & 0xff000000);
9046 }
9047 
9048 //
9049 // EXTERNAL INTERFACE
9050 //
9051 
hufCompress(const unsigned short raw[],int nRaw,char compressed[])9052 static int hufCompress(const unsigned short raw[], int nRaw,
9053                        char compressed[]) {
9054   if (nRaw == 0) return 0;
9055 
9056   std::vector<long long> freq(HUF_ENCSIZE);
9057 
9058   countFrequencies(freq, raw, nRaw);
9059 
9060   int im = 0;
9061   int iM = 0;
9062   hufBuildEncTable(freq.data(), &im, &iM);
9063 
9064   char *tableStart = compressed + 20;
9065   char *tableEnd = tableStart;
9066   hufPackEncTable(freq.data(), im, iM, &tableEnd);
9067   int tableLength = tableEnd - tableStart;
9068 
9069   char *dataStart = tableEnd;
9070   int nBits = hufEncode(freq.data(), raw, nRaw, iM, dataStart);
9071   int data_length = (nBits + 7) / 8;
9072 
9073   writeUInt(compressed, im);
9074   writeUInt(compressed + 4, iM);
9075   writeUInt(compressed + 8, tableLength);
9076   writeUInt(compressed + 12, nBits);
9077   writeUInt(compressed + 16, 0);  // room for future extensions
9078 
9079   return dataStart + data_length - compressed;
9080 }
9081 
hufUncompress(const char compressed[],int nCompressed,std::vector<unsigned short> * raw)9082 static bool hufUncompress(const char compressed[], int nCompressed,
9083                           std::vector<unsigned short> *raw) {
9084   if (nCompressed == 0) {
9085     if (raw->size() != 0) return false;
9086 
9087     return false;
9088   }
9089 
9090   int im = readUInt(compressed);
9091   int iM = readUInt(compressed + 4);
9092   // int tableLength = readUInt (compressed + 8);
9093   int nBits = readUInt(compressed + 12);
9094 
9095   if (im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE) return false;
9096 
9097   const char *ptr = compressed + 20;
9098 
9099   //
9100   // Fast decoder needs at least 2x64-bits of compressed data, and
9101   // needs to be run-able on this platform. Otherwise, fall back
9102   // to the original decoder
9103   //
9104 
9105   // if (FastHufDecoder::enabled() && nBits > 128)
9106   //{
9107   //    FastHufDecoder fhd (ptr, nCompressed - (ptr - compressed), im, iM, iM);
9108   //    fhd.decode ((unsigned char*)ptr, nBits, raw, nRaw);
9109   //}
9110   // else
9111   {
9112     std::vector<long long> freq(HUF_ENCSIZE);
9113     std::vector<HufDec> hdec(HUF_DECSIZE);
9114 
9115     hufClearDecTable(&hdec.at(0));
9116 
9117     hufUnpackEncTable(&ptr, nCompressed - (ptr - compressed), im, iM,
9118                       &freq.at(0));
9119 
9120     {
9121       if (nBits > 8 * (nCompressed - (ptr - compressed))) {
9122         return false;
9123       }
9124 
9125       hufBuildDecTable(&freq.at(0), im, iM, &hdec.at(0));
9126       hufDecode(&freq.at(0), &hdec.at(0), ptr, nBits, iM, raw->size(),
9127                 raw->data());
9128     }
9129     // catch (...)
9130     //{
9131     //    hufFreeDecTable (hdec);
9132     //    throw;
9133     //}
9134 
9135     hufFreeDecTable(&hdec.at(0));
9136   }
9137 
9138   return true;
9139 }
9140 
9141 //
9142 // Functions to compress the range of values in the pixel data
9143 //
9144 
9145 const int USHORT_RANGE = (1 << 16);
9146 const int BITMAP_SIZE = (USHORT_RANGE >> 3);
9147 
bitmapFromData(const unsigned short data[],int nData,unsigned char bitmap[BITMAP_SIZE],unsigned short & minNonZero,unsigned short & maxNonZero)9148 static void bitmapFromData(const unsigned short data[/*nData*/], int nData,
9149                            unsigned char bitmap[BITMAP_SIZE],
9150                            unsigned short &minNonZero,
9151                            unsigned short &maxNonZero) {
9152   for (int i = 0; i < BITMAP_SIZE; ++i) bitmap[i] = 0;
9153 
9154   for (int i = 0; i < nData; ++i) bitmap[data[i] >> 3] |= (1 << (data[i] & 7));
9155 
9156   bitmap[0] &= ~1;  // zero is not explicitly stored in
9157                     // the bitmap; we assume that the
9158                     // data always contain zeroes
9159   minNonZero = BITMAP_SIZE - 1;
9160   maxNonZero = 0;
9161 
9162   for (int i = 0; i < BITMAP_SIZE; ++i) {
9163     if (bitmap[i]) {
9164       if (minNonZero > i) minNonZero = i;
9165       if (maxNonZero < i) maxNonZero = i;
9166     }
9167   }
9168 }
9169 
forwardLutFromBitmap(const unsigned char bitmap[BITMAP_SIZE],unsigned short lut[USHORT_RANGE])9170 static unsigned short forwardLutFromBitmap(
9171     const unsigned char bitmap[BITMAP_SIZE], unsigned short lut[USHORT_RANGE]) {
9172   int k = 0;
9173 
9174   for (int i = 0; i < USHORT_RANGE; ++i) {
9175     if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7))))
9176       lut[i] = k++;
9177     else
9178       lut[i] = 0;
9179   }
9180 
9181   return k - 1;  // maximum value stored in lut[],
9182 }  // i.e. number of ones in bitmap minus 1
9183 
reverseLutFromBitmap(const unsigned char bitmap[BITMAP_SIZE],unsigned short lut[USHORT_RANGE])9184 static unsigned short reverseLutFromBitmap(
9185     const unsigned char bitmap[BITMAP_SIZE], unsigned short lut[USHORT_RANGE]) {
9186   int k = 0;
9187 
9188   for (int i = 0; i < USHORT_RANGE; ++i) {
9189     if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7)))) lut[k++] = i;
9190   }
9191 
9192   int n = k - 1;
9193 
9194   while (k < USHORT_RANGE) lut[k++] = 0;
9195 
9196   return n;  // maximum k where lut[k] is non-zero,
9197 }  // i.e. number of ones in bitmap minus 1
9198 
applyLut(const unsigned short lut[USHORT_RANGE],unsigned short data[],int nData)9199 static void applyLut(const unsigned short lut[USHORT_RANGE],
9200                      unsigned short data[/*nData*/], int nData) {
9201   for (int i = 0; i < nData; ++i) data[i] = lut[data[i]];
9202 }
9203 
9204 #ifdef __clang__
9205 #pragma clang diagnostic pop
9206 #endif  // __clang__
9207 
9208 #ifdef _MSC_VER
9209 #pragma warning(pop)
9210 #endif
9211 
CompressPiz(unsigned char * outPtr,unsigned int * outSize,const unsigned char * inPtr,size_t inSize,const std::vector<ChannelInfo> & channelInfo,int data_width,int num_lines)9212 static bool CompressPiz(unsigned char *outPtr, unsigned int *outSize,
9213                         const unsigned char *inPtr, size_t inSize,
9214                         const std::vector<ChannelInfo> &channelInfo,
9215                         int data_width, int num_lines) {
9216   std::vector<unsigned char> bitmap(BITMAP_SIZE);
9217   unsigned short minNonZero;
9218   unsigned short maxNonZero;
9219 
9220 #if !MINIZ_LITTLE_ENDIAN
9221   // @todo { PIZ compression on BigEndian architecture. }
9222   assert(0);
9223   return false;
9224 #endif
9225 
9226   // Assume `inSize` is multiple of 2 or 4.
9227   std::vector<unsigned short> tmpBuffer(inSize / sizeof(unsigned short));
9228 
9229   std::vector<PIZChannelData> channelData(channelInfo.size());
9230   unsigned short *tmpBufferEnd = &tmpBuffer.at(0);
9231 
9232   for (size_t c = 0; c < channelData.size(); c++) {
9233     PIZChannelData &cd = channelData[c];
9234 
9235     cd.start = tmpBufferEnd;
9236     cd.end = cd.start;
9237 
9238     cd.nx = data_width;
9239     cd.ny = num_lines;
9240     // cd.ys = c.channel().ySampling;
9241 
9242     size_t pixelSize = sizeof(int);  // UINT and FLOAT
9243     if (channelInfo[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
9244       pixelSize = sizeof(short);
9245     }
9246 
9247     cd.size = static_cast<int>(pixelSize / sizeof(short));
9248 
9249     tmpBufferEnd += cd.nx * cd.ny * cd.size;
9250   }
9251 
9252   const unsigned char *ptr = inPtr;
9253   for (int y = 0; y < num_lines; ++y) {
9254     for (size_t i = 0; i < channelData.size(); ++i) {
9255       PIZChannelData &cd = channelData[i];
9256 
9257       // if (modp (y, cd.ys) != 0)
9258       //    continue;
9259 
9260       size_t n = static_cast<size_t>(cd.nx * cd.size);
9261       memcpy(cd.end, ptr, n * sizeof(unsigned short));
9262       ptr += n * sizeof(unsigned short);
9263       cd.end += n;
9264     }
9265   }
9266 
9267   bitmapFromData(&tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()),
9268                  bitmap.data(), minNonZero, maxNonZero);
9269 
9270   std::vector<unsigned short> lut(USHORT_RANGE);
9271   unsigned short maxValue = forwardLutFromBitmap(bitmap.data(), lut.data());
9272   applyLut(lut.data(), &tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()));
9273 
9274   //
9275   // Store range compression info in _outBuffer
9276   //
9277 
9278   char *buf = reinterpret_cast<char *>(outPtr);
9279 
9280   memcpy(buf, &minNonZero, sizeof(unsigned short));
9281   buf += sizeof(unsigned short);
9282   memcpy(buf, &maxNonZero, sizeof(unsigned short));
9283   buf += sizeof(unsigned short);
9284 
9285   if (minNonZero <= maxNonZero) {
9286     memcpy(buf, reinterpret_cast<char *>(&bitmap[0] + minNonZero),
9287            maxNonZero - minNonZero + 1);
9288     buf += maxNonZero - minNonZero + 1;
9289   }
9290 
9291   //
9292   // Apply wavelet encoding
9293   //
9294 
9295   for (size_t i = 0; i < channelData.size(); ++i) {
9296     PIZChannelData &cd = channelData[i];
9297 
9298     for (int j = 0; j < cd.size; ++j) {
9299       wav2Encode(cd.start + j, cd.nx, cd.size, cd.ny, cd.nx * cd.size,
9300                  maxValue);
9301     }
9302   }
9303 
9304   //
9305   // Apply Huffman encoding; append the result to _outBuffer
9306   //
9307 
9308   // length header(4byte), then huff data. Initialize length header with zero,
9309   // then later fill it by `length`.
9310   char *lengthPtr = buf;
9311   int zero = 0;
9312   memcpy(buf, &zero, sizeof(int));
9313   buf += sizeof(int);
9314 
9315   int length =
9316       hufCompress(&tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()), buf);
9317   memcpy(lengthPtr, &length, sizeof(int));
9318 
9319   (*outSize) = static_cast<unsigned int>(
9320       (reinterpret_cast<unsigned char *>(buf) - outPtr) +
9321       static_cast<unsigned int>(length));
9322 
9323   // Use uncompressed data when compressed data is larger than uncompressed.
9324   // (Issue 40)
9325   if ((*outSize) >= inSize) {
9326     (*outSize) = static_cast<unsigned int>(inSize);
9327     memcpy(outPtr, inPtr, inSize);
9328   }
9329   return true;
9330 }
9331 
DecompressPiz(unsigned char * outPtr,const unsigned char * inPtr,size_t tmpBufSize,size_t inLen,int num_channels,const EXRChannelInfo * channels,int data_width,int num_lines)9332 static bool DecompressPiz(unsigned char *outPtr, const unsigned char *inPtr,
9333                           size_t tmpBufSize, size_t inLen, int num_channels,
9334                           const EXRChannelInfo *channels, int data_width,
9335                           int num_lines) {
9336   if (inLen == tmpBufSize) {
9337     // Data is not compressed(Issue 40).
9338     memcpy(outPtr, inPtr, inLen);
9339     return true;
9340   }
9341 
9342   std::vector<unsigned char> bitmap(BITMAP_SIZE);
9343   unsigned short minNonZero;
9344   unsigned short maxNonZero;
9345 
9346 #if !MINIZ_LITTLE_ENDIAN
9347   // @todo { PIZ compression on BigEndian architecture. }
9348   assert(0);
9349   return false;
9350 #endif
9351 
9352   memset(bitmap.data(), 0, BITMAP_SIZE);
9353 
9354   const unsigned char *ptr = inPtr;
9355   // minNonZero = *(reinterpret_cast<const unsigned short *>(ptr));
9356   tinyexr::cpy2(&minNonZero, reinterpret_cast<const unsigned short *>(ptr));
9357   // maxNonZero = *(reinterpret_cast<const unsigned short *>(ptr + 2));
9358   tinyexr::cpy2(&maxNonZero, reinterpret_cast<const unsigned short *>(ptr + 2));
9359   ptr += 4;
9360 
9361   if (maxNonZero >= BITMAP_SIZE) {
9362     return false;
9363   }
9364 
9365   if (minNonZero <= maxNonZero) {
9366     memcpy(reinterpret_cast<char *>(&bitmap[0] + minNonZero), ptr,
9367            maxNonZero - minNonZero + 1);
9368     ptr += maxNonZero - minNonZero + 1;
9369   }
9370 
9371   std::vector<unsigned short> lut(USHORT_RANGE);
9372   memset(lut.data(), 0, sizeof(unsigned short) * USHORT_RANGE);
9373   unsigned short maxValue = reverseLutFromBitmap(bitmap.data(), lut.data());
9374 
9375   //
9376   // Huffman decoding
9377   //
9378 
9379   int length;
9380 
9381   // length = *(reinterpret_cast<const int *>(ptr));
9382   tinyexr::cpy4(&length, reinterpret_cast<const int *>(ptr));
9383   ptr += sizeof(int);
9384 
9385   if (size_t((ptr - inPtr) + length) > inLen) {
9386     return false;
9387   }
9388 
9389   std::vector<unsigned short> tmpBuffer(tmpBufSize);
9390   hufUncompress(reinterpret_cast<const char *>(ptr), length, &tmpBuffer);
9391 
9392   //
9393   // Wavelet decoding
9394   //
9395 
9396   std::vector<PIZChannelData> channelData(static_cast<size_t>(num_channels));
9397 
9398   unsigned short *tmpBufferEnd = &tmpBuffer.at(0);
9399 
9400   for (size_t i = 0; i < static_cast<size_t>(num_channels); ++i) {
9401     const EXRChannelInfo &chan = channels[i];
9402 
9403     size_t pixelSize = sizeof(int);  // UINT and FLOAT
9404     if (chan.pixel_type == TINYEXR_PIXELTYPE_HALF) {
9405       pixelSize = sizeof(short);
9406     }
9407 
9408     channelData[i].start = tmpBufferEnd;
9409     channelData[i].end = channelData[i].start;
9410     channelData[i].nx = data_width;
9411     channelData[i].ny = num_lines;
9412     // channelData[i].ys = 1;
9413     channelData[i].size = static_cast<int>(pixelSize / sizeof(short));
9414 
9415     tmpBufferEnd += channelData[i].nx * channelData[i].ny * channelData[i].size;
9416   }
9417 
9418   for (size_t i = 0; i < channelData.size(); ++i) {
9419     PIZChannelData &cd = channelData[i];
9420 
9421     for (int j = 0; j < cd.size; ++j) {
9422       wav2Decode(cd.start + j, cd.nx, cd.size, cd.ny, cd.nx * cd.size,
9423                  maxValue);
9424     }
9425   }
9426 
9427   //
9428   // Expand the pixel data to their original range
9429   //
9430 
9431   applyLut(lut.data(), &tmpBuffer.at(0), static_cast<int>(tmpBufSize));
9432 
9433   for (int y = 0; y < num_lines; y++) {
9434     for (size_t i = 0; i < channelData.size(); ++i) {
9435       PIZChannelData &cd = channelData[i];
9436 
9437       // if (modp (y, cd.ys) != 0)
9438       //    continue;
9439 
9440       size_t n = static_cast<size_t>(cd.nx * cd.size);
9441       memcpy(outPtr, cd.end, static_cast<size_t>(n * sizeof(unsigned short)));
9442       outPtr += n * sizeof(unsigned short);
9443       cd.end += n;
9444     }
9445   }
9446 
9447   return true;
9448 }
9449 #endif  // TINYEXR_USE_PIZ
9450 
9451 #if TINYEXR_USE_ZFP
9452 struct ZFPCompressionParam {
9453   double rate;
9454   int precision;
9455   double tolerance;
9456   int type;  // TINYEXR_ZFP_COMPRESSIONTYPE_*
9457 
ZFPCompressionParamZFPCompressionParam9458   ZFPCompressionParam() {
9459     type = TINYEXR_ZFP_COMPRESSIONTYPE_RATE;
9460     rate = 2.0;
9461     precision = 0;
9462     tolerance = 0.0f;
9463   }
9464 };
9465 
FindZFPCompressionParam(ZFPCompressionParam * param,const EXRAttribute * attributes,int num_attributes)9466 bool FindZFPCompressionParam(ZFPCompressionParam *param,
9467                              const EXRAttribute *attributes,
9468                              int num_attributes) {
9469   bool foundType = false;
9470 
9471   for (int i = 0; i < num_attributes; i++) {
9472     if ((strcmp(attributes[i].name, "zfpCompressionType") == 0) &&
9473         (attributes[i].size == 1)) {
9474       param->type = static_cast<int>(attributes[i].value[0]);
9475 
9476       foundType = true;
9477     }
9478   }
9479 
9480   if (!foundType) {
9481     return false;
9482   }
9483 
9484   if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) {
9485     for (int i = 0; i < num_attributes; i++) {
9486       if ((strcmp(attributes[i].name, "zfpCompressionRate") == 0) &&
9487           (attributes[i].size == 8)) {
9488         param->rate = *(reinterpret_cast<double *>(attributes[i].value));
9489         return true;
9490       }
9491     }
9492   } else if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) {
9493     for (int i = 0; i < num_attributes; i++) {
9494       if ((strcmp(attributes[i].name, "zfpCompressionPrecision") == 0) &&
9495           (attributes[i].size == 4)) {
9496         param->rate = *(reinterpret_cast<int *>(attributes[i].value));
9497         return true;
9498       }
9499     }
9500   } else if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) {
9501     for (int i = 0; i < num_attributes; i++) {
9502       if ((strcmp(attributes[i].name, "zfpCompressionTolerance") == 0) &&
9503           (attributes[i].size == 8)) {
9504         param->tolerance = *(reinterpret_cast<double *>(attributes[i].value));
9505         return true;
9506       }
9507     }
9508   } else {
9509     assert(0);
9510   }
9511 
9512   return false;
9513 }
9514 
9515 // Assume pixel format is FLOAT for all channels.
DecompressZfp(float * dst,int dst_width,int dst_num_lines,int num_channels,const unsigned char * src,unsigned long src_size,const ZFPCompressionParam & param)9516 static bool DecompressZfp(float *dst, int dst_width, int dst_num_lines,
9517                           int num_channels, const unsigned char *src,
9518                           unsigned long src_size,
9519                           const ZFPCompressionParam &param) {
9520   size_t uncompressed_size = dst_width * dst_num_lines * num_channels;
9521 
9522   if (uncompressed_size == src_size) {
9523     // Data is not compressed(Issue 40).
9524     memcpy(dst, src, src_size);
9525   }
9526 
9527   zfp_stream *zfp = NULL;
9528   zfp_field *field = NULL;
9529 
9530   assert((dst_width % 4) == 0);
9531   assert((dst_num_lines % 4) == 0);
9532 
9533   if ((dst_width & 3U) || (dst_num_lines & 3U)) {
9534     return false;
9535   }
9536 
9537   field =
9538       zfp_field_2d(reinterpret_cast<void *>(const_cast<unsigned char *>(src)),
9539                    zfp_type_float, dst_width, dst_num_lines * num_channels);
9540   zfp = zfp_stream_open(NULL);
9541 
9542   if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) {
9543     zfp_stream_set_rate(zfp, param.rate, zfp_type_float, /* dimention */ 2,
9544                         /* write random access */ 0);
9545   } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) {
9546     zfp_stream_set_precision(zfp, param.precision, zfp_type_float);
9547   } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) {
9548     zfp_stream_set_accuracy(zfp, param.tolerance, zfp_type_float);
9549   } else {
9550     assert(0);
9551   }
9552 
9553   size_t buf_size = zfp_stream_maximum_size(zfp, field);
9554   std::vector<unsigned char> buf(buf_size);
9555   memcpy(&buf.at(0), src, src_size);
9556 
9557   bitstream *stream = stream_open(&buf.at(0), buf_size);
9558   zfp_stream_set_bit_stream(zfp, stream);
9559   zfp_stream_rewind(zfp);
9560 
9561   size_t image_size = dst_width * dst_num_lines;
9562 
9563   for (int c = 0; c < num_channels; c++) {
9564     // decompress 4x4 pixel block.
9565     for (int y = 0; y < dst_num_lines; y += 4) {
9566       for (int x = 0; x < dst_width; x += 4) {
9567         float fblock[16];
9568         zfp_decode_block_float_2(zfp, fblock);
9569         for (int j = 0; j < 4; j++) {
9570           for (int i = 0; i < 4; i++) {
9571             dst[c * image_size + ((y + j) * dst_width + (x + i))] =
9572                 fblock[j * 4 + i];
9573           }
9574         }
9575       }
9576     }
9577   }
9578 
9579   zfp_field_free(field);
9580   zfp_stream_close(zfp);
9581   stream_close(stream);
9582 
9583   return true;
9584 }
9585 
9586 // Assume pixel format is FLOAT for all channels.
CompressZfp(std::vector<unsigned char> * outBuf,unsigned int * outSize,const float * inPtr,int width,int num_lines,int num_channels,const ZFPCompressionParam & param)9587 bool CompressZfp(std::vector<unsigned char> *outBuf, unsigned int *outSize,
9588                  const float *inPtr, int width, int num_lines, int num_channels,
9589                  const ZFPCompressionParam &param) {
9590   zfp_stream *zfp = NULL;
9591   zfp_field *field = NULL;
9592 
9593   assert((width % 4) == 0);
9594   assert((num_lines % 4) == 0);
9595 
9596   if ((width & 3U) || (num_lines & 3U)) {
9597     return false;
9598   }
9599 
9600   // create input array.
9601   field = zfp_field_2d(reinterpret_cast<void *>(const_cast<float *>(inPtr)),
9602                        zfp_type_float, width, num_lines * num_channels);
9603 
9604   zfp = zfp_stream_open(NULL);
9605 
9606   if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) {
9607     zfp_stream_set_rate(zfp, param.rate, zfp_type_float, 2, 0);
9608   } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) {
9609     zfp_stream_set_precision(zfp, param.precision, zfp_type_float);
9610   } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) {
9611     zfp_stream_set_accuracy(zfp, param.tolerance, zfp_type_float);
9612   } else {
9613     assert(0);
9614   }
9615 
9616   size_t buf_size = zfp_stream_maximum_size(zfp, field);
9617 
9618   outBuf->resize(buf_size);
9619 
9620   bitstream *stream = stream_open(&outBuf->at(0), buf_size);
9621   zfp_stream_set_bit_stream(zfp, stream);
9622   zfp_field_free(field);
9623 
9624   size_t image_size = width * num_lines;
9625 
9626   for (int c = 0; c < num_channels; c++) {
9627     // compress 4x4 pixel block.
9628     for (int y = 0; y < num_lines; y += 4) {
9629       for (int x = 0; x < width; x += 4) {
9630         float fblock[16];
9631         for (int j = 0; j < 4; j++) {
9632           for (int i = 0; i < 4; i++) {
9633             fblock[j * 4 + i] =
9634                 inPtr[c * image_size + ((y + j) * width + (x + i))];
9635           }
9636         }
9637         zfp_encode_block_float_2(zfp, fblock);
9638       }
9639     }
9640   }
9641 
9642   zfp_stream_flush(zfp);
9643   (*outSize) = zfp_stream_compressed_size(zfp);
9644 
9645   zfp_stream_close(zfp);
9646 
9647   return true;
9648 }
9649 
9650 #endif
9651 
9652 //
9653 // -----------------------------------------------------------------
9654 //
9655 
9656 // TODO(syoyo): Refactor function arguments.
DecodePixelData(unsigned char ** out_images,const int * requested_pixel_types,const unsigned char * data_ptr,size_t data_len,int compression_type,int line_order,int width,int height,int x_stride,int y,int line_no,int num_lines,size_t pixel_data_size,size_t num_attributes,const EXRAttribute * attributes,size_t num_channels,const EXRChannelInfo * channels,const std::vector<size_t> & channel_offset_list)9657 static bool DecodePixelData(/* out */ unsigned char **out_images,
9658                             const int *requested_pixel_types,
9659                             const unsigned char *data_ptr, size_t data_len,
9660                             int compression_type, int line_order, int width,
9661                             int height, int x_stride, int y, int line_no,
9662                             int num_lines, size_t pixel_data_size,
9663                             size_t num_attributes,
9664                             const EXRAttribute *attributes, size_t num_channels,
9665                             const EXRChannelInfo *channels,
9666                             const std::vector<size_t> &channel_offset_list) {
9667   if (compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {  // PIZ
9668 #if TINYEXR_USE_PIZ
9669     if ((width == 0) || (num_lines == 0) || (pixel_data_size == 0)) {
9670       // Invalid input #90
9671       return false;
9672     }
9673 
9674     // Allocate original data size.
9675     std::vector<unsigned char> outBuf(static_cast<size_t>(
9676         static_cast<size_t>(width * num_lines) * pixel_data_size));
9677     size_t tmpBufLen = outBuf.size();
9678 
9679     bool ret = tinyexr::DecompressPiz(
9680         reinterpret_cast<unsigned char *>(&outBuf.at(0)), data_ptr, tmpBufLen,
9681         data_len, static_cast<int>(num_channels), channels, width, num_lines);
9682 
9683     if (!ret) {
9684       return false;
9685     }
9686 
9687     // For PIZ_COMPRESSION:
9688     //   pixel sample data for channel 0 for scanline 0
9689     //   pixel sample data for channel 1 for scanline 0
9690     //   pixel sample data for channel ... for scanline 0
9691     //   pixel sample data for channel n for scanline 0
9692     //   pixel sample data for channel 0 for scanline 1
9693     //   pixel sample data for channel 1 for scanline 1
9694     //   pixel sample data for channel ... for scanline 1
9695     //   pixel sample data for channel n for scanline 1
9696     //   ...
9697     for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
9698       if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
9699         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
9700           const unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
9701               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
9702                          channel_offset_list[c] * static_cast<size_t>(width)));
9703           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
9704             FP16 hf;
9705 
9706             // hf.u = line_ptr[u];
9707             // use `cpy` to avoid unaligned memory access when compiler's
9708             // optimization is on.
9709             tinyexr::cpy2(&(hf.u), line_ptr + u);
9710 
9711             tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
9712 
9713             if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
9714               unsigned short *image =
9715                   reinterpret_cast<unsigned short **>(out_images)[c];
9716               if (line_order == 0) {
9717                 image += (static_cast<size_t>(line_no) + v) *
9718                              static_cast<size_t>(x_stride) +
9719                          u;
9720               } else {
9721                 image += static_cast<size_t>(
9722                              (height - 1 - (line_no + static_cast<int>(v)))) *
9723                              static_cast<size_t>(x_stride) +
9724                          u;
9725               }
9726               *image = hf.u;
9727             } else {  // HALF -> FLOAT
9728               FP32 f32 = half_to_float(hf);
9729               float *image = reinterpret_cast<float **>(out_images)[c];
9730               size_t offset = 0;
9731               if (line_order == 0) {
9732                 offset = (static_cast<size_t>(line_no) + v) *
9733                              static_cast<size_t>(x_stride) +
9734                          u;
9735               } else {
9736                 offset = static_cast<size_t>(
9737                              (height - 1 - (line_no + static_cast<int>(v)))) *
9738                              static_cast<size_t>(x_stride) +
9739                          u;
9740               }
9741               image += offset;
9742               *image = f32.f;
9743             }
9744           }
9745         }
9746       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
9747         assert(requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT);
9748 
9749         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
9750           const unsigned int *line_ptr = reinterpret_cast<unsigned int *>(
9751               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
9752                          channel_offset_list[c] * static_cast<size_t>(width)));
9753           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
9754             unsigned int val;
9755             // val = line_ptr[u];
9756             tinyexr::cpy4(&val, line_ptr + u);
9757 
9758             tinyexr::swap4(&val);
9759 
9760             unsigned int *image =
9761                 reinterpret_cast<unsigned int **>(out_images)[c];
9762             if (line_order == 0) {
9763               image += (static_cast<size_t>(line_no) + v) *
9764                            static_cast<size_t>(x_stride) +
9765                        u;
9766             } else {
9767               image += static_cast<size_t>(
9768                            (height - 1 - (line_no + static_cast<int>(v)))) *
9769                            static_cast<size_t>(x_stride) +
9770                        u;
9771             }
9772             *image = val;
9773           }
9774         }
9775       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
9776         assert(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT);
9777         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
9778           const float *line_ptr = reinterpret_cast<float *>(&outBuf.at(
9779               v * pixel_data_size * static_cast<size_t>(x_stride) +
9780               channel_offset_list[c] * static_cast<size_t>(x_stride)));
9781           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
9782             float val;
9783             // val = line_ptr[u];
9784             tinyexr::cpy4(&val, line_ptr + u);
9785 
9786             tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
9787 
9788             float *image = reinterpret_cast<float **>(out_images)[c];
9789             if (line_order == 0) {
9790               image += (static_cast<size_t>(line_no) + v) *
9791                            static_cast<size_t>(x_stride) +
9792                        u;
9793             } else {
9794               image += static_cast<size_t>(
9795                            (height - 1 - (line_no + static_cast<int>(v)))) *
9796                            static_cast<size_t>(x_stride) +
9797                        u;
9798             }
9799             *image = val;
9800           }
9801         }
9802       } else {
9803         assert(0);
9804       }
9805     }
9806 #else
9807     assert(0 && "PIZ is enabled in this build");
9808     return false;
9809 #endif
9810 
9811   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS ||
9812              compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
9813     // Allocate original data size.
9814     std::vector<unsigned char> outBuf(static_cast<size_t>(width) *
9815                                       static_cast<size_t>(num_lines) *
9816                                       pixel_data_size);
9817 
9818     unsigned long dstLen = static_cast<unsigned long>(outBuf.size());
9819     assert(dstLen > 0);
9820     if (!tinyexr::DecompressZip(
9821             reinterpret_cast<unsigned char *>(&outBuf.at(0)), &dstLen, data_ptr,
9822             static_cast<unsigned long>(data_len))) {
9823       return false;
9824     }
9825 
9826     // For ZIP_COMPRESSION:
9827     //   pixel sample data for channel 0 for scanline 0
9828     //   pixel sample data for channel 1 for scanline 0
9829     //   pixel sample data for channel ... for scanline 0
9830     //   pixel sample data for channel n for scanline 0
9831     //   pixel sample data for channel 0 for scanline 1
9832     //   pixel sample data for channel 1 for scanline 1
9833     //   pixel sample data for channel ... for scanline 1
9834     //   pixel sample data for channel n for scanline 1
9835     //   ...
9836     for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
9837       if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
9838         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
9839           const unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
9840               &outBuf.at(v * static_cast<size_t>(pixel_data_size) *
9841                              static_cast<size_t>(width) +
9842                          channel_offset_list[c] * static_cast<size_t>(width)));
9843           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
9844             tinyexr::FP16 hf;
9845 
9846             // hf.u = line_ptr[u];
9847             tinyexr::cpy2(&(hf.u), line_ptr + u);
9848 
9849             tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
9850 
9851             if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
9852               unsigned short *image =
9853                   reinterpret_cast<unsigned short **>(out_images)[c];
9854               if (line_order == 0) {
9855                 image += (static_cast<size_t>(line_no) + v) *
9856                              static_cast<size_t>(x_stride) +
9857                          u;
9858               } else {
9859                 image += (static_cast<size_t>(height) - 1U -
9860                           (static_cast<size_t>(line_no) + v)) *
9861                              static_cast<size_t>(x_stride) +
9862                          u;
9863               }
9864               *image = hf.u;
9865             } else {  // HALF -> FLOAT
9866               tinyexr::FP32 f32 = half_to_float(hf);
9867               float *image = reinterpret_cast<float **>(out_images)[c];
9868               size_t offset = 0;
9869               if (line_order == 0) {
9870                 offset = (static_cast<size_t>(line_no) + v) *
9871                              static_cast<size_t>(x_stride) +
9872                          u;
9873               } else {
9874                 offset = (static_cast<size_t>(height) - 1U -
9875                           (static_cast<size_t>(line_no) + v)) *
9876                              static_cast<size_t>(x_stride) +
9877                          u;
9878               }
9879               image += offset;
9880 
9881               *image = f32.f;
9882             }
9883           }
9884         }
9885       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
9886         assert(requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT);
9887 
9888         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
9889           const unsigned int *line_ptr = reinterpret_cast<unsigned int *>(
9890               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
9891                          channel_offset_list[c] * static_cast<size_t>(width)));
9892           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
9893             unsigned int val;
9894             // val = line_ptr[u];
9895             tinyexr::cpy4(&val, line_ptr + u);
9896 
9897             tinyexr::swap4(&val);
9898 
9899             unsigned int *image =
9900                 reinterpret_cast<unsigned int **>(out_images)[c];
9901             if (line_order == 0) {
9902               image += (static_cast<size_t>(line_no) + v) *
9903                            static_cast<size_t>(x_stride) +
9904                        u;
9905             } else {
9906               image += (static_cast<size_t>(height) - 1U -
9907                         (static_cast<size_t>(line_no) + v)) *
9908                            static_cast<size_t>(x_stride) +
9909                        u;
9910             }
9911             *image = val;
9912           }
9913         }
9914       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
9915         assert(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT);
9916         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
9917           const float *line_ptr = reinterpret_cast<float *>(
9918               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
9919                          channel_offset_list[c] * static_cast<size_t>(width)));
9920           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
9921             float val;
9922             // val = line_ptr[u];
9923             tinyexr::cpy4(&val, line_ptr + u);
9924 
9925             tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
9926 
9927             float *image = reinterpret_cast<float **>(out_images)[c];
9928             if (line_order == 0) {
9929               image += (static_cast<size_t>(line_no) + v) *
9930                            static_cast<size_t>(x_stride) +
9931                        u;
9932             } else {
9933               image += (static_cast<size_t>(height) - 1U -
9934                         (static_cast<size_t>(line_no) + v)) *
9935                            static_cast<size_t>(x_stride) +
9936                        u;
9937             }
9938             *image = val;
9939           }
9940         }
9941       } else {
9942         assert(0);
9943         return false;
9944       }
9945     }
9946   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) {
9947     // Allocate original data size.
9948     std::vector<unsigned char> outBuf(static_cast<size_t>(width) *
9949                                       static_cast<size_t>(num_lines) *
9950                                       pixel_data_size);
9951 
9952     unsigned long dstLen = static_cast<unsigned long>(outBuf.size());
9953     if (dstLen == 0) {
9954       return false;
9955     }
9956 
9957     if (!tinyexr::DecompressRle(reinterpret_cast<unsigned char *>(&outBuf.at(0)),
9958                            dstLen, data_ptr,
9959                            static_cast<unsigned long>(data_len))) {
9960       return false;
9961     }
9962 
9963     // For RLE_COMPRESSION:
9964     //   pixel sample data for channel 0 for scanline 0
9965     //   pixel sample data for channel 1 for scanline 0
9966     //   pixel sample data for channel ... for scanline 0
9967     //   pixel sample data for channel n for scanline 0
9968     //   pixel sample data for channel 0 for scanline 1
9969     //   pixel sample data for channel 1 for scanline 1
9970     //   pixel sample data for channel ... for scanline 1
9971     //   pixel sample data for channel n for scanline 1
9972     //   ...
9973     for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
9974       if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
9975         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
9976           const unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
9977               &outBuf.at(v * static_cast<size_t>(pixel_data_size) *
9978                              static_cast<size_t>(width) +
9979                          channel_offset_list[c] * static_cast<size_t>(width)));
9980           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
9981             tinyexr::FP16 hf;
9982 
9983             // hf.u = line_ptr[u];
9984             tinyexr::cpy2(&(hf.u), line_ptr + u);
9985 
9986             tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
9987 
9988             if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
9989               unsigned short *image =
9990                   reinterpret_cast<unsigned short **>(out_images)[c];
9991               if (line_order == 0) {
9992                 image += (static_cast<size_t>(line_no) + v) *
9993                              static_cast<size_t>(x_stride) +
9994                          u;
9995               } else {
9996                 image += (static_cast<size_t>(height) - 1U -
9997                           (static_cast<size_t>(line_no) + v)) *
9998                              static_cast<size_t>(x_stride) +
9999                          u;
10000               }
10001               *image = hf.u;
10002             } else {  // HALF -> FLOAT
10003               tinyexr::FP32 f32 = half_to_float(hf);
10004               float *image = reinterpret_cast<float **>(out_images)[c];
10005               if (line_order == 0) {
10006                 image += (static_cast<size_t>(line_no) + v) *
10007                              static_cast<size_t>(x_stride) +
10008                          u;
10009               } else {
10010                 image += (static_cast<size_t>(height) - 1U -
10011                           (static_cast<size_t>(line_no) + v)) *
10012                              static_cast<size_t>(x_stride) +
10013                          u;
10014               }
10015               *image = f32.f;
10016             }
10017           }
10018         }
10019       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
10020         assert(requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT);
10021 
10022         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
10023           const unsigned int *line_ptr = reinterpret_cast<unsigned int *>(
10024               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
10025                          channel_offset_list[c] * static_cast<size_t>(width)));
10026           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
10027             unsigned int val;
10028             // val = line_ptr[u];
10029             tinyexr::cpy4(&val, line_ptr + u);
10030 
10031             tinyexr::swap4(&val);
10032 
10033             unsigned int *image =
10034                 reinterpret_cast<unsigned int **>(out_images)[c];
10035             if (line_order == 0) {
10036               image += (static_cast<size_t>(line_no) + v) *
10037                            static_cast<size_t>(x_stride) +
10038                        u;
10039             } else {
10040               image += (static_cast<size_t>(height) - 1U -
10041                         (static_cast<size_t>(line_no) + v)) *
10042                            static_cast<size_t>(x_stride) +
10043                        u;
10044             }
10045             *image = val;
10046           }
10047         }
10048       } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
10049         assert(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT);
10050         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
10051           const float *line_ptr = reinterpret_cast<float *>(
10052               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
10053                          channel_offset_list[c] * static_cast<size_t>(width)));
10054           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
10055             float val;
10056             // val = line_ptr[u];
10057             tinyexr::cpy4(&val, line_ptr + u);
10058 
10059             tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
10060 
10061             float *image = reinterpret_cast<float **>(out_images)[c];
10062             if (line_order == 0) {
10063               image += (static_cast<size_t>(line_no) + v) *
10064                            static_cast<size_t>(x_stride) +
10065                        u;
10066             } else {
10067               image += (static_cast<size_t>(height) - 1U -
10068                         (static_cast<size_t>(line_no) + v)) *
10069                            static_cast<size_t>(x_stride) +
10070                        u;
10071             }
10072             *image = val;
10073           }
10074         }
10075       } else {
10076         assert(0);
10077         return false;
10078       }
10079     }
10080   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
10081 #if TINYEXR_USE_ZFP
10082     tinyexr::ZFPCompressionParam zfp_compression_param;
10083     if (!FindZFPCompressionParam(&zfp_compression_param, attributes,
10084                                  num_attributes)) {
10085       assert(0);
10086       return false;
10087     }
10088 
10089     // Allocate original data size.
10090     std::vector<unsigned char> outBuf(static_cast<size_t>(width) *
10091                                       static_cast<size_t>(num_lines) *
10092                                       pixel_data_size);
10093 
10094     unsigned long dstLen = outBuf.size();
10095     assert(dstLen > 0);
10096     tinyexr::DecompressZfp(reinterpret_cast<float *>(&outBuf.at(0)), width,
10097                            num_lines, num_channels, data_ptr,
10098                            static_cast<unsigned long>(data_len),
10099                            zfp_compression_param);
10100 
10101     // For ZFP_COMPRESSION:
10102     //   pixel sample data for channel 0 for scanline 0
10103     //   pixel sample data for channel 1 for scanline 0
10104     //   pixel sample data for channel ... for scanline 0
10105     //   pixel sample data for channel n for scanline 0
10106     //   pixel sample data for channel 0 for scanline 1
10107     //   pixel sample data for channel 1 for scanline 1
10108     //   pixel sample data for channel ... for scanline 1
10109     //   pixel sample data for channel n for scanline 1
10110     //   ...
10111     for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
10112       assert(channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT);
10113       if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
10114         assert(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT);
10115         for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
10116           const float *line_ptr = reinterpret_cast<float *>(
10117               &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
10118                          channel_offset_list[c] * static_cast<size_t>(width)));
10119           for (size_t u = 0; u < static_cast<size_t>(width); u++) {
10120             float val;
10121             tinyexr::cpy4(&val, line_ptr + u);
10122 
10123             tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
10124 
10125             float *image = reinterpret_cast<float **>(out_images)[c];
10126             if (line_order == 0) {
10127               image += (static_cast<size_t>(line_no) + v) *
10128                            static_cast<size_t>(x_stride) +
10129                        u;
10130             } else {
10131               image += (static_cast<size_t>(height) - 1U -
10132                         (static_cast<size_t>(line_no) + v)) *
10133                            static_cast<size_t>(x_stride) +
10134                        u;
10135             }
10136             *image = val;
10137           }
10138         }
10139       } else {
10140         assert(0);
10141         return false;
10142       }
10143     }
10144 #else
10145     (void)attributes;
10146     (void)num_attributes;
10147     (void)num_channels;
10148     assert(0);
10149     return false;
10150 #endif
10151   } else if (compression_type == TINYEXR_COMPRESSIONTYPE_NONE) {
10152     for (size_t c = 0; c < num_channels; c++) {
10153       for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
10154         if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
10155           const unsigned short *line_ptr =
10156               reinterpret_cast<const unsigned short *>(
10157                   data_ptr + v * pixel_data_size * size_t(width) +
10158                   channel_offset_list[c] * static_cast<size_t>(width));
10159 
10160           if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
10161             unsigned short *outLine =
10162                 reinterpret_cast<unsigned short *>(out_images[c]);
10163             if (line_order == 0) {
10164               outLine += (size_t(y) + v) * size_t(x_stride);
10165             } else {
10166               outLine +=
10167                   (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
10168             }
10169 
10170             for (int u = 0; u < width; u++) {
10171               tinyexr::FP16 hf;
10172 
10173               // hf.u = line_ptr[u];
10174               tinyexr::cpy2(&(hf.u), line_ptr + u);
10175 
10176               tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
10177 
10178               outLine[u] = hf.u;
10179             }
10180           } else if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) {
10181             float *outLine = reinterpret_cast<float *>(out_images[c]);
10182             if (line_order == 0) {
10183               outLine += (size_t(y) + v) * size_t(x_stride);
10184             } else {
10185               outLine +=
10186                   (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
10187             }
10188 
10189             if (reinterpret_cast<const unsigned char *>(line_ptr + width) >
10190                 (data_ptr + data_len)) {
10191               // Insufficient data size
10192               return false;
10193             }
10194 
10195             for (int u = 0; u < width; u++) {
10196               tinyexr::FP16 hf;
10197 
10198               // address may not be aliged. use byte-wise copy for safety.#76
10199               // hf.u = line_ptr[u];
10200               tinyexr::cpy2(&(hf.u), line_ptr + u);
10201 
10202               tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
10203 
10204               tinyexr::FP32 f32 = half_to_float(hf);
10205 
10206               outLine[u] = f32.f;
10207             }
10208           } else {
10209             assert(0);
10210             return false;
10211           }
10212         } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
10213           const float *line_ptr = reinterpret_cast<const float *>(
10214               data_ptr + v * pixel_data_size * size_t(width) +
10215               channel_offset_list[c] * static_cast<size_t>(width));
10216 
10217           float *outLine = reinterpret_cast<float *>(out_images[c]);
10218           if (line_order == 0) {
10219             outLine += (size_t(y) + v) * size_t(x_stride);
10220           } else {
10221             outLine +=
10222                 (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
10223           }
10224 
10225           if (reinterpret_cast<const unsigned char *>(line_ptr + width) >
10226               (data_ptr + data_len)) {
10227             // Insufficient data size
10228             return false;
10229           }
10230 
10231           for (int u = 0; u < width; u++) {
10232             float val;
10233             tinyexr::cpy4(&val, line_ptr + u);
10234 
10235             tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
10236 
10237             outLine[u] = val;
10238           }
10239         } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
10240           const unsigned int *line_ptr = reinterpret_cast<const unsigned int *>(
10241               data_ptr + v * pixel_data_size * size_t(width) +
10242               channel_offset_list[c] * static_cast<size_t>(width));
10243 
10244           unsigned int *outLine =
10245               reinterpret_cast<unsigned int *>(out_images[c]);
10246           if (line_order == 0) {
10247             outLine += (size_t(y) + v) * size_t(x_stride);
10248           } else {
10249             outLine +=
10250                 (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
10251           }
10252 
10253           for (int u = 0; u < width; u++) {
10254             if (reinterpret_cast<const unsigned char *>(line_ptr + u) >=
10255                 (data_ptr + data_len)) {
10256               // Corrupsed data?
10257               return false;
10258             }
10259 
10260             unsigned int val;
10261             tinyexr::cpy4(&val, line_ptr + u);
10262 
10263             tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
10264 
10265             outLine[u] = val;
10266           }
10267         }
10268       }
10269     }
10270   }
10271 
10272   return true;
10273 }
10274 
DecodeTiledPixelData(unsigned char ** out_images,int * width,int * height,const int * requested_pixel_types,const unsigned char * data_ptr,size_t data_len,int compression_type,int line_order,int data_width,int data_height,int tile_offset_x,int tile_offset_y,int tile_size_x,int tile_size_y,size_t pixel_data_size,size_t num_attributes,const EXRAttribute * attributes,size_t num_channels,const EXRChannelInfo * channels,const std::vector<size_t> & channel_offset_list)10275 static void DecodeTiledPixelData(
10276     unsigned char **out_images, int *width, int *height,
10277     const int *requested_pixel_types, const unsigned char *data_ptr,
10278     size_t data_len, int compression_type, int line_order, int data_width,
10279     int data_height, int tile_offset_x, int tile_offset_y, int tile_size_x,
10280     int tile_size_y, size_t pixel_data_size, size_t num_attributes,
10281     const EXRAttribute *attributes, size_t num_channels,
10282     const EXRChannelInfo *channels,
10283     const std::vector<size_t> &channel_offset_list) {
10284   assert(tile_offset_x * tile_size_x < data_width);
10285   assert(tile_offset_y * tile_size_y < data_height);
10286 
10287   // Compute actual image size in a tile.
10288   if ((tile_offset_x + 1) * tile_size_x >= data_width) {
10289     (*width) = data_width - (tile_offset_x * tile_size_x);
10290   } else {
10291     (*width) = tile_size_x;
10292   }
10293 
10294   if ((tile_offset_y + 1) * tile_size_y >= data_height) {
10295     (*height) = data_height - (tile_offset_y * tile_size_y);
10296   } else {
10297     (*height) = tile_size_y;
10298   }
10299 
10300   // Image size = tile size.
10301   DecodePixelData(out_images, requested_pixel_types, data_ptr, data_len,
10302                   compression_type, line_order, (*width), tile_size_y,
10303                   /* stride */ tile_size_x, /* y */ 0, /* line_no */ 0,
10304                   (*height), pixel_data_size, num_attributes, attributes,
10305                   num_channels, channels, channel_offset_list);
10306 }
10307 
ComputeChannelLayout(std::vector<size_t> * channel_offset_list,int * pixel_data_size,size_t * channel_offset,int num_channels,const EXRChannelInfo * channels)10308 static bool ComputeChannelLayout(std::vector<size_t> *channel_offset_list,
10309                                  int *pixel_data_size, size_t *channel_offset,
10310                                  int num_channels,
10311                                  const EXRChannelInfo *channels) {
10312   channel_offset_list->resize(static_cast<size_t>(num_channels));
10313 
10314   (*pixel_data_size) = 0;
10315   (*channel_offset) = 0;
10316 
10317   for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
10318     (*channel_offset_list)[c] = (*channel_offset);
10319     if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
10320       (*pixel_data_size) += sizeof(unsigned short);
10321       (*channel_offset) += sizeof(unsigned short);
10322     } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
10323       (*pixel_data_size) += sizeof(float);
10324       (*channel_offset) += sizeof(float);
10325     } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
10326       (*pixel_data_size) += sizeof(unsigned int);
10327       (*channel_offset) += sizeof(unsigned int);
10328     } else {
10329       // ???
10330       return false;
10331     }
10332   }
10333   return true;
10334 }
10335 
AllocateImage(int num_channels,const EXRChannelInfo * channels,const int * requested_pixel_types,int data_width,int data_height)10336 static unsigned char **AllocateImage(int num_channels,
10337                                      const EXRChannelInfo *channels,
10338                                      const int *requested_pixel_types,
10339                                      int data_width, int data_height) {
10340   unsigned char **images =
10341       reinterpret_cast<unsigned char **>(static_cast<float **>(
10342           malloc(sizeof(float *) * static_cast<size_t>(num_channels))));
10343 
10344   for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
10345     size_t data_len =
10346         static_cast<size_t>(data_width) * static_cast<size_t>(data_height);
10347     if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
10348       // pixel_data_size += sizeof(unsigned short);
10349       // channel_offset += sizeof(unsigned short);
10350       // Alloc internal image for half type.
10351       if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
10352         images[c] =
10353             reinterpret_cast<unsigned char *>(static_cast<unsigned short *>(
10354                 malloc(sizeof(unsigned short) * data_len)));
10355       } else if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) {
10356         images[c] = reinterpret_cast<unsigned char *>(
10357             static_cast<float *>(malloc(sizeof(float) * data_len)));
10358       } else {
10359         assert(0);
10360       }
10361     } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
10362       // pixel_data_size += sizeof(float);
10363       // channel_offset += sizeof(float);
10364       images[c] = reinterpret_cast<unsigned char *>(
10365           static_cast<float *>(malloc(sizeof(float) * data_len)));
10366     } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
10367       // pixel_data_size += sizeof(unsigned int);
10368       // channel_offset += sizeof(unsigned int);
10369       images[c] = reinterpret_cast<unsigned char *>(
10370           static_cast<unsigned int *>(malloc(sizeof(unsigned int) * data_len)));
10371     } else {
10372       assert(0);
10373     }
10374   }
10375 
10376   return images;
10377 }
10378 
ParseEXRHeader(HeaderInfo * info,bool * empty_header,const EXRVersion * version,std::string * err,const unsigned char * buf,size_t size)10379 static int ParseEXRHeader(HeaderInfo *info, bool *empty_header,
10380                           const EXRVersion *version, std::string *err,
10381                           const unsigned char *buf, size_t size) {
10382   const char *marker = reinterpret_cast<const char *>(&buf[0]);
10383 
10384   if (empty_header) {
10385     (*empty_header) = false;
10386   }
10387 
10388   if (version->multipart) {
10389     if (size > 0 && marker[0] == '\0') {
10390       // End of header list.
10391       if (empty_header) {
10392         (*empty_header) = true;
10393       }
10394       return TINYEXR_SUCCESS;
10395     }
10396   }
10397 
10398   // According to the spec, the header of every OpenEXR file must contain at
10399   // least the following attributes:
10400   //
10401   // channels chlist
10402   // compression compression
10403   // dataWindow box2i
10404   // displayWindow box2i
10405   // lineOrder lineOrder
10406   // pixelAspectRatio float
10407   // screenWindowCenter v2f
10408   // screenWindowWidth float
10409   bool has_channels = false;
10410   bool has_compression = false;
10411   bool has_data_window = false;
10412   bool has_display_window = false;
10413   bool has_line_order = false;
10414   bool has_pixel_aspect_ratio = false;
10415   bool has_screen_window_center = false;
10416   bool has_screen_window_width = false;
10417 
10418   info->data_window[0] = 0;
10419   info->data_window[1] = 0;
10420   info->data_window[2] = 0;
10421   info->data_window[3] = 0;
10422   info->line_order = 0;  // @fixme
10423   info->display_window[0] = 0;
10424   info->display_window[1] = 0;
10425   info->display_window[2] = 0;
10426   info->display_window[3] = 0;
10427   info->screen_window_center[0] = 0.0f;
10428   info->screen_window_center[1] = 0.0f;
10429   info->screen_window_width = -1.0f;
10430   info->pixel_aspect_ratio = -1.0f;
10431 
10432   info->tile_size_x = -1;
10433   info->tile_size_y = -1;
10434   info->tile_level_mode = -1;
10435   info->tile_rounding_mode = -1;
10436 
10437   info->attributes.clear();
10438 
10439   // Read attributes
10440   size_t orig_size = size;
10441   for (size_t nattr = 0; nattr < TINYEXR_MAX_HEADER_ATTRIBUTES; nattr++) {
10442     if (0 == size) {
10443       if (err) {
10444         (*err) += "Insufficient data size for attributes.\n";
10445       }
10446       return TINYEXR_ERROR_INVALID_DATA;
10447     } else if (marker[0] == '\0') {
10448       size--;
10449       break;
10450     }
10451 
10452     std::string attr_name;
10453     std::string attr_type;
10454     std::vector<unsigned char> data;
10455     size_t marker_size;
10456     if (!tinyexr::ReadAttribute(&attr_name, &attr_type, &data, &marker_size,
10457                                 marker, size)) {
10458       if (err) {
10459         (*err) += "Failed to read attribute.\n";
10460       }
10461       return TINYEXR_ERROR_INVALID_DATA;
10462     }
10463     marker += marker_size;
10464     size -= marker_size;
10465 
10466     if (version->tiled && attr_name.compare("tiles") == 0) {
10467       unsigned int x_size, y_size;
10468       unsigned char tile_mode;
10469       assert(data.size() == 9);
10470       memcpy(&x_size, &data.at(0), sizeof(int));
10471       memcpy(&y_size, &data.at(4), sizeof(int));
10472       tile_mode = data[8];
10473       tinyexr::swap4(&x_size);
10474       tinyexr::swap4(&y_size);
10475 
10476       info->tile_size_x = static_cast<int>(x_size);
10477       info->tile_size_y = static_cast<int>(y_size);
10478 
10479       // mode = levelMode + roundingMode * 16
10480       info->tile_level_mode = tile_mode & 0x3;
10481       info->tile_rounding_mode = (tile_mode >> 4) & 0x1;
10482 
10483     } else if (attr_name.compare("compression") == 0) {
10484       bool ok = false;
10485       if (data[0] < TINYEXR_COMPRESSIONTYPE_PIZ) {
10486         ok = true;
10487       }
10488 
10489       if (data[0] == TINYEXR_COMPRESSIONTYPE_PIZ) {
10490 #if TINYEXR_USE_PIZ
10491         ok = true;
10492 #else
10493         if (err) {
10494           (*err) = "PIZ compression is not supported.";
10495         }
10496         return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
10497 #endif
10498       }
10499 
10500       if (data[0] == TINYEXR_COMPRESSIONTYPE_ZFP) {
10501 #if TINYEXR_USE_ZFP
10502         ok = true;
10503 #else
10504         if (err) {
10505           (*err) = "ZFP compression is not supported.";
10506         }
10507         return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
10508 #endif
10509       }
10510 
10511       if (!ok) {
10512         if (err) {
10513           (*err) = "Unknown compression type.";
10514         }
10515         return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
10516       }
10517 
10518       info->compression_type = static_cast<int>(data[0]);
10519       has_compression = true;
10520 
10521     } else if (attr_name.compare("channels") == 0) {
10522       // name: zero-terminated string, from 1 to 255 bytes long
10523       // pixel type: int, possible values are: UINT = 0 HALF = 1 FLOAT = 2
10524       // pLinear: unsigned char, possible values are 0 and 1
10525       // reserved: three chars, should be zero
10526       // xSampling: int
10527       // ySampling: int
10528 
10529       if (!ReadChannelInfo(info->channels, data)) {
10530         if (err) {
10531           (*err) += "Failed to parse channel info.\n";
10532         }
10533         return TINYEXR_ERROR_INVALID_DATA;
10534       }
10535 
10536       if (info->channels.size() < 1) {
10537         if (err) {
10538           (*err) += "# of channels is zero.\n";
10539         }
10540         return TINYEXR_ERROR_INVALID_DATA;
10541       }
10542 
10543       has_channels = true;
10544 
10545     } else if (attr_name.compare("dataWindow") == 0) {
10546       if (data.size() >= 16) {
10547         memcpy(&info->data_window[0], &data.at(0), sizeof(int));
10548         memcpy(&info->data_window[1], &data.at(4), sizeof(int));
10549         memcpy(&info->data_window[2], &data.at(8), sizeof(int));
10550         memcpy(&info->data_window[3], &data.at(12), sizeof(int));
10551         tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[0]));
10552         tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[1]));
10553         tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[2]));
10554         tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[3]));
10555         has_data_window = true;
10556       }
10557     } else if (attr_name.compare("displayWindow") == 0) {
10558       if (data.size() >= 16) {
10559         memcpy(&info->display_window[0], &data.at(0), sizeof(int));
10560         memcpy(&info->display_window[1], &data.at(4), sizeof(int));
10561         memcpy(&info->display_window[2], &data.at(8), sizeof(int));
10562         memcpy(&info->display_window[3], &data.at(12), sizeof(int));
10563         tinyexr::swap4(
10564             reinterpret_cast<unsigned int *>(&info->display_window[0]));
10565         tinyexr::swap4(
10566             reinterpret_cast<unsigned int *>(&info->display_window[1]));
10567         tinyexr::swap4(
10568             reinterpret_cast<unsigned int *>(&info->display_window[2]));
10569         tinyexr::swap4(
10570             reinterpret_cast<unsigned int *>(&info->display_window[3]));
10571 
10572         has_display_window = true;
10573       }
10574     } else if (attr_name.compare("lineOrder") == 0) {
10575       if (data.size() >= 1) {
10576         info->line_order = static_cast<int>(data[0]);
10577         has_line_order = true;
10578       }
10579     } else if (attr_name.compare("pixelAspectRatio") == 0) {
10580       if (data.size() >= sizeof(float)) {
10581         memcpy(&info->pixel_aspect_ratio, &data.at(0), sizeof(float));
10582         tinyexr::swap4(
10583             reinterpret_cast<unsigned int *>(&info->pixel_aspect_ratio));
10584         has_pixel_aspect_ratio = true;
10585       }
10586     } else if (attr_name.compare("screenWindowCenter") == 0) {
10587       if (data.size() >= 8) {
10588         memcpy(&info->screen_window_center[0], &data.at(0), sizeof(float));
10589         memcpy(&info->screen_window_center[1], &data.at(4), sizeof(float));
10590         tinyexr::swap4(
10591             reinterpret_cast<unsigned int *>(&info->screen_window_center[0]));
10592         tinyexr::swap4(
10593             reinterpret_cast<unsigned int *>(&info->screen_window_center[1]));
10594         has_screen_window_center = true;
10595       }
10596     } else if (attr_name.compare("screenWindowWidth") == 0) {
10597       if (data.size() >= sizeof(float)) {
10598         memcpy(&info->screen_window_width, &data.at(0), sizeof(float));
10599         tinyexr::swap4(
10600             reinterpret_cast<unsigned int *>(&info->screen_window_width));
10601 
10602         has_screen_window_width = true;
10603       }
10604     } else if (attr_name.compare("chunkCount") == 0) {
10605       if (data.size() >= sizeof(int)) {
10606         memcpy(&info->chunk_count, &data.at(0), sizeof(int));
10607         tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->chunk_count));
10608       }
10609     } else {
10610       // Custom attribute(up to TINYEXR_MAX_CUSTOM_ATTRIBUTES)
10611       if (info->attributes.size() < TINYEXR_MAX_CUSTOM_ATTRIBUTES) {
10612         EXRAttribute attrib;
10613 #ifdef _MSC_VER
10614         strncpy_s(attrib.name, attr_name.c_str(), 255);
10615         strncpy_s(attrib.type, attr_type.c_str(), 255);
10616 #else
10617         strncpy(attrib.name, attr_name.c_str(), 255);
10618         strncpy(attrib.type, attr_type.c_str(), 255);
10619 #endif
10620         attrib.name[255] = '\0';
10621         attrib.type[255] = '\0';
10622         attrib.size = static_cast<int>(data.size());
10623         attrib.value = static_cast<unsigned char *>(malloc(data.size()));
10624         memcpy(reinterpret_cast<char *>(attrib.value), &data.at(0),
10625                data.size());
10626         info->attributes.push_back(attrib);
10627       }
10628     }
10629   }
10630 
10631   // Check if required attributes exist
10632   {
10633     std::stringstream ss_err;
10634 
10635     if (!has_compression) {
10636       ss_err << "\"compression\" attribute not found in the header."
10637              << std::endl;
10638     }
10639 
10640     if (!has_channels) {
10641       ss_err << "\"channels\" attribute not found in the header." << std::endl;
10642     }
10643 
10644     if (!has_line_order) {
10645       ss_err << "\"lineOrder\" attribute not found in the header." << std::endl;
10646     }
10647 
10648     if (!has_display_window) {
10649       ss_err << "\"displayWindow\" attribute not found in the header."
10650              << std::endl;
10651     }
10652 
10653     if (!has_data_window) {
10654       ss_err << "\"dataWindow\" attribute not found in the header or invalid."
10655              << std::endl;
10656     }
10657 
10658     if (!has_pixel_aspect_ratio) {
10659       ss_err << "\"pixelAspectRatio\" attribute not found in the header."
10660              << std::endl;
10661     }
10662 
10663     if (!has_screen_window_width) {
10664       ss_err << "\"screenWindowWidth\" attribute not found in the header."
10665              << std::endl;
10666     }
10667 
10668     if (!has_screen_window_center) {
10669       ss_err << "\"screenWindowCenter\" attribute not found in the header."
10670              << std::endl;
10671     }
10672 
10673     if (!(ss_err.str().empty())) {
10674       if (err) {
10675         (*err) += ss_err.str();
10676       }
10677       return TINYEXR_ERROR_INVALID_HEADER;
10678     }
10679   }
10680 
10681   info->header_len = static_cast<unsigned int>(orig_size - size);
10682 
10683   return TINYEXR_SUCCESS;
10684 }
10685 
10686 // C++ HeaderInfo to C EXRHeader conversion.
ConvertHeader(EXRHeader * exr_header,const HeaderInfo & info)10687 static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) {
10688   exr_header->pixel_aspect_ratio = info.pixel_aspect_ratio;
10689   exr_header->screen_window_center[0] = info.screen_window_center[0];
10690   exr_header->screen_window_center[1] = info.screen_window_center[1];
10691   exr_header->screen_window_width = info.screen_window_width;
10692   exr_header->chunk_count = info.chunk_count;
10693   exr_header->display_window[0] = info.display_window[0];
10694   exr_header->display_window[1] = info.display_window[1];
10695   exr_header->display_window[2] = info.display_window[2];
10696   exr_header->display_window[3] = info.display_window[3];
10697   exr_header->data_window[0] = info.data_window[0];
10698   exr_header->data_window[1] = info.data_window[1];
10699   exr_header->data_window[2] = info.data_window[2];
10700   exr_header->data_window[3] = info.data_window[3];
10701   exr_header->line_order = info.line_order;
10702   exr_header->compression_type = info.compression_type;
10703 
10704   exr_header->tile_size_x = info.tile_size_x;
10705   exr_header->tile_size_y = info.tile_size_y;
10706   exr_header->tile_level_mode = info.tile_level_mode;
10707   exr_header->tile_rounding_mode = info.tile_rounding_mode;
10708 
10709   exr_header->num_channels = static_cast<int>(info.channels.size());
10710 
10711   exr_header->channels = static_cast<EXRChannelInfo *>(malloc(
10712       sizeof(EXRChannelInfo) * static_cast<size_t>(exr_header->num_channels)));
10713   for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
10714 #ifdef _MSC_VER
10715     strncpy_s(exr_header->channels[c].name, info.channels[c].name.c_str(), 255);
10716 #else
10717     strncpy(exr_header->channels[c].name, info.channels[c].name.c_str(), 255);
10718 #endif
10719     // manually add '\0' for safety.
10720     exr_header->channels[c].name[255] = '\0';
10721 
10722     exr_header->channels[c].pixel_type = info.channels[c].pixel_type;
10723     exr_header->channels[c].p_linear = info.channels[c].p_linear;
10724     exr_header->channels[c].x_sampling = info.channels[c].x_sampling;
10725     exr_header->channels[c].y_sampling = info.channels[c].y_sampling;
10726   }
10727 
10728   exr_header->pixel_types = static_cast<int *>(
10729       malloc(sizeof(int) * static_cast<size_t>(exr_header->num_channels)));
10730   for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
10731     exr_header->pixel_types[c] = info.channels[c].pixel_type;
10732   }
10733 
10734   // Initially fill with values of `pixel_types`
10735   exr_header->requested_pixel_types = static_cast<int *>(
10736       malloc(sizeof(int) * static_cast<size_t>(exr_header->num_channels)));
10737   for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
10738     exr_header->requested_pixel_types[c] = info.channels[c].pixel_type;
10739   }
10740 
10741   exr_header->num_custom_attributes = static_cast<int>(info.attributes.size());
10742 
10743   if (exr_header->num_custom_attributes > 0) {
10744     // TODO(syoyo): Report warning when # of attributes exceeds
10745     // `TINYEXR_MAX_CUSTOM_ATTRIBUTES`
10746     if (exr_header->num_custom_attributes > TINYEXR_MAX_CUSTOM_ATTRIBUTES) {
10747       exr_header->num_custom_attributes = TINYEXR_MAX_CUSTOM_ATTRIBUTES;
10748     }
10749 
10750     exr_header->custom_attributes = static_cast<EXRAttribute *>(malloc(
10751         sizeof(EXRAttribute) * size_t(exr_header->num_custom_attributes)));
10752 
10753     for (size_t i = 0; i < info.attributes.size(); i++) {
10754       memcpy(exr_header->custom_attributes[i].name, info.attributes[i].name,
10755              256);
10756       memcpy(exr_header->custom_attributes[i].type, info.attributes[i].type,
10757              256);
10758       exr_header->custom_attributes[i].size = info.attributes[i].size;
10759       // Just copy poiner
10760       exr_header->custom_attributes[i].value = info.attributes[i].value;
10761     }
10762 
10763   } else {
10764     exr_header->custom_attributes = NULL;
10765   }
10766 
10767   exr_header->header_len = info.header_len;
10768 }
10769 
DecodeChunk(EXRImage * exr_image,const EXRHeader * exr_header,const std::vector<tinyexr::tinyexr_uint64> & offsets,const unsigned char * head,const size_t size,std::string * err)10770 static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
10771                        const std::vector<tinyexr::tinyexr_uint64> &offsets,
10772                        const unsigned char *head, const size_t size,
10773                        std::string *err) {
10774   int num_channels = exr_header->num_channels;
10775 
10776   int num_scanline_blocks = 1;
10777   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
10778     num_scanline_blocks = 16;
10779   } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
10780     num_scanline_blocks = 32;
10781   } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
10782     num_scanline_blocks = 16;
10783   }
10784 
10785   int data_width = exr_header->data_window[2] - exr_header->data_window[0] + 1;
10786   int data_height = exr_header->data_window[3] - exr_header->data_window[1] + 1;
10787 
10788   if ((data_width < 0) || (data_height < 0)) {
10789     if (err) {
10790       std::stringstream ss;
10791       ss << "Invalid data width or data height: " << data_width << ", "
10792          << data_height << std::endl;
10793       (*err) += ss.str();
10794     }
10795     return TINYEXR_ERROR_INVALID_DATA;
10796   }
10797 
10798   // Do not allow too large data_width and data_height. header invalid?
10799   {
10800     const int threshold = 1024 * 8192;  // heuristics
10801     if ((data_width > threshold) || (data_height > threshold)) {
10802       if (err) {
10803         std::stringstream ss;
10804         ss << "data_with or data_height too large. data_width: " << data_width
10805            << ", "
10806            << "data_height = " << data_height << std::endl;
10807         (*err) += ss.str();
10808       }
10809       return TINYEXR_ERROR_INVALID_DATA;
10810     }
10811   }
10812 
10813   size_t num_blocks = offsets.size();
10814 
10815   std::vector<size_t> channel_offset_list;
10816   int pixel_data_size = 0;
10817   size_t channel_offset = 0;
10818   if (!tinyexr::ComputeChannelLayout(&channel_offset_list, &pixel_data_size,
10819                                      &channel_offset, num_channels,
10820                                      exr_header->channels)) {
10821     if (err) {
10822       (*err) += "Failed to compute channel layout.\n";
10823     }
10824     return TINYEXR_ERROR_INVALID_DATA;
10825   }
10826 
10827   bool invalid_data = false;  // TODO(LTE): Use atomic lock for MT safety.
10828 
10829   if (exr_header->tiled) {
10830     // value check
10831     if (exr_header->tile_size_x < 0) {
10832       if (err) {
10833         std::stringstream ss;
10834         ss << "Invalid tile size x : " << exr_header->tile_size_x << "\n";
10835         (*err) += ss.str();
10836       }
10837       return TINYEXR_ERROR_INVALID_HEADER;
10838     }
10839 
10840     if (exr_header->tile_size_y < 0) {
10841       if (err) {
10842         std::stringstream ss;
10843         ss << "Invalid tile size y : " << exr_header->tile_size_y << "\n";
10844         (*err) += ss.str();
10845       }
10846       return TINYEXR_ERROR_INVALID_HEADER;
10847     }
10848 
10849     size_t num_tiles = offsets.size();  // = # of blocks
10850 
10851     exr_image->tiles = static_cast<EXRTile *>(
10852         calloc(sizeof(EXRTile), static_cast<size_t>(num_tiles)));
10853 
10854     for (size_t tile_idx = 0; tile_idx < num_tiles; tile_idx++) {
10855       // Allocate memory for each tile.
10856       exr_image->tiles[tile_idx].images = tinyexr::AllocateImage(
10857           num_channels, exr_header->channels, exr_header->requested_pixel_types,
10858           exr_header->tile_size_x, exr_header->tile_size_y);
10859 
10860       // 16 byte: tile coordinates
10861       // 4 byte : data size
10862       // ~      : data(uncompressed or compressed)
10863       if (offsets[tile_idx] + sizeof(int) * 5 > size) {
10864         if (err) {
10865           (*err) += "Insufficient data size.\n";
10866         }
10867         return TINYEXR_ERROR_INVALID_DATA;
10868       }
10869 
10870       size_t data_size = size_t(size - (offsets[tile_idx] + sizeof(int) * 5));
10871       const unsigned char *data_ptr =
10872           reinterpret_cast<const unsigned char *>(head + offsets[tile_idx]);
10873 
10874       int tile_coordinates[4];
10875       memcpy(tile_coordinates, data_ptr, sizeof(int) * 4);
10876       tinyexr::swap4(reinterpret_cast<unsigned int *>(&tile_coordinates[0]));
10877       tinyexr::swap4(reinterpret_cast<unsigned int *>(&tile_coordinates[1]));
10878       tinyexr::swap4(reinterpret_cast<unsigned int *>(&tile_coordinates[2]));
10879       tinyexr::swap4(reinterpret_cast<unsigned int *>(&tile_coordinates[3]));
10880 
10881       // @todo{ LoD }
10882       if (tile_coordinates[2] != 0) {
10883         return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
10884       }
10885       if (tile_coordinates[3] != 0) {
10886         return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
10887       }
10888 
10889       int data_len;
10890       memcpy(&data_len, data_ptr + 16,
10891              sizeof(int));  // 16 = sizeof(tile_coordinates)
10892       tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
10893 
10894       if (data_len < 4 || size_t(data_len) > data_size) {
10895         if (err) {
10896           (*err) += "Insufficient data length.\n";
10897         }
10898         return TINYEXR_ERROR_INVALID_DATA;
10899       }
10900 
10901       // Move to data addr: 20 = 16 + 4;
10902       data_ptr += 20;
10903 
10904       tinyexr::DecodeTiledPixelData(
10905           exr_image->tiles[tile_idx].images,
10906           &(exr_image->tiles[tile_idx].width),
10907           &(exr_image->tiles[tile_idx].height),
10908           exr_header->requested_pixel_types, data_ptr,
10909           static_cast<size_t>(data_len), exr_header->compression_type,
10910           exr_header->line_order, data_width, data_height, tile_coordinates[0],
10911           tile_coordinates[1], exr_header->tile_size_x, exr_header->tile_size_y,
10912           static_cast<size_t>(pixel_data_size),
10913           static_cast<size_t>(exr_header->num_custom_attributes),
10914           exr_header->custom_attributes,
10915           static_cast<size_t>(exr_header->num_channels), exr_header->channels,
10916           channel_offset_list);
10917 
10918       exr_image->tiles[tile_idx].offset_x = tile_coordinates[0];
10919       exr_image->tiles[tile_idx].offset_y = tile_coordinates[1];
10920       exr_image->tiles[tile_idx].level_x = tile_coordinates[2];
10921       exr_image->tiles[tile_idx].level_y = tile_coordinates[3];
10922 
10923       exr_image->num_tiles = static_cast<int>(num_tiles);
10924     }
10925   } else {  // scanline format
10926 
10927     // Don't allow too large image(256GB * pixel_data_size or more). Workaround
10928     // for #104.
10929     size_t total_data_len =
10930         size_t(data_width) * size_t(data_height) * size_t(num_channels);
10931     const bool total_data_len_overflown = sizeof(void*) == 8 ? (total_data_len >= 0x4000000000) : false;
10932     if ((total_data_len == 0) || total_data_len_overflown ) {
10933       if (err) {
10934         std::stringstream ss;
10935         ss << "Image data size is zero or too large: width = " << data_width
10936            << ", height = " << data_height << ", channels = " << num_channels
10937            << std::endl;
10938         (*err) += ss.str();
10939       }
10940       return TINYEXR_ERROR_INVALID_DATA;
10941     }
10942 
10943     exr_image->images = tinyexr::AllocateImage(
10944         num_channels, exr_header->channels, exr_header->requested_pixel_types,
10945         data_width, data_height);
10946 
10947 #ifdef _OPENMP
10948 #pragma omp parallel for
10949 #endif
10950     for (int y = 0; y < static_cast<int>(num_blocks); y++) {
10951       size_t y_idx = static_cast<size_t>(y);
10952 
10953       if (offsets[y_idx] + sizeof(int) * 2 > size) {
10954         invalid_data = true;
10955       } else {
10956         // 4 byte: scan line
10957         // 4 byte: data size
10958         // ~     : pixel data(uncompressed or compressed)
10959         size_t data_size = size_t(size - (offsets[y_idx] + sizeof(int) * 2));
10960         const unsigned char *data_ptr =
10961             reinterpret_cast<const unsigned char *>(head + offsets[y_idx]);
10962 
10963         int line_no;
10964         memcpy(&line_no, data_ptr, sizeof(int));
10965         int data_len;
10966         memcpy(&data_len, data_ptr + 4, sizeof(int));
10967         tinyexr::swap4(reinterpret_cast<unsigned int *>(&line_no));
10968         tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
10969 
10970         if (size_t(data_len) > data_size) {
10971           invalid_data = true;
10972 
10973         } else if ((line_no > (2 << 20)) || (line_no < -(2 << 20))) {
10974           // Too large value. Assume this is invalid
10975           // 2**20 = 1048576 = heuristic value.
10976           invalid_data = true;
10977         } else if (data_len == 0) {
10978           // TODO(syoyo): May be ok to raise the threshold for example `data_len
10979           // < 4`
10980           invalid_data = true;
10981         } else {
10982           // line_no may be negative.
10983           int end_line_no = (std::min)(line_no + num_scanline_blocks,
10984                                        (exr_header->data_window[3] + 1));
10985 
10986           int num_lines = end_line_no - line_no;
10987 
10988           if (num_lines <= 0) {
10989             invalid_data = true;
10990           } else {
10991             // Move to data addr: 8 = 4 + 4;
10992             data_ptr += 8;
10993 
10994             // Adjust line_no with data_window.bmin.y
10995 
10996             // overflow check
10997             tinyexr_int64 lno = static_cast<tinyexr_int64>(line_no) - static_cast<tinyexr_int64>(exr_header->data_window[1]);
10998             if (lno > std::numeric_limits<int>::max()) {
10999               line_no = -1; // invalid
11000             } else if (lno < -std::numeric_limits<int>::max()) {
11001               line_no = -1; // invalid
11002             } else {
11003               line_no -= exr_header->data_window[1];
11004             }
11005 
11006             if (line_no < 0) {
11007               invalid_data = true;
11008             } else {
11009               if (!tinyexr::DecodePixelData(
11010                       exr_image->images, exr_header->requested_pixel_types,
11011                       data_ptr, static_cast<size_t>(data_len),
11012                       exr_header->compression_type, exr_header->line_order,
11013                       data_width, data_height, data_width, y, line_no,
11014                       num_lines, static_cast<size_t>(pixel_data_size),
11015                       static_cast<size_t>(exr_header->num_custom_attributes),
11016                       exr_header->custom_attributes,
11017                       static_cast<size_t>(exr_header->num_channels),
11018                       exr_header->channels, channel_offset_list)) {
11019                 invalid_data = true;
11020               }
11021             }
11022           }
11023         }
11024       }
11025     }  // omp parallel
11026   }
11027 
11028   if (invalid_data) {
11029     if (err) {
11030       std::stringstream ss;
11031       (*err) += "Invalid data found when decoding pixels.\n";
11032     }
11033     return TINYEXR_ERROR_INVALID_DATA;
11034   }
11035 
11036   // Overwrite `pixel_type` with `requested_pixel_type`.
11037   {
11038     for (int c = 0; c < exr_header->num_channels; c++) {
11039       exr_header->pixel_types[c] = exr_header->requested_pixel_types[c];
11040     }
11041   }
11042 
11043   {
11044     exr_image->num_channels = num_channels;
11045 
11046     exr_image->width = data_width;
11047     exr_image->height = data_height;
11048   }
11049 
11050   return TINYEXR_SUCCESS;
11051 }
11052 
ReconstructLineOffsets(std::vector<tinyexr::tinyexr_uint64> * offsets,size_t n,const unsigned char * head,const unsigned char * marker,const size_t size)11053 static bool ReconstructLineOffsets(
11054     std::vector<tinyexr::tinyexr_uint64> *offsets, size_t n,
11055     const unsigned char *head, const unsigned char *marker, const size_t size) {
11056   assert(head < marker);
11057   assert(offsets->size() == n);
11058 
11059   for (size_t i = 0; i < n; i++) {
11060     size_t offset = static_cast<size_t>(marker - head);
11061     // Offset should not exceed whole EXR file/data size.
11062     if ((offset + sizeof(tinyexr::tinyexr_uint64)) >= size) {
11063       return false;
11064     }
11065 
11066     int y;
11067     unsigned int data_len;
11068 
11069     memcpy(&y, marker, sizeof(int));
11070     memcpy(&data_len, marker + 4, sizeof(unsigned int));
11071 
11072     if (data_len >= size) {
11073       return false;
11074     }
11075 
11076     tinyexr::swap4(reinterpret_cast<unsigned int *>(&y));
11077     tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
11078 
11079     (*offsets)[i] = offset;
11080 
11081     marker += data_len + 8;  // 8 = 4 bytes(y) + 4 bytes(data_len)
11082   }
11083 
11084   return true;
11085 }
11086 
DecodeEXRImage(EXRImage * exr_image,const EXRHeader * exr_header,const unsigned char * head,const unsigned char * marker,const size_t size,const char ** err)11087 static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header,
11088                           const unsigned char *head,
11089                           const unsigned char *marker, const size_t size,
11090                           const char **err) {
11091   if (exr_image == NULL || exr_header == NULL || head == NULL ||
11092       marker == NULL || (size <= tinyexr::kEXRVersionSize)) {
11093     tinyexr::SetErrorMessage("Invalid argument for DecodeEXRImage().", err);
11094     return TINYEXR_ERROR_INVALID_ARGUMENT;
11095   }
11096 
11097   int num_scanline_blocks = 1;
11098   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
11099     num_scanline_blocks = 16;
11100   } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
11101     num_scanline_blocks = 32;
11102   } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
11103     num_scanline_blocks = 16;
11104   }
11105 
11106   int data_width = exr_header->data_window[2] - exr_header->data_window[0];
11107   if (data_width >= std::numeric_limits<int>::max()) {
11108     // Issue 63
11109     tinyexr::SetErrorMessage("Invalid data width value", err);
11110     return TINYEXR_ERROR_INVALID_DATA;
11111   }
11112   data_width++;
11113 
11114   int data_height = exr_header->data_window[3] - exr_header->data_window[1];
11115   if (data_height >= std::numeric_limits<int>::max()) {
11116     tinyexr::SetErrorMessage("Invalid data height value", err);
11117     return TINYEXR_ERROR_INVALID_DATA;
11118   }
11119   data_height++;
11120 
11121   if ((data_width < 0) || (data_height < 0)) {
11122     tinyexr::SetErrorMessage("data width or data height is negative.", err);
11123     return TINYEXR_ERROR_INVALID_DATA;
11124   }
11125 
11126   // Do not allow too large data_width and data_height. header invalid?
11127   {
11128     const int threshold = 1024 * 8192;  // heuristics
11129     if (data_width > threshold) {
11130       tinyexr::SetErrorMessage("data width too large.", err);
11131       return TINYEXR_ERROR_INVALID_DATA;
11132     }
11133     if (data_height > threshold) {
11134       tinyexr::SetErrorMessage("data height too large.", err);
11135       return TINYEXR_ERROR_INVALID_DATA;
11136     }
11137   }
11138 
11139   // Read offset tables.
11140   size_t num_blocks = 0;
11141 
11142   if (exr_header->chunk_count > 0) {
11143     // Use `chunkCount` attribute.
11144     num_blocks = static_cast<size_t>(exr_header->chunk_count);
11145   } else if (exr_header->tiled) {
11146     // @todo { LoD }
11147     size_t num_x_tiles = static_cast<size_t>(data_width) /
11148                          static_cast<size_t>(exr_header->tile_size_x);
11149     if (num_x_tiles * static_cast<size_t>(exr_header->tile_size_x) <
11150         static_cast<size_t>(data_width)) {
11151       num_x_tiles++;
11152     }
11153     size_t num_y_tiles = static_cast<size_t>(data_height) /
11154                          static_cast<size_t>(exr_header->tile_size_y);
11155     if (num_y_tiles * static_cast<size_t>(exr_header->tile_size_y) <
11156         static_cast<size_t>(data_height)) {
11157       num_y_tiles++;
11158     }
11159 
11160     num_blocks = num_x_tiles * num_y_tiles;
11161   } else {
11162     num_blocks = static_cast<size_t>(data_height) /
11163                  static_cast<size_t>(num_scanline_blocks);
11164     if (num_blocks * static_cast<size_t>(num_scanline_blocks) <
11165         static_cast<size_t>(data_height)) {
11166       num_blocks++;
11167     }
11168   }
11169 
11170   std::vector<tinyexr::tinyexr_uint64> offsets(num_blocks);
11171 
11172   for (size_t y = 0; y < num_blocks; y++) {
11173     tinyexr::tinyexr_uint64 offset;
11174     // Issue #81
11175     if ((marker + sizeof(tinyexr_uint64)) >= (head + size)) {
11176       tinyexr::SetErrorMessage("Insufficient data size in offset table.", err);
11177       return TINYEXR_ERROR_INVALID_DATA;
11178     }
11179 
11180     memcpy(&offset, marker, sizeof(tinyexr::tinyexr_uint64));
11181     tinyexr::swap8(&offset);
11182     if (offset >= size) {
11183       tinyexr::SetErrorMessage("Invalid offset value in DecodeEXRImage.", err);
11184       return TINYEXR_ERROR_INVALID_DATA;
11185     }
11186     marker += sizeof(tinyexr::tinyexr_uint64);  // = 8
11187     offsets[y] = offset;
11188   }
11189 
11190   // If line offsets are invalid, we try to reconstruct it.
11191   // See OpenEXR/IlmImf/ImfScanLineInputFile.cpp::readLineOffsets() for details.
11192   for (size_t y = 0; y < num_blocks; y++) {
11193     if (offsets[y] <= 0) {
11194       // TODO(syoyo) Report as warning?
11195       // if (err) {
11196       //  stringstream ss;
11197       //  ss << "Incomplete lineOffsets." << std::endl;
11198       //  (*err) += ss.str();
11199       //}
11200       bool ret =
11201           ReconstructLineOffsets(&offsets, num_blocks, head, marker, size);
11202       if (ret) {
11203         // OK
11204         break;
11205       } else {
11206         tinyexr::SetErrorMessage(
11207             "Cannot reconstruct lineOffset table in DecodeEXRImage.", err);
11208         return TINYEXR_ERROR_INVALID_DATA;
11209       }
11210     }
11211   }
11212 
11213   {
11214     std::string e;
11215     int ret = DecodeChunk(exr_image, exr_header, offsets, head, size, &e);
11216 
11217     if (ret != TINYEXR_SUCCESS) {
11218       if (!e.empty()) {
11219         tinyexr::SetErrorMessage(e, err);
11220       }
11221 
11222       // release memory(if exists)
11223       if ((exr_header->num_channels > 0) && exr_image && exr_image->images) {
11224         for (size_t c = 0; c < size_t(exr_header->num_channels); c++) {
11225           if (exr_image->images[c]) {
11226             free(exr_image->images[c]);
11227             exr_image->images[c] = NULL;
11228           }
11229         }
11230         free(exr_image->images);
11231         exr_image->images = NULL;
11232       }
11233     }
11234 
11235     return ret;
11236   }
11237 }
11238 
11239 }  // namespace tinyexr
11240 
LoadEXR(float ** out_rgba,int * width,int * height,const char * filename,const char ** err)11241 int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
11242             const char **err) {
11243   if (out_rgba == NULL) {
11244     tinyexr::SetErrorMessage("Invalid argument for LoadEXR()", err);
11245     return TINYEXR_ERROR_INVALID_ARGUMENT;
11246   }
11247 
11248   EXRVersion exr_version;
11249   EXRImage exr_image;
11250   EXRHeader exr_header;
11251   InitEXRHeader(&exr_header);
11252   InitEXRImage(&exr_image);
11253 
11254   {
11255     int ret = ParseEXRVersionFromFile(&exr_version, filename);
11256     if (ret != TINYEXR_SUCCESS) {
11257       tinyexr::SetErrorMessage("Invalid EXR header.", err);
11258       return ret;
11259     }
11260 
11261     if (exr_version.multipart || exr_version.non_image) {
11262       tinyexr::SetErrorMessage(
11263           "Loading multipart or DeepImage is not supported  in LoadEXR() API",
11264           err);
11265       return TINYEXR_ERROR_INVALID_DATA;  // @fixme.
11266     }
11267   }
11268 
11269   {
11270     int ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename, err);
11271     if (ret != TINYEXR_SUCCESS) {
11272       FreeEXRHeader(&exr_header);
11273       return ret;
11274     }
11275   }
11276 
11277   // Read HALF channel as FLOAT.
11278   for (int i = 0; i < exr_header.num_channels; i++) {
11279     if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
11280       exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
11281     }
11282   }
11283 
11284   {
11285     int ret = LoadEXRImageFromFile(&exr_image, &exr_header, filename, err);
11286     if (ret != TINYEXR_SUCCESS) {
11287       FreeEXRHeader(&exr_header);
11288       return ret;
11289     }
11290   }
11291 
11292   // RGBA
11293   int idxR = -1;
11294   int idxG = -1;
11295   int idxB = -1;
11296   int idxA = -1;
11297   for (int c = 0; c < exr_header.num_channels; c++) {
11298     if (strcmp(exr_header.channels[c].name, "R") == 0) {
11299       idxR = c;
11300     } else if (strcmp(exr_header.channels[c].name, "G") == 0) {
11301       idxG = c;
11302     } else if (strcmp(exr_header.channels[c].name, "B") == 0) {
11303       idxB = c;
11304     } else if (strcmp(exr_header.channels[c].name, "A") == 0) {
11305       idxA = c;
11306     }
11307   }
11308 
11309   if (exr_header.num_channels == 1) {
11310     // Grayscale channel only.
11311 
11312     (*out_rgba) = reinterpret_cast<float *>(
11313         malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
11314                static_cast<size_t>(exr_image.height)));
11315 
11316     if (exr_header.tiled) {
11317       for (int it = 0; it < exr_image.num_tiles; it++) {
11318         for (int j = 0; j < exr_header.tile_size_y; j++) {
11319           for (int i = 0; i < exr_header.tile_size_x; i++) {
11320             const int ii =
11321                 exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
11322             const int jj =
11323                 exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
11324             const int idx = ii + jj * exr_image.width;
11325 
11326             // out of region check.
11327             if (ii >= exr_image.width) {
11328               continue;
11329             }
11330             if (jj >= exr_image.height) {
11331               continue;
11332             }
11333             const int srcIdx = i + j * exr_header.tile_size_x;
11334             unsigned char **src = exr_image.tiles[it].images;
11335             (*out_rgba)[4 * idx + 0] =
11336                 reinterpret_cast<float **>(src)[0][srcIdx];
11337             (*out_rgba)[4 * idx + 1] =
11338                 reinterpret_cast<float **>(src)[0][srcIdx];
11339             (*out_rgba)[4 * idx + 2] =
11340                 reinterpret_cast<float **>(src)[0][srcIdx];
11341             (*out_rgba)[4 * idx + 3] =
11342                 reinterpret_cast<float **>(src)[0][srcIdx];
11343           }
11344         }
11345       }
11346     } else {
11347       for (int i = 0; i < exr_image.width * exr_image.height; i++) {
11348         const float val = reinterpret_cast<float **>(exr_image.images)[0][i];
11349         (*out_rgba)[4 * i + 0] = val;
11350         (*out_rgba)[4 * i + 1] = val;
11351         (*out_rgba)[4 * i + 2] = val;
11352         (*out_rgba)[4 * i + 3] = val;
11353       }
11354     }
11355   } else {
11356     // Assume RGB(A)
11357 
11358     if (idxR == -1) {
11359       tinyexr::SetErrorMessage("R channel not found", err);
11360 
11361       // @todo { free exr_image }
11362       FreeEXRHeader(&exr_header);
11363       return TINYEXR_ERROR_INVALID_DATA;
11364     }
11365 
11366     if (idxG == -1) {
11367       tinyexr::SetErrorMessage("G channel not found", err);
11368       // @todo { free exr_image }
11369       FreeEXRHeader(&exr_header);
11370       return TINYEXR_ERROR_INVALID_DATA;
11371     }
11372 
11373     if (idxB == -1) {
11374       tinyexr::SetErrorMessage("B channel not found", err);
11375       // @todo { free exr_image }
11376       FreeEXRHeader(&exr_header);
11377       return TINYEXR_ERROR_INVALID_DATA;
11378     }
11379 
11380     (*out_rgba) = reinterpret_cast<float *>(
11381         malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
11382                static_cast<size_t>(exr_image.height)));
11383     if (exr_header.tiled) {
11384       for (int it = 0; it < exr_image.num_tiles; it++) {
11385         for (int j = 0; j < exr_header.tile_size_y; j++) {
11386           for (int i = 0; i < exr_header.tile_size_x; i++) {
11387             const int ii =
11388                 exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
11389             const int jj =
11390                 exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
11391             const int idx = ii + jj * exr_image.width;
11392 
11393             // out of region check.
11394             if (ii >= exr_image.width) {
11395               continue;
11396             }
11397             if (jj >= exr_image.height) {
11398               continue;
11399             }
11400             const int srcIdx = i + j * exr_header.tile_size_x;
11401             unsigned char **src = exr_image.tiles[it].images;
11402             (*out_rgba)[4 * idx + 0] =
11403                 reinterpret_cast<float **>(src)[idxR][srcIdx];
11404             (*out_rgba)[4 * idx + 1] =
11405                 reinterpret_cast<float **>(src)[idxG][srcIdx];
11406             (*out_rgba)[4 * idx + 2] =
11407                 reinterpret_cast<float **>(src)[idxB][srcIdx];
11408             if (idxA != -1) {
11409               (*out_rgba)[4 * idx + 3] =
11410                   reinterpret_cast<float **>(src)[idxA][srcIdx];
11411             } else {
11412               (*out_rgba)[4 * idx + 3] = 1.0;
11413             }
11414           }
11415         }
11416       }
11417     } else {
11418       for (int i = 0; i < exr_image.width * exr_image.height; i++) {
11419         (*out_rgba)[4 * i + 0] =
11420             reinterpret_cast<float **>(exr_image.images)[idxR][i];
11421         (*out_rgba)[4 * i + 1] =
11422             reinterpret_cast<float **>(exr_image.images)[idxG][i];
11423         (*out_rgba)[4 * i + 2] =
11424             reinterpret_cast<float **>(exr_image.images)[idxB][i];
11425         if (idxA != -1) {
11426           (*out_rgba)[4 * i + 3] =
11427               reinterpret_cast<float **>(exr_image.images)[idxA][i];
11428         } else {
11429           (*out_rgba)[4 * i + 3] = 1.0;
11430         }
11431       }
11432     }
11433   }
11434 
11435   (*width) = exr_image.width;
11436   (*height) = exr_image.height;
11437 
11438   FreeEXRHeader(&exr_header);
11439   FreeEXRImage(&exr_image);
11440 
11441   return TINYEXR_SUCCESS;
11442 }
11443 
IsEXR(const char * filename)11444 int IsEXR(const char *filename) {
11445   EXRVersion exr_version;
11446 
11447   int ret = ParseEXRVersionFromFile(&exr_version, filename);
11448   if (ret != TINYEXR_SUCCESS) {
11449     return TINYEXR_ERROR_INVALID_HEADER;
11450   }
11451 
11452   return TINYEXR_SUCCESS;
11453 }
11454 
ParseEXRHeaderFromMemory(EXRHeader * exr_header,const EXRVersion * version,const unsigned char * memory,size_t size,const char ** err)11455 int ParseEXRHeaderFromMemory(EXRHeader *exr_header, const EXRVersion *version,
11456                              const unsigned char *memory, size_t size,
11457                              const char **err) {
11458   if (memory == NULL || exr_header == NULL) {
11459     tinyexr::SetErrorMessage(
11460         "Invalid argument. `memory` or `exr_header` argument is null in "
11461         "ParseEXRHeaderFromMemory()",
11462         err);
11463 
11464     // Invalid argument
11465     return TINYEXR_ERROR_INVALID_ARGUMENT;
11466   }
11467 
11468   if (size < tinyexr::kEXRVersionSize) {
11469     tinyexr::SetErrorMessage("Insufficient header/data size.\n", err);
11470     return TINYEXR_ERROR_INVALID_DATA;
11471   }
11472 
11473   const unsigned char *marker = memory + tinyexr::kEXRVersionSize;
11474   size_t marker_size = size - tinyexr::kEXRVersionSize;
11475 
11476   tinyexr::HeaderInfo info;
11477   info.clear();
11478 
11479   std::string err_str;
11480   int ret = ParseEXRHeader(&info, NULL, version, &err_str, marker, marker_size);
11481 
11482   if (ret != TINYEXR_SUCCESS) {
11483     if (err && !err_str.empty()) {
11484       tinyexr::SetErrorMessage(err_str, err);
11485     }
11486   }
11487 
11488   ConvertHeader(exr_header, info);
11489 
11490   // transfoer `tiled` from version.
11491   exr_header->tiled = version->tiled;
11492 
11493   return ret;
11494 }
11495 
LoadEXRFromMemory(float ** out_rgba,int * width,int * height,const unsigned char * memory,size_t size,const char ** err)11496 int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
11497                       const unsigned char *memory, size_t size,
11498                       const char **err) {
11499   if (out_rgba == NULL || memory == NULL) {
11500     tinyexr::SetErrorMessage("Invalid argument for LoadEXRFromMemory", err);
11501     return TINYEXR_ERROR_INVALID_ARGUMENT;
11502   }
11503 
11504   EXRVersion exr_version;
11505   EXRImage exr_image;
11506   EXRHeader exr_header;
11507 
11508   InitEXRHeader(&exr_header);
11509 
11510   int ret = ParseEXRVersionFromMemory(&exr_version, memory, size);
11511   if (ret != TINYEXR_SUCCESS) {
11512     tinyexr::SetErrorMessage("Failed to parse EXR version", err);
11513     return ret;
11514   }
11515 
11516   ret = ParseEXRHeaderFromMemory(&exr_header, &exr_version, memory, size, err);
11517   if (ret != TINYEXR_SUCCESS) {
11518     return ret;
11519   }
11520 
11521   // Read HALF channel as FLOAT.
11522   for (int i = 0; i < exr_header.num_channels; i++) {
11523     if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
11524       exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
11525     }
11526   }
11527 
11528   InitEXRImage(&exr_image);
11529   ret = LoadEXRImageFromMemory(&exr_image, &exr_header, memory, size, err);
11530   if (ret != TINYEXR_SUCCESS) {
11531     return ret;
11532   }
11533 
11534   // RGBA
11535   int idxR = -1;
11536   int idxG = -1;
11537   int idxB = -1;
11538   int idxA = -1;
11539   for (int c = 0; c < exr_header.num_channels; c++) {
11540     if (strcmp(exr_header.channels[c].name, "R") == 0) {
11541       idxR = c;
11542     } else if (strcmp(exr_header.channels[c].name, "G") == 0) {
11543       idxG = c;
11544     } else if (strcmp(exr_header.channels[c].name, "B") == 0) {
11545       idxB = c;
11546     } else if (strcmp(exr_header.channels[c].name, "A") == 0) {
11547       idxA = c;
11548     }
11549   }
11550 
11551   // TODO(syoyo): Refactor removing same code as used in LoadEXR().
11552   if (exr_header.num_channels == 1) {
11553     // Grayscale channel only.
11554 
11555     (*out_rgba) = reinterpret_cast<float *>(
11556         malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
11557                static_cast<size_t>(exr_image.height)));
11558 
11559     if (exr_header.tiled) {
11560       for (int it = 0; it < exr_image.num_tiles; it++) {
11561         for (int j = 0; j < exr_header.tile_size_y; j++) {
11562           for (int i = 0; i < exr_header.tile_size_x; i++) {
11563             const int ii =
11564                 exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
11565             const int jj =
11566                 exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
11567             const int idx = ii + jj * exr_image.width;
11568 
11569             // out of region check.
11570             if (ii >= exr_image.width) {
11571               continue;
11572             }
11573             if (jj >= exr_image.height) {
11574               continue;
11575             }
11576             const int srcIdx = i + j * exr_header.tile_size_x;
11577             unsigned char **src = exr_image.tiles[it].images;
11578             (*out_rgba)[4 * idx + 0] =
11579                 reinterpret_cast<float **>(src)[0][srcIdx];
11580             (*out_rgba)[4 * idx + 1] =
11581                 reinterpret_cast<float **>(src)[0][srcIdx];
11582             (*out_rgba)[4 * idx + 2] =
11583                 reinterpret_cast<float **>(src)[0][srcIdx];
11584             (*out_rgba)[4 * idx + 3] =
11585                 reinterpret_cast<float **>(src)[0][srcIdx];
11586           }
11587         }
11588       }
11589     } else {
11590       for (int i = 0; i < exr_image.width * exr_image.height; i++) {
11591         const float val = reinterpret_cast<float **>(exr_image.images)[0][i];
11592         (*out_rgba)[4 * i + 0] = val;
11593         (*out_rgba)[4 * i + 1] = val;
11594         (*out_rgba)[4 * i + 2] = val;
11595         (*out_rgba)[4 * i + 3] = val;
11596       }
11597     }
11598 
11599   } else {
11600     // TODO(syoyo): Support non RGBA image.
11601 
11602     if (idxR == -1) {
11603       tinyexr::SetErrorMessage("R channel not found", err);
11604 
11605       // @todo { free exr_image }
11606       return TINYEXR_ERROR_INVALID_DATA;
11607     }
11608 
11609     if (idxG == -1) {
11610       tinyexr::SetErrorMessage("G channel not found", err);
11611       // @todo { free exr_image }
11612       return TINYEXR_ERROR_INVALID_DATA;
11613     }
11614 
11615     if (idxB == -1) {
11616       tinyexr::SetErrorMessage("B channel not found", err);
11617       // @todo { free exr_image }
11618       return TINYEXR_ERROR_INVALID_DATA;
11619     }
11620 
11621     (*out_rgba) = reinterpret_cast<float *>(
11622         malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
11623                static_cast<size_t>(exr_image.height)));
11624 
11625     if (exr_header.tiled) {
11626       for (int it = 0; it < exr_image.num_tiles; it++) {
11627         for (int j = 0; j < exr_header.tile_size_y; j++)
11628           for (int i = 0; i < exr_header.tile_size_x; i++) {
11629             const int ii =
11630                 exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
11631             const int jj =
11632                 exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
11633             const int idx = ii + jj * exr_image.width;
11634 
11635             // out of region check.
11636             if (ii >= exr_image.width) {
11637               continue;
11638             }
11639             if (jj >= exr_image.height) {
11640               continue;
11641             }
11642             const int srcIdx = i + j * exr_header.tile_size_x;
11643             unsigned char **src = exr_image.tiles[it].images;
11644             (*out_rgba)[4 * idx + 0] =
11645                 reinterpret_cast<float **>(src)[idxR][srcIdx];
11646             (*out_rgba)[4 * idx + 1] =
11647                 reinterpret_cast<float **>(src)[idxG][srcIdx];
11648             (*out_rgba)[4 * idx + 2] =
11649                 reinterpret_cast<float **>(src)[idxB][srcIdx];
11650             if (idxA != -1) {
11651               (*out_rgba)[4 * idx + 3] =
11652                   reinterpret_cast<float **>(src)[idxA][srcIdx];
11653             } else {
11654               (*out_rgba)[4 * idx + 3] = 1.0;
11655             }
11656           }
11657       }
11658     } else {
11659       for (int i = 0; i < exr_image.width * exr_image.height; i++) {
11660         (*out_rgba)[4 * i + 0] =
11661             reinterpret_cast<float **>(exr_image.images)[idxR][i];
11662         (*out_rgba)[4 * i + 1] =
11663             reinterpret_cast<float **>(exr_image.images)[idxG][i];
11664         (*out_rgba)[4 * i + 2] =
11665             reinterpret_cast<float **>(exr_image.images)[idxB][i];
11666         if (idxA != -1) {
11667           (*out_rgba)[4 * i + 3] =
11668               reinterpret_cast<float **>(exr_image.images)[idxA][i];
11669         } else {
11670           (*out_rgba)[4 * i + 3] = 1.0;
11671         }
11672       }
11673     }
11674   }
11675 
11676   (*width) = exr_image.width;
11677   (*height) = exr_image.height;
11678 
11679   FreeEXRHeader(&exr_header);
11680   FreeEXRImage(&exr_image);
11681 
11682   return TINYEXR_SUCCESS;
11683 }
11684 
LoadEXRImageFromFile(EXRImage * exr_image,const EXRHeader * exr_header,const char * filename,const char ** err)11685 int LoadEXRImageFromFile(EXRImage *exr_image, const EXRHeader *exr_header,
11686                          const char *filename, const char **err) {
11687   if (exr_image == NULL) {
11688     tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromFile", err);
11689     return TINYEXR_ERROR_INVALID_ARGUMENT;
11690   }
11691 
11692 #ifdef _WIN32
11693   FILE *fp = NULL;
11694   fopen_s(&fp, filename, "rb");
11695 #else
11696   FILE *fp = fopen(filename, "rb");
11697 #endif
11698   if (!fp) {
11699     tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err);
11700     return TINYEXR_ERROR_CANT_OPEN_FILE;
11701   }
11702 
11703   size_t filesize;
11704   // Compute size
11705   fseek(fp, 0, SEEK_END);
11706   filesize = static_cast<size_t>(ftell(fp));
11707   fseek(fp, 0, SEEK_SET);
11708 
11709   if (filesize < 16) {
11710     tinyexr::SetErrorMessage("File size too short " + std::string(filename),
11711                              err);
11712     return TINYEXR_ERROR_INVALID_FILE;
11713   }
11714 
11715   std::vector<unsigned char> buf(filesize);  // @todo { use mmap }
11716   {
11717     size_t ret;
11718     ret = fread(&buf[0], 1, filesize, fp);
11719     assert(ret == filesize);
11720     fclose(fp);
11721     (void)ret;
11722   }
11723 
11724   return LoadEXRImageFromMemory(exr_image, exr_header, &buf.at(0), filesize,
11725                                 err);
11726 }
11727 
LoadEXRImageFromMemory(EXRImage * exr_image,const EXRHeader * exr_header,const unsigned char * memory,const size_t size,const char ** err)11728 int LoadEXRImageFromMemory(EXRImage *exr_image, const EXRHeader *exr_header,
11729                            const unsigned char *memory, const size_t size,
11730                            const char **err) {
11731   if (exr_image == NULL || memory == NULL ||
11732       (size < tinyexr::kEXRVersionSize)) {
11733     tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromMemory",
11734                              err);
11735     return TINYEXR_ERROR_INVALID_ARGUMENT;
11736   }
11737 
11738   if (exr_header->header_len == 0) {
11739     tinyexr::SetErrorMessage("EXRHeader variable is not initialized.", err);
11740     return TINYEXR_ERROR_INVALID_ARGUMENT;
11741   }
11742 
11743   const unsigned char *head = memory;
11744   const unsigned char *marker = reinterpret_cast<const unsigned char *>(
11745       memory + exr_header->header_len +
11746       8);  // +8 for magic number + version header.
11747   return tinyexr::DecodeEXRImage(exr_image, exr_header, head, marker, size,
11748                                  err);
11749 }
11750 
SaveEXRImageToMemory(const EXRImage * exr_image,const EXRHeader * exr_header,unsigned char ** memory_out,const char ** err)11751 size_t SaveEXRImageToMemory(const EXRImage *exr_image,
11752                             const EXRHeader *exr_header,
11753                             unsigned char **memory_out, const char **err) {
11754   if (exr_image == NULL || memory_out == NULL ||
11755       exr_header->compression_type < 0) {
11756     tinyexr::SetErrorMessage("Invalid argument for SaveEXRImageToMemory", err);
11757     return 0;
11758   }
11759 
11760 #if !TINYEXR_USE_PIZ
11761   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
11762     tinyexr::SetErrorMessage("PIZ compression is not supported in this build",
11763                              err);
11764     return 0;
11765   }
11766 #endif
11767 
11768 #if !TINYEXR_USE_ZFP
11769   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
11770     tinyexr::SetErrorMessage("ZFP compression is not supported in this build",
11771                              err);
11772     return 0;
11773   }
11774 #endif
11775 
11776 #if TINYEXR_USE_ZFP
11777   for (size_t i = 0; i < static_cast<size_t>(exr_header->num_channels); i++) {
11778     if (exr_header->requested_pixel_types[i] != TINYEXR_PIXELTYPE_FLOAT) {
11779       tinyexr::SetErrorMessage("Pixel type must be FLOAT for ZFP compression",
11780                                err);
11781       return 0;
11782     }
11783   }
11784 #endif
11785 
11786   std::vector<unsigned char> memory;
11787 
11788   // Header
11789   {
11790     const char header[] = {0x76, 0x2f, 0x31, 0x01};
11791     memory.insert(memory.end(), header, header + 4);
11792   }
11793 
11794   // Version, scanline.
11795   {
11796     char marker[] = {2, 0, 0, 0};
11797     /* @todo
11798     if (exr_header->tiled) {
11799       marker[1] |= 0x2;
11800     }
11801     if (exr_header->long_name) {
11802       marker[1] |= 0x4;
11803     }
11804     if (exr_header->non_image) {
11805       marker[1] |= 0x8;
11806     }
11807     if (exr_header->multipart) {
11808       marker[1] |= 0x10;
11809     }
11810     */
11811     memory.insert(memory.end(), marker, marker + 4);
11812   }
11813 
11814   int num_scanlines = 1;
11815   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
11816     num_scanlines = 16;
11817   } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
11818     num_scanlines = 32;
11819   } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
11820     num_scanlines = 16;
11821   }
11822 
11823   // Write attributes.
11824   std::vector<tinyexr::ChannelInfo> channels;
11825   {
11826     std::vector<unsigned char> data;
11827 
11828     for (int c = 0; c < exr_header->num_channels; c++) {
11829       tinyexr::ChannelInfo info;
11830       info.p_linear = 0;
11831       info.pixel_type = exr_header->requested_pixel_types[c];
11832       info.x_sampling = 1;
11833       info.y_sampling = 1;
11834       info.name = std::string(exr_header->channels[c].name);
11835       channels.push_back(info);
11836     }
11837 
11838     tinyexr::WriteChannelInfo(data, channels);
11839 
11840     tinyexr::WriteAttributeToMemory(&memory, "channels", "chlist", &data.at(0),
11841                                     static_cast<int>(data.size()));
11842   }
11843 
11844   {
11845     int comp = exr_header->compression_type;
11846     tinyexr::swap4(reinterpret_cast<unsigned int *>(&comp));
11847     tinyexr::WriteAttributeToMemory(
11848         &memory, "compression", "compression",
11849         reinterpret_cast<const unsigned char *>(&comp), 1);
11850   }
11851 
11852   {
11853     int data[4] = {0, 0, exr_image->width - 1, exr_image->height - 1};
11854     tinyexr::swap4(reinterpret_cast<unsigned int *>(&data[0]));
11855     tinyexr::swap4(reinterpret_cast<unsigned int *>(&data[1]));
11856     tinyexr::swap4(reinterpret_cast<unsigned int *>(&data[2]));
11857     tinyexr::swap4(reinterpret_cast<unsigned int *>(&data[3]));
11858     tinyexr::WriteAttributeToMemory(
11859         &memory, "dataWindow", "box2i",
11860         reinterpret_cast<const unsigned char *>(data), sizeof(int) * 4);
11861     tinyexr::WriteAttributeToMemory(
11862         &memory, "displayWindow", "box2i",
11863         reinterpret_cast<const unsigned char *>(data), sizeof(int) * 4);
11864   }
11865 
11866   {
11867     unsigned char line_order = 0;  // @fixme { read line_order from EXRHeader }
11868     tinyexr::WriteAttributeToMemory(&memory, "lineOrder", "lineOrder",
11869                                     &line_order, 1);
11870   }
11871 
11872   {
11873     float aspectRatio = 1.0f;
11874     tinyexr::swap4(reinterpret_cast<unsigned int *>(&aspectRatio));
11875     tinyexr::WriteAttributeToMemory(
11876         &memory, "pixelAspectRatio", "float",
11877         reinterpret_cast<const unsigned char *>(&aspectRatio), sizeof(float));
11878   }
11879 
11880   {
11881     float center[2] = {0.0f, 0.0f};
11882     tinyexr::swap4(reinterpret_cast<unsigned int *>(&center[0]));
11883     tinyexr::swap4(reinterpret_cast<unsigned int *>(&center[1]));
11884     tinyexr::WriteAttributeToMemory(
11885         &memory, "screenWindowCenter", "v2f",
11886         reinterpret_cast<const unsigned char *>(center), 2 * sizeof(float));
11887   }
11888 
11889   {
11890     float w = static_cast<float>(exr_image->width);
11891     tinyexr::swap4(reinterpret_cast<unsigned int *>(&w));
11892     tinyexr::WriteAttributeToMemory(&memory, "screenWindowWidth", "float",
11893                                     reinterpret_cast<const unsigned char *>(&w),
11894                                     sizeof(float));
11895   }
11896 
11897   // Custom attributes
11898   if (exr_header->num_custom_attributes > 0) {
11899     for (int i = 0; i < exr_header->num_custom_attributes; i++) {
11900       tinyexr::WriteAttributeToMemory(
11901           &memory, exr_header->custom_attributes[i].name,
11902           exr_header->custom_attributes[i].type,
11903           reinterpret_cast<const unsigned char *>(
11904               exr_header->custom_attributes[i].value),
11905           exr_header->custom_attributes[i].size);
11906     }
11907   }
11908 
11909   {  // end of header
11910     unsigned char e = 0;
11911     memory.push_back(e);
11912   }
11913 
11914   int num_blocks = exr_image->height / num_scanlines;
11915   if (num_blocks * num_scanlines < exr_image->height) {
11916     num_blocks++;
11917   }
11918 
11919   std::vector<tinyexr::tinyexr_uint64> offsets(static_cast<size_t>(num_blocks));
11920 
11921   size_t headerSize = memory.size();
11922   tinyexr::tinyexr_uint64 offset =
11923       headerSize +
11924       static_cast<size_t>(num_blocks) *
11925           sizeof(
11926               tinyexr::tinyexr_int64);  // sizeof(header) + sizeof(offsetTable)
11927 
11928   std::vector<std::vector<unsigned char> > data_list(
11929       static_cast<size_t>(num_blocks));
11930   std::vector<size_t> channel_offset_list(
11931       static_cast<size_t>(exr_header->num_channels));
11932 
11933   int pixel_data_size = 0;
11934   size_t channel_offset = 0;
11935   for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
11936     channel_offset_list[c] = channel_offset;
11937     if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
11938       pixel_data_size += sizeof(unsigned short);
11939       channel_offset += sizeof(unsigned short);
11940     } else if (exr_header->requested_pixel_types[c] ==
11941                TINYEXR_PIXELTYPE_FLOAT) {
11942       pixel_data_size += sizeof(float);
11943       channel_offset += sizeof(float);
11944     } else if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT) {
11945       pixel_data_size += sizeof(unsigned int);
11946       channel_offset += sizeof(unsigned int);
11947     } else {
11948       assert(0);
11949     }
11950   }
11951 
11952 #if TINYEXR_USE_ZFP
11953   tinyexr::ZFPCompressionParam zfp_compression_param;
11954 
11955   // Use ZFP compression parameter from custom attributes(if such a parameter
11956   // exists)
11957   {
11958     bool ret = tinyexr::FindZFPCompressionParam(
11959         &zfp_compression_param, exr_header->custom_attributes,
11960         exr_header->num_custom_attributes);
11961 
11962     if (!ret) {
11963       // Use predefined compression parameter.
11964       zfp_compression_param.type = 0;
11965       zfp_compression_param.rate = 2;
11966     }
11967   }
11968 #endif
11969 
11970 // Use signed int since some OpenMP compiler doesn't allow unsigned type for
11971 // `parallel for`
11972 #ifdef _OPENMP
11973 #pragma omp parallel for
11974 #endif
11975   for (int i = 0; i < num_blocks; i++) {
11976     size_t ii = static_cast<size_t>(i);
11977     int start_y = num_scanlines * i;
11978     int endY = (std::min)(num_scanlines * (i + 1), exr_image->height);
11979     int h = endY - start_y;
11980 
11981     std::vector<unsigned char> buf(
11982         static_cast<size_t>(exr_image->width * h * pixel_data_size));
11983 
11984     for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
11985       if (exr_header->pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
11986         if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) {
11987           for (int y = 0; y < h; y++) {
11988             // Assume increasing Y
11989             float *line_ptr = reinterpret_cast<float *>(&buf.at(
11990                 static_cast<size_t>(pixel_data_size * y * exr_image->width) +
11991                 channel_offset_list[c] *
11992                     static_cast<size_t>(exr_image->width)));
11993             for (int x = 0; x < exr_image->width; x++) {
11994               tinyexr::FP16 h16;
11995               h16.u = reinterpret_cast<unsigned short **>(
11996                   exr_image->images)[c][(y + start_y) * exr_image->width + x];
11997 
11998               tinyexr::FP32 f32 = half_to_float(h16);
11999 
12000               tinyexr::swap4(reinterpret_cast<unsigned int *>(&f32.f));
12001 
12002               // line_ptr[x] = f32.f;
12003               tinyexr::cpy4(line_ptr + x, &(f32.f));
12004             }
12005           }
12006         } else if (exr_header->requested_pixel_types[c] ==
12007                    TINYEXR_PIXELTYPE_HALF) {
12008           for (int y = 0; y < h; y++) {
12009             // Assume increasing Y
12010             unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
12011                 &buf.at(static_cast<size_t>(pixel_data_size * y *
12012                                             exr_image->width) +
12013                         channel_offset_list[c] *
12014                             static_cast<size_t>(exr_image->width)));
12015             for (int x = 0; x < exr_image->width; x++) {
12016               unsigned short val = reinterpret_cast<unsigned short **>(
12017                   exr_image->images)[c][(y + start_y) * exr_image->width + x];
12018 
12019               tinyexr::swap2(&val);
12020 
12021               // line_ptr[x] = val;
12022               tinyexr::cpy2(line_ptr + x, &val);
12023             }
12024           }
12025         } else {
12026           assert(0);
12027         }
12028 
12029       } else if (exr_header->pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) {
12030         if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
12031           for (int y = 0; y < h; y++) {
12032             // Assume increasing Y
12033             unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
12034                 &buf.at(static_cast<size_t>(pixel_data_size * y *
12035                                             exr_image->width) +
12036                         channel_offset_list[c] *
12037                             static_cast<size_t>(exr_image->width)));
12038             for (int x = 0; x < exr_image->width; x++) {
12039               tinyexr::FP32 f32;
12040               f32.f = reinterpret_cast<float **>(
12041                   exr_image->images)[c][(y + start_y) * exr_image->width + x];
12042 
12043               tinyexr::FP16 h16;
12044               h16 = float_to_half_full(f32);
12045 
12046               tinyexr::swap2(reinterpret_cast<unsigned short *>(&h16.u));
12047 
12048               // line_ptr[x] = h16.u;
12049               tinyexr::cpy2(line_ptr + x, &(h16.u));
12050             }
12051           }
12052         } else if (exr_header->requested_pixel_types[c] ==
12053                    TINYEXR_PIXELTYPE_FLOAT) {
12054           for (int y = 0; y < h; y++) {
12055             // Assume increasing Y
12056             float *line_ptr = reinterpret_cast<float *>(&buf.at(
12057                 static_cast<size_t>(pixel_data_size * y * exr_image->width) +
12058                 channel_offset_list[c] *
12059                     static_cast<size_t>(exr_image->width)));
12060             for (int x = 0; x < exr_image->width; x++) {
12061               float val = reinterpret_cast<float **>(
12062                   exr_image->images)[c][(y + start_y) * exr_image->width + x];
12063 
12064               tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
12065 
12066               // line_ptr[x] = val;
12067               tinyexr::cpy4(line_ptr + x, &val);
12068             }
12069           }
12070         } else {
12071           assert(0);
12072         }
12073       } else if (exr_header->pixel_types[c] == TINYEXR_PIXELTYPE_UINT) {
12074         for (int y = 0; y < h; y++) {
12075           // Assume increasing Y
12076           unsigned int *line_ptr = reinterpret_cast<unsigned int *>(&buf.at(
12077               static_cast<size_t>(pixel_data_size * y * exr_image->width) +
12078               channel_offset_list[c] * static_cast<size_t>(exr_image->width)));
12079           for (int x = 0; x < exr_image->width; x++) {
12080             unsigned int val = reinterpret_cast<unsigned int **>(
12081                 exr_image->images)[c][(y + start_y) * exr_image->width + x];
12082 
12083             tinyexr::swap4(&val);
12084 
12085             // line_ptr[x] = val;
12086             tinyexr::cpy4(line_ptr + x, &val);
12087           }
12088         }
12089       }
12090     }
12091 
12092     if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_NONE) {
12093       // 4 byte: scan line
12094       // 4 byte: data size
12095       // ~     : pixel data(uncompressed)
12096       std::vector<unsigned char> header(8);
12097       unsigned int data_len = static_cast<unsigned int>(buf.size());
12098       memcpy(&header.at(0), &start_y, sizeof(int));
12099       memcpy(&header.at(4), &data_len, sizeof(unsigned int));
12100 
12101       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(0)));
12102       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(4)));
12103 
12104       data_list[ii].insert(data_list[ii].end(), header.begin(), header.end());
12105       data_list[ii].insert(data_list[ii].end(), buf.begin(),
12106                            buf.begin() + data_len);
12107 
12108     } else if ((exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) ||
12109                (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIP)) {
12110 #if TINYEXR_USE_MINIZ
12111       std::vector<unsigned char> block(tinyexr::miniz::mz_compressBound(
12112           static_cast<unsigned long>(buf.size())));
12113 #else
12114       std::vector<unsigned char> block(
12115           compressBound(static_cast<uLong>(buf.size())));
12116 #endif
12117       tinyexr::tinyexr_uint64 outSize = block.size();
12118 
12119       tinyexr::CompressZip(&block.at(0), outSize,
12120                            reinterpret_cast<const unsigned char *>(&buf.at(0)),
12121                            static_cast<unsigned long>(buf.size()));
12122 
12123       // 4 byte: scan line
12124       // 4 byte: data size
12125       // ~     : pixel data(compressed)
12126       std::vector<unsigned char> header(8);
12127       unsigned int data_len = static_cast<unsigned int>(outSize);  // truncate
12128       memcpy(&header.at(0), &start_y, sizeof(int));
12129       memcpy(&header.at(4), &data_len, sizeof(unsigned int));
12130 
12131       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(0)));
12132       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(4)));
12133 
12134       data_list[ii].insert(data_list[ii].end(), header.begin(), header.end());
12135       data_list[ii].insert(data_list[ii].end(), block.begin(),
12136                            block.begin() + data_len);
12137 
12138     } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_RLE) {
12139       // (buf.size() * 3) / 2 would be enough.
12140       std::vector<unsigned char> block((buf.size() * 3) / 2);
12141 
12142       tinyexr::tinyexr_uint64 outSize = block.size();
12143 
12144       tinyexr::CompressRle(&block.at(0), outSize,
12145                            reinterpret_cast<const unsigned char *>(&buf.at(0)),
12146                            static_cast<unsigned long>(buf.size()));
12147 
12148       // 4 byte: scan line
12149       // 4 byte: data size
12150       // ~     : pixel data(compressed)
12151       std::vector<unsigned char> header(8);
12152       unsigned int data_len = static_cast<unsigned int>(outSize);  // truncate
12153       memcpy(&header.at(0), &start_y, sizeof(int));
12154       memcpy(&header.at(4), &data_len, sizeof(unsigned int));
12155 
12156       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(0)));
12157       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(4)));
12158 
12159       data_list[ii].insert(data_list[ii].end(), header.begin(), header.end());
12160       data_list[ii].insert(data_list[ii].end(), block.begin(),
12161                            block.begin() + data_len);
12162 
12163     } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
12164 #if TINYEXR_USE_PIZ
12165       unsigned int bufLen =
12166           8192 + static_cast<unsigned int>(
12167                      2 * static_cast<unsigned int>(
12168                              buf.size()));  // @fixme { compute good bound. }
12169       std::vector<unsigned char> block(bufLen);
12170       unsigned int outSize = static_cast<unsigned int>(block.size());
12171 
12172       CompressPiz(&block.at(0), &outSize,
12173                   reinterpret_cast<const unsigned char *>(&buf.at(0)),
12174                   buf.size(), channels, exr_image->width, h);
12175 
12176       // 4 byte: scan line
12177       // 4 byte: data size
12178       // ~     : pixel data(compressed)
12179       std::vector<unsigned char> header(8);
12180       unsigned int data_len = outSize;
12181       memcpy(&header.at(0), &start_y, sizeof(int));
12182       memcpy(&header.at(4), &data_len, sizeof(unsigned int));
12183 
12184       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(0)));
12185       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(4)));
12186 
12187       data_list[ii].insert(data_list[ii].end(), header.begin(), header.end());
12188       data_list[ii].insert(data_list[ii].end(), block.begin(),
12189                            block.begin() + data_len);
12190 
12191 #else
12192       assert(0);
12193 #endif
12194     } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
12195 #if TINYEXR_USE_ZFP
12196       std::vector<unsigned char> block;
12197       unsigned int outSize;
12198 
12199       tinyexr::CompressZfp(
12200           &block, &outSize, reinterpret_cast<const float *>(&buf.at(0)),
12201           exr_image->width, h, exr_header->num_channels, zfp_compression_param);
12202 
12203       // 4 byte: scan line
12204       // 4 byte: data size
12205       // ~     : pixel data(compressed)
12206       std::vector<unsigned char> header(8);
12207       unsigned int data_len = outSize;
12208       memcpy(&header.at(0), &start_y, sizeof(int));
12209       memcpy(&header.at(4), &data_len, sizeof(unsigned int));
12210 
12211       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(0)));
12212       tinyexr::swap4(reinterpret_cast<unsigned int *>(&header.at(4)));
12213 
12214       data_list[ii].insert(data_list[ii].end(), header.begin(), header.end());
12215       data_list[ii].insert(data_list[ii].end(), block.begin(),
12216                            block.begin() + data_len);
12217 
12218 #else
12219       assert(0);
12220 #endif
12221     } else {
12222       assert(0);
12223     }
12224   }  // omp parallel
12225 
12226   for (size_t i = 0; i < static_cast<size_t>(num_blocks); i++) {
12227     offsets[i] = offset;
12228     tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64 *>(&offsets[i]));
12229     offset += data_list[i].size();
12230   }
12231 
12232   size_t totalSize = static_cast<size_t>(offset);
12233   {
12234     memory.insert(
12235         memory.end(), reinterpret_cast<unsigned char *>(&offsets.at(0)),
12236         reinterpret_cast<unsigned char *>(&offsets.at(0)) +
12237             sizeof(tinyexr::tinyexr_uint64) * static_cast<size_t>(num_blocks));
12238   }
12239 
12240   if (memory.size() == 0) {
12241     tinyexr::SetErrorMessage("Output memory size is zero", err);
12242     return 0;
12243   }
12244 
12245   (*memory_out) = static_cast<unsigned char *>(malloc(totalSize));
12246   memcpy((*memory_out), &memory.at(0), memory.size());
12247   unsigned char *memory_ptr = *memory_out + memory.size();
12248 
12249   for (size_t i = 0; i < static_cast<size_t>(num_blocks); i++) {
12250     memcpy(memory_ptr, &data_list[i].at(0), data_list[i].size());
12251     memory_ptr += data_list[i].size();
12252   }
12253 
12254   return totalSize;  // OK
12255 }
12256 
SaveEXRImageToFile(const EXRImage * exr_image,const EXRHeader * exr_header,const char * filename,const char ** err)12257 int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header,
12258                        const char *filename, const char **err) {
12259   if (exr_image == NULL || filename == NULL ||
12260       exr_header->compression_type < 0) {
12261     tinyexr::SetErrorMessage("Invalid argument for SaveEXRImageToFile", err);
12262     return TINYEXR_ERROR_INVALID_ARGUMENT;
12263   }
12264 
12265 #if !TINYEXR_USE_PIZ
12266   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
12267     tinyexr::SetErrorMessage("PIZ compression is not supported in this build",
12268                              err);
12269     return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
12270   }
12271 #endif
12272 
12273 #if !TINYEXR_USE_ZFP
12274   if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
12275     tinyexr::SetErrorMessage("ZFP compression is not supported in this build",
12276                              err);
12277     return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
12278   }
12279 #endif
12280 
12281 #ifdef _WIN32
12282   FILE *fp = NULL;
12283   fopen_s(&fp, filename, "wb");
12284 #else
12285   FILE *fp = fopen(filename, "wb");
12286 #endif
12287   if (!fp) {
12288     tinyexr::SetErrorMessage("Cannot write a file", err);
12289     return TINYEXR_ERROR_CANT_WRITE_FILE;
12290   }
12291 
12292   unsigned char *mem = NULL;
12293   size_t mem_size = SaveEXRImageToMemory(exr_image, exr_header, &mem, err);
12294   if (mem_size == 0) {
12295     return TINYEXR_ERROR_SERIALZATION_FAILED;
12296   }
12297 
12298   size_t written_size = 0;
12299   if ((mem_size > 0) && mem) {
12300     written_size = fwrite(mem, 1, mem_size, fp);
12301   }
12302   free(mem);
12303 
12304   fclose(fp);
12305 
12306   if (written_size != mem_size) {
12307     tinyexr::SetErrorMessage("Cannot write a file", err);
12308     return TINYEXR_ERROR_CANT_WRITE_FILE;
12309   }
12310 
12311   return TINYEXR_SUCCESS;
12312 }
12313 
LoadDeepEXR(DeepImage * deep_image,const char * filename,const char ** err)12314 int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
12315   if (deep_image == NULL) {
12316     tinyexr::SetErrorMessage("Invalid argument for LoadDeepEXR", err);
12317     return TINYEXR_ERROR_INVALID_ARGUMENT;
12318   }
12319 
12320 #ifdef _MSC_VER
12321   FILE *fp = NULL;
12322   errno_t errcode = fopen_s(&fp, filename, "rb");
12323   if ((0 != errcode) || (!fp)) {
12324     tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename),
12325                              err);
12326     return TINYEXR_ERROR_CANT_OPEN_FILE;
12327   }
12328 #else
12329   FILE *fp = fopen(filename, "rb");
12330   if (!fp) {
12331     tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename),
12332                              err);
12333     return TINYEXR_ERROR_CANT_OPEN_FILE;
12334   }
12335 #endif
12336 
12337   size_t filesize;
12338   // Compute size
12339   fseek(fp, 0, SEEK_END);
12340   filesize = static_cast<size_t>(ftell(fp));
12341   fseek(fp, 0, SEEK_SET);
12342 
12343   if (filesize == 0) {
12344     fclose(fp);
12345     tinyexr::SetErrorMessage("File size is zero : " + std::string(filename),
12346                              err);
12347     return TINYEXR_ERROR_INVALID_FILE;
12348   }
12349 
12350   std::vector<char> buf(filesize);  // @todo { use mmap }
12351   {
12352     size_t ret;
12353     ret = fread(&buf[0], 1, filesize, fp);
12354     assert(ret == filesize);
12355     (void)ret;
12356   }
12357   fclose(fp);
12358 
12359   const char *head = &buf[0];
12360   const char *marker = &buf[0];
12361 
12362   // Header check.
12363   {
12364     const char header[] = {0x76, 0x2f, 0x31, 0x01};
12365 
12366     if (memcmp(marker, header, 4) != 0) {
12367       tinyexr::SetErrorMessage("Invalid magic number", err);
12368       return TINYEXR_ERROR_INVALID_MAGIC_NUMBER;
12369     }
12370     marker += 4;
12371   }
12372 
12373   // Version, scanline.
12374   {
12375     // ver 2.0, scanline, deep bit on(0x800)
12376     // must be [2, 0, 0, 0]
12377     if (marker[0] != 2 || marker[1] != 8 || marker[2] != 0 || marker[3] != 0) {
12378       tinyexr::SetErrorMessage("Unsupported version or scanline", err);
12379       return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
12380     }
12381 
12382     marker += 4;
12383   }
12384 
12385   int dx = -1;
12386   int dy = -1;
12387   int dw = -1;
12388   int dh = -1;
12389   int num_scanline_blocks = 1;  // 16 for ZIP compression.
12390   int compression_type = -1;
12391   int num_channels = -1;
12392   std::vector<tinyexr::ChannelInfo> channels;
12393 
12394   // Read attributes
12395   size_t size = filesize - tinyexr::kEXRVersionSize;
12396   for (;;) {
12397     if (0 == size) {
12398       return TINYEXR_ERROR_INVALID_DATA;
12399     } else if (marker[0] == '\0') {
12400       marker++;
12401       size--;
12402       break;
12403     }
12404 
12405     std::string attr_name;
12406     std::string attr_type;
12407     std::vector<unsigned char> data;
12408     size_t marker_size;
12409     if (!tinyexr::ReadAttribute(&attr_name, &attr_type, &data, &marker_size,
12410                                 marker, size)) {
12411       std::stringstream ss;
12412       ss << "Failed to parse attribute\n";
12413       tinyexr::SetErrorMessage(ss.str(), err);
12414       return TINYEXR_ERROR_INVALID_DATA;
12415     }
12416     marker += marker_size;
12417     size -= marker_size;
12418 
12419     if (attr_name.compare("compression") == 0) {
12420       compression_type = data[0];
12421       if (compression_type > TINYEXR_COMPRESSIONTYPE_PIZ) {
12422         std::stringstream ss;
12423         ss << "Unsupported compression type : " << compression_type;
12424         tinyexr::SetErrorMessage(ss.str(), err);
12425         return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
12426       }
12427 
12428       if (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
12429         num_scanline_blocks = 16;
12430       }
12431 
12432     } else if (attr_name.compare("channels") == 0) {
12433       // name: zero-terminated string, from 1 to 255 bytes long
12434       // pixel type: int, possible values are: UINT = 0 HALF = 1 FLOAT = 2
12435       // pLinear: unsigned char, possible values are 0 and 1
12436       // reserved: three chars, should be zero
12437       // xSampling: int
12438       // ySampling: int
12439 
12440       if (!tinyexr::ReadChannelInfo(channels, data)) {
12441         tinyexr::SetErrorMessage("Failed to parse channel info", err);
12442         return TINYEXR_ERROR_INVALID_DATA;
12443       }
12444 
12445       num_channels = static_cast<int>(channels.size());
12446 
12447       if (num_channels < 1) {
12448         tinyexr::SetErrorMessage("Invalid channels format", err);
12449         return TINYEXR_ERROR_INVALID_DATA;
12450       }
12451 
12452     } else if (attr_name.compare("dataWindow") == 0) {
12453       memcpy(&dx, &data.at(0), sizeof(int));
12454       memcpy(&dy, &data.at(4), sizeof(int));
12455       memcpy(&dw, &data.at(8), sizeof(int));
12456       memcpy(&dh, &data.at(12), sizeof(int));
12457       tinyexr::swap4(reinterpret_cast<unsigned int *>(&dx));
12458       tinyexr::swap4(reinterpret_cast<unsigned int *>(&dy));
12459       tinyexr::swap4(reinterpret_cast<unsigned int *>(&dw));
12460       tinyexr::swap4(reinterpret_cast<unsigned int *>(&dh));
12461 
12462     } else if (attr_name.compare("displayWindow") == 0) {
12463       int x;
12464       int y;
12465       int w;
12466       int h;
12467       memcpy(&x, &data.at(0), sizeof(int));
12468       memcpy(&y, &data.at(4), sizeof(int));
12469       memcpy(&w, &data.at(8), sizeof(int));
12470       memcpy(&h, &data.at(12), sizeof(int));
12471       tinyexr::swap4(reinterpret_cast<unsigned int *>(&x));
12472       tinyexr::swap4(reinterpret_cast<unsigned int *>(&y));
12473       tinyexr::swap4(reinterpret_cast<unsigned int *>(&w));
12474       tinyexr::swap4(reinterpret_cast<unsigned int *>(&h));
12475     }
12476   }
12477 
12478   assert(dx >= 0);
12479   assert(dy >= 0);
12480   assert(dw >= 0);
12481   assert(dh >= 0);
12482   assert(num_channels >= 1);
12483 
12484   int data_width = dw - dx + 1;
12485   int data_height = dh - dy + 1;
12486 
12487   std::vector<float> image(
12488       static_cast<size_t>(data_width * data_height * 4));  // 4 = RGBA
12489 
12490   // Read offset tables.
12491   int num_blocks = data_height / num_scanline_blocks;
12492   if (num_blocks * num_scanline_blocks < data_height) {
12493     num_blocks++;
12494   }
12495 
12496   std::vector<tinyexr::tinyexr_int64> offsets(static_cast<size_t>(num_blocks));
12497 
12498   for (size_t y = 0; y < static_cast<size_t>(num_blocks); y++) {
12499     tinyexr::tinyexr_int64 offset;
12500     memcpy(&offset, marker, sizeof(tinyexr::tinyexr_int64));
12501     tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64 *>(&offset));
12502     marker += sizeof(tinyexr::tinyexr_int64);  // = 8
12503     offsets[y] = offset;
12504   }
12505 
12506 #if TINYEXR_USE_PIZ
12507   if ((compression_type == TINYEXR_COMPRESSIONTYPE_NONE) ||
12508       (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) ||
12509       (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) ||
12510       (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) ||
12511       (compression_type == TINYEXR_COMPRESSIONTYPE_PIZ)) {
12512 #else
12513   if ((compression_type == TINYEXR_COMPRESSIONTYPE_NONE) ||
12514       (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) ||
12515       (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) ||
12516       (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP)) {
12517 #endif
12518     // OK
12519   } else {
12520     tinyexr::SetErrorMessage("Unsupported compression format", err);
12521     return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
12522   }
12523 
12524   deep_image->image = static_cast<float ***>(
12525       malloc(sizeof(float **) * static_cast<size_t>(num_channels)));
12526   for (int c = 0; c < num_channels; c++) {
12527     deep_image->image[c] = static_cast<float **>(
12528         malloc(sizeof(float *) * static_cast<size_t>(data_height)));
12529     for (int y = 0; y < data_height; y++) {
12530     }
12531   }
12532 
12533   deep_image->offset_table = static_cast<int **>(
12534       malloc(sizeof(int *) * static_cast<size_t>(data_height)));
12535   for (int y = 0; y < data_height; y++) {
12536     deep_image->offset_table[y] = static_cast<int *>(
12537         malloc(sizeof(int) * static_cast<size_t>(data_width)));
12538   }
12539 
12540   for (size_t y = 0; y < static_cast<size_t>(num_blocks); y++) {
12541     const unsigned char *data_ptr =
12542         reinterpret_cast<const unsigned char *>(head + offsets[y]);
12543 
12544     // int: y coordinate
12545     // int64: packed size of pixel offset table
12546     // int64: packed size of sample data
12547     // int64: unpacked size of sample data
12548     // compressed pixel offset table
12549     // compressed sample data
12550     int line_no;
12551     tinyexr::tinyexr_int64 packedOffsetTableSize;
12552     tinyexr::tinyexr_int64 packedSampleDataSize;
12553     tinyexr::tinyexr_int64 unpackedSampleDataSize;
12554     memcpy(&line_no, data_ptr, sizeof(int));
12555     memcpy(&packedOffsetTableSize, data_ptr + 4,
12556            sizeof(tinyexr::tinyexr_int64));
12557     memcpy(&packedSampleDataSize, data_ptr + 12,
12558            sizeof(tinyexr::tinyexr_int64));
12559     memcpy(&unpackedSampleDataSize, data_ptr + 20,
12560            sizeof(tinyexr::tinyexr_int64));
12561 
12562     tinyexr::swap4(reinterpret_cast<unsigned int *>(&line_no));
12563     tinyexr::swap8(
12564         reinterpret_cast<tinyexr::tinyexr_uint64 *>(&packedOffsetTableSize));
12565     tinyexr::swap8(
12566         reinterpret_cast<tinyexr::tinyexr_uint64 *>(&packedSampleDataSize));
12567     tinyexr::swap8(
12568         reinterpret_cast<tinyexr::tinyexr_uint64 *>(&unpackedSampleDataSize));
12569 
12570     std::vector<int> pixelOffsetTable(static_cast<size_t>(data_width));
12571 
12572     // decode pixel offset table.
12573     {
12574       unsigned long dstLen =
12575           static_cast<unsigned long>(pixelOffsetTable.size() * sizeof(int));
12576       if (!tinyexr::DecompressZip(
12577               reinterpret_cast<unsigned char *>(&pixelOffsetTable.at(0)),
12578               &dstLen, data_ptr + 28,
12579               static_cast<unsigned long>(packedOffsetTableSize))) {
12580         return false;
12581       }
12582 
12583       assert(dstLen == pixelOffsetTable.size() * sizeof(int));
12584       for (size_t i = 0; i < static_cast<size_t>(data_width); i++) {
12585         deep_image->offset_table[y][i] = pixelOffsetTable[i];
12586       }
12587     }
12588 
12589     std::vector<unsigned char> sample_data(
12590         static_cast<size_t>(unpackedSampleDataSize));
12591 
12592     // decode sample data.
12593     {
12594       unsigned long dstLen = static_cast<unsigned long>(unpackedSampleDataSize);
12595       if (dstLen) {
12596         if (!tinyexr::DecompressZip(
12597                 reinterpret_cast<unsigned char *>(&sample_data.at(0)), &dstLen,
12598                 data_ptr + 28 + packedOffsetTableSize,
12599                 static_cast<unsigned long>(packedSampleDataSize))) {
12600           return false;
12601         }
12602         assert(dstLen == static_cast<unsigned long>(unpackedSampleDataSize));
12603       }
12604     }
12605 
12606     // decode sample
12607     int sampleSize = -1;
12608     std::vector<int> channel_offset_list(static_cast<size_t>(num_channels));
12609     {
12610       int channel_offset = 0;
12611       for (size_t i = 0; i < static_cast<size_t>(num_channels); i++) {
12612         channel_offset_list[i] = channel_offset;
12613         if (channels[i].pixel_type == TINYEXR_PIXELTYPE_UINT) {  // UINT
12614           channel_offset += 4;
12615         } else if (channels[i].pixel_type == TINYEXR_PIXELTYPE_HALF) {  // half
12616           channel_offset += 2;
12617         } else if (channels[i].pixel_type ==
12618                    TINYEXR_PIXELTYPE_FLOAT) {  // float
12619           channel_offset += 4;
12620         } else {
12621           assert(0);
12622         }
12623       }
12624       sampleSize = channel_offset;
12625     }
12626     assert(sampleSize >= 2);
12627 
12628     assert(static_cast<size_t>(
12629                pixelOffsetTable[static_cast<size_t>(data_width - 1)] *
12630                sampleSize) == sample_data.size());
12631     int samples_per_line = static_cast<int>(sample_data.size()) / sampleSize;
12632 
12633     //
12634     // Alloc memory
12635     //
12636 
12637     //
12638     // pixel data is stored as image[channels][pixel_samples]
12639     //
12640     {
12641       tinyexr::tinyexr_uint64 data_offset = 0;
12642       for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
12643         deep_image->image[c][y] = static_cast<float *>(
12644             malloc(sizeof(float) * static_cast<size_t>(samples_per_line)));
12645 
12646         if (channels[c].pixel_type == 0) {  // UINT
12647           for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) {
12648             unsigned int ui;
12649             unsigned int *src_ptr = reinterpret_cast<unsigned int *>(
12650                 &sample_data.at(size_t(data_offset) + x * sizeof(int)));
12651             tinyexr::cpy4(&ui, src_ptr);
12652             deep_image->image[c][y][x] = static_cast<float>(ui);  // @fixme
12653           }
12654           data_offset +=
12655               sizeof(unsigned int) * static_cast<size_t>(samples_per_line);
12656         } else if (channels[c].pixel_type == 1) {  // half
12657           for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) {
12658             tinyexr::FP16 f16;
12659             const unsigned short *src_ptr = reinterpret_cast<unsigned short *>(
12660                 &sample_data.at(size_t(data_offset) + x * sizeof(short)));
12661             tinyexr::cpy2(&(f16.u), src_ptr);
12662             tinyexr::FP32 f32 = half_to_float(f16);
12663             deep_image->image[c][y][x] = f32.f;
12664           }
12665           data_offset += sizeof(short) * static_cast<size_t>(samples_per_line);
12666         } else {  // float
12667           for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) {
12668             float f;
12669             const float *src_ptr = reinterpret_cast<float *>(
12670                 &sample_data.at(size_t(data_offset) + x * sizeof(float)));
12671             tinyexr::cpy4(&f, src_ptr);
12672             deep_image->image[c][y][x] = f;
12673           }
12674           data_offset += sizeof(float) * static_cast<size_t>(samples_per_line);
12675         }
12676       }
12677     }
12678   }  // y
12679 
12680   deep_image->width = data_width;
12681   deep_image->height = data_height;
12682 
12683   deep_image->channel_names = static_cast<const char **>(
12684       malloc(sizeof(const char *) * static_cast<size_t>(num_channels)));
12685   for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
12686 #ifdef _WIN32
12687     deep_image->channel_names[c] = _strdup(channels[c].name.c_str());
12688 #else
12689     deep_image->channel_names[c] = strdup(channels[c].name.c_str());
12690 #endif
12691   }
12692   deep_image->num_channels = num_channels;
12693 
12694   return TINYEXR_SUCCESS;
12695 }
12696 
12697 void InitEXRImage(EXRImage *exr_image) {
12698   if (exr_image == NULL) {
12699     return;
12700   }
12701 
12702   exr_image->width = 0;
12703   exr_image->height = 0;
12704   exr_image->num_channels = 0;
12705 
12706   exr_image->images = NULL;
12707   exr_image->tiles = NULL;
12708 
12709   exr_image->num_tiles = 0;
12710 }
12711 
12712 void FreeEXRErrorMessage(const char *msg) {
12713   if (msg) {
12714     free(reinterpret_cast<void *>(const_cast<char *>(msg)));
12715   }
12716   return;
12717 }
12718 
12719 void InitEXRHeader(EXRHeader *exr_header) {
12720   if (exr_header == NULL) {
12721     return;
12722   }
12723 
12724   memset(exr_header, 0, sizeof(EXRHeader));
12725 }
12726 
12727 int FreeEXRHeader(EXRHeader *exr_header) {
12728   if (exr_header == NULL) {
12729     return TINYEXR_ERROR_INVALID_ARGUMENT;
12730   }
12731 
12732   if (exr_header->channels) {
12733     free(exr_header->channels);
12734   }
12735 
12736   if (exr_header->pixel_types) {
12737     free(exr_header->pixel_types);
12738   }
12739 
12740   if (exr_header->requested_pixel_types) {
12741     free(exr_header->requested_pixel_types);
12742   }
12743 
12744   for (int i = 0; i < exr_header->num_custom_attributes; i++) {
12745     if (exr_header->custom_attributes[i].value) {
12746       free(exr_header->custom_attributes[i].value);
12747     }
12748   }
12749 
12750   if (exr_header->custom_attributes) {
12751     free(exr_header->custom_attributes);
12752   }
12753 
12754   return TINYEXR_SUCCESS;
12755 }
12756 
12757 int FreeEXRImage(EXRImage *exr_image) {
12758   if (exr_image == NULL) {
12759     return TINYEXR_ERROR_INVALID_ARGUMENT;
12760   }
12761 
12762   for (int i = 0; i < exr_image->num_channels; i++) {
12763     if (exr_image->images && exr_image->images[i]) {
12764       free(exr_image->images[i]);
12765     }
12766   }
12767 
12768   if (exr_image->images) {
12769     free(exr_image->images);
12770   }
12771 
12772   if (exr_image->tiles) {
12773     for (int tid = 0; tid < exr_image->num_tiles; tid++) {
12774       for (int i = 0; i < exr_image->num_channels; i++) {
12775         if (exr_image->tiles[tid].images && exr_image->tiles[tid].images[i]) {
12776           free(exr_image->tiles[tid].images[i]);
12777         }
12778       }
12779       if (exr_image->tiles[tid].images) {
12780         free(exr_image->tiles[tid].images);
12781       }
12782     }
12783     free(exr_image->tiles);
12784   }
12785 
12786   return TINYEXR_SUCCESS;
12787 }
12788 
12789 int ParseEXRHeaderFromFile(EXRHeader *exr_header, const EXRVersion *exr_version,
12790                            const char *filename, const char **err) {
12791   if (exr_header == NULL || exr_version == NULL || filename == NULL) {
12792     tinyexr::SetErrorMessage("Invalid argument for ParseEXRHeaderFromFile",
12793                              err);
12794     return TINYEXR_ERROR_INVALID_ARGUMENT;
12795   }
12796 
12797 #ifdef _WIN32
12798   FILE *fp = NULL;
12799   fopen_s(&fp, filename, "rb");
12800 #else
12801   FILE *fp = fopen(filename, "rb");
12802 #endif
12803   if (!fp) {
12804     tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err);
12805     return TINYEXR_ERROR_CANT_OPEN_FILE;
12806   }
12807 
12808   size_t filesize;
12809   // Compute size
12810   fseek(fp, 0, SEEK_END);
12811   filesize = static_cast<size_t>(ftell(fp));
12812   fseek(fp, 0, SEEK_SET);
12813 
12814   std::vector<unsigned char> buf(filesize);  // @todo { use mmap }
12815   {
12816     size_t ret;
12817     ret = fread(&buf[0], 1, filesize, fp);
12818     assert(ret == filesize);
12819     fclose(fp);
12820 
12821     if (ret != filesize) {
12822       tinyexr::SetErrorMessage("fread() error on " + std::string(filename),
12823                                err);
12824       return TINYEXR_ERROR_INVALID_FILE;
12825     }
12826   }
12827 
12828   return ParseEXRHeaderFromMemory(exr_header, exr_version, &buf.at(0), filesize,
12829                                   err);
12830 }
12831 
12832 int ParseEXRMultipartHeaderFromMemory(EXRHeader ***exr_headers,
12833                                       int *num_headers,
12834                                       const EXRVersion *exr_version,
12835                                       const unsigned char *memory, size_t size,
12836                                       const char **err) {
12837   if (memory == NULL || exr_headers == NULL || num_headers == NULL ||
12838       exr_version == NULL) {
12839     // Invalid argument
12840     tinyexr::SetErrorMessage(
12841         "Invalid argument for ParseEXRMultipartHeaderFromMemory", err);
12842     return TINYEXR_ERROR_INVALID_ARGUMENT;
12843   }
12844 
12845   if (size < tinyexr::kEXRVersionSize) {
12846     tinyexr::SetErrorMessage("Data size too short", err);
12847     return TINYEXR_ERROR_INVALID_DATA;
12848   }
12849 
12850   const unsigned char *marker = memory + tinyexr::kEXRVersionSize;
12851   size_t marker_size = size - tinyexr::kEXRVersionSize;
12852 
12853   std::vector<tinyexr::HeaderInfo> infos;
12854 
12855   for (;;) {
12856     tinyexr::HeaderInfo info;
12857     info.clear();
12858 
12859     std::string err_str;
12860     bool empty_header = false;
12861     int ret = ParseEXRHeader(&info, &empty_header, exr_version, &err_str,
12862                              marker, marker_size);
12863 
12864     if (ret != TINYEXR_SUCCESS) {
12865       tinyexr::SetErrorMessage(err_str, err);
12866       return ret;
12867     }
12868 
12869     if (empty_header) {
12870       marker += 1;  // skip '\0'
12871       break;
12872     }
12873 
12874     // `chunkCount` must exist in the header.
12875     if (info.chunk_count == 0) {
12876       tinyexr::SetErrorMessage(
12877           "`chunkCount' attribute is not found in the header.", err);
12878       return TINYEXR_ERROR_INVALID_DATA;
12879     }
12880 
12881     infos.push_back(info);
12882 
12883     // move to next header.
12884     marker += info.header_len;
12885     size -= info.header_len;
12886   }
12887 
12888   // allocate memory for EXRHeader and create array of EXRHeader pointers.
12889   (*exr_headers) =
12890       static_cast<EXRHeader **>(malloc(sizeof(EXRHeader *) * infos.size()));
12891   for (size_t i = 0; i < infos.size(); i++) {
12892     EXRHeader *exr_header = static_cast<EXRHeader *>(malloc(sizeof(EXRHeader)));
12893 
12894     ConvertHeader(exr_header, infos[i]);
12895 
12896     // transfoer `tiled` from version.
12897     exr_header->tiled = exr_version->tiled;
12898 
12899     (*exr_headers)[i] = exr_header;
12900   }
12901 
12902   (*num_headers) = static_cast<int>(infos.size());
12903 
12904   return TINYEXR_SUCCESS;
12905 }
12906 
12907 int ParseEXRMultipartHeaderFromFile(EXRHeader ***exr_headers, int *num_headers,
12908                                     const EXRVersion *exr_version,
12909                                     const char *filename, const char **err) {
12910   if (exr_headers == NULL || num_headers == NULL || exr_version == NULL ||
12911       filename == NULL) {
12912     tinyexr::SetErrorMessage(
12913         "Invalid argument for ParseEXRMultipartHeaderFromFile()", err);
12914     return TINYEXR_ERROR_INVALID_ARGUMENT;
12915   }
12916 
12917 #ifdef _WIN32
12918   FILE *fp = NULL;
12919   fopen_s(&fp, filename, "rb");
12920 #else
12921   FILE *fp = fopen(filename, "rb");
12922 #endif
12923   if (!fp) {
12924     tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err);
12925     return TINYEXR_ERROR_CANT_OPEN_FILE;
12926   }
12927 
12928   size_t filesize;
12929   // Compute size
12930   fseek(fp, 0, SEEK_END);
12931   filesize = static_cast<size_t>(ftell(fp));
12932   fseek(fp, 0, SEEK_SET);
12933 
12934   std::vector<unsigned char> buf(filesize);  // @todo { use mmap }
12935   {
12936     size_t ret;
12937     ret = fread(&buf[0], 1, filesize, fp);
12938     assert(ret == filesize);
12939     fclose(fp);
12940 
12941     if (ret != filesize) {
12942       tinyexr::SetErrorMessage("`fread' error. file may be corrupted.", err);
12943       return TINYEXR_ERROR_INVALID_FILE;
12944     }
12945   }
12946 
12947   return ParseEXRMultipartHeaderFromMemory(
12948       exr_headers, num_headers, exr_version, &buf.at(0), filesize, err);
12949 }
12950 
12951 int ParseEXRVersionFromMemory(EXRVersion *version, const unsigned char *memory,
12952                               size_t size) {
12953   if (version == NULL || memory == NULL) {
12954     return TINYEXR_ERROR_INVALID_ARGUMENT;
12955   }
12956 
12957   if (size < tinyexr::kEXRVersionSize) {
12958     return TINYEXR_ERROR_INVALID_DATA;
12959   }
12960 
12961   const unsigned char *marker = memory;
12962 
12963   // Header check.
12964   {
12965     const char header[] = {0x76, 0x2f, 0x31, 0x01};
12966 
12967     if (memcmp(marker, header, 4) != 0) {
12968       return TINYEXR_ERROR_INVALID_MAGIC_NUMBER;
12969     }
12970     marker += 4;
12971   }
12972 
12973   version->tiled = false;
12974   version->long_name = false;
12975   version->non_image = false;
12976   version->multipart = false;
12977 
12978   // Parse version header.
12979   {
12980     // must be 2
12981     if (marker[0] != 2) {
12982       return TINYEXR_ERROR_INVALID_EXR_VERSION;
12983     }
12984 
12985     if (version == NULL) {
12986       return TINYEXR_SUCCESS;  // May OK
12987     }
12988 
12989     version->version = 2;
12990 
12991     if (marker[1] & 0x2) {  // 9th bit
12992       version->tiled = true;
12993     }
12994     if (marker[1] & 0x4) {  // 10th bit
12995       version->long_name = true;
12996     }
12997     if (marker[1] & 0x8) {        // 11th bit
12998       version->non_image = true;  // (deep image)
12999     }
13000     if (marker[1] & 0x10) {  // 12th bit
13001       version->multipart = true;
13002     }
13003   }
13004 
13005   return TINYEXR_SUCCESS;
13006 }
13007 
13008 int ParseEXRVersionFromFile(EXRVersion *version, const char *filename) {
13009   if (filename == NULL) {
13010     return TINYEXR_ERROR_INVALID_ARGUMENT;
13011   }
13012 
13013 #ifdef _WIN32
13014   FILE *fp = NULL;
13015   fopen_s(&fp, filename, "rb");
13016 #else
13017   FILE *fp = fopen(filename, "rb");
13018 #endif
13019   if (!fp) {
13020     return TINYEXR_ERROR_CANT_OPEN_FILE;
13021   }
13022 
13023   size_t file_size;
13024   // Compute size
13025   fseek(fp, 0, SEEK_END);
13026   file_size = static_cast<size_t>(ftell(fp));
13027   fseek(fp, 0, SEEK_SET);
13028 
13029   if (file_size < tinyexr::kEXRVersionSize) {
13030     return TINYEXR_ERROR_INVALID_FILE;
13031   }
13032 
13033   unsigned char buf[tinyexr::kEXRVersionSize];
13034   size_t ret = fread(&buf[0], 1, tinyexr::kEXRVersionSize, fp);
13035   fclose(fp);
13036 
13037   if (ret != tinyexr::kEXRVersionSize) {
13038     return TINYEXR_ERROR_INVALID_FILE;
13039   }
13040 
13041   return ParseEXRVersionFromMemory(version, buf, tinyexr::kEXRVersionSize);
13042 }
13043 
13044 int LoadEXRMultipartImageFromMemory(EXRImage *exr_images,
13045                                     const EXRHeader **exr_headers,
13046                                     unsigned int num_parts,
13047                                     const unsigned char *memory,
13048                                     const size_t size, const char **err) {
13049   if (exr_images == NULL || exr_headers == NULL || num_parts == 0 ||
13050       memory == NULL || (size <= tinyexr::kEXRVersionSize)) {
13051     tinyexr::SetErrorMessage(
13052         "Invalid argument for LoadEXRMultipartImageFromMemory()", err);
13053     return TINYEXR_ERROR_INVALID_ARGUMENT;
13054   }
13055 
13056   // compute total header size.
13057   size_t total_header_size = 0;
13058   for (unsigned int i = 0; i < num_parts; i++) {
13059     if (exr_headers[i]->header_len == 0) {
13060       tinyexr::SetErrorMessage("EXRHeader variable is not initialized.", err);
13061       return TINYEXR_ERROR_INVALID_ARGUMENT;
13062     }
13063 
13064     total_header_size += exr_headers[i]->header_len;
13065   }
13066 
13067   const char *marker = reinterpret_cast<const char *>(
13068       memory + total_header_size + 4 +
13069       4);  // +8 for magic number and version header.
13070 
13071   marker += 1;  // Skip empty header.
13072 
13073   // NOTE 1:
13074   //   In multipart image, There is 'part number' before chunk data.
13075   //   4 byte : part number
13076   //   4+     : chunk
13077   //
13078   // NOTE 2:
13079   //   EXR spec says 'part number' is 'unsigned long' but actually this is
13080   //   'unsigned int(4 bytes)' in OpenEXR implementation...
13081   //   http://www.openexr.com/openexrfilelayout.pdf
13082 
13083   // Load chunk offset table.
13084   std::vector<std::vector<tinyexr::tinyexr_uint64> > chunk_offset_table_list;
13085   for (size_t i = 0; i < static_cast<size_t>(num_parts); i++) {
13086     std::vector<tinyexr::tinyexr_uint64> offset_table(
13087         static_cast<size_t>(exr_headers[i]->chunk_count));
13088 
13089     for (size_t c = 0; c < offset_table.size(); c++) {
13090       tinyexr::tinyexr_uint64 offset;
13091       memcpy(&offset, marker, 8);
13092       tinyexr::swap8(&offset);
13093 
13094       if (offset >= size) {
13095         tinyexr::SetErrorMessage("Invalid offset size in EXR header chunks.",
13096                                  err);
13097         return TINYEXR_ERROR_INVALID_DATA;
13098       }
13099 
13100       offset_table[c] = offset + 4;  // +4 to skip 'part number'
13101       marker += 8;
13102     }
13103 
13104     chunk_offset_table_list.push_back(offset_table);
13105   }
13106 
13107   // Decode image.
13108   for (size_t i = 0; i < static_cast<size_t>(num_parts); i++) {
13109     std::vector<tinyexr::tinyexr_uint64> &offset_table =
13110         chunk_offset_table_list[i];
13111 
13112     // First check 'part number' is identitical to 'i'
13113     for (size_t c = 0; c < offset_table.size(); c++) {
13114       const unsigned char *part_number_addr =
13115           memory + offset_table[c] - 4;  // -4 to move to 'part number' field.
13116       unsigned int part_no;
13117       memcpy(&part_no, part_number_addr, sizeof(unsigned int));  // 4
13118       tinyexr::swap4(&part_no);
13119 
13120       if (part_no != i) {
13121         tinyexr::SetErrorMessage("Invalid `part number' in EXR header chunks.",
13122                                  err);
13123         return TINYEXR_ERROR_INVALID_DATA;
13124       }
13125     }
13126 
13127     std::string e;
13128     int ret = tinyexr::DecodeChunk(&exr_images[i], exr_headers[i], offset_table,
13129                                    memory, size, &e);
13130     if (ret != TINYEXR_SUCCESS) {
13131       if (!e.empty()) {
13132         tinyexr::SetErrorMessage(e, err);
13133       }
13134       return ret;
13135     }
13136   }
13137 
13138   return TINYEXR_SUCCESS;
13139 }
13140 
13141 int LoadEXRMultipartImageFromFile(EXRImage *exr_images,
13142                                   const EXRHeader **exr_headers,
13143                                   unsigned int num_parts, const char *filename,
13144                                   const char **err) {
13145   if (exr_images == NULL || exr_headers == NULL || num_parts == 0) {
13146     tinyexr::SetErrorMessage(
13147         "Invalid argument for LoadEXRMultipartImageFromFile", err);
13148     return TINYEXR_ERROR_INVALID_ARGUMENT;
13149   }
13150 
13151 #ifdef _WIN32
13152   FILE *fp = NULL;
13153   fopen_s(&fp, filename, "rb");
13154 #else
13155   FILE *fp = fopen(filename, "rb");
13156 #endif
13157   if (!fp) {
13158     tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err);
13159     return TINYEXR_ERROR_CANT_OPEN_FILE;
13160   }
13161 
13162   size_t filesize;
13163   // Compute size
13164   fseek(fp, 0, SEEK_END);
13165   filesize = static_cast<size_t>(ftell(fp));
13166   fseek(fp, 0, SEEK_SET);
13167 
13168   std::vector<unsigned char> buf(filesize);  //  @todo { use mmap }
13169   {
13170     size_t ret;
13171     ret = fread(&buf[0], 1, filesize, fp);
13172     assert(ret == filesize);
13173     fclose(fp);
13174     (void)ret;
13175   }
13176 
13177   return LoadEXRMultipartImageFromMemory(exr_images, exr_headers, num_parts,
13178                                          &buf.at(0), filesize, err);
13179 }
13180 
13181 int SaveEXR(const float *data, int width, int height, int components,
13182             const int save_as_fp16, const char *outfilename, const char **err) {
13183   if ((components == 1) || components == 3 || components == 4) {
13184     // OK
13185   } else {
13186     std::stringstream ss;
13187     ss << "Unsupported component value : " << components << std::endl;
13188 
13189     tinyexr::SetErrorMessage(ss.str(), err);
13190     return TINYEXR_ERROR_INVALID_ARGUMENT;
13191   }
13192 
13193   EXRHeader header;
13194   InitEXRHeader(&header);
13195 
13196   if ((width < 16) && (height < 16)) {
13197     // No compression for small image.
13198     header.compression_type = TINYEXR_COMPRESSIONTYPE_NONE;
13199   } else {
13200     header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP;
13201   }
13202 
13203   EXRImage image;
13204   InitEXRImage(&image);
13205 
13206   image.num_channels = components;
13207 
13208   std::vector<float> images[4];
13209 
13210   if (components == 1) {
13211     images[0].resize(static_cast<size_t>(width * height));
13212     memcpy(images[0].data(), data, sizeof(float) * size_t(width * height));
13213   } else {
13214     images[0].resize(static_cast<size_t>(width * height));
13215     images[1].resize(static_cast<size_t>(width * height));
13216     images[2].resize(static_cast<size_t>(width * height));
13217     images[3].resize(static_cast<size_t>(width * height));
13218 
13219     // Split RGB(A)RGB(A)RGB(A)... into R, G and B(and A) layers
13220     for (size_t i = 0; i < static_cast<size_t>(width * height); i++) {
13221       images[0][i] = data[static_cast<size_t>(components) * i + 0];
13222       images[1][i] = data[static_cast<size_t>(components) * i + 1];
13223       images[2][i] = data[static_cast<size_t>(components) * i + 2];
13224       if (components == 4) {
13225         images[3][i] = data[static_cast<size_t>(components) * i + 3];
13226       }
13227     }
13228   }
13229 
13230   float *image_ptr[4] = {0, 0, 0, 0};
13231   if (components == 4) {
13232     image_ptr[0] = &(images[3].at(0));  // A
13233     image_ptr[1] = &(images[2].at(0));  // B
13234     image_ptr[2] = &(images[1].at(0));  // G
13235     image_ptr[3] = &(images[0].at(0));  // R
13236   } else if (components == 3) {
13237     image_ptr[0] = &(images[2].at(0));  // B
13238     image_ptr[1] = &(images[1].at(0));  // G
13239     image_ptr[2] = &(images[0].at(0));  // R
13240   } else if (components == 1) {
13241     image_ptr[0] = &(images[0].at(0));  // A
13242   }
13243 
13244   image.images = reinterpret_cast<unsigned char **>(image_ptr);
13245   image.width = width;
13246   image.height = height;
13247 
13248   header.num_channels = components;
13249   header.channels = static_cast<EXRChannelInfo *>(malloc(
13250       sizeof(EXRChannelInfo) * static_cast<size_t>(header.num_channels)));
13251   // Must be (A)BGR order, since most of EXR viewers expect this channel order.
13252   if (components == 4) {
13253 #ifdef _MSC_VER
13254     strncpy_s(header.channels[0].name, "A", 255);
13255     strncpy_s(header.channels[1].name, "B", 255);
13256     strncpy_s(header.channels[2].name, "G", 255);
13257     strncpy_s(header.channels[3].name, "R", 255);
13258 #else
13259     strncpy(header.channels[0].name, "A", 255);
13260     strncpy(header.channels[1].name, "B", 255);
13261     strncpy(header.channels[2].name, "G", 255);
13262     strncpy(header.channels[3].name, "R", 255);
13263 #endif
13264     header.channels[0].name[strlen("A")] = '\0';
13265     header.channels[1].name[strlen("B")] = '\0';
13266     header.channels[2].name[strlen("G")] = '\0';
13267     header.channels[3].name[strlen("R")] = '\0';
13268   } else if (components == 3) {
13269 #ifdef _MSC_VER
13270     strncpy_s(header.channels[0].name, "B", 255);
13271     strncpy_s(header.channels[1].name, "G", 255);
13272     strncpy_s(header.channels[2].name, "R", 255);
13273 #else
13274     strncpy(header.channels[0].name, "B", 255);
13275     strncpy(header.channels[1].name, "G", 255);
13276     strncpy(header.channels[2].name, "R", 255);
13277 #endif
13278     header.channels[0].name[strlen("B")] = '\0';
13279     header.channels[1].name[strlen("G")] = '\0';
13280     header.channels[2].name[strlen("R")] = '\0';
13281   } else {
13282 #ifdef _MSC_VER
13283     strncpy_s(header.channels[0].name, "A", 255);
13284 #else
13285     strncpy(header.channels[0].name, "A", 255);
13286 #endif
13287     header.channels[0].name[strlen("A")] = '\0';
13288   }
13289 
13290   header.pixel_types = static_cast<int *>(
13291       malloc(sizeof(int) * static_cast<size_t>(header.num_channels)));
13292   header.requested_pixel_types = static_cast<int *>(
13293       malloc(sizeof(int) * static_cast<size_t>(header.num_channels)));
13294   for (int i = 0; i < header.num_channels; i++) {
13295     header.pixel_types[i] =
13296         TINYEXR_PIXELTYPE_FLOAT;  // pixel type of input image
13297 
13298     if (save_as_fp16 > 0) {
13299       header.requested_pixel_types[i] =
13300           TINYEXR_PIXELTYPE_HALF;  // save with half(fp16) pixel format
13301     } else {
13302       header.requested_pixel_types[i] =
13303           TINYEXR_PIXELTYPE_FLOAT;  // save with float(fp32) pixel format(i.e.
13304                                     // no precision reduction)
13305     }
13306   }
13307 
13308   int ret = SaveEXRImageToFile(&image, &header, outfilename, err);
13309   if (ret != TINYEXR_SUCCESS) {
13310     return ret;
13311   }
13312 
13313   free(header.channels);
13314   free(header.pixel_types);
13315   free(header.requested_pixel_types);
13316 
13317   return ret;
13318 }
13319 
13320 #ifdef __clang__
13321 // zero-as-null-ppinter-constant
13322 #pragma clang diagnostic pop
13323 #endif
13324 
13325 #endif  // TINYEXR_IMPLEMENTATION_DEIFNED
13326 #endif  // TINYEXR_IMPLEMENTATION
13327