1cc1dc7a3Sopenharmony_ci/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb
2cc1dc7a3Sopenharmony_ci                                  no warranty implied; use at your own risk
3cc1dc7a3Sopenharmony_ci
4cc1dc7a3Sopenharmony_ci   Do this:
5cc1dc7a3Sopenharmony_ci      #define STB_IMAGE_IMPLEMENTATION
6cc1dc7a3Sopenharmony_ci   before you include this file in *one* C or C++ file to create the implementation.
7cc1dc7a3Sopenharmony_ci
8cc1dc7a3Sopenharmony_ci   // i.e. it should look like this:
9cc1dc7a3Sopenharmony_ci   #include ...
10cc1dc7a3Sopenharmony_ci   #include ...
11cc1dc7a3Sopenharmony_ci   #include ...
12cc1dc7a3Sopenharmony_ci   #define STB_IMAGE_IMPLEMENTATION
13cc1dc7a3Sopenharmony_ci   #include "stb_image.h"
14cc1dc7a3Sopenharmony_ci
15cc1dc7a3Sopenharmony_ci   You can #define STBI_ASSERT(x) before the #include to avoid using assert.h.
16cc1dc7a3Sopenharmony_ci   And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free
17cc1dc7a3Sopenharmony_ci
18cc1dc7a3Sopenharmony_ci
19cc1dc7a3Sopenharmony_ci   QUICK NOTES:
20cc1dc7a3Sopenharmony_ci      Primarily of interest to game developers and other people who can
21cc1dc7a3Sopenharmony_ci          avoid problematic images and only need the trivial interface
22cc1dc7a3Sopenharmony_ci
23cc1dc7a3Sopenharmony_ci      JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib)
24cc1dc7a3Sopenharmony_ci      PNG 1/2/4/8/16-bit-per-channel
25cc1dc7a3Sopenharmony_ci
26cc1dc7a3Sopenharmony_ci      TGA (not sure what subset, if a subset)
27cc1dc7a3Sopenharmony_ci      BMP non-1bpp, non-RLE
28cc1dc7a3Sopenharmony_ci      PSD (composited view only, no extra channels, 8/16 bit-per-channel)
29cc1dc7a3Sopenharmony_ci
30cc1dc7a3Sopenharmony_ci      GIF (*comp always reports as 4-channel)
31cc1dc7a3Sopenharmony_ci      HDR (radiance rgbE format)
32cc1dc7a3Sopenharmony_ci      PIC (Softimage PIC)
33cc1dc7a3Sopenharmony_ci      PNM (PPM and PGM binary only)
34cc1dc7a3Sopenharmony_ci
35cc1dc7a3Sopenharmony_ci      Animated GIF still needs a proper API, but here's one way to do it:
36cc1dc7a3Sopenharmony_ci          http://gist.github.com/urraka/685d9a6340b26b830d49
37cc1dc7a3Sopenharmony_ci
38cc1dc7a3Sopenharmony_ci      - decode from memory or through FILE (define STBI_NO_STDIO to remove code)
39cc1dc7a3Sopenharmony_ci      - decode from arbitrary I/O callbacks
40cc1dc7a3Sopenharmony_ci      - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON)
41cc1dc7a3Sopenharmony_ci
42cc1dc7a3Sopenharmony_ci   Full documentation under "DOCUMENTATION" below.
43cc1dc7a3Sopenharmony_ci
44cc1dc7a3Sopenharmony_ci
45cc1dc7a3Sopenharmony_ciLICENSE
46cc1dc7a3Sopenharmony_ci
47cc1dc7a3Sopenharmony_ci  See end of file for license information.
48cc1dc7a3Sopenharmony_ci
49cc1dc7a3Sopenharmony_ciRECENT REVISION HISTORY:
50cc1dc7a3Sopenharmony_ci
51cc1dc7a3Sopenharmony_ci      2.28  (2023-01-29) many error fixes, security errors, just tons of stuff
52cc1dc7a3Sopenharmony_ci      2.27  (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes
53cc1dc7a3Sopenharmony_ci      2.26  (2020-07-13) many minor fixes
54cc1dc7a3Sopenharmony_ci      2.25  (2020-02-02) fix warnings
55cc1dc7a3Sopenharmony_ci      2.24  (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically
56cc1dc7a3Sopenharmony_ci      2.23  (2019-08-11) fix clang static analysis warning
57cc1dc7a3Sopenharmony_ci      2.22  (2019-03-04) gif fixes, fix warnings
58cc1dc7a3Sopenharmony_ci      2.21  (2019-02-25) fix typo in comment
59cc1dc7a3Sopenharmony_ci      2.20  (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs
60cc1dc7a3Sopenharmony_ci      2.19  (2018-02-11) fix warning
61cc1dc7a3Sopenharmony_ci      2.18  (2018-01-30) fix warnings
62cc1dc7a3Sopenharmony_ci      2.17  (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings
63cc1dc7a3Sopenharmony_ci      2.16  (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes
64cc1dc7a3Sopenharmony_ci      2.15  (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC
65cc1dc7a3Sopenharmony_ci      2.14  (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
66cc1dc7a3Sopenharmony_ci      2.13  (2016-12-04) experimental 16-bit API, only for PNG so far; fixes
67cc1dc7a3Sopenharmony_ci      2.12  (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
68cc1dc7a3Sopenharmony_ci      2.11  (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64
69cc1dc7a3Sopenharmony_ci                         RGB-format JPEG; remove white matting in PSD;
70cc1dc7a3Sopenharmony_ci                         allocate large structures on the stack;
71cc1dc7a3Sopenharmony_ci                         correct channel count for PNG & BMP
72cc1dc7a3Sopenharmony_ci      2.10  (2016-01-22) avoid warning introduced in 2.09
73cc1dc7a3Sopenharmony_ci      2.09  (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
74cc1dc7a3Sopenharmony_ci
75cc1dc7a3Sopenharmony_ci   See end of file for full revision history.
76cc1dc7a3Sopenharmony_ci
77cc1dc7a3Sopenharmony_ci
78cc1dc7a3Sopenharmony_ci ============================    Contributors    =========================
79cc1dc7a3Sopenharmony_ci
80cc1dc7a3Sopenharmony_ci Image formats                          Extensions, features
81cc1dc7a3Sopenharmony_ci    Sean Barrett (jpeg, png, bmp)          Jetro Lauha (stbi_info)
82cc1dc7a3Sopenharmony_ci    Nicolas Schulz (hdr, psd)              Martin "SpartanJ" Golini (stbi_info)
83cc1dc7a3Sopenharmony_ci    Jonathan Dummer (tga)                  James "moose2000" Brown (iPhone PNG)
84cc1dc7a3Sopenharmony_ci    Jean-Marc Lienher (gif)                Ben "Disch" Wenger (io callbacks)
85cc1dc7a3Sopenharmony_ci    Tom Seddon (pic)                       Omar Cornut (1/2/4-bit PNG)
86cc1dc7a3Sopenharmony_ci    Thatcher Ulrich (psd)                  Nicolas Guillemot (vertical flip)
87cc1dc7a3Sopenharmony_ci    Ken Miller (pgm, ppm)                  Richard Mitton (16-bit PSD)
88cc1dc7a3Sopenharmony_ci    github:urraka (animated gif)           Junggon Kim (PNM comments)
89cc1dc7a3Sopenharmony_ci    Christopher Forseth (animated gif)     Daniel Gibson (16-bit TGA)
90cc1dc7a3Sopenharmony_ci                                           socks-the-fox (16-bit PNG)
91cc1dc7a3Sopenharmony_ci                                           Jeremy Sawicki (handle all ImageNet JPGs)
92cc1dc7a3Sopenharmony_ci Optimizations & bugfixes                  Mikhail Morozov (1-bit BMP)
93cc1dc7a3Sopenharmony_ci    Fabian "ryg" Giesen                    Anael Seghezzi (is-16-bit query)
94cc1dc7a3Sopenharmony_ci    Arseny Kapoulkine                      Simon Breuss (16-bit PNM)
95cc1dc7a3Sopenharmony_ci    John-Mark Allen
96cc1dc7a3Sopenharmony_ci    Carmelo J Fdez-Aguera
97cc1dc7a3Sopenharmony_ci
98cc1dc7a3Sopenharmony_ci Bug & warning fixes
99cc1dc7a3Sopenharmony_ci    Marc LeBlanc            David Woo          Guillaume George     Martins Mozeiko
100cc1dc7a3Sopenharmony_ci    Christpher Lloyd        Jerry Jansson      Joseph Thomson       Blazej Dariusz Roszkowski
101cc1dc7a3Sopenharmony_ci    Phil Jordan                                Dave Moore           Roy Eltham
102cc1dc7a3Sopenharmony_ci    Hayaki Saito            Nathan Reed        Won Chun
103cc1dc7a3Sopenharmony_ci    Luke Graham             Johan Duparc       Nick Verigakis       the Horde3D community
104cc1dc7a3Sopenharmony_ci    Thomas Ruf              Ronny Chevalier                         github:rlyeh
105cc1dc7a3Sopenharmony_ci    Janez Zemva             John Bartholomew   Michal Cichon        github:romigrou
106cc1dc7a3Sopenharmony_ci    Jonathan Blow           Ken Hamada         Tero Hanninen        github:svdijk
107cc1dc7a3Sopenharmony_ci    Eugene Golushkov        Laurent Gomila     Cort Stratton        github:snagar
108cc1dc7a3Sopenharmony_ci    Aruelien Pocheville     Sergio Gonzalez    Thibault Reuille     github:Zelex
109cc1dc7a3Sopenharmony_ci    Cass Everitt            Ryamond Barbiero                        github:grim210
110cc1dc7a3Sopenharmony_ci    Paul Du Bois            Engin Manap        Aldo Culquicondor    github:sammyhw
111cc1dc7a3Sopenharmony_ci    Philipp Wiesemann       Dale Weiler        Oriol Ferrer Mesia   github:phprus
112cc1dc7a3Sopenharmony_ci    Josh Tobin              Neil Bickford      Matthew Gregan       github:poppolopoppo
113cc1dc7a3Sopenharmony_ci    Julian Raschke          Gregory Mullen     Christian Floisand   github:darealshinji
114cc1dc7a3Sopenharmony_ci    Baldur Karlsson         Kevin Schmidt      JR Smith             github:Michaelangel007
115cc1dc7a3Sopenharmony_ci                            Brad Weinberger    Matvey Cherevko      github:mosra
116cc1dc7a3Sopenharmony_ci    Luca Sas                Alexander Veselov  Zack Middleton       [reserved]
117cc1dc7a3Sopenharmony_ci    Ryan C. Gordon          [reserved]                              [reserved]
118cc1dc7a3Sopenharmony_ci                     DO NOT ADD YOUR NAME HERE
119cc1dc7a3Sopenharmony_ci
120cc1dc7a3Sopenharmony_ci                     Jacko Dirks
121cc1dc7a3Sopenharmony_ci
122cc1dc7a3Sopenharmony_ci  To add your name to the credits, pick a random blank space in the middle and fill it.
123cc1dc7a3Sopenharmony_ci  80% of merge conflicts on stb PRs are due to people adding their name at the end
124cc1dc7a3Sopenharmony_ci  of the credits.
125cc1dc7a3Sopenharmony_ci*/
126cc1dc7a3Sopenharmony_ci
127cc1dc7a3Sopenharmony_ci#ifndef STBI_INCLUDE_STB_IMAGE_H
128cc1dc7a3Sopenharmony_ci#define STBI_INCLUDE_STB_IMAGE_H
129cc1dc7a3Sopenharmony_ci
130cc1dc7a3Sopenharmony_ci// DOCUMENTATION
131cc1dc7a3Sopenharmony_ci//
132cc1dc7a3Sopenharmony_ci// Limitations:
133cc1dc7a3Sopenharmony_ci//    - no 12-bit-per-channel JPEG
134cc1dc7a3Sopenharmony_ci//    - no JPEGs with arithmetic coding
135cc1dc7a3Sopenharmony_ci//    - GIF always returns *comp=4
136cc1dc7a3Sopenharmony_ci//
137cc1dc7a3Sopenharmony_ci// Basic usage (see HDR discussion below for HDR usage):
138cc1dc7a3Sopenharmony_ci//    int x,y,n;
139cc1dc7a3Sopenharmony_ci//    unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
140cc1dc7a3Sopenharmony_ci//    // ... process data if not NULL ...
141cc1dc7a3Sopenharmony_ci//    // ... x = width, y = height, n = # 8-bit components per pixel ...
142cc1dc7a3Sopenharmony_ci//    // ... replace '0' with '1'..'4' to force that many components per pixel
143cc1dc7a3Sopenharmony_ci//    // ... but 'n' will always be the number that it would have been if you said 0
144cc1dc7a3Sopenharmony_ci//    stbi_image_free(data);
145cc1dc7a3Sopenharmony_ci//
146cc1dc7a3Sopenharmony_ci// Standard parameters:
147cc1dc7a3Sopenharmony_ci//    int *x                 -- outputs image width in pixels
148cc1dc7a3Sopenharmony_ci//    int *y                 -- outputs image height in pixels
149cc1dc7a3Sopenharmony_ci//    int *channels_in_file  -- outputs # of image components in image file
150cc1dc7a3Sopenharmony_ci//    int desired_channels   -- if non-zero, # of image components requested in result
151cc1dc7a3Sopenharmony_ci//
152cc1dc7a3Sopenharmony_ci// The return value from an image loader is an 'unsigned char *' which points
153cc1dc7a3Sopenharmony_ci// to the pixel data, or NULL on an allocation failure or if the image is
154cc1dc7a3Sopenharmony_ci// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels,
155cc1dc7a3Sopenharmony_ci// with each pixel consisting of N interleaved 8-bit components; the first
156cc1dc7a3Sopenharmony_ci// pixel pointed to is top-left-most in the image. There is no padding between
157cc1dc7a3Sopenharmony_ci// image scanlines or between pixels, regardless of format. The number of
158cc1dc7a3Sopenharmony_ci// components N is 'desired_channels' if desired_channels is non-zero, or
159cc1dc7a3Sopenharmony_ci// *channels_in_file otherwise. If desired_channels is non-zero,
160cc1dc7a3Sopenharmony_ci// *channels_in_file has the number of components that _would_ have been
161cc1dc7a3Sopenharmony_ci// output otherwise. E.g. if you set desired_channels to 4, you will always
162cc1dc7a3Sopenharmony_ci// get RGBA output, but you can check *channels_in_file to see if it's trivially
163cc1dc7a3Sopenharmony_ci// opaque because e.g. there were only 3 channels in the source image.
164cc1dc7a3Sopenharmony_ci//
165cc1dc7a3Sopenharmony_ci// An output image with N components has the following components interleaved
166cc1dc7a3Sopenharmony_ci// in this order in each pixel:
167cc1dc7a3Sopenharmony_ci//
168cc1dc7a3Sopenharmony_ci//     N=#comp     components
169cc1dc7a3Sopenharmony_ci//       1           grey
170cc1dc7a3Sopenharmony_ci//       2           grey, alpha
171cc1dc7a3Sopenharmony_ci//       3           red, green, blue
172cc1dc7a3Sopenharmony_ci//       4           red, green, blue, alpha
173cc1dc7a3Sopenharmony_ci//
174cc1dc7a3Sopenharmony_ci// If image loading fails for any reason, the return value will be NULL,
175cc1dc7a3Sopenharmony_ci// and *x, *y, *channels_in_file will be unchanged. The function
176cc1dc7a3Sopenharmony_ci// stbi_failure_reason() can be queried for an extremely brief, end-user
177cc1dc7a3Sopenharmony_ci// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS
178cc1dc7a3Sopenharmony_ci// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
179cc1dc7a3Sopenharmony_ci// more user-friendly ones.
180cc1dc7a3Sopenharmony_ci//
181cc1dc7a3Sopenharmony_ci// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized.
182cc1dc7a3Sopenharmony_ci//
183cc1dc7a3Sopenharmony_ci// To query the width, height and component count of an image without having to
184cc1dc7a3Sopenharmony_ci// decode the full file, you can use the stbi_info family of functions:
185cc1dc7a3Sopenharmony_ci//
186cc1dc7a3Sopenharmony_ci//   int x,y,n,ok;
187cc1dc7a3Sopenharmony_ci//   ok = stbi_info(filename, &x, &y, &n);
188cc1dc7a3Sopenharmony_ci//   // returns ok=1 and sets x, y, n if image is a supported format,
189cc1dc7a3Sopenharmony_ci//   // 0 otherwise.
190cc1dc7a3Sopenharmony_ci//
191cc1dc7a3Sopenharmony_ci// Note that stb_image pervasively uses ints in its public API for sizes,
192cc1dc7a3Sopenharmony_ci// including sizes of memory buffers. This is now part of the API and thus
193cc1dc7a3Sopenharmony_ci// hard to change without causing breakage. As a result, the various image
194cc1dc7a3Sopenharmony_ci// loaders all have certain limits on image size; these differ somewhat
195cc1dc7a3Sopenharmony_ci// by format but generally boil down to either just under 2GB or just under
196cc1dc7a3Sopenharmony_ci// 1GB. When the decoded image would be larger than this, stb_image decoding
197cc1dc7a3Sopenharmony_ci// will fail.
198cc1dc7a3Sopenharmony_ci//
199cc1dc7a3Sopenharmony_ci// Additionally, stb_image will reject image files that have any of their
200cc1dc7a3Sopenharmony_ci// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS,
201cc1dc7a3Sopenharmony_ci// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit,
202cc1dc7a3Sopenharmony_ci// the only way to have an image with such dimensions load correctly
203cc1dc7a3Sopenharmony_ci// is for it to have a rather extreme aspect ratio. Either way, the
204cc1dc7a3Sopenharmony_ci// assumption here is that such larger images are likely to be malformed
205cc1dc7a3Sopenharmony_ci// or malicious. If you do need to load an image with individual dimensions
206cc1dc7a3Sopenharmony_ci// larger than that, and it still fits in the overall size limit, you can
207cc1dc7a3Sopenharmony_ci// #define STBI_MAX_DIMENSIONS on your own to be something larger.
208cc1dc7a3Sopenharmony_ci//
209cc1dc7a3Sopenharmony_ci// ===========================================================================
210cc1dc7a3Sopenharmony_ci//
211cc1dc7a3Sopenharmony_ci// UNICODE:
212cc1dc7a3Sopenharmony_ci//
213cc1dc7a3Sopenharmony_ci//   If compiling for Windows and you wish to use Unicode filenames, compile
214cc1dc7a3Sopenharmony_ci//   with
215cc1dc7a3Sopenharmony_ci//       #define STBI_WINDOWS_UTF8
216cc1dc7a3Sopenharmony_ci//   and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert
217cc1dc7a3Sopenharmony_ci//   Windows wchar_t filenames to utf8.
218cc1dc7a3Sopenharmony_ci//
219cc1dc7a3Sopenharmony_ci// ===========================================================================
220cc1dc7a3Sopenharmony_ci//
221cc1dc7a3Sopenharmony_ci// Philosophy
222cc1dc7a3Sopenharmony_ci//
223cc1dc7a3Sopenharmony_ci// stb libraries are designed with the following priorities:
224cc1dc7a3Sopenharmony_ci//
225cc1dc7a3Sopenharmony_ci//    1. easy to use
226cc1dc7a3Sopenharmony_ci//    2. easy to maintain
227cc1dc7a3Sopenharmony_ci//    3. good performance
228cc1dc7a3Sopenharmony_ci//
229cc1dc7a3Sopenharmony_ci// Sometimes I let "good performance" creep up in priority over "easy to maintain",
230cc1dc7a3Sopenharmony_ci// and for best performance I may provide less-easy-to-use APIs that give higher
231cc1dc7a3Sopenharmony_ci// performance, in addition to the easy-to-use ones. Nevertheless, it's important
232cc1dc7a3Sopenharmony_ci// to keep in mind that from the standpoint of you, a client of this library,
233cc1dc7a3Sopenharmony_ci// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all.
234cc1dc7a3Sopenharmony_ci//
235cc1dc7a3Sopenharmony_ci// Some secondary priorities arise directly from the first two, some of which
236cc1dc7a3Sopenharmony_ci// provide more explicit reasons why performance can't be emphasized.
237cc1dc7a3Sopenharmony_ci//
238cc1dc7a3Sopenharmony_ci//    - Portable ("ease of use")
239cc1dc7a3Sopenharmony_ci//    - Small source code footprint ("easy to maintain")
240cc1dc7a3Sopenharmony_ci//    - No dependencies ("ease of use")
241cc1dc7a3Sopenharmony_ci//
242cc1dc7a3Sopenharmony_ci// ===========================================================================
243cc1dc7a3Sopenharmony_ci//
244cc1dc7a3Sopenharmony_ci// I/O callbacks
245cc1dc7a3Sopenharmony_ci//
246cc1dc7a3Sopenharmony_ci// I/O callbacks allow you to read from arbitrary sources, like packaged
247cc1dc7a3Sopenharmony_ci// files or some other source. Data read from callbacks are processed
248cc1dc7a3Sopenharmony_ci// through a small internal buffer (currently 128 bytes) to try to reduce
249cc1dc7a3Sopenharmony_ci// overhead.
250cc1dc7a3Sopenharmony_ci//
251cc1dc7a3Sopenharmony_ci// The three functions you must define are "read" (reads some bytes of data),
252cc1dc7a3Sopenharmony_ci// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end).
253cc1dc7a3Sopenharmony_ci//
254cc1dc7a3Sopenharmony_ci// ===========================================================================
255cc1dc7a3Sopenharmony_ci//
256cc1dc7a3Sopenharmony_ci// SIMD support
257cc1dc7a3Sopenharmony_ci//
258cc1dc7a3Sopenharmony_ci// The JPEG decoder will try to automatically use SIMD kernels on x86 when
259cc1dc7a3Sopenharmony_ci// supported by the compiler. For ARM Neon support, you must explicitly
260cc1dc7a3Sopenharmony_ci// request it.
261cc1dc7a3Sopenharmony_ci//
262cc1dc7a3Sopenharmony_ci// (The old do-it-yourself SIMD API is no longer supported in the current
263cc1dc7a3Sopenharmony_ci// code.)
264cc1dc7a3Sopenharmony_ci//
265cc1dc7a3Sopenharmony_ci// On x86, SSE2 will automatically be used when available based on a run-time
266cc1dc7a3Sopenharmony_ci// test; if not, the generic C versions are used as a fall-back. On ARM targets,
267cc1dc7a3Sopenharmony_ci// the typical path is to have separate builds for NEON and non-NEON devices
268cc1dc7a3Sopenharmony_ci// (at least this is true for iOS and Android). Therefore, the NEON support is
269cc1dc7a3Sopenharmony_ci// toggled by a build flag: define STBI_NEON to get NEON loops.
270cc1dc7a3Sopenharmony_ci//
271cc1dc7a3Sopenharmony_ci// If for some reason you do not want to use any of SIMD code, or if
272cc1dc7a3Sopenharmony_ci// you have issues compiling it, you can disable it entirely by
273cc1dc7a3Sopenharmony_ci// defining STBI_NO_SIMD.
274cc1dc7a3Sopenharmony_ci//
275cc1dc7a3Sopenharmony_ci// ===========================================================================
276cc1dc7a3Sopenharmony_ci//
277cc1dc7a3Sopenharmony_ci// HDR image support   (disable by defining STBI_NO_HDR)
278cc1dc7a3Sopenharmony_ci//
279cc1dc7a3Sopenharmony_ci// stb_image supports loading HDR images in general, and currently the Radiance
280cc1dc7a3Sopenharmony_ci// .HDR file format specifically. You can still load any file through the existing
281cc1dc7a3Sopenharmony_ci// interface; if you attempt to load an HDR file, it will be automatically remapped
282cc1dc7a3Sopenharmony_ci// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
283cc1dc7a3Sopenharmony_ci// both of these constants can be reconfigured through this interface:
284cc1dc7a3Sopenharmony_ci//
285cc1dc7a3Sopenharmony_ci//     stbi_hdr_to_ldr_gamma(2.2f);
286cc1dc7a3Sopenharmony_ci//     stbi_hdr_to_ldr_scale(1.0f);
287cc1dc7a3Sopenharmony_ci//
288cc1dc7a3Sopenharmony_ci// (note, do not use _inverse_ constants; stbi_image will invert them
289cc1dc7a3Sopenharmony_ci// appropriately).
290cc1dc7a3Sopenharmony_ci//
291cc1dc7a3Sopenharmony_ci// Additionally, there is a new, parallel interface for loading files as
292cc1dc7a3Sopenharmony_ci// (linear) floats to preserve the full dynamic range:
293cc1dc7a3Sopenharmony_ci//
294cc1dc7a3Sopenharmony_ci//    float *data = stbi_loadf(filename, &x, &y, &n, 0);
295cc1dc7a3Sopenharmony_ci//
296cc1dc7a3Sopenharmony_ci// If you load LDR images through this interface, those images will
297cc1dc7a3Sopenharmony_ci// be promoted to floating point values, run through the inverse of
298cc1dc7a3Sopenharmony_ci// constants corresponding to the above:
299cc1dc7a3Sopenharmony_ci//
300cc1dc7a3Sopenharmony_ci//     stbi_ldr_to_hdr_scale(1.0f);
301cc1dc7a3Sopenharmony_ci//     stbi_ldr_to_hdr_gamma(2.2f);
302cc1dc7a3Sopenharmony_ci//
303cc1dc7a3Sopenharmony_ci// Finally, given a filename (or an open file or memory block--see header
304cc1dc7a3Sopenharmony_ci// file for details) containing image data, you can query for the "most
305cc1dc7a3Sopenharmony_ci// appropriate" interface to use (that is, whether the image is HDR or
306cc1dc7a3Sopenharmony_ci// not), using:
307cc1dc7a3Sopenharmony_ci//
308cc1dc7a3Sopenharmony_ci//     stbi_is_hdr(char *filename);
309cc1dc7a3Sopenharmony_ci//
310cc1dc7a3Sopenharmony_ci// ===========================================================================
311cc1dc7a3Sopenharmony_ci//
312cc1dc7a3Sopenharmony_ci// iPhone PNG support:
313cc1dc7a3Sopenharmony_ci//
314cc1dc7a3Sopenharmony_ci// We optionally support converting iPhone-formatted PNGs (which store
315cc1dc7a3Sopenharmony_ci// premultiplied BGRA) back to RGB, even though they're internally encoded
316cc1dc7a3Sopenharmony_ci// differently. To enable this conversion, call
317cc1dc7a3Sopenharmony_ci// stbi_convert_iphone_png_to_rgb(1).
318cc1dc7a3Sopenharmony_ci//
319cc1dc7a3Sopenharmony_ci// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per
320cc1dc7a3Sopenharmony_ci// pixel to remove any premultiplied alpha *only* if the image file explicitly
321cc1dc7a3Sopenharmony_ci// says there's premultiplied data (currently only happens in iPhone images,
322cc1dc7a3Sopenharmony_ci// and only if iPhone convert-to-rgb processing is on).
323cc1dc7a3Sopenharmony_ci//
324cc1dc7a3Sopenharmony_ci// ===========================================================================
325cc1dc7a3Sopenharmony_ci//
326cc1dc7a3Sopenharmony_ci// ADDITIONAL CONFIGURATION
327cc1dc7a3Sopenharmony_ci//
328cc1dc7a3Sopenharmony_ci//  - You can suppress implementation of any of the decoders to reduce
329cc1dc7a3Sopenharmony_ci//    your code footprint by #defining one or more of the following
330cc1dc7a3Sopenharmony_ci//    symbols before creating the implementation.
331cc1dc7a3Sopenharmony_ci//
332cc1dc7a3Sopenharmony_ci//        STBI_NO_JPEG
333cc1dc7a3Sopenharmony_ci//        STBI_NO_PNG
334cc1dc7a3Sopenharmony_ci//        STBI_NO_BMP
335cc1dc7a3Sopenharmony_ci//        STBI_NO_PSD
336cc1dc7a3Sopenharmony_ci//        STBI_NO_TGA
337cc1dc7a3Sopenharmony_ci//        STBI_NO_GIF
338cc1dc7a3Sopenharmony_ci//        STBI_NO_HDR
339cc1dc7a3Sopenharmony_ci//        STBI_NO_PIC
340cc1dc7a3Sopenharmony_ci//        STBI_NO_PNM   (.ppm and .pgm)
341cc1dc7a3Sopenharmony_ci//
342cc1dc7a3Sopenharmony_ci//  - You can request *only* certain decoders and suppress all other ones
343cc1dc7a3Sopenharmony_ci//    (this will be more forward-compatible, as addition of new decoders
344cc1dc7a3Sopenharmony_ci//    doesn't require you to disable them explicitly):
345cc1dc7a3Sopenharmony_ci//
346cc1dc7a3Sopenharmony_ci//        STBI_ONLY_JPEG
347cc1dc7a3Sopenharmony_ci//        STBI_ONLY_PNG
348cc1dc7a3Sopenharmony_ci//        STBI_ONLY_BMP
349cc1dc7a3Sopenharmony_ci//        STBI_ONLY_PSD
350cc1dc7a3Sopenharmony_ci//        STBI_ONLY_TGA
351cc1dc7a3Sopenharmony_ci//        STBI_ONLY_GIF
352cc1dc7a3Sopenharmony_ci//        STBI_ONLY_HDR
353cc1dc7a3Sopenharmony_ci//        STBI_ONLY_PIC
354cc1dc7a3Sopenharmony_ci//        STBI_ONLY_PNM   (.ppm and .pgm)
355cc1dc7a3Sopenharmony_ci//
356cc1dc7a3Sopenharmony_ci//   - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still
357cc1dc7a3Sopenharmony_ci//     want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB
358cc1dc7a3Sopenharmony_ci//
359cc1dc7a3Sopenharmony_ci//  - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater
360cc1dc7a3Sopenharmony_ci//    than that size (in either width or height) without further processing.
361cc1dc7a3Sopenharmony_ci//    This is to let programs in the wild set an upper bound to prevent
362cc1dc7a3Sopenharmony_ci//    denial-of-service attacks on untrusted data, as one could generate a
363cc1dc7a3Sopenharmony_ci//    valid image of gigantic dimensions and force stb_image to allocate a
364cc1dc7a3Sopenharmony_ci//    huge block of memory and spend disproportionate time decoding it. By
365cc1dc7a3Sopenharmony_ci//    default this is set to (1 << 24), which is 16777216, but that's still
366cc1dc7a3Sopenharmony_ci//    very big.
367cc1dc7a3Sopenharmony_ci
368cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_STDIO
369cc1dc7a3Sopenharmony_ci#include <stdio.h>
370cc1dc7a3Sopenharmony_ci#endif // STBI_NO_STDIO
371cc1dc7a3Sopenharmony_ci
372cc1dc7a3Sopenharmony_ci#define STBI_VERSION 1
373cc1dc7a3Sopenharmony_ci
374cc1dc7a3Sopenharmony_cienum
375cc1dc7a3Sopenharmony_ci{
376cc1dc7a3Sopenharmony_ci   STBI_default = 0, // only used for desired_channels
377cc1dc7a3Sopenharmony_ci
378cc1dc7a3Sopenharmony_ci   STBI_grey       = 1,
379cc1dc7a3Sopenharmony_ci   STBI_grey_alpha = 2,
380cc1dc7a3Sopenharmony_ci   STBI_rgb        = 3,
381cc1dc7a3Sopenharmony_ci   STBI_rgb_alpha  = 4
382cc1dc7a3Sopenharmony_ci};
383cc1dc7a3Sopenharmony_ci
384cc1dc7a3Sopenharmony_ci#include <stdlib.h>
385cc1dc7a3Sopenharmony_citypedef unsigned char stbi_uc;
386cc1dc7a3Sopenharmony_citypedef unsigned short stbi_us;
387cc1dc7a3Sopenharmony_ci
388cc1dc7a3Sopenharmony_ci#ifdef __cplusplus
389cc1dc7a3Sopenharmony_ciextern "C" {
390cc1dc7a3Sopenharmony_ci#endif
391cc1dc7a3Sopenharmony_ci
392cc1dc7a3Sopenharmony_ci#ifndef STBIDEF
393cc1dc7a3Sopenharmony_ci#ifdef STB_IMAGE_STATIC
394cc1dc7a3Sopenharmony_ci#define STBIDEF static
395cc1dc7a3Sopenharmony_ci#else
396cc1dc7a3Sopenharmony_ci#define STBIDEF extern
397cc1dc7a3Sopenharmony_ci#endif
398cc1dc7a3Sopenharmony_ci#endif
399cc1dc7a3Sopenharmony_ci
400cc1dc7a3Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////
401cc1dc7a3Sopenharmony_ci//
402cc1dc7a3Sopenharmony_ci// PRIMARY API - works on images of any type
403cc1dc7a3Sopenharmony_ci//
404cc1dc7a3Sopenharmony_ci
405cc1dc7a3Sopenharmony_ci//
406cc1dc7a3Sopenharmony_ci// load image by filename, open file, or memory buffer
407cc1dc7a3Sopenharmony_ci//
408cc1dc7a3Sopenharmony_ci
409cc1dc7a3Sopenharmony_citypedef struct
410cc1dc7a3Sopenharmony_ci{
411cc1dc7a3Sopenharmony_ci   int      (*read)  (void *user,char *data,int size);   // fill 'data' with 'size' bytes.  return number of bytes actually read
412cc1dc7a3Sopenharmony_ci   void     (*skip)  (void *user,int n);                 // skip the next 'n' bytes, or 'unget' the last -n bytes if negative
413cc1dc7a3Sopenharmony_ci   int      (*eof)   (void *user);                       // returns nonzero if we are at end of file/data
414cc1dc7a3Sopenharmony_ci} stbi_io_callbacks;
415cc1dc7a3Sopenharmony_ci
416cc1dc7a3Sopenharmony_ci////////////////////////////////////
417cc1dc7a3Sopenharmony_ci//
418cc1dc7a3Sopenharmony_ci// 8-bits-per-channel interface
419cc1dc7a3Sopenharmony_ci//
420cc1dc7a3Sopenharmony_ci
421cc1dc7a3Sopenharmony_ciSTBIDEF stbi_uc *stbi_load_from_memory   (stbi_uc           const *buffer, int len   , int *x, int *y, int *channels_in_file, int desired_channels);
422cc1dc7a3Sopenharmony_ciSTBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk  , void *user, int *x, int *y, int *channels_in_file, int desired_channels);
423cc1dc7a3Sopenharmony_ci
424cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_STDIO
425cc1dc7a3Sopenharmony_ciSTBIDEF stbi_uc *stbi_load            (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
426cc1dc7a3Sopenharmony_ciSTBIDEF stbi_uc *stbi_load_from_file  (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
427cc1dc7a3Sopenharmony_ci// for stbi_load_from_file, file pointer is left pointing immediately after image
428cc1dc7a3Sopenharmony_ci#endif
429cc1dc7a3Sopenharmony_ci
430cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_GIF
431cc1dc7a3Sopenharmony_ciSTBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
432cc1dc7a3Sopenharmony_ci#endif
433cc1dc7a3Sopenharmony_ci
434cc1dc7a3Sopenharmony_ci#ifdef STBI_WINDOWS_UTF8
435cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
436cc1dc7a3Sopenharmony_ci#endif
437cc1dc7a3Sopenharmony_ci
438cc1dc7a3Sopenharmony_ci////////////////////////////////////
439cc1dc7a3Sopenharmony_ci//
440cc1dc7a3Sopenharmony_ci// 16-bits-per-channel interface
441cc1dc7a3Sopenharmony_ci//
442cc1dc7a3Sopenharmony_ci
443cc1dc7a3Sopenharmony_ciSTBIDEF stbi_us *stbi_load_16_from_memory   (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
444cc1dc7a3Sopenharmony_ciSTBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
445cc1dc7a3Sopenharmony_ci
446cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_STDIO
447cc1dc7a3Sopenharmony_ciSTBIDEF stbi_us *stbi_load_16          (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
448cc1dc7a3Sopenharmony_ciSTBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
449cc1dc7a3Sopenharmony_ci#endif
450cc1dc7a3Sopenharmony_ci
451cc1dc7a3Sopenharmony_ci////////////////////////////////////
452cc1dc7a3Sopenharmony_ci//
453cc1dc7a3Sopenharmony_ci// float-per-channel interface
454cc1dc7a3Sopenharmony_ci//
455cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_LINEAR
456cc1dc7a3Sopenharmony_ci   STBIDEF float *stbi_loadf_from_memory     (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
457cc1dc7a3Sopenharmony_ci   STBIDEF float *stbi_loadf_from_callbacks  (stbi_io_callbacks const *clbk, void *user, int *x, int *y,  int *channels_in_file, int desired_channels);
458cc1dc7a3Sopenharmony_ci
459cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_STDIO
460cc1dc7a3Sopenharmony_ci   STBIDEF float *stbi_loadf            (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
461cc1dc7a3Sopenharmony_ci   STBIDEF float *stbi_loadf_from_file  (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
462cc1dc7a3Sopenharmony_ci   #endif
463cc1dc7a3Sopenharmony_ci#endif
464cc1dc7a3Sopenharmony_ci
465cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_HDR
466cc1dc7a3Sopenharmony_ci   STBIDEF void   stbi_hdr_to_ldr_gamma(float gamma);
467cc1dc7a3Sopenharmony_ci   STBIDEF void   stbi_hdr_to_ldr_scale(float scale);
468cc1dc7a3Sopenharmony_ci#endif // STBI_NO_HDR
469cc1dc7a3Sopenharmony_ci
470cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_LINEAR
471cc1dc7a3Sopenharmony_ci   STBIDEF void   stbi_ldr_to_hdr_gamma(float gamma);
472cc1dc7a3Sopenharmony_ci   STBIDEF void   stbi_ldr_to_hdr_scale(float scale);
473cc1dc7a3Sopenharmony_ci#endif // STBI_NO_LINEAR
474cc1dc7a3Sopenharmony_ci
475cc1dc7a3Sopenharmony_ci// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR
476cc1dc7a3Sopenharmony_ciSTBIDEF int    stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
477cc1dc7a3Sopenharmony_ciSTBIDEF int    stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);
478cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_STDIO
479cc1dc7a3Sopenharmony_ciSTBIDEF int      stbi_is_hdr          (char const *filename);
480cc1dc7a3Sopenharmony_ciSTBIDEF int      stbi_is_hdr_from_file(FILE *f);
481cc1dc7a3Sopenharmony_ci#endif // STBI_NO_STDIO
482cc1dc7a3Sopenharmony_ci
483cc1dc7a3Sopenharmony_ci
484cc1dc7a3Sopenharmony_ci// get a VERY brief reason for failure
485cc1dc7a3Sopenharmony_ci// on most compilers (and ALL modern mainstream compilers) this is threadsafe
486cc1dc7a3Sopenharmony_ciSTBIDEF const char *stbi_failure_reason  (void);
487cc1dc7a3Sopenharmony_ci
488cc1dc7a3Sopenharmony_ci// free the loaded image -- this is just free()
489cc1dc7a3Sopenharmony_ciSTBIDEF void     stbi_image_free      (void *retval_from_stbi_load);
490cc1dc7a3Sopenharmony_ci
491cc1dc7a3Sopenharmony_ci// get image dimensions & components without fully decoding
492cc1dc7a3Sopenharmony_ciSTBIDEF int      stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
493cc1dc7a3Sopenharmony_ciSTBIDEF int      stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);
494cc1dc7a3Sopenharmony_ciSTBIDEF int      stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len);
495cc1dc7a3Sopenharmony_ciSTBIDEF int      stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user);
496cc1dc7a3Sopenharmony_ci
497cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_STDIO
498cc1dc7a3Sopenharmony_ciSTBIDEF int      stbi_info               (char const *filename,     int *x, int *y, int *comp);
499cc1dc7a3Sopenharmony_ciSTBIDEF int      stbi_info_from_file     (FILE *f,                  int *x, int *y, int *comp);
500cc1dc7a3Sopenharmony_ciSTBIDEF int      stbi_is_16_bit          (char const *filename);
501cc1dc7a3Sopenharmony_ciSTBIDEF int      stbi_is_16_bit_from_file(FILE *f);
502cc1dc7a3Sopenharmony_ci#endif
503cc1dc7a3Sopenharmony_ci
504cc1dc7a3Sopenharmony_ci
505cc1dc7a3Sopenharmony_ci
506cc1dc7a3Sopenharmony_ci// for image formats that explicitly notate that they have premultiplied alpha,
507cc1dc7a3Sopenharmony_ci// we just return the colors as stored in the file. set this flag to force
508cc1dc7a3Sopenharmony_ci// unpremultiplication. results are undefined if the unpremultiply overflow.
509cc1dc7a3Sopenharmony_ciSTBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply);
510cc1dc7a3Sopenharmony_ci
511cc1dc7a3Sopenharmony_ci// indicate whether we should process iphone images back to canonical format,
512cc1dc7a3Sopenharmony_ci// or just pass them through "as-is"
513cc1dc7a3Sopenharmony_ciSTBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
514cc1dc7a3Sopenharmony_ci
515cc1dc7a3Sopenharmony_ci// flip the image vertically, so the first pixel in the output array is the bottom left
516cc1dc7a3Sopenharmony_ciSTBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
517cc1dc7a3Sopenharmony_ci
518cc1dc7a3Sopenharmony_ci// as above, but only applies to images loaded on the thread that calls the function
519cc1dc7a3Sopenharmony_ci// this function is only available if your compiler supports thread-local variables;
520cc1dc7a3Sopenharmony_ci// calling it will fail to link if your compiler doesn't
521cc1dc7a3Sopenharmony_ciSTBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply);
522cc1dc7a3Sopenharmony_ciSTBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert);
523cc1dc7a3Sopenharmony_ciSTBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip);
524cc1dc7a3Sopenharmony_ci
525cc1dc7a3Sopenharmony_ci// ZLIB client - used by PNG, available for other purposes
526cc1dc7a3Sopenharmony_ci
527cc1dc7a3Sopenharmony_ciSTBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
528cc1dc7a3Sopenharmony_ciSTBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header);
529cc1dc7a3Sopenharmony_ciSTBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);
530cc1dc7a3Sopenharmony_ciSTBIDEF int   stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
531cc1dc7a3Sopenharmony_ci
532cc1dc7a3Sopenharmony_ciSTBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);
533cc1dc7a3Sopenharmony_ciSTBIDEF int   stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
534cc1dc7a3Sopenharmony_ci
535cc1dc7a3Sopenharmony_ci
536cc1dc7a3Sopenharmony_ci#ifdef __cplusplus
537cc1dc7a3Sopenharmony_ci}
538cc1dc7a3Sopenharmony_ci#endif
539cc1dc7a3Sopenharmony_ci
540cc1dc7a3Sopenharmony_ci//
541cc1dc7a3Sopenharmony_ci//
542cc1dc7a3Sopenharmony_ci////   end header file   /////////////////////////////////////////////////////
543cc1dc7a3Sopenharmony_ci#endif // STBI_INCLUDE_STB_IMAGE_H
544cc1dc7a3Sopenharmony_ci
545cc1dc7a3Sopenharmony_ci#ifdef STB_IMAGE_IMPLEMENTATION
546cc1dc7a3Sopenharmony_ci
547cc1dc7a3Sopenharmony_ci#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \
548cc1dc7a3Sopenharmony_ci  || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \
549cc1dc7a3Sopenharmony_ci  || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \
550cc1dc7a3Sopenharmony_ci  || defined(STBI_ONLY_ZLIB)
551cc1dc7a3Sopenharmony_ci   #ifndef STBI_ONLY_JPEG
552cc1dc7a3Sopenharmony_ci   #define STBI_NO_JPEG
553cc1dc7a3Sopenharmony_ci   #endif
554cc1dc7a3Sopenharmony_ci   #ifndef STBI_ONLY_PNG
555cc1dc7a3Sopenharmony_ci   #define STBI_NO_PNG
556cc1dc7a3Sopenharmony_ci   #endif
557cc1dc7a3Sopenharmony_ci   #ifndef STBI_ONLY_BMP
558cc1dc7a3Sopenharmony_ci   #define STBI_NO_BMP
559cc1dc7a3Sopenharmony_ci   #endif
560cc1dc7a3Sopenharmony_ci   #ifndef STBI_ONLY_PSD
561cc1dc7a3Sopenharmony_ci   #define STBI_NO_PSD
562cc1dc7a3Sopenharmony_ci   #endif
563cc1dc7a3Sopenharmony_ci   #ifndef STBI_ONLY_TGA
564cc1dc7a3Sopenharmony_ci   #define STBI_NO_TGA
565cc1dc7a3Sopenharmony_ci   #endif
566cc1dc7a3Sopenharmony_ci   #ifndef STBI_ONLY_GIF
567cc1dc7a3Sopenharmony_ci   #define STBI_NO_GIF
568cc1dc7a3Sopenharmony_ci   #endif
569cc1dc7a3Sopenharmony_ci   #ifndef STBI_ONLY_HDR
570cc1dc7a3Sopenharmony_ci   #define STBI_NO_HDR
571cc1dc7a3Sopenharmony_ci   #endif
572cc1dc7a3Sopenharmony_ci   #ifndef STBI_ONLY_PIC
573cc1dc7a3Sopenharmony_ci   #define STBI_NO_PIC
574cc1dc7a3Sopenharmony_ci   #endif
575cc1dc7a3Sopenharmony_ci   #ifndef STBI_ONLY_PNM
576cc1dc7a3Sopenharmony_ci   #define STBI_NO_PNM
577cc1dc7a3Sopenharmony_ci   #endif
578cc1dc7a3Sopenharmony_ci#endif
579cc1dc7a3Sopenharmony_ci
580cc1dc7a3Sopenharmony_ci#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB)
581cc1dc7a3Sopenharmony_ci#define STBI_NO_ZLIB
582cc1dc7a3Sopenharmony_ci#endif
583cc1dc7a3Sopenharmony_ci
584cc1dc7a3Sopenharmony_ci
585cc1dc7a3Sopenharmony_ci#include <stdarg.h>
586cc1dc7a3Sopenharmony_ci#include <stddef.h> // ptrdiff_t on osx
587cc1dc7a3Sopenharmony_ci#include <stdlib.h>
588cc1dc7a3Sopenharmony_ci#include <string.h>
589cc1dc7a3Sopenharmony_ci#include <limits.h>
590cc1dc7a3Sopenharmony_ci
591cc1dc7a3Sopenharmony_ci#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
592cc1dc7a3Sopenharmony_ci#include <math.h>  // ldexp, pow
593cc1dc7a3Sopenharmony_ci#endif
594cc1dc7a3Sopenharmony_ci
595cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_STDIO
596cc1dc7a3Sopenharmony_ci#include <stdio.h>
597cc1dc7a3Sopenharmony_ci#endif
598cc1dc7a3Sopenharmony_ci
599cc1dc7a3Sopenharmony_ci#ifndef STBI_ASSERT
600cc1dc7a3Sopenharmony_ci#include <assert.h>
601cc1dc7a3Sopenharmony_ci#define STBI_ASSERT(x) assert(x)
602cc1dc7a3Sopenharmony_ci#endif
603cc1dc7a3Sopenharmony_ci
604cc1dc7a3Sopenharmony_ci#ifdef __cplusplus
605cc1dc7a3Sopenharmony_ci#define STBI_EXTERN extern "C"
606cc1dc7a3Sopenharmony_ci#else
607cc1dc7a3Sopenharmony_ci#define STBI_EXTERN extern
608cc1dc7a3Sopenharmony_ci#endif
609cc1dc7a3Sopenharmony_ci
610cc1dc7a3Sopenharmony_ci
611cc1dc7a3Sopenharmony_ci#ifndef _MSC_VER
612cc1dc7a3Sopenharmony_ci   #ifdef __cplusplus
613cc1dc7a3Sopenharmony_ci   #define stbi_inline inline
614cc1dc7a3Sopenharmony_ci   #else
615cc1dc7a3Sopenharmony_ci   #define stbi_inline
616cc1dc7a3Sopenharmony_ci   #endif
617cc1dc7a3Sopenharmony_ci#else
618cc1dc7a3Sopenharmony_ci   #define stbi_inline __forceinline
619cc1dc7a3Sopenharmony_ci#endif
620cc1dc7a3Sopenharmony_ci
621cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_THREAD_LOCALS
622cc1dc7a3Sopenharmony_ci   #if defined(__cplusplus) &&  __cplusplus >= 201103L
623cc1dc7a3Sopenharmony_ci      #define STBI_THREAD_LOCAL       thread_local
624cc1dc7a3Sopenharmony_ci   #elif defined(__GNUC__) && __GNUC__ < 5
625cc1dc7a3Sopenharmony_ci      #define STBI_THREAD_LOCAL       __thread
626cc1dc7a3Sopenharmony_ci   #elif defined(_MSC_VER)
627cc1dc7a3Sopenharmony_ci      #define STBI_THREAD_LOCAL       __declspec(thread)
628cc1dc7a3Sopenharmony_ci   #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
629cc1dc7a3Sopenharmony_ci      #define STBI_THREAD_LOCAL       _Thread_local
630cc1dc7a3Sopenharmony_ci   #endif
631cc1dc7a3Sopenharmony_ci
632cc1dc7a3Sopenharmony_ci   #ifndef STBI_THREAD_LOCAL
633cc1dc7a3Sopenharmony_ci      #if defined(__GNUC__)
634cc1dc7a3Sopenharmony_ci        #define STBI_THREAD_LOCAL       __thread
635cc1dc7a3Sopenharmony_ci      #endif
636cc1dc7a3Sopenharmony_ci   #endif
637cc1dc7a3Sopenharmony_ci#endif
638cc1dc7a3Sopenharmony_ci
639cc1dc7a3Sopenharmony_ci#if defined(_MSC_VER) || defined(__SYMBIAN32__)
640cc1dc7a3Sopenharmony_citypedef unsigned short stbi__uint16;
641cc1dc7a3Sopenharmony_citypedef   signed short stbi__int16;
642cc1dc7a3Sopenharmony_citypedef unsigned int   stbi__uint32;
643cc1dc7a3Sopenharmony_citypedef   signed int   stbi__int32;
644cc1dc7a3Sopenharmony_ci#else
645cc1dc7a3Sopenharmony_ci#include <stdint.h>
646cc1dc7a3Sopenharmony_citypedef uint16_t stbi__uint16;
647cc1dc7a3Sopenharmony_citypedef int16_t  stbi__int16;
648cc1dc7a3Sopenharmony_citypedef uint32_t stbi__uint32;
649cc1dc7a3Sopenharmony_citypedef int32_t  stbi__int32;
650cc1dc7a3Sopenharmony_ci#endif
651cc1dc7a3Sopenharmony_ci
652cc1dc7a3Sopenharmony_ci// should produce compiler error if size is wrong
653cc1dc7a3Sopenharmony_citypedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
654cc1dc7a3Sopenharmony_ci
655cc1dc7a3Sopenharmony_ci#ifdef _MSC_VER
656cc1dc7a3Sopenharmony_ci#define STBI_NOTUSED(v)  (void)(v)
657cc1dc7a3Sopenharmony_ci#else
658cc1dc7a3Sopenharmony_ci#define STBI_NOTUSED(v)  (void)sizeof(v)
659cc1dc7a3Sopenharmony_ci#endif
660cc1dc7a3Sopenharmony_ci
661cc1dc7a3Sopenharmony_ci#ifdef _MSC_VER
662cc1dc7a3Sopenharmony_ci#define STBI_HAS_LROTL
663cc1dc7a3Sopenharmony_ci#endif
664cc1dc7a3Sopenharmony_ci
665cc1dc7a3Sopenharmony_ci#ifdef STBI_HAS_LROTL
666cc1dc7a3Sopenharmony_ci   #define stbi_lrot(x,y)  _lrotl(x,y)
667cc1dc7a3Sopenharmony_ci#else
668cc1dc7a3Sopenharmony_ci   #define stbi_lrot(x,y)  (((x) << (y)) | ((x) >> (-(y) & 31)))
669cc1dc7a3Sopenharmony_ci#endif
670cc1dc7a3Sopenharmony_ci
671cc1dc7a3Sopenharmony_ci#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED))
672cc1dc7a3Sopenharmony_ci// ok
673cc1dc7a3Sopenharmony_ci#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED)
674cc1dc7a3Sopenharmony_ci// ok
675cc1dc7a3Sopenharmony_ci#else
676cc1dc7a3Sopenharmony_ci#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)."
677cc1dc7a3Sopenharmony_ci#endif
678cc1dc7a3Sopenharmony_ci
679cc1dc7a3Sopenharmony_ci#ifndef STBI_MALLOC
680cc1dc7a3Sopenharmony_ci#define STBI_MALLOC(sz)           malloc(sz)
681cc1dc7a3Sopenharmony_ci#define STBI_REALLOC(p,newsz)     realloc(p,newsz)
682cc1dc7a3Sopenharmony_ci#define STBI_FREE(p)              free(p)
683cc1dc7a3Sopenharmony_ci#endif
684cc1dc7a3Sopenharmony_ci
685cc1dc7a3Sopenharmony_ci#ifndef STBI_REALLOC_SIZED
686cc1dc7a3Sopenharmony_ci#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz)
687cc1dc7a3Sopenharmony_ci#endif
688cc1dc7a3Sopenharmony_ci
689cc1dc7a3Sopenharmony_ci// x86/x64 detection
690cc1dc7a3Sopenharmony_ci#if defined(__x86_64__) || defined(_M_X64)
691cc1dc7a3Sopenharmony_ci#define STBI__X64_TARGET
692cc1dc7a3Sopenharmony_ci#elif defined(__i386) || defined(_M_IX86)
693cc1dc7a3Sopenharmony_ci#define STBI__X86_TARGET
694cc1dc7a3Sopenharmony_ci#endif
695cc1dc7a3Sopenharmony_ci
696cc1dc7a3Sopenharmony_ci#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD)
697cc1dc7a3Sopenharmony_ci// gcc doesn't support sse2 intrinsics unless you compile with -msse2,
698cc1dc7a3Sopenharmony_ci// which in turn means it gets to use SSE2 everywhere. This is unfortunate,
699cc1dc7a3Sopenharmony_ci// but previous attempts to provide the SSE2 functions with runtime
700cc1dc7a3Sopenharmony_ci// detection caused numerous issues. The way architecture extensions are
701cc1dc7a3Sopenharmony_ci// exposed in GCC/Clang is, sadly, not really suited for one-file libs.
702cc1dc7a3Sopenharmony_ci// New behavior: if compiled with -msse2, we use SSE2 without any
703cc1dc7a3Sopenharmony_ci// detection; if not, we don't use it at all.
704cc1dc7a3Sopenharmony_ci#define STBI_NO_SIMD
705cc1dc7a3Sopenharmony_ci#endif
706cc1dc7a3Sopenharmony_ci
707cc1dc7a3Sopenharmony_ci#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD)
708cc1dc7a3Sopenharmony_ci// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET
709cc1dc7a3Sopenharmony_ci//
710cc1dc7a3Sopenharmony_ci// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the
711cc1dc7a3Sopenharmony_ci// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant.
712cc1dc7a3Sopenharmony_ci// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not
713cc1dc7a3Sopenharmony_ci// simultaneously enabling "-mstackrealign".
714cc1dc7a3Sopenharmony_ci//
715cc1dc7a3Sopenharmony_ci// See https://github.com/nothings/stb/issues/81 for more information.
716cc1dc7a3Sopenharmony_ci//
717cc1dc7a3Sopenharmony_ci// So default to no SSE2 on 32-bit MinGW. If you've read this far and added
718cc1dc7a3Sopenharmony_ci// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2.
719cc1dc7a3Sopenharmony_ci#define STBI_NO_SIMD
720cc1dc7a3Sopenharmony_ci#endif
721cc1dc7a3Sopenharmony_ci
722cc1dc7a3Sopenharmony_ci#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET))
723cc1dc7a3Sopenharmony_ci#define STBI_SSE2
724cc1dc7a3Sopenharmony_ci#include <emmintrin.h>
725cc1dc7a3Sopenharmony_ci
726cc1dc7a3Sopenharmony_ci#ifdef _MSC_VER
727cc1dc7a3Sopenharmony_ci
728cc1dc7a3Sopenharmony_ci#if _MSC_VER >= 1400  // not VC6
729cc1dc7a3Sopenharmony_ci#include <intrin.h> // __cpuid
730cc1dc7a3Sopenharmony_cistatic int stbi__cpuid3(void)
731cc1dc7a3Sopenharmony_ci{
732cc1dc7a3Sopenharmony_ci   int info[4];
733cc1dc7a3Sopenharmony_ci   __cpuid(info,1);
734cc1dc7a3Sopenharmony_ci   return info[3];
735cc1dc7a3Sopenharmony_ci}
736cc1dc7a3Sopenharmony_ci#else
737cc1dc7a3Sopenharmony_cistatic int stbi__cpuid3(void)
738cc1dc7a3Sopenharmony_ci{
739cc1dc7a3Sopenharmony_ci   int res;
740cc1dc7a3Sopenharmony_ci   __asm {
741cc1dc7a3Sopenharmony_ci      mov  eax,1
742cc1dc7a3Sopenharmony_ci      cpuid
743cc1dc7a3Sopenharmony_ci      mov  res,edx
744cc1dc7a3Sopenharmony_ci   }
745cc1dc7a3Sopenharmony_ci   return res;
746cc1dc7a3Sopenharmony_ci}
747cc1dc7a3Sopenharmony_ci#endif
748cc1dc7a3Sopenharmony_ci
749cc1dc7a3Sopenharmony_ci#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name
750cc1dc7a3Sopenharmony_ci
751cc1dc7a3Sopenharmony_ci#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2)
752cc1dc7a3Sopenharmony_cistatic int stbi__sse2_available(void)
753cc1dc7a3Sopenharmony_ci{
754cc1dc7a3Sopenharmony_ci   int info3 = stbi__cpuid3();
755cc1dc7a3Sopenharmony_ci   return ((info3 >> 26) & 1) != 0;
756cc1dc7a3Sopenharmony_ci}
757cc1dc7a3Sopenharmony_ci#endif
758cc1dc7a3Sopenharmony_ci
759cc1dc7a3Sopenharmony_ci#else // assume GCC-style if not VC++
760cc1dc7a3Sopenharmony_ci#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
761cc1dc7a3Sopenharmony_ci
762cc1dc7a3Sopenharmony_ci#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2)
763cc1dc7a3Sopenharmony_cistatic int stbi__sse2_available(void)
764cc1dc7a3Sopenharmony_ci{
765cc1dc7a3Sopenharmony_ci   // If we're even attempting to compile this on GCC/Clang, that means
766cc1dc7a3Sopenharmony_ci   // -msse2 is on, which means the compiler is allowed to use SSE2
767cc1dc7a3Sopenharmony_ci   // instructions at will, and so are we.
768cc1dc7a3Sopenharmony_ci   return 1;
769cc1dc7a3Sopenharmony_ci}
770cc1dc7a3Sopenharmony_ci#endif
771cc1dc7a3Sopenharmony_ci
772cc1dc7a3Sopenharmony_ci#endif
773cc1dc7a3Sopenharmony_ci#endif
774cc1dc7a3Sopenharmony_ci
775cc1dc7a3Sopenharmony_ci// ARM NEON
776cc1dc7a3Sopenharmony_ci#if defined(STBI_NO_SIMD) && defined(STBI_NEON)
777cc1dc7a3Sopenharmony_ci#undef STBI_NEON
778cc1dc7a3Sopenharmony_ci#endif
779cc1dc7a3Sopenharmony_ci
780cc1dc7a3Sopenharmony_ci#ifdef STBI_NEON
781cc1dc7a3Sopenharmony_ci#include <arm_neon.h>
782cc1dc7a3Sopenharmony_ci#ifdef _MSC_VER
783cc1dc7a3Sopenharmony_ci#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name
784cc1dc7a3Sopenharmony_ci#else
785cc1dc7a3Sopenharmony_ci#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
786cc1dc7a3Sopenharmony_ci#endif
787cc1dc7a3Sopenharmony_ci#endif
788cc1dc7a3Sopenharmony_ci
789cc1dc7a3Sopenharmony_ci#ifndef STBI_SIMD_ALIGN
790cc1dc7a3Sopenharmony_ci#define STBI_SIMD_ALIGN(type, name) type name
791cc1dc7a3Sopenharmony_ci#endif
792cc1dc7a3Sopenharmony_ci
793cc1dc7a3Sopenharmony_ci#ifndef STBI_MAX_DIMENSIONS
794cc1dc7a3Sopenharmony_ci#define STBI_MAX_DIMENSIONS (1 << 24)
795cc1dc7a3Sopenharmony_ci#endif
796cc1dc7a3Sopenharmony_ci
797cc1dc7a3Sopenharmony_ci///////////////////////////////////////////////
798cc1dc7a3Sopenharmony_ci//
799cc1dc7a3Sopenharmony_ci//  stbi__context struct and start_xxx functions
800cc1dc7a3Sopenharmony_ci
801cc1dc7a3Sopenharmony_ci// stbi__context structure is our basic context used by all images, so it
802cc1dc7a3Sopenharmony_ci// contains all the IO context, plus some basic image information
803cc1dc7a3Sopenharmony_citypedef struct
804cc1dc7a3Sopenharmony_ci{
805cc1dc7a3Sopenharmony_ci   stbi__uint32 img_x, img_y;
806cc1dc7a3Sopenharmony_ci   int img_n, img_out_n;
807cc1dc7a3Sopenharmony_ci
808cc1dc7a3Sopenharmony_ci   stbi_io_callbacks io;
809cc1dc7a3Sopenharmony_ci   void *io_user_data;
810cc1dc7a3Sopenharmony_ci
811cc1dc7a3Sopenharmony_ci   int read_from_callbacks;
812cc1dc7a3Sopenharmony_ci   int buflen;
813cc1dc7a3Sopenharmony_ci   stbi_uc buffer_start[128];
814cc1dc7a3Sopenharmony_ci   int callback_already_read;
815cc1dc7a3Sopenharmony_ci
816cc1dc7a3Sopenharmony_ci   stbi_uc *img_buffer, *img_buffer_end;
817cc1dc7a3Sopenharmony_ci   stbi_uc *img_buffer_original, *img_buffer_original_end;
818cc1dc7a3Sopenharmony_ci} stbi__context;
819cc1dc7a3Sopenharmony_ci
820cc1dc7a3Sopenharmony_ci
821cc1dc7a3Sopenharmony_cistatic void stbi__refill_buffer(stbi__context *s);
822cc1dc7a3Sopenharmony_ci
823cc1dc7a3Sopenharmony_ci// initialize a memory-decode context
824cc1dc7a3Sopenharmony_cistatic void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)
825cc1dc7a3Sopenharmony_ci{
826cc1dc7a3Sopenharmony_ci   s->io.read = NULL;
827cc1dc7a3Sopenharmony_ci   s->read_from_callbacks = 0;
828cc1dc7a3Sopenharmony_ci   s->callback_already_read = 0;
829cc1dc7a3Sopenharmony_ci   s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer;
830cc1dc7a3Sopenharmony_ci   s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
831cc1dc7a3Sopenharmony_ci}
832cc1dc7a3Sopenharmony_ci
833cc1dc7a3Sopenharmony_ci// initialize a callback-based context
834cc1dc7a3Sopenharmony_cistatic void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user)
835cc1dc7a3Sopenharmony_ci{
836cc1dc7a3Sopenharmony_ci   s->io = *c;
837cc1dc7a3Sopenharmony_ci   s->io_user_data = user;
838cc1dc7a3Sopenharmony_ci   s->buflen = sizeof(s->buffer_start);
839cc1dc7a3Sopenharmony_ci   s->read_from_callbacks = 1;
840cc1dc7a3Sopenharmony_ci   s->callback_already_read = 0;
841cc1dc7a3Sopenharmony_ci   s->img_buffer = s->img_buffer_original = s->buffer_start;
842cc1dc7a3Sopenharmony_ci   stbi__refill_buffer(s);
843cc1dc7a3Sopenharmony_ci   s->img_buffer_original_end = s->img_buffer_end;
844cc1dc7a3Sopenharmony_ci}
845cc1dc7a3Sopenharmony_ci
846cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_STDIO
847cc1dc7a3Sopenharmony_ci
848cc1dc7a3Sopenharmony_cistatic int stbi__stdio_read(void *user, char *data, int size)
849cc1dc7a3Sopenharmony_ci{
850cc1dc7a3Sopenharmony_ci   return (int) fread(data,1,size,(FILE*) user);
851cc1dc7a3Sopenharmony_ci}
852cc1dc7a3Sopenharmony_ci
853cc1dc7a3Sopenharmony_cistatic void stbi__stdio_skip(void *user, int n)
854cc1dc7a3Sopenharmony_ci{
855cc1dc7a3Sopenharmony_ci   int ch;
856cc1dc7a3Sopenharmony_ci   fseek((FILE*) user, n, SEEK_CUR);
857cc1dc7a3Sopenharmony_ci   ch = fgetc((FILE*) user);  /* have to read a byte to reset feof()'s flag */
858cc1dc7a3Sopenharmony_ci   if (ch != EOF) {
859cc1dc7a3Sopenharmony_ci      ungetc(ch, (FILE *) user);  /* push byte back onto stream if valid. */
860cc1dc7a3Sopenharmony_ci   }
861cc1dc7a3Sopenharmony_ci}
862cc1dc7a3Sopenharmony_ci
863cc1dc7a3Sopenharmony_cistatic int stbi__stdio_eof(void *user)
864cc1dc7a3Sopenharmony_ci{
865cc1dc7a3Sopenharmony_ci   return feof((FILE*) user) || ferror((FILE *) user);
866cc1dc7a3Sopenharmony_ci}
867cc1dc7a3Sopenharmony_ci
868cc1dc7a3Sopenharmony_cistatic stbi_io_callbacks stbi__stdio_callbacks =
869cc1dc7a3Sopenharmony_ci{
870cc1dc7a3Sopenharmony_ci   stbi__stdio_read,
871cc1dc7a3Sopenharmony_ci   stbi__stdio_skip,
872cc1dc7a3Sopenharmony_ci   stbi__stdio_eof,
873cc1dc7a3Sopenharmony_ci};
874cc1dc7a3Sopenharmony_ci
875cc1dc7a3Sopenharmony_cistatic void stbi__start_file(stbi__context *s, FILE *f)
876cc1dc7a3Sopenharmony_ci{
877cc1dc7a3Sopenharmony_ci   stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f);
878cc1dc7a3Sopenharmony_ci}
879cc1dc7a3Sopenharmony_ci
880cc1dc7a3Sopenharmony_ci//static void stop_file(stbi__context *s) { }
881cc1dc7a3Sopenharmony_ci
882cc1dc7a3Sopenharmony_ci#endif // !STBI_NO_STDIO
883cc1dc7a3Sopenharmony_ci
884cc1dc7a3Sopenharmony_cistatic void stbi__rewind(stbi__context *s)
885cc1dc7a3Sopenharmony_ci{
886cc1dc7a3Sopenharmony_ci   // conceptually rewind SHOULD rewind to the beginning of the stream,
887cc1dc7a3Sopenharmony_ci   // but we just rewind to the beginning of the initial buffer, because
888cc1dc7a3Sopenharmony_ci   // we only use it after doing 'test', which only ever looks at at most 92 bytes
889cc1dc7a3Sopenharmony_ci   s->img_buffer = s->img_buffer_original;
890cc1dc7a3Sopenharmony_ci   s->img_buffer_end = s->img_buffer_original_end;
891cc1dc7a3Sopenharmony_ci}
892cc1dc7a3Sopenharmony_ci
893cc1dc7a3Sopenharmony_cienum
894cc1dc7a3Sopenharmony_ci{
895cc1dc7a3Sopenharmony_ci   STBI_ORDER_RGB,
896cc1dc7a3Sopenharmony_ci   STBI_ORDER_BGR
897cc1dc7a3Sopenharmony_ci};
898cc1dc7a3Sopenharmony_ci
899cc1dc7a3Sopenharmony_citypedef struct
900cc1dc7a3Sopenharmony_ci{
901cc1dc7a3Sopenharmony_ci   int bits_per_channel;
902cc1dc7a3Sopenharmony_ci   int num_channels;
903cc1dc7a3Sopenharmony_ci   int channel_order;
904cc1dc7a3Sopenharmony_ci} stbi__result_info;
905cc1dc7a3Sopenharmony_ci
906cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_JPEG
907cc1dc7a3Sopenharmony_cistatic int      stbi__jpeg_test(stbi__context *s);
908cc1dc7a3Sopenharmony_cistatic void    *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
909cc1dc7a3Sopenharmony_cistatic int      stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp);
910cc1dc7a3Sopenharmony_ci#endif
911cc1dc7a3Sopenharmony_ci
912cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_PNG
913cc1dc7a3Sopenharmony_cistatic int      stbi__png_test(stbi__context *s);
914cc1dc7a3Sopenharmony_cistatic void    *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
915cc1dc7a3Sopenharmony_cistatic int      stbi__png_info(stbi__context *s, int *x, int *y, int *comp);
916cc1dc7a3Sopenharmony_cistatic int      stbi__png_is16(stbi__context *s);
917cc1dc7a3Sopenharmony_ci#endif
918cc1dc7a3Sopenharmony_ci
919cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_BMP
920cc1dc7a3Sopenharmony_cistatic int      stbi__bmp_test(stbi__context *s);
921cc1dc7a3Sopenharmony_cistatic void    *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
922cc1dc7a3Sopenharmony_cistatic int      stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp);
923cc1dc7a3Sopenharmony_ci#endif
924cc1dc7a3Sopenharmony_ci
925cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_TGA
926cc1dc7a3Sopenharmony_cistatic int      stbi__tga_test(stbi__context *s);
927cc1dc7a3Sopenharmony_cistatic void    *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
928cc1dc7a3Sopenharmony_cistatic int      stbi__tga_info(stbi__context *s, int *x, int *y, int *comp);
929cc1dc7a3Sopenharmony_ci#endif
930cc1dc7a3Sopenharmony_ci
931cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_PSD
932cc1dc7a3Sopenharmony_cistatic int      stbi__psd_test(stbi__context *s);
933cc1dc7a3Sopenharmony_cistatic void    *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc);
934cc1dc7a3Sopenharmony_cistatic int      stbi__psd_info(stbi__context *s, int *x, int *y, int *comp);
935cc1dc7a3Sopenharmony_cistatic int      stbi__psd_is16(stbi__context *s);
936cc1dc7a3Sopenharmony_ci#endif
937cc1dc7a3Sopenharmony_ci
938cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_HDR
939cc1dc7a3Sopenharmony_cistatic int      stbi__hdr_test(stbi__context *s);
940cc1dc7a3Sopenharmony_cistatic float   *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
941cc1dc7a3Sopenharmony_cistatic int      stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp);
942cc1dc7a3Sopenharmony_ci#endif
943cc1dc7a3Sopenharmony_ci
944cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_PIC
945cc1dc7a3Sopenharmony_cistatic int      stbi__pic_test(stbi__context *s);
946cc1dc7a3Sopenharmony_cistatic void    *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
947cc1dc7a3Sopenharmony_cistatic int      stbi__pic_info(stbi__context *s, int *x, int *y, int *comp);
948cc1dc7a3Sopenharmony_ci#endif
949cc1dc7a3Sopenharmony_ci
950cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_GIF
951cc1dc7a3Sopenharmony_cistatic int      stbi__gif_test(stbi__context *s);
952cc1dc7a3Sopenharmony_cistatic void    *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
953cc1dc7a3Sopenharmony_cistatic void    *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
954cc1dc7a3Sopenharmony_cistatic int      stbi__gif_info(stbi__context *s, int *x, int *y, int *comp);
955cc1dc7a3Sopenharmony_ci#endif
956cc1dc7a3Sopenharmony_ci
957cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_PNM
958cc1dc7a3Sopenharmony_cistatic int      stbi__pnm_test(stbi__context *s);
959cc1dc7a3Sopenharmony_cistatic void    *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
960cc1dc7a3Sopenharmony_cistatic int      stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
961cc1dc7a3Sopenharmony_cistatic int      stbi__pnm_is16(stbi__context *s);
962cc1dc7a3Sopenharmony_ci#endif
963cc1dc7a3Sopenharmony_ci
964cc1dc7a3Sopenharmony_cistatic
965cc1dc7a3Sopenharmony_ci#ifdef STBI_THREAD_LOCAL
966cc1dc7a3Sopenharmony_ciSTBI_THREAD_LOCAL
967cc1dc7a3Sopenharmony_ci#endif
968cc1dc7a3Sopenharmony_ciconst char *stbi__g_failure_reason;
969cc1dc7a3Sopenharmony_ci
970cc1dc7a3Sopenharmony_ciSTBIDEF const char *stbi_failure_reason(void)
971cc1dc7a3Sopenharmony_ci{
972cc1dc7a3Sopenharmony_ci   return stbi__g_failure_reason;
973cc1dc7a3Sopenharmony_ci}
974cc1dc7a3Sopenharmony_ci
975cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_FAILURE_STRINGS
976cc1dc7a3Sopenharmony_cistatic int stbi__err(const char *str)
977cc1dc7a3Sopenharmony_ci{
978cc1dc7a3Sopenharmony_ci   stbi__g_failure_reason = str;
979cc1dc7a3Sopenharmony_ci   return 0;
980cc1dc7a3Sopenharmony_ci}
981cc1dc7a3Sopenharmony_ci#endif
982cc1dc7a3Sopenharmony_ci
983cc1dc7a3Sopenharmony_cistatic void *stbi__malloc(size_t size)
984cc1dc7a3Sopenharmony_ci{
985cc1dc7a3Sopenharmony_ci    return STBI_MALLOC(size);
986cc1dc7a3Sopenharmony_ci}
987cc1dc7a3Sopenharmony_ci
988cc1dc7a3Sopenharmony_ci// stb_image uses ints pervasively, including for offset calculations.
989cc1dc7a3Sopenharmony_ci// therefore the largest decoded image size we can support with the
990cc1dc7a3Sopenharmony_ci// current code, even on 64-bit targets, is INT_MAX. this is not a
991cc1dc7a3Sopenharmony_ci// significant limitation for the intended use case.
992cc1dc7a3Sopenharmony_ci//
993cc1dc7a3Sopenharmony_ci// we do, however, need to make sure our size calculations don't
994cc1dc7a3Sopenharmony_ci// overflow. hence a few helper functions for size calculations that
995cc1dc7a3Sopenharmony_ci// multiply integers together, making sure that they're non-negative
996cc1dc7a3Sopenharmony_ci// and no overflow occurs.
997cc1dc7a3Sopenharmony_ci
998cc1dc7a3Sopenharmony_ci// return 1 if the sum is valid, 0 on overflow.
999cc1dc7a3Sopenharmony_ci// negative terms are considered invalid.
1000cc1dc7a3Sopenharmony_cistatic int stbi__addsizes_valid(int a, int b)
1001cc1dc7a3Sopenharmony_ci{
1002cc1dc7a3Sopenharmony_ci   if (b < 0) return 0;
1003cc1dc7a3Sopenharmony_ci   // now 0 <= b <= INT_MAX, hence also
1004cc1dc7a3Sopenharmony_ci   // 0 <= INT_MAX - b <= INTMAX.
1005cc1dc7a3Sopenharmony_ci   // And "a + b <= INT_MAX" (which might overflow) is the
1006cc1dc7a3Sopenharmony_ci   // same as a <= INT_MAX - b (no overflow)
1007cc1dc7a3Sopenharmony_ci   return a <= INT_MAX - b;
1008cc1dc7a3Sopenharmony_ci}
1009cc1dc7a3Sopenharmony_ci
1010cc1dc7a3Sopenharmony_ci// returns 1 if the product is valid, 0 on overflow.
1011cc1dc7a3Sopenharmony_ci// negative factors are considered invalid.
1012cc1dc7a3Sopenharmony_cistatic int stbi__mul2sizes_valid(int a, int b)
1013cc1dc7a3Sopenharmony_ci{
1014cc1dc7a3Sopenharmony_ci   if (a < 0 || b < 0) return 0;
1015cc1dc7a3Sopenharmony_ci   if (b == 0) return 1; // mul-by-0 is always safe
1016cc1dc7a3Sopenharmony_ci   // portable way to check for no overflows in a*b
1017cc1dc7a3Sopenharmony_ci   return a <= INT_MAX/b;
1018cc1dc7a3Sopenharmony_ci}
1019cc1dc7a3Sopenharmony_ci
1020cc1dc7a3Sopenharmony_ci#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)
1021cc1dc7a3Sopenharmony_ci// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow
1022cc1dc7a3Sopenharmony_cistatic int stbi__mad2sizes_valid(int a, int b, int add)
1023cc1dc7a3Sopenharmony_ci{
1024cc1dc7a3Sopenharmony_ci   return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add);
1025cc1dc7a3Sopenharmony_ci}
1026cc1dc7a3Sopenharmony_ci#endif
1027cc1dc7a3Sopenharmony_ci
1028cc1dc7a3Sopenharmony_ci// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow
1029cc1dc7a3Sopenharmony_cistatic int stbi__mad3sizes_valid(int a, int b, int c, int add)
1030cc1dc7a3Sopenharmony_ci{
1031cc1dc7a3Sopenharmony_ci   return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
1032cc1dc7a3Sopenharmony_ci      stbi__addsizes_valid(a*b*c, add);
1033cc1dc7a3Sopenharmony_ci}
1034cc1dc7a3Sopenharmony_ci
1035cc1dc7a3Sopenharmony_ci// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow
1036cc1dc7a3Sopenharmony_ci#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM)
1037cc1dc7a3Sopenharmony_cistatic int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
1038cc1dc7a3Sopenharmony_ci{
1039cc1dc7a3Sopenharmony_ci   return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
1040cc1dc7a3Sopenharmony_ci      stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add);
1041cc1dc7a3Sopenharmony_ci}
1042cc1dc7a3Sopenharmony_ci#endif
1043cc1dc7a3Sopenharmony_ci
1044cc1dc7a3Sopenharmony_ci#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)
1045cc1dc7a3Sopenharmony_ci// mallocs with size overflow checking
1046cc1dc7a3Sopenharmony_cistatic void *stbi__malloc_mad2(int a, int b, int add)
1047cc1dc7a3Sopenharmony_ci{
1048cc1dc7a3Sopenharmony_ci   if (!stbi__mad2sizes_valid(a, b, add)) return NULL;
1049cc1dc7a3Sopenharmony_ci   return stbi__malloc(a*b + add);
1050cc1dc7a3Sopenharmony_ci}
1051cc1dc7a3Sopenharmony_ci#endif
1052cc1dc7a3Sopenharmony_ci
1053cc1dc7a3Sopenharmony_cistatic void *stbi__malloc_mad3(int a, int b, int c, int add)
1054cc1dc7a3Sopenharmony_ci{
1055cc1dc7a3Sopenharmony_ci   if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL;
1056cc1dc7a3Sopenharmony_ci   return stbi__malloc(a*b*c + add);
1057cc1dc7a3Sopenharmony_ci}
1058cc1dc7a3Sopenharmony_ci
1059cc1dc7a3Sopenharmony_ci#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM)
1060cc1dc7a3Sopenharmony_cistatic void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
1061cc1dc7a3Sopenharmony_ci{
1062cc1dc7a3Sopenharmony_ci   if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL;
1063cc1dc7a3Sopenharmony_ci   return stbi__malloc(a*b*c*d + add);
1064cc1dc7a3Sopenharmony_ci}
1065cc1dc7a3Sopenharmony_ci#endif
1066cc1dc7a3Sopenharmony_ci
1067cc1dc7a3Sopenharmony_ci// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow.
1068cc1dc7a3Sopenharmony_cistatic int stbi__addints_valid(int a, int b)
1069cc1dc7a3Sopenharmony_ci{
1070cc1dc7a3Sopenharmony_ci   if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow
1071cc1dc7a3Sopenharmony_ci   if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0.
1072cc1dc7a3Sopenharmony_ci   return a <= INT_MAX - b;
1073cc1dc7a3Sopenharmony_ci}
1074cc1dc7a3Sopenharmony_ci
1075cc1dc7a3Sopenharmony_ci// returns 1 if the product of two signed shorts is valid, 0 on overflow.
1076cc1dc7a3Sopenharmony_cistatic int stbi__mul2shorts_valid(short a, short b)
1077cc1dc7a3Sopenharmony_ci{
1078cc1dc7a3Sopenharmony_ci   if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow
1079cc1dc7a3Sopenharmony_ci   if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid
1080cc1dc7a3Sopenharmony_ci   if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN
1081cc1dc7a3Sopenharmony_ci   return a >= SHRT_MIN / b;
1082cc1dc7a3Sopenharmony_ci}
1083cc1dc7a3Sopenharmony_ci
1084cc1dc7a3Sopenharmony_ci// stbi__err - error
1085cc1dc7a3Sopenharmony_ci// stbi__errpf - error returning pointer to float
1086cc1dc7a3Sopenharmony_ci// stbi__errpuc - error returning pointer to unsigned char
1087cc1dc7a3Sopenharmony_ci
1088cc1dc7a3Sopenharmony_ci#ifdef STBI_NO_FAILURE_STRINGS
1089cc1dc7a3Sopenharmony_ci   #define stbi__err(x,y)  0
1090cc1dc7a3Sopenharmony_ci#elif defined(STBI_FAILURE_USERMSG)
1091cc1dc7a3Sopenharmony_ci   #define stbi__err(x,y)  stbi__err(y)
1092cc1dc7a3Sopenharmony_ci#else
1093cc1dc7a3Sopenharmony_ci   #define stbi__err(x,y)  stbi__err(x)
1094cc1dc7a3Sopenharmony_ci#endif
1095cc1dc7a3Sopenharmony_ci
1096cc1dc7a3Sopenharmony_ci#define stbi__errpf(x,y)   ((float *)(size_t) (stbi__err(x,y)?NULL:NULL))
1097cc1dc7a3Sopenharmony_ci#define stbi__errpuc(x,y)  ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL))
1098cc1dc7a3Sopenharmony_ci
1099cc1dc7a3Sopenharmony_ciSTBIDEF void stbi_image_free(void *retval_from_stbi_load)
1100cc1dc7a3Sopenharmony_ci{
1101cc1dc7a3Sopenharmony_ci   STBI_FREE(retval_from_stbi_load);
1102cc1dc7a3Sopenharmony_ci}
1103cc1dc7a3Sopenharmony_ci
1104cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_LINEAR
1105cc1dc7a3Sopenharmony_cistatic float   *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
1106cc1dc7a3Sopenharmony_ci#endif
1107cc1dc7a3Sopenharmony_ci
1108cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_HDR
1109cc1dc7a3Sopenharmony_cistatic stbi_uc *stbi__hdr_to_ldr(float   *data, int x, int y, int comp);
1110cc1dc7a3Sopenharmony_ci#endif
1111cc1dc7a3Sopenharmony_ci
1112cc1dc7a3Sopenharmony_cistatic int stbi__vertically_flip_on_load_global = 0;
1113cc1dc7a3Sopenharmony_ci
1114cc1dc7a3Sopenharmony_ciSTBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
1115cc1dc7a3Sopenharmony_ci{
1116cc1dc7a3Sopenharmony_ci   stbi__vertically_flip_on_load_global = flag_true_if_should_flip;
1117cc1dc7a3Sopenharmony_ci}
1118cc1dc7a3Sopenharmony_ci
1119cc1dc7a3Sopenharmony_ci#ifndef STBI_THREAD_LOCAL
1120cc1dc7a3Sopenharmony_ci#define stbi__vertically_flip_on_load  stbi__vertically_flip_on_load_global
1121cc1dc7a3Sopenharmony_ci#else
1122cc1dc7a3Sopenharmony_cistatic STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set;
1123cc1dc7a3Sopenharmony_ci
1124cc1dc7a3Sopenharmony_ciSTBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip)
1125cc1dc7a3Sopenharmony_ci{
1126cc1dc7a3Sopenharmony_ci   stbi__vertically_flip_on_load_local = flag_true_if_should_flip;
1127cc1dc7a3Sopenharmony_ci   stbi__vertically_flip_on_load_set = 1;
1128cc1dc7a3Sopenharmony_ci}
1129cc1dc7a3Sopenharmony_ci
1130cc1dc7a3Sopenharmony_ci#define stbi__vertically_flip_on_load  (stbi__vertically_flip_on_load_set       \
1131cc1dc7a3Sopenharmony_ci                                         ? stbi__vertically_flip_on_load_local  \
1132cc1dc7a3Sopenharmony_ci                                         : stbi__vertically_flip_on_load_global)
1133cc1dc7a3Sopenharmony_ci#endif // STBI_THREAD_LOCAL
1134cc1dc7a3Sopenharmony_ci
1135cc1dc7a3Sopenharmony_cistatic void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
1136cc1dc7a3Sopenharmony_ci{
1137cc1dc7a3Sopenharmony_ci   memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields
1138cc1dc7a3Sopenharmony_ci   ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed
1139cc1dc7a3Sopenharmony_ci   ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order
1140cc1dc7a3Sopenharmony_ci   ri->num_channels = 0;
1141cc1dc7a3Sopenharmony_ci
1142cc1dc7a3Sopenharmony_ci   // test the formats with a very explicit header first (at least a FOURCC
1143cc1dc7a3Sopenharmony_ci   // or distinctive magic number first)
1144cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_PNG
1145cc1dc7a3Sopenharmony_ci   if (stbi__png_test(s))  return stbi__png_load(s,x,y,comp,req_comp, ri);
1146cc1dc7a3Sopenharmony_ci   #endif
1147cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_BMP
1148cc1dc7a3Sopenharmony_ci   if (stbi__bmp_test(s))  return stbi__bmp_load(s,x,y,comp,req_comp, ri);
1149cc1dc7a3Sopenharmony_ci   #endif
1150cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_GIF
1151cc1dc7a3Sopenharmony_ci   if (stbi__gif_test(s))  return stbi__gif_load(s,x,y,comp,req_comp, ri);
1152cc1dc7a3Sopenharmony_ci   #endif
1153cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_PSD
1154cc1dc7a3Sopenharmony_ci   if (stbi__psd_test(s))  return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc);
1155cc1dc7a3Sopenharmony_ci   #else
1156cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(bpc);
1157cc1dc7a3Sopenharmony_ci   #endif
1158cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_PIC
1159cc1dc7a3Sopenharmony_ci   if (stbi__pic_test(s))  return stbi__pic_load(s,x,y,comp,req_comp, ri);
1160cc1dc7a3Sopenharmony_ci   #endif
1161cc1dc7a3Sopenharmony_ci
1162cc1dc7a3Sopenharmony_ci   // then the formats that can end up attempting to load with just 1 or 2
1163cc1dc7a3Sopenharmony_ci   // bytes matching expectations; these are prone to false positives, so
1164cc1dc7a3Sopenharmony_ci   // try them later
1165cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_JPEG
1166cc1dc7a3Sopenharmony_ci   if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri);
1167cc1dc7a3Sopenharmony_ci   #endif
1168cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_PNM
1169cc1dc7a3Sopenharmony_ci   if (stbi__pnm_test(s))  return stbi__pnm_load(s,x,y,comp,req_comp, ri);
1170cc1dc7a3Sopenharmony_ci   #endif
1171cc1dc7a3Sopenharmony_ci
1172cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_HDR
1173cc1dc7a3Sopenharmony_ci   if (stbi__hdr_test(s)) {
1174cc1dc7a3Sopenharmony_ci      float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri);
1175cc1dc7a3Sopenharmony_ci      return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
1176cc1dc7a3Sopenharmony_ci   }
1177cc1dc7a3Sopenharmony_ci   #endif
1178cc1dc7a3Sopenharmony_ci
1179cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_TGA
1180cc1dc7a3Sopenharmony_ci   // test tga last because it's a crappy test!
1181cc1dc7a3Sopenharmony_ci   if (stbi__tga_test(s))
1182cc1dc7a3Sopenharmony_ci      return stbi__tga_load(s,x,y,comp,req_comp, ri);
1183cc1dc7a3Sopenharmony_ci   #endif
1184cc1dc7a3Sopenharmony_ci
1185cc1dc7a3Sopenharmony_ci   return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt");
1186cc1dc7a3Sopenharmony_ci}
1187cc1dc7a3Sopenharmony_ci
1188cc1dc7a3Sopenharmony_cistatic stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels)
1189cc1dc7a3Sopenharmony_ci{
1190cc1dc7a3Sopenharmony_ci   int i;
1191cc1dc7a3Sopenharmony_ci   int img_len = w * h * channels;
1192cc1dc7a3Sopenharmony_ci   stbi_uc *reduced;
1193cc1dc7a3Sopenharmony_ci
1194cc1dc7a3Sopenharmony_ci   reduced = (stbi_uc *) stbi__malloc(img_len);
1195cc1dc7a3Sopenharmony_ci   if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory");
1196cc1dc7a3Sopenharmony_ci
1197cc1dc7a3Sopenharmony_ci   for (i = 0; i < img_len; ++i)
1198cc1dc7a3Sopenharmony_ci      reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling
1199cc1dc7a3Sopenharmony_ci
1200cc1dc7a3Sopenharmony_ci   STBI_FREE(orig);
1201cc1dc7a3Sopenharmony_ci   return reduced;
1202cc1dc7a3Sopenharmony_ci}
1203cc1dc7a3Sopenharmony_ci
1204cc1dc7a3Sopenharmony_cistatic stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels)
1205cc1dc7a3Sopenharmony_ci{
1206cc1dc7a3Sopenharmony_ci   int i;
1207cc1dc7a3Sopenharmony_ci   int img_len = w * h * channels;
1208cc1dc7a3Sopenharmony_ci   stbi__uint16 *enlarged;
1209cc1dc7a3Sopenharmony_ci
1210cc1dc7a3Sopenharmony_ci   enlarged = (stbi__uint16 *) stbi__malloc(img_len*2);
1211cc1dc7a3Sopenharmony_ci   if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
1212cc1dc7a3Sopenharmony_ci
1213cc1dc7a3Sopenharmony_ci   for (i = 0; i < img_len; ++i)
1214cc1dc7a3Sopenharmony_ci      enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff
1215cc1dc7a3Sopenharmony_ci
1216cc1dc7a3Sopenharmony_ci   STBI_FREE(orig);
1217cc1dc7a3Sopenharmony_ci   return enlarged;
1218cc1dc7a3Sopenharmony_ci}
1219cc1dc7a3Sopenharmony_ci
1220cc1dc7a3Sopenharmony_cistatic void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel)
1221cc1dc7a3Sopenharmony_ci{
1222cc1dc7a3Sopenharmony_ci   int row;
1223cc1dc7a3Sopenharmony_ci   size_t bytes_per_row = (size_t)w * bytes_per_pixel;
1224cc1dc7a3Sopenharmony_ci   stbi_uc temp[2048];
1225cc1dc7a3Sopenharmony_ci   stbi_uc *bytes = (stbi_uc *)image;
1226cc1dc7a3Sopenharmony_ci
1227cc1dc7a3Sopenharmony_ci   for (row = 0; row < (h>>1); row++) {
1228cc1dc7a3Sopenharmony_ci      stbi_uc *row0 = bytes + row*bytes_per_row;
1229cc1dc7a3Sopenharmony_ci      stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row;
1230cc1dc7a3Sopenharmony_ci      // swap row0 with row1
1231cc1dc7a3Sopenharmony_ci      size_t bytes_left = bytes_per_row;
1232cc1dc7a3Sopenharmony_ci      while (bytes_left) {
1233cc1dc7a3Sopenharmony_ci         size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp);
1234cc1dc7a3Sopenharmony_ci         memcpy(temp, row0, bytes_copy);
1235cc1dc7a3Sopenharmony_ci         memcpy(row0, row1, bytes_copy);
1236cc1dc7a3Sopenharmony_ci         memcpy(row1, temp, bytes_copy);
1237cc1dc7a3Sopenharmony_ci         row0 += bytes_copy;
1238cc1dc7a3Sopenharmony_ci         row1 += bytes_copy;
1239cc1dc7a3Sopenharmony_ci         bytes_left -= bytes_copy;
1240cc1dc7a3Sopenharmony_ci      }
1241cc1dc7a3Sopenharmony_ci   }
1242cc1dc7a3Sopenharmony_ci}
1243cc1dc7a3Sopenharmony_ci
1244cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_GIF
1245cc1dc7a3Sopenharmony_cistatic void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel)
1246cc1dc7a3Sopenharmony_ci{
1247cc1dc7a3Sopenharmony_ci   int slice;
1248cc1dc7a3Sopenharmony_ci   int slice_size = w * h * bytes_per_pixel;
1249cc1dc7a3Sopenharmony_ci
1250cc1dc7a3Sopenharmony_ci   stbi_uc *bytes = (stbi_uc *)image;
1251cc1dc7a3Sopenharmony_ci   for (slice = 0; slice < z; ++slice) {
1252cc1dc7a3Sopenharmony_ci      stbi__vertical_flip(bytes, w, h, bytes_per_pixel);
1253cc1dc7a3Sopenharmony_ci      bytes += slice_size;
1254cc1dc7a3Sopenharmony_ci   }
1255cc1dc7a3Sopenharmony_ci}
1256cc1dc7a3Sopenharmony_ci#endif
1257cc1dc7a3Sopenharmony_ci
1258cc1dc7a3Sopenharmony_cistatic unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
1259cc1dc7a3Sopenharmony_ci{
1260cc1dc7a3Sopenharmony_ci   stbi__result_info ri;
1261cc1dc7a3Sopenharmony_ci   void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8);
1262cc1dc7a3Sopenharmony_ci
1263cc1dc7a3Sopenharmony_ci   if (result == NULL)
1264cc1dc7a3Sopenharmony_ci      return NULL;
1265cc1dc7a3Sopenharmony_ci
1266cc1dc7a3Sopenharmony_ci   // it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
1267cc1dc7a3Sopenharmony_ci   STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
1268cc1dc7a3Sopenharmony_ci
1269cc1dc7a3Sopenharmony_ci   if (ri.bits_per_channel != 8) {
1270cc1dc7a3Sopenharmony_ci      result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
1271cc1dc7a3Sopenharmony_ci      ri.bits_per_channel = 8;
1272cc1dc7a3Sopenharmony_ci   }
1273cc1dc7a3Sopenharmony_ci
1274cc1dc7a3Sopenharmony_ci   // @TODO: move stbi__convert_format to here
1275cc1dc7a3Sopenharmony_ci
1276cc1dc7a3Sopenharmony_ci   if (stbi__vertically_flip_on_load) {
1277cc1dc7a3Sopenharmony_ci      int channels = req_comp ? req_comp : *comp;
1278cc1dc7a3Sopenharmony_ci      stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc));
1279cc1dc7a3Sopenharmony_ci   }
1280cc1dc7a3Sopenharmony_ci
1281cc1dc7a3Sopenharmony_ci   return (unsigned char *) result;
1282cc1dc7a3Sopenharmony_ci}
1283cc1dc7a3Sopenharmony_ci
1284cc1dc7a3Sopenharmony_cistatic stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
1285cc1dc7a3Sopenharmony_ci{
1286cc1dc7a3Sopenharmony_ci   stbi__result_info ri;
1287cc1dc7a3Sopenharmony_ci   void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16);
1288cc1dc7a3Sopenharmony_ci
1289cc1dc7a3Sopenharmony_ci   if (result == NULL)
1290cc1dc7a3Sopenharmony_ci      return NULL;
1291cc1dc7a3Sopenharmony_ci
1292cc1dc7a3Sopenharmony_ci   // it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
1293cc1dc7a3Sopenharmony_ci   STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
1294cc1dc7a3Sopenharmony_ci
1295cc1dc7a3Sopenharmony_ci   if (ri.bits_per_channel != 16) {
1296cc1dc7a3Sopenharmony_ci      result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
1297cc1dc7a3Sopenharmony_ci      ri.bits_per_channel = 16;
1298cc1dc7a3Sopenharmony_ci   }
1299cc1dc7a3Sopenharmony_ci
1300cc1dc7a3Sopenharmony_ci   // @TODO: move stbi__convert_format16 to here
1301cc1dc7a3Sopenharmony_ci   // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision
1302cc1dc7a3Sopenharmony_ci
1303cc1dc7a3Sopenharmony_ci   if (stbi__vertically_flip_on_load) {
1304cc1dc7a3Sopenharmony_ci      int channels = req_comp ? req_comp : *comp;
1305cc1dc7a3Sopenharmony_ci      stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16));
1306cc1dc7a3Sopenharmony_ci   }
1307cc1dc7a3Sopenharmony_ci
1308cc1dc7a3Sopenharmony_ci   return (stbi__uint16 *) result;
1309cc1dc7a3Sopenharmony_ci}
1310cc1dc7a3Sopenharmony_ci
1311cc1dc7a3Sopenharmony_ci#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR)
1312cc1dc7a3Sopenharmony_cistatic void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp)
1313cc1dc7a3Sopenharmony_ci{
1314cc1dc7a3Sopenharmony_ci   if (stbi__vertically_flip_on_load && result != NULL) {
1315cc1dc7a3Sopenharmony_ci      int channels = req_comp ? req_comp : *comp;
1316cc1dc7a3Sopenharmony_ci      stbi__vertical_flip(result, *x, *y, channels * sizeof(float));
1317cc1dc7a3Sopenharmony_ci   }
1318cc1dc7a3Sopenharmony_ci}
1319cc1dc7a3Sopenharmony_ci#endif
1320cc1dc7a3Sopenharmony_ci
1321cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_STDIO
1322cc1dc7a3Sopenharmony_ci
1323cc1dc7a3Sopenharmony_ci#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)
1324cc1dc7a3Sopenharmony_ciSTBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
1325cc1dc7a3Sopenharmony_ciSTBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default);
1326cc1dc7a3Sopenharmony_ci#endif
1327cc1dc7a3Sopenharmony_ci
1328cc1dc7a3Sopenharmony_ci#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)
1329cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
1330cc1dc7a3Sopenharmony_ci{
1331cc1dc7a3Sopenharmony_ci	return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
1332cc1dc7a3Sopenharmony_ci}
1333cc1dc7a3Sopenharmony_ci#endif
1334cc1dc7a3Sopenharmony_ci
1335cc1dc7a3Sopenharmony_cistatic FILE *stbi__fopen(char const *filename, char const *mode)
1336cc1dc7a3Sopenharmony_ci{
1337cc1dc7a3Sopenharmony_ci   FILE *f;
1338cc1dc7a3Sopenharmony_ci#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)
1339cc1dc7a3Sopenharmony_ci   wchar_t wMode[64];
1340cc1dc7a3Sopenharmony_ci   wchar_t wFilename[1024];
1341cc1dc7a3Sopenharmony_ci	if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))
1342cc1dc7a3Sopenharmony_ci      return 0;
1343cc1dc7a3Sopenharmony_ci
1344cc1dc7a3Sopenharmony_ci	if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))
1345cc1dc7a3Sopenharmony_ci      return 0;
1346cc1dc7a3Sopenharmony_ci
1347cc1dc7a3Sopenharmony_ci#if defined(_MSC_VER) && _MSC_VER >= 1400
1348cc1dc7a3Sopenharmony_ci	if (0 != _wfopen_s(&f, wFilename, wMode))
1349cc1dc7a3Sopenharmony_ci		f = 0;
1350cc1dc7a3Sopenharmony_ci#else
1351cc1dc7a3Sopenharmony_ci   f = _wfopen(wFilename, wMode);
1352cc1dc7a3Sopenharmony_ci#endif
1353cc1dc7a3Sopenharmony_ci
1354cc1dc7a3Sopenharmony_ci#elif defined(_MSC_VER) && _MSC_VER >= 1400
1355cc1dc7a3Sopenharmony_ci   if (0 != fopen_s(&f, filename, mode))
1356cc1dc7a3Sopenharmony_ci      f=0;
1357cc1dc7a3Sopenharmony_ci#else
1358cc1dc7a3Sopenharmony_ci   f = fopen(filename, mode);
1359cc1dc7a3Sopenharmony_ci#endif
1360cc1dc7a3Sopenharmony_ci   return f;
1361cc1dc7a3Sopenharmony_ci}
1362cc1dc7a3Sopenharmony_ci
1363cc1dc7a3Sopenharmony_ci
1364cc1dc7a3Sopenharmony_ciSTBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp)
1365cc1dc7a3Sopenharmony_ci{
1366cc1dc7a3Sopenharmony_ci   FILE *f = stbi__fopen(filename, "rb");
1367cc1dc7a3Sopenharmony_ci   unsigned char *result;
1368cc1dc7a3Sopenharmony_ci   if (!f) return stbi__errpuc("can't fopen", "Unable to open file");
1369cc1dc7a3Sopenharmony_ci   result = stbi_load_from_file(f,x,y,comp,req_comp);
1370cc1dc7a3Sopenharmony_ci   fclose(f);
1371cc1dc7a3Sopenharmony_ci   return result;
1372cc1dc7a3Sopenharmony_ci}
1373cc1dc7a3Sopenharmony_ci
1374cc1dc7a3Sopenharmony_ciSTBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
1375cc1dc7a3Sopenharmony_ci{
1376cc1dc7a3Sopenharmony_ci   unsigned char *result;
1377cc1dc7a3Sopenharmony_ci   stbi__context s;
1378cc1dc7a3Sopenharmony_ci   stbi__start_file(&s,f);
1379cc1dc7a3Sopenharmony_ci   result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
1380cc1dc7a3Sopenharmony_ci   if (result) {
1381cc1dc7a3Sopenharmony_ci      // need to 'unget' all the characters in the IO buffer
1382cc1dc7a3Sopenharmony_ci      fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
1383cc1dc7a3Sopenharmony_ci   }
1384cc1dc7a3Sopenharmony_ci   return result;
1385cc1dc7a3Sopenharmony_ci}
1386cc1dc7a3Sopenharmony_ci
1387cc1dc7a3Sopenharmony_ciSTBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp)
1388cc1dc7a3Sopenharmony_ci{
1389cc1dc7a3Sopenharmony_ci   stbi__uint16 *result;
1390cc1dc7a3Sopenharmony_ci   stbi__context s;
1391cc1dc7a3Sopenharmony_ci   stbi__start_file(&s,f);
1392cc1dc7a3Sopenharmony_ci   result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp);
1393cc1dc7a3Sopenharmony_ci   if (result) {
1394cc1dc7a3Sopenharmony_ci      // need to 'unget' all the characters in the IO buffer
1395cc1dc7a3Sopenharmony_ci      fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
1396cc1dc7a3Sopenharmony_ci   }
1397cc1dc7a3Sopenharmony_ci   return result;
1398cc1dc7a3Sopenharmony_ci}
1399cc1dc7a3Sopenharmony_ci
1400cc1dc7a3Sopenharmony_ciSTBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp)
1401cc1dc7a3Sopenharmony_ci{
1402cc1dc7a3Sopenharmony_ci   FILE *f = stbi__fopen(filename, "rb");
1403cc1dc7a3Sopenharmony_ci   stbi__uint16 *result;
1404cc1dc7a3Sopenharmony_ci   if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file");
1405cc1dc7a3Sopenharmony_ci   result = stbi_load_from_file_16(f,x,y,comp,req_comp);
1406cc1dc7a3Sopenharmony_ci   fclose(f);
1407cc1dc7a3Sopenharmony_ci   return result;
1408cc1dc7a3Sopenharmony_ci}
1409cc1dc7a3Sopenharmony_ci
1410cc1dc7a3Sopenharmony_ci
1411cc1dc7a3Sopenharmony_ci#endif //!STBI_NO_STDIO
1412cc1dc7a3Sopenharmony_ci
1413cc1dc7a3Sopenharmony_ciSTBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels)
1414cc1dc7a3Sopenharmony_ci{
1415cc1dc7a3Sopenharmony_ci   stbi__context s;
1416cc1dc7a3Sopenharmony_ci   stbi__start_mem(&s,buffer,len);
1417cc1dc7a3Sopenharmony_ci   return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
1418cc1dc7a3Sopenharmony_ci}
1419cc1dc7a3Sopenharmony_ci
1420cc1dc7a3Sopenharmony_ciSTBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels)
1421cc1dc7a3Sopenharmony_ci{
1422cc1dc7a3Sopenharmony_ci   stbi__context s;
1423cc1dc7a3Sopenharmony_ci   stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
1424cc1dc7a3Sopenharmony_ci   return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
1425cc1dc7a3Sopenharmony_ci}
1426cc1dc7a3Sopenharmony_ci
1427cc1dc7a3Sopenharmony_ciSTBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
1428cc1dc7a3Sopenharmony_ci{
1429cc1dc7a3Sopenharmony_ci   stbi__context s;
1430cc1dc7a3Sopenharmony_ci   stbi__start_mem(&s,buffer,len);
1431cc1dc7a3Sopenharmony_ci   return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
1432cc1dc7a3Sopenharmony_ci}
1433cc1dc7a3Sopenharmony_ci
1434cc1dc7a3Sopenharmony_ciSTBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
1435cc1dc7a3Sopenharmony_ci{
1436cc1dc7a3Sopenharmony_ci   stbi__context s;
1437cc1dc7a3Sopenharmony_ci   stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
1438cc1dc7a3Sopenharmony_ci   return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
1439cc1dc7a3Sopenharmony_ci}
1440cc1dc7a3Sopenharmony_ci
1441cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_GIF
1442cc1dc7a3Sopenharmony_ciSTBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
1443cc1dc7a3Sopenharmony_ci{
1444cc1dc7a3Sopenharmony_ci   unsigned char *result;
1445cc1dc7a3Sopenharmony_ci   stbi__context s;
1446cc1dc7a3Sopenharmony_ci   stbi__start_mem(&s,buffer,len);
1447cc1dc7a3Sopenharmony_ci
1448cc1dc7a3Sopenharmony_ci   result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp);
1449cc1dc7a3Sopenharmony_ci   if (stbi__vertically_flip_on_load && result) {
1450cc1dc7a3Sopenharmony_ci      stbi__vertical_flip_slices( result, *x, *y, *z, *comp );
1451cc1dc7a3Sopenharmony_ci   }
1452cc1dc7a3Sopenharmony_ci
1453cc1dc7a3Sopenharmony_ci   return result;
1454cc1dc7a3Sopenharmony_ci}
1455cc1dc7a3Sopenharmony_ci#endif
1456cc1dc7a3Sopenharmony_ci
1457cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_LINEAR
1458cc1dc7a3Sopenharmony_cistatic float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
1459cc1dc7a3Sopenharmony_ci{
1460cc1dc7a3Sopenharmony_ci   unsigned char *data;
1461cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_HDR
1462cc1dc7a3Sopenharmony_ci   if (stbi__hdr_test(s)) {
1463cc1dc7a3Sopenharmony_ci      stbi__result_info ri;
1464cc1dc7a3Sopenharmony_ci      float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri);
1465cc1dc7a3Sopenharmony_ci      if (hdr_data)
1466cc1dc7a3Sopenharmony_ci         stbi__float_postprocess(hdr_data,x,y,comp,req_comp);
1467cc1dc7a3Sopenharmony_ci      return hdr_data;
1468cc1dc7a3Sopenharmony_ci   }
1469cc1dc7a3Sopenharmony_ci   #endif
1470cc1dc7a3Sopenharmony_ci   data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp);
1471cc1dc7a3Sopenharmony_ci   if (data)
1472cc1dc7a3Sopenharmony_ci      return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
1473cc1dc7a3Sopenharmony_ci   return stbi__errpf("unknown image type", "Image not of any known type, or corrupt");
1474cc1dc7a3Sopenharmony_ci}
1475cc1dc7a3Sopenharmony_ci
1476cc1dc7a3Sopenharmony_ciSTBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
1477cc1dc7a3Sopenharmony_ci{
1478cc1dc7a3Sopenharmony_ci   stbi__context s;
1479cc1dc7a3Sopenharmony_ci   stbi__start_mem(&s,buffer,len);
1480cc1dc7a3Sopenharmony_ci   return stbi__loadf_main(&s,x,y,comp,req_comp);
1481cc1dc7a3Sopenharmony_ci}
1482cc1dc7a3Sopenharmony_ci
1483cc1dc7a3Sopenharmony_ciSTBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
1484cc1dc7a3Sopenharmony_ci{
1485cc1dc7a3Sopenharmony_ci   stbi__context s;
1486cc1dc7a3Sopenharmony_ci   stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
1487cc1dc7a3Sopenharmony_ci   return stbi__loadf_main(&s,x,y,comp,req_comp);
1488cc1dc7a3Sopenharmony_ci}
1489cc1dc7a3Sopenharmony_ci
1490cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_STDIO
1491cc1dc7a3Sopenharmony_ciSTBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp)
1492cc1dc7a3Sopenharmony_ci{
1493cc1dc7a3Sopenharmony_ci   float *result;
1494cc1dc7a3Sopenharmony_ci   FILE *f = stbi__fopen(filename, "rb");
1495cc1dc7a3Sopenharmony_ci   if (!f) return stbi__errpf("can't fopen", "Unable to open file");
1496cc1dc7a3Sopenharmony_ci   result = stbi_loadf_from_file(f,x,y,comp,req_comp);
1497cc1dc7a3Sopenharmony_ci   fclose(f);
1498cc1dc7a3Sopenharmony_ci   return result;
1499cc1dc7a3Sopenharmony_ci}
1500cc1dc7a3Sopenharmony_ci
1501cc1dc7a3Sopenharmony_ciSTBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
1502cc1dc7a3Sopenharmony_ci{
1503cc1dc7a3Sopenharmony_ci   stbi__context s;
1504cc1dc7a3Sopenharmony_ci   stbi__start_file(&s,f);
1505cc1dc7a3Sopenharmony_ci   return stbi__loadf_main(&s,x,y,comp,req_comp);
1506cc1dc7a3Sopenharmony_ci}
1507cc1dc7a3Sopenharmony_ci#endif // !STBI_NO_STDIO
1508cc1dc7a3Sopenharmony_ci
1509cc1dc7a3Sopenharmony_ci#endif // !STBI_NO_LINEAR
1510cc1dc7a3Sopenharmony_ci
1511cc1dc7a3Sopenharmony_ci// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is
1512cc1dc7a3Sopenharmony_ci// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always
1513cc1dc7a3Sopenharmony_ci// reports false!
1514cc1dc7a3Sopenharmony_ci
1515cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len)
1516cc1dc7a3Sopenharmony_ci{
1517cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_HDR
1518cc1dc7a3Sopenharmony_ci   stbi__context s;
1519cc1dc7a3Sopenharmony_ci   stbi__start_mem(&s,buffer,len);
1520cc1dc7a3Sopenharmony_ci   return stbi__hdr_test(&s);
1521cc1dc7a3Sopenharmony_ci   #else
1522cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(buffer);
1523cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(len);
1524cc1dc7a3Sopenharmony_ci   return 0;
1525cc1dc7a3Sopenharmony_ci   #endif
1526cc1dc7a3Sopenharmony_ci}
1527cc1dc7a3Sopenharmony_ci
1528cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_STDIO
1529cc1dc7a3Sopenharmony_ciSTBIDEF int      stbi_is_hdr          (char const *filename)
1530cc1dc7a3Sopenharmony_ci{
1531cc1dc7a3Sopenharmony_ci   FILE *f = stbi__fopen(filename, "rb");
1532cc1dc7a3Sopenharmony_ci   int result=0;
1533cc1dc7a3Sopenharmony_ci   if (f) {
1534cc1dc7a3Sopenharmony_ci      result = stbi_is_hdr_from_file(f);
1535cc1dc7a3Sopenharmony_ci      fclose(f);
1536cc1dc7a3Sopenharmony_ci   }
1537cc1dc7a3Sopenharmony_ci   return result;
1538cc1dc7a3Sopenharmony_ci}
1539cc1dc7a3Sopenharmony_ci
1540cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_is_hdr_from_file(FILE *f)
1541cc1dc7a3Sopenharmony_ci{
1542cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_HDR
1543cc1dc7a3Sopenharmony_ci   long pos = ftell(f);
1544cc1dc7a3Sopenharmony_ci   int res;
1545cc1dc7a3Sopenharmony_ci   stbi__context s;
1546cc1dc7a3Sopenharmony_ci   stbi__start_file(&s,f);
1547cc1dc7a3Sopenharmony_ci   res = stbi__hdr_test(&s);
1548cc1dc7a3Sopenharmony_ci   fseek(f, pos, SEEK_SET);
1549cc1dc7a3Sopenharmony_ci   return res;
1550cc1dc7a3Sopenharmony_ci   #else
1551cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(f);
1552cc1dc7a3Sopenharmony_ci   return 0;
1553cc1dc7a3Sopenharmony_ci   #endif
1554cc1dc7a3Sopenharmony_ci}
1555cc1dc7a3Sopenharmony_ci#endif // !STBI_NO_STDIO
1556cc1dc7a3Sopenharmony_ci
1557cc1dc7a3Sopenharmony_ciSTBIDEF int      stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user)
1558cc1dc7a3Sopenharmony_ci{
1559cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_HDR
1560cc1dc7a3Sopenharmony_ci   stbi__context s;
1561cc1dc7a3Sopenharmony_ci   stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
1562cc1dc7a3Sopenharmony_ci   return stbi__hdr_test(&s);
1563cc1dc7a3Sopenharmony_ci   #else
1564cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(clbk);
1565cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(user);
1566cc1dc7a3Sopenharmony_ci   return 0;
1567cc1dc7a3Sopenharmony_ci   #endif
1568cc1dc7a3Sopenharmony_ci}
1569cc1dc7a3Sopenharmony_ci
1570cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_LINEAR
1571cc1dc7a3Sopenharmony_cistatic float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f;
1572cc1dc7a3Sopenharmony_ci
1573cc1dc7a3Sopenharmony_ciSTBIDEF void   stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; }
1574cc1dc7a3Sopenharmony_ciSTBIDEF void   stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; }
1575cc1dc7a3Sopenharmony_ci#endif
1576cc1dc7a3Sopenharmony_ci
1577cc1dc7a3Sopenharmony_cistatic float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f;
1578cc1dc7a3Sopenharmony_ci
1579cc1dc7a3Sopenharmony_ciSTBIDEF void   stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; }
1580cc1dc7a3Sopenharmony_ciSTBIDEF void   stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; }
1581cc1dc7a3Sopenharmony_ci
1582cc1dc7a3Sopenharmony_ci
1583cc1dc7a3Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////
1584cc1dc7a3Sopenharmony_ci//
1585cc1dc7a3Sopenharmony_ci// Common code used by all image loaders
1586cc1dc7a3Sopenharmony_ci//
1587cc1dc7a3Sopenharmony_ci
1588cc1dc7a3Sopenharmony_cienum
1589cc1dc7a3Sopenharmony_ci{
1590cc1dc7a3Sopenharmony_ci   STBI__SCAN_load=0,
1591cc1dc7a3Sopenharmony_ci   STBI__SCAN_type,
1592cc1dc7a3Sopenharmony_ci   STBI__SCAN_header
1593cc1dc7a3Sopenharmony_ci};
1594cc1dc7a3Sopenharmony_ci
1595cc1dc7a3Sopenharmony_cistatic void stbi__refill_buffer(stbi__context *s)
1596cc1dc7a3Sopenharmony_ci{
1597cc1dc7a3Sopenharmony_ci   int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen);
1598cc1dc7a3Sopenharmony_ci   s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original);
1599cc1dc7a3Sopenharmony_ci   if (n == 0) {
1600cc1dc7a3Sopenharmony_ci      // at end of file, treat same as if from memory, but need to handle case
1601cc1dc7a3Sopenharmony_ci      // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file
1602cc1dc7a3Sopenharmony_ci      s->read_from_callbacks = 0;
1603cc1dc7a3Sopenharmony_ci      s->img_buffer = s->buffer_start;
1604cc1dc7a3Sopenharmony_ci      s->img_buffer_end = s->buffer_start+1;
1605cc1dc7a3Sopenharmony_ci      *s->img_buffer = 0;
1606cc1dc7a3Sopenharmony_ci   } else {
1607cc1dc7a3Sopenharmony_ci      s->img_buffer = s->buffer_start;
1608cc1dc7a3Sopenharmony_ci      s->img_buffer_end = s->buffer_start + n;
1609cc1dc7a3Sopenharmony_ci   }
1610cc1dc7a3Sopenharmony_ci}
1611cc1dc7a3Sopenharmony_ci
1612cc1dc7a3Sopenharmony_cistbi_inline static stbi_uc stbi__get8(stbi__context *s)
1613cc1dc7a3Sopenharmony_ci{
1614cc1dc7a3Sopenharmony_ci   if (s->img_buffer < s->img_buffer_end)
1615cc1dc7a3Sopenharmony_ci      return *s->img_buffer++;
1616cc1dc7a3Sopenharmony_ci   if (s->read_from_callbacks) {
1617cc1dc7a3Sopenharmony_ci      stbi__refill_buffer(s);
1618cc1dc7a3Sopenharmony_ci      return *s->img_buffer++;
1619cc1dc7a3Sopenharmony_ci   }
1620cc1dc7a3Sopenharmony_ci   return 0;
1621cc1dc7a3Sopenharmony_ci}
1622cc1dc7a3Sopenharmony_ci
1623cc1dc7a3Sopenharmony_ci#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
1624cc1dc7a3Sopenharmony_ci// nothing
1625cc1dc7a3Sopenharmony_ci#else
1626cc1dc7a3Sopenharmony_cistbi_inline static int stbi__at_eof(stbi__context *s)
1627cc1dc7a3Sopenharmony_ci{
1628cc1dc7a3Sopenharmony_ci   if (s->io.read) {
1629cc1dc7a3Sopenharmony_ci      if (!(s->io.eof)(s->io_user_data)) return 0;
1630cc1dc7a3Sopenharmony_ci      // if feof() is true, check if buffer = end
1631cc1dc7a3Sopenharmony_ci      // special case: we've only got the special 0 character at the end
1632cc1dc7a3Sopenharmony_ci      if (s->read_from_callbacks == 0) return 1;
1633cc1dc7a3Sopenharmony_ci   }
1634cc1dc7a3Sopenharmony_ci
1635cc1dc7a3Sopenharmony_ci   return s->img_buffer >= s->img_buffer_end;
1636cc1dc7a3Sopenharmony_ci}
1637cc1dc7a3Sopenharmony_ci#endif
1638cc1dc7a3Sopenharmony_ci
1639cc1dc7a3Sopenharmony_ci#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC)
1640cc1dc7a3Sopenharmony_ci// nothing
1641cc1dc7a3Sopenharmony_ci#else
1642cc1dc7a3Sopenharmony_cistatic void stbi__skip(stbi__context *s, int n)
1643cc1dc7a3Sopenharmony_ci{
1644cc1dc7a3Sopenharmony_ci   if (n == 0) return;  // already there!
1645cc1dc7a3Sopenharmony_ci   if (n < 0) {
1646cc1dc7a3Sopenharmony_ci      s->img_buffer = s->img_buffer_end;
1647cc1dc7a3Sopenharmony_ci      return;
1648cc1dc7a3Sopenharmony_ci   }
1649cc1dc7a3Sopenharmony_ci   if (s->io.read) {
1650cc1dc7a3Sopenharmony_ci      int blen = (int) (s->img_buffer_end - s->img_buffer);
1651cc1dc7a3Sopenharmony_ci      if (blen < n) {
1652cc1dc7a3Sopenharmony_ci         s->img_buffer = s->img_buffer_end;
1653cc1dc7a3Sopenharmony_ci         (s->io.skip)(s->io_user_data, n - blen);
1654cc1dc7a3Sopenharmony_ci         return;
1655cc1dc7a3Sopenharmony_ci      }
1656cc1dc7a3Sopenharmony_ci   }
1657cc1dc7a3Sopenharmony_ci   s->img_buffer += n;
1658cc1dc7a3Sopenharmony_ci}
1659cc1dc7a3Sopenharmony_ci#endif
1660cc1dc7a3Sopenharmony_ci
1661cc1dc7a3Sopenharmony_ci#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM)
1662cc1dc7a3Sopenharmony_ci// nothing
1663cc1dc7a3Sopenharmony_ci#else
1664cc1dc7a3Sopenharmony_cistatic int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)
1665cc1dc7a3Sopenharmony_ci{
1666cc1dc7a3Sopenharmony_ci   if (s->io.read) {
1667cc1dc7a3Sopenharmony_ci      int blen = (int) (s->img_buffer_end - s->img_buffer);
1668cc1dc7a3Sopenharmony_ci      if (blen < n) {
1669cc1dc7a3Sopenharmony_ci         int res, count;
1670cc1dc7a3Sopenharmony_ci
1671cc1dc7a3Sopenharmony_ci         memcpy(buffer, s->img_buffer, blen);
1672cc1dc7a3Sopenharmony_ci
1673cc1dc7a3Sopenharmony_ci         count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen);
1674cc1dc7a3Sopenharmony_ci         res = (count == (n-blen));
1675cc1dc7a3Sopenharmony_ci         s->img_buffer = s->img_buffer_end;
1676cc1dc7a3Sopenharmony_ci         return res;
1677cc1dc7a3Sopenharmony_ci      }
1678cc1dc7a3Sopenharmony_ci   }
1679cc1dc7a3Sopenharmony_ci
1680cc1dc7a3Sopenharmony_ci   if (s->img_buffer+n <= s->img_buffer_end) {
1681cc1dc7a3Sopenharmony_ci      memcpy(buffer, s->img_buffer, n);
1682cc1dc7a3Sopenharmony_ci      s->img_buffer += n;
1683cc1dc7a3Sopenharmony_ci      return 1;
1684cc1dc7a3Sopenharmony_ci   } else
1685cc1dc7a3Sopenharmony_ci      return 0;
1686cc1dc7a3Sopenharmony_ci}
1687cc1dc7a3Sopenharmony_ci#endif
1688cc1dc7a3Sopenharmony_ci
1689cc1dc7a3Sopenharmony_ci#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)
1690cc1dc7a3Sopenharmony_ci// nothing
1691cc1dc7a3Sopenharmony_ci#else
1692cc1dc7a3Sopenharmony_cistatic int stbi__get16be(stbi__context *s)
1693cc1dc7a3Sopenharmony_ci{
1694cc1dc7a3Sopenharmony_ci   int z = stbi__get8(s);
1695cc1dc7a3Sopenharmony_ci   return (z << 8) + stbi__get8(s);
1696cc1dc7a3Sopenharmony_ci}
1697cc1dc7a3Sopenharmony_ci#endif
1698cc1dc7a3Sopenharmony_ci
1699cc1dc7a3Sopenharmony_ci#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)
1700cc1dc7a3Sopenharmony_ci// nothing
1701cc1dc7a3Sopenharmony_ci#else
1702cc1dc7a3Sopenharmony_cistatic stbi__uint32 stbi__get32be(stbi__context *s)
1703cc1dc7a3Sopenharmony_ci{
1704cc1dc7a3Sopenharmony_ci   stbi__uint32 z = stbi__get16be(s);
1705cc1dc7a3Sopenharmony_ci   return (z << 16) + stbi__get16be(s);
1706cc1dc7a3Sopenharmony_ci}
1707cc1dc7a3Sopenharmony_ci#endif
1708cc1dc7a3Sopenharmony_ci
1709cc1dc7a3Sopenharmony_ci#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF)
1710cc1dc7a3Sopenharmony_ci// nothing
1711cc1dc7a3Sopenharmony_ci#else
1712cc1dc7a3Sopenharmony_cistatic int stbi__get16le(stbi__context *s)
1713cc1dc7a3Sopenharmony_ci{
1714cc1dc7a3Sopenharmony_ci   int z = stbi__get8(s);
1715cc1dc7a3Sopenharmony_ci   return z + (stbi__get8(s) << 8);
1716cc1dc7a3Sopenharmony_ci}
1717cc1dc7a3Sopenharmony_ci#endif
1718cc1dc7a3Sopenharmony_ci
1719cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_BMP
1720cc1dc7a3Sopenharmony_cistatic stbi__uint32 stbi__get32le(stbi__context *s)
1721cc1dc7a3Sopenharmony_ci{
1722cc1dc7a3Sopenharmony_ci   stbi__uint32 z = stbi__get16le(s);
1723cc1dc7a3Sopenharmony_ci   z += (stbi__uint32)stbi__get16le(s) << 16;
1724cc1dc7a3Sopenharmony_ci   return z;
1725cc1dc7a3Sopenharmony_ci}
1726cc1dc7a3Sopenharmony_ci#endif
1727cc1dc7a3Sopenharmony_ci
1728cc1dc7a3Sopenharmony_ci#define STBI__BYTECAST(x)  ((stbi_uc) ((x) & 255))  // truncate int to byte without warnings
1729cc1dc7a3Sopenharmony_ci
1730cc1dc7a3Sopenharmony_ci#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
1731cc1dc7a3Sopenharmony_ci// nothing
1732cc1dc7a3Sopenharmony_ci#else
1733cc1dc7a3Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////
1734cc1dc7a3Sopenharmony_ci//
1735cc1dc7a3Sopenharmony_ci//  generic converter from built-in img_n to req_comp
1736cc1dc7a3Sopenharmony_ci//    individual types do this automatically as much as possible (e.g. jpeg
1737cc1dc7a3Sopenharmony_ci//    does all cases internally since it needs to colorspace convert anyway,
1738cc1dc7a3Sopenharmony_ci//    and it never has alpha, so very few cases ). png can automatically
1739cc1dc7a3Sopenharmony_ci//    interleave an alpha=255 channel, but falls back to this for other cases
1740cc1dc7a3Sopenharmony_ci//
1741cc1dc7a3Sopenharmony_ci//  assume data buffer is malloced, so malloc a new one and free that one
1742cc1dc7a3Sopenharmony_ci//  only failure mode is malloc failing
1743cc1dc7a3Sopenharmony_ci
1744cc1dc7a3Sopenharmony_cistatic stbi_uc stbi__compute_y(int r, int g, int b)
1745cc1dc7a3Sopenharmony_ci{
1746cc1dc7a3Sopenharmony_ci   return (stbi_uc) (((r*77) + (g*150) +  (29*b)) >> 8);
1747cc1dc7a3Sopenharmony_ci}
1748cc1dc7a3Sopenharmony_ci#endif
1749cc1dc7a3Sopenharmony_ci
1750cc1dc7a3Sopenharmony_ci#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
1751cc1dc7a3Sopenharmony_ci// nothing
1752cc1dc7a3Sopenharmony_ci#else
1753cc1dc7a3Sopenharmony_cistatic unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y)
1754cc1dc7a3Sopenharmony_ci{
1755cc1dc7a3Sopenharmony_ci   int i,j;
1756cc1dc7a3Sopenharmony_ci   unsigned char *good;
1757cc1dc7a3Sopenharmony_ci
1758cc1dc7a3Sopenharmony_ci   if (req_comp == img_n) return data;
1759cc1dc7a3Sopenharmony_ci   STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
1760cc1dc7a3Sopenharmony_ci
1761cc1dc7a3Sopenharmony_ci   good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0);
1762cc1dc7a3Sopenharmony_ci   if (good == NULL) {
1763cc1dc7a3Sopenharmony_ci      STBI_FREE(data);
1764cc1dc7a3Sopenharmony_ci      return stbi__errpuc("outofmem", "Out of memory");
1765cc1dc7a3Sopenharmony_ci   }
1766cc1dc7a3Sopenharmony_ci
1767cc1dc7a3Sopenharmony_ci   for (j=0; j < (int) y; ++j) {
1768cc1dc7a3Sopenharmony_ci      unsigned char *src  = data + j * x * img_n   ;
1769cc1dc7a3Sopenharmony_ci      unsigned char *dest = good + j * x * req_comp;
1770cc1dc7a3Sopenharmony_ci
1771cc1dc7a3Sopenharmony_ci      #define STBI__COMBO(a,b)  ((a)*8+(b))
1772cc1dc7a3Sopenharmony_ci      #define STBI__CASE(a,b)   case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
1773cc1dc7a3Sopenharmony_ci      // convert source image with img_n components to one with req_comp components;
1774cc1dc7a3Sopenharmony_ci      // avoid switch per pixel, so use switch per scanline and massive macros
1775cc1dc7a3Sopenharmony_ci      switch (STBI__COMBO(img_n, req_comp)) {
1776cc1dc7a3Sopenharmony_ci         STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255;                                     } break;
1777cc1dc7a3Sopenharmony_ci         STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0];                                  } break;
1778cc1dc7a3Sopenharmony_ci         STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255;                     } break;
1779cc1dc7a3Sopenharmony_ci         STBI__CASE(2,1) { dest[0]=src[0];                                                  } break;
1780cc1dc7a3Sopenharmony_ci         STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0];                                  } break;
1781cc1dc7a3Sopenharmony_ci         STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1];                  } break;
1782cc1dc7a3Sopenharmony_ci         STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255;        } break;
1783cc1dc7a3Sopenharmony_ci         STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]);                   } break;
1784cc1dc7a3Sopenharmony_ci         STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255;    } break;
1785cc1dc7a3Sopenharmony_ci         STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]);                   } break;
1786cc1dc7a3Sopenharmony_ci         STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break;
1787cc1dc7a3Sopenharmony_ci         STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];                    } break;
1788cc1dc7a3Sopenharmony_ci         default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion");
1789cc1dc7a3Sopenharmony_ci      }
1790cc1dc7a3Sopenharmony_ci      #undef STBI__CASE
1791cc1dc7a3Sopenharmony_ci   }
1792cc1dc7a3Sopenharmony_ci
1793cc1dc7a3Sopenharmony_ci   STBI_FREE(data);
1794cc1dc7a3Sopenharmony_ci   return good;
1795cc1dc7a3Sopenharmony_ci}
1796cc1dc7a3Sopenharmony_ci#endif
1797cc1dc7a3Sopenharmony_ci
1798cc1dc7a3Sopenharmony_ci#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
1799cc1dc7a3Sopenharmony_ci// nothing
1800cc1dc7a3Sopenharmony_ci#else
1801cc1dc7a3Sopenharmony_cistatic stbi__uint16 stbi__compute_y_16(int r, int g, int b)
1802cc1dc7a3Sopenharmony_ci{
1803cc1dc7a3Sopenharmony_ci   return (stbi__uint16) (((r*77) + (g*150) +  (29*b)) >> 8);
1804cc1dc7a3Sopenharmony_ci}
1805cc1dc7a3Sopenharmony_ci#endif
1806cc1dc7a3Sopenharmony_ci
1807cc1dc7a3Sopenharmony_ci#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
1808cc1dc7a3Sopenharmony_ci// nothing
1809cc1dc7a3Sopenharmony_ci#else
1810cc1dc7a3Sopenharmony_cistatic stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)
1811cc1dc7a3Sopenharmony_ci{
1812cc1dc7a3Sopenharmony_ci   int i,j;
1813cc1dc7a3Sopenharmony_ci   stbi__uint16 *good;
1814cc1dc7a3Sopenharmony_ci
1815cc1dc7a3Sopenharmony_ci   if (req_comp == img_n) return data;
1816cc1dc7a3Sopenharmony_ci   STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
1817cc1dc7a3Sopenharmony_ci
1818cc1dc7a3Sopenharmony_ci   good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2);
1819cc1dc7a3Sopenharmony_ci   if (good == NULL) {
1820cc1dc7a3Sopenharmony_ci      STBI_FREE(data);
1821cc1dc7a3Sopenharmony_ci      return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
1822cc1dc7a3Sopenharmony_ci   }
1823cc1dc7a3Sopenharmony_ci
1824cc1dc7a3Sopenharmony_ci   for (j=0; j < (int) y; ++j) {
1825cc1dc7a3Sopenharmony_ci      stbi__uint16 *src  = data + j * x * img_n   ;
1826cc1dc7a3Sopenharmony_ci      stbi__uint16 *dest = good + j * x * req_comp;
1827cc1dc7a3Sopenharmony_ci
1828cc1dc7a3Sopenharmony_ci      #define STBI__COMBO(a,b)  ((a)*8+(b))
1829cc1dc7a3Sopenharmony_ci      #define STBI__CASE(a,b)   case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
1830cc1dc7a3Sopenharmony_ci      // convert source image with img_n components to one with req_comp components;
1831cc1dc7a3Sopenharmony_ci      // avoid switch per pixel, so use switch per scanline and massive macros
1832cc1dc7a3Sopenharmony_ci      switch (STBI__COMBO(img_n, req_comp)) {
1833cc1dc7a3Sopenharmony_ci         STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff;                                     } break;
1834cc1dc7a3Sopenharmony_ci         STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0];                                     } break;
1835cc1dc7a3Sopenharmony_ci         STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff;                     } break;
1836cc1dc7a3Sopenharmony_ci         STBI__CASE(2,1) { dest[0]=src[0];                                                     } break;
1837cc1dc7a3Sopenharmony_ci         STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0];                                     } break;
1838cc1dc7a3Sopenharmony_ci         STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1];                     } break;
1839cc1dc7a3Sopenharmony_ci         STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff;        } break;
1840cc1dc7a3Sopenharmony_ci         STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]);                   } break;
1841cc1dc7a3Sopenharmony_ci         STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break;
1842cc1dc7a3Sopenharmony_ci         STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]);                   } break;
1843cc1dc7a3Sopenharmony_ci         STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break;
1844cc1dc7a3Sopenharmony_ci         STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];                       } break;
1845cc1dc7a3Sopenharmony_ci         default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion");
1846cc1dc7a3Sopenharmony_ci      }
1847cc1dc7a3Sopenharmony_ci      #undef STBI__CASE
1848cc1dc7a3Sopenharmony_ci   }
1849cc1dc7a3Sopenharmony_ci
1850cc1dc7a3Sopenharmony_ci   STBI_FREE(data);
1851cc1dc7a3Sopenharmony_ci   return good;
1852cc1dc7a3Sopenharmony_ci}
1853cc1dc7a3Sopenharmony_ci#endif
1854cc1dc7a3Sopenharmony_ci
1855cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_LINEAR
1856cc1dc7a3Sopenharmony_cistatic float   *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
1857cc1dc7a3Sopenharmony_ci{
1858cc1dc7a3Sopenharmony_ci   int i,k,n;
1859cc1dc7a3Sopenharmony_ci   float *output;
1860cc1dc7a3Sopenharmony_ci   if (!data) return NULL;
1861cc1dc7a3Sopenharmony_ci   output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0);
1862cc1dc7a3Sopenharmony_ci   if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); }
1863cc1dc7a3Sopenharmony_ci   // compute number of non-alpha components
1864cc1dc7a3Sopenharmony_ci   if (comp & 1) n = comp; else n = comp-1;
1865cc1dc7a3Sopenharmony_ci   for (i=0; i < x*y; ++i) {
1866cc1dc7a3Sopenharmony_ci      for (k=0; k < n; ++k) {
1867cc1dc7a3Sopenharmony_ci         output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale);
1868cc1dc7a3Sopenharmony_ci      }
1869cc1dc7a3Sopenharmony_ci   }
1870cc1dc7a3Sopenharmony_ci   if (n < comp) {
1871cc1dc7a3Sopenharmony_ci      for (i=0; i < x*y; ++i) {
1872cc1dc7a3Sopenharmony_ci         output[i*comp + n] = data[i*comp + n]/255.0f;
1873cc1dc7a3Sopenharmony_ci      }
1874cc1dc7a3Sopenharmony_ci   }
1875cc1dc7a3Sopenharmony_ci   STBI_FREE(data);
1876cc1dc7a3Sopenharmony_ci   return output;
1877cc1dc7a3Sopenharmony_ci}
1878cc1dc7a3Sopenharmony_ci#endif
1879cc1dc7a3Sopenharmony_ci
1880cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_HDR
1881cc1dc7a3Sopenharmony_ci#define stbi__float2int(x)   ((int) (x))
1882cc1dc7a3Sopenharmony_cistatic stbi_uc *stbi__hdr_to_ldr(float   *data, int x, int y, int comp)
1883cc1dc7a3Sopenharmony_ci{
1884cc1dc7a3Sopenharmony_ci   int i,k,n;
1885cc1dc7a3Sopenharmony_ci   stbi_uc *output;
1886cc1dc7a3Sopenharmony_ci   if (!data) return NULL;
1887cc1dc7a3Sopenharmony_ci   output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0);
1888cc1dc7a3Sopenharmony_ci   if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); }
1889cc1dc7a3Sopenharmony_ci   // compute number of non-alpha components
1890cc1dc7a3Sopenharmony_ci   if (comp & 1) n = comp; else n = comp-1;
1891cc1dc7a3Sopenharmony_ci   for (i=0; i < x*y; ++i) {
1892cc1dc7a3Sopenharmony_ci      for (k=0; k < n; ++k) {
1893cc1dc7a3Sopenharmony_ci         float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f;
1894cc1dc7a3Sopenharmony_ci         if (z < 0) z = 0;
1895cc1dc7a3Sopenharmony_ci         if (z > 255) z = 255;
1896cc1dc7a3Sopenharmony_ci         output[i*comp + k] = (stbi_uc) stbi__float2int(z);
1897cc1dc7a3Sopenharmony_ci      }
1898cc1dc7a3Sopenharmony_ci      if (k < comp) {
1899cc1dc7a3Sopenharmony_ci         float z = data[i*comp+k] * 255 + 0.5f;
1900cc1dc7a3Sopenharmony_ci         if (z < 0) z = 0;
1901cc1dc7a3Sopenharmony_ci         if (z > 255) z = 255;
1902cc1dc7a3Sopenharmony_ci         output[i*comp + k] = (stbi_uc) stbi__float2int(z);
1903cc1dc7a3Sopenharmony_ci      }
1904cc1dc7a3Sopenharmony_ci   }
1905cc1dc7a3Sopenharmony_ci   STBI_FREE(data);
1906cc1dc7a3Sopenharmony_ci   return output;
1907cc1dc7a3Sopenharmony_ci}
1908cc1dc7a3Sopenharmony_ci#endif
1909cc1dc7a3Sopenharmony_ci
1910cc1dc7a3Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////
1911cc1dc7a3Sopenharmony_ci//
1912cc1dc7a3Sopenharmony_ci//  "baseline" JPEG/JFIF decoder
1913cc1dc7a3Sopenharmony_ci//
1914cc1dc7a3Sopenharmony_ci//    simple implementation
1915cc1dc7a3Sopenharmony_ci//      - doesn't support delayed output of y-dimension
1916cc1dc7a3Sopenharmony_ci//      - simple interface (only one output format: 8-bit interleaved RGB)
1917cc1dc7a3Sopenharmony_ci//      - doesn't try to recover corrupt jpegs
1918cc1dc7a3Sopenharmony_ci//      - doesn't allow partial loading, loading multiple at once
1919cc1dc7a3Sopenharmony_ci//      - still fast on x86 (copying globals into locals doesn't help x86)
1920cc1dc7a3Sopenharmony_ci//      - allocates lots of intermediate memory (full size of all components)
1921cc1dc7a3Sopenharmony_ci//        - non-interleaved case requires this anyway
1922cc1dc7a3Sopenharmony_ci//        - allows good upsampling (see next)
1923cc1dc7a3Sopenharmony_ci//    high-quality
1924cc1dc7a3Sopenharmony_ci//      - upsampled channels are bilinearly interpolated, even across blocks
1925cc1dc7a3Sopenharmony_ci//      - quality integer IDCT derived from IJG's 'slow'
1926cc1dc7a3Sopenharmony_ci//    performance
1927cc1dc7a3Sopenharmony_ci//      - fast huffman; reasonable integer IDCT
1928cc1dc7a3Sopenharmony_ci//      - some SIMD kernels for common paths on targets with SSE2/NEON
1929cc1dc7a3Sopenharmony_ci//      - uses a lot of intermediate memory, could cache poorly
1930cc1dc7a3Sopenharmony_ci
1931cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_JPEG
1932cc1dc7a3Sopenharmony_ci
1933cc1dc7a3Sopenharmony_ci// huffman decoding acceleration
1934cc1dc7a3Sopenharmony_ci#define FAST_BITS   9  // larger handles more cases; smaller stomps less cache
1935cc1dc7a3Sopenharmony_ci
1936cc1dc7a3Sopenharmony_citypedef struct
1937cc1dc7a3Sopenharmony_ci{
1938cc1dc7a3Sopenharmony_ci   stbi_uc  fast[1 << FAST_BITS];
1939cc1dc7a3Sopenharmony_ci   // weirdly, repacking this into AoS is a 10% speed loss, instead of a win
1940cc1dc7a3Sopenharmony_ci   stbi__uint16 code[256];
1941cc1dc7a3Sopenharmony_ci   stbi_uc  values[256];
1942cc1dc7a3Sopenharmony_ci   stbi_uc  size[257];
1943cc1dc7a3Sopenharmony_ci   unsigned int maxcode[18];
1944cc1dc7a3Sopenharmony_ci   int    delta[17];   // old 'firstsymbol' - old 'firstcode'
1945cc1dc7a3Sopenharmony_ci} stbi__huffman;
1946cc1dc7a3Sopenharmony_ci
1947cc1dc7a3Sopenharmony_citypedef struct
1948cc1dc7a3Sopenharmony_ci{
1949cc1dc7a3Sopenharmony_ci   stbi__context *s;
1950cc1dc7a3Sopenharmony_ci   stbi__huffman huff_dc[4];
1951cc1dc7a3Sopenharmony_ci   stbi__huffman huff_ac[4];
1952cc1dc7a3Sopenharmony_ci   stbi__uint16 dequant[4][64];
1953cc1dc7a3Sopenharmony_ci   stbi__int16 fast_ac[4][1 << FAST_BITS];
1954cc1dc7a3Sopenharmony_ci
1955cc1dc7a3Sopenharmony_ci// sizes for components, interleaved MCUs
1956cc1dc7a3Sopenharmony_ci   int img_h_max, img_v_max;
1957cc1dc7a3Sopenharmony_ci   int img_mcu_x, img_mcu_y;
1958cc1dc7a3Sopenharmony_ci   int img_mcu_w, img_mcu_h;
1959cc1dc7a3Sopenharmony_ci
1960cc1dc7a3Sopenharmony_ci// definition of jpeg image component
1961cc1dc7a3Sopenharmony_ci   struct
1962cc1dc7a3Sopenharmony_ci   {
1963cc1dc7a3Sopenharmony_ci      int id;
1964cc1dc7a3Sopenharmony_ci      int h,v;
1965cc1dc7a3Sopenharmony_ci      int tq;
1966cc1dc7a3Sopenharmony_ci      int hd,ha;
1967cc1dc7a3Sopenharmony_ci      int dc_pred;
1968cc1dc7a3Sopenharmony_ci
1969cc1dc7a3Sopenharmony_ci      int x,y,w2,h2;
1970cc1dc7a3Sopenharmony_ci      stbi_uc *data;
1971cc1dc7a3Sopenharmony_ci      void *raw_data, *raw_coeff;
1972cc1dc7a3Sopenharmony_ci      stbi_uc *linebuf;
1973cc1dc7a3Sopenharmony_ci      short   *coeff;   // progressive only
1974cc1dc7a3Sopenharmony_ci      int      coeff_w, coeff_h; // number of 8x8 coefficient blocks
1975cc1dc7a3Sopenharmony_ci   } img_comp[4];
1976cc1dc7a3Sopenharmony_ci
1977cc1dc7a3Sopenharmony_ci   stbi__uint32   code_buffer; // jpeg entropy-coded buffer
1978cc1dc7a3Sopenharmony_ci   int            code_bits;   // number of valid bits
1979cc1dc7a3Sopenharmony_ci   unsigned char  marker;      // marker seen while filling entropy buffer
1980cc1dc7a3Sopenharmony_ci   int            nomore;      // flag if we saw a marker so must stop
1981cc1dc7a3Sopenharmony_ci
1982cc1dc7a3Sopenharmony_ci   int            progressive;
1983cc1dc7a3Sopenharmony_ci   int            spec_start;
1984cc1dc7a3Sopenharmony_ci   int            spec_end;
1985cc1dc7a3Sopenharmony_ci   int            succ_high;
1986cc1dc7a3Sopenharmony_ci   int            succ_low;
1987cc1dc7a3Sopenharmony_ci   int            eob_run;
1988cc1dc7a3Sopenharmony_ci   int            jfif;
1989cc1dc7a3Sopenharmony_ci   int            app14_color_transform; // Adobe APP14 tag
1990cc1dc7a3Sopenharmony_ci   int            rgb;
1991cc1dc7a3Sopenharmony_ci
1992cc1dc7a3Sopenharmony_ci   int scan_n, order[4];
1993cc1dc7a3Sopenharmony_ci   int restart_interval, todo;
1994cc1dc7a3Sopenharmony_ci
1995cc1dc7a3Sopenharmony_ci// kernels
1996cc1dc7a3Sopenharmony_ci   void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]);
1997cc1dc7a3Sopenharmony_ci   void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step);
1998cc1dc7a3Sopenharmony_ci   stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs);
1999cc1dc7a3Sopenharmony_ci} stbi__jpeg;
2000cc1dc7a3Sopenharmony_ci
2001cc1dc7a3Sopenharmony_cistatic int stbi__build_huffman(stbi__huffman *h, int *count)
2002cc1dc7a3Sopenharmony_ci{
2003cc1dc7a3Sopenharmony_ci   int i,j,k=0;
2004cc1dc7a3Sopenharmony_ci   unsigned int code;
2005cc1dc7a3Sopenharmony_ci   // build size list for each symbol (from JPEG spec)
2006cc1dc7a3Sopenharmony_ci   for (i=0; i < 16; ++i) {
2007cc1dc7a3Sopenharmony_ci      for (j=0; j < count[i]; ++j) {
2008cc1dc7a3Sopenharmony_ci         h->size[k++] = (stbi_uc) (i+1);
2009cc1dc7a3Sopenharmony_ci         if(k >= 257) return stbi__err("bad size list","Corrupt JPEG");
2010cc1dc7a3Sopenharmony_ci      }
2011cc1dc7a3Sopenharmony_ci   }
2012cc1dc7a3Sopenharmony_ci   h->size[k] = 0;
2013cc1dc7a3Sopenharmony_ci
2014cc1dc7a3Sopenharmony_ci   // compute actual symbols (from jpeg spec)
2015cc1dc7a3Sopenharmony_ci   code = 0;
2016cc1dc7a3Sopenharmony_ci   k = 0;
2017cc1dc7a3Sopenharmony_ci   for(j=1; j <= 16; ++j) {
2018cc1dc7a3Sopenharmony_ci      // compute delta to add to code to compute symbol id
2019cc1dc7a3Sopenharmony_ci      h->delta[j] = k - code;
2020cc1dc7a3Sopenharmony_ci      if (h->size[k] == j) {
2021cc1dc7a3Sopenharmony_ci         while (h->size[k] == j)
2022cc1dc7a3Sopenharmony_ci            h->code[k++] = (stbi__uint16) (code++);
2023cc1dc7a3Sopenharmony_ci         if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG");
2024cc1dc7a3Sopenharmony_ci      }
2025cc1dc7a3Sopenharmony_ci      // compute largest code + 1 for this size, preshifted as needed later
2026cc1dc7a3Sopenharmony_ci      h->maxcode[j] = code << (16-j);
2027cc1dc7a3Sopenharmony_ci      code <<= 1;
2028cc1dc7a3Sopenharmony_ci   }
2029cc1dc7a3Sopenharmony_ci   h->maxcode[j] = 0xffffffff;
2030cc1dc7a3Sopenharmony_ci
2031cc1dc7a3Sopenharmony_ci   // build non-spec acceleration table; 255 is flag for not-accelerated
2032cc1dc7a3Sopenharmony_ci   memset(h->fast, 255, 1 << FAST_BITS);
2033cc1dc7a3Sopenharmony_ci   for (i=0; i < k; ++i) {
2034cc1dc7a3Sopenharmony_ci      int s = h->size[i];
2035cc1dc7a3Sopenharmony_ci      if (s <= FAST_BITS) {
2036cc1dc7a3Sopenharmony_ci         int c = h->code[i] << (FAST_BITS-s);
2037cc1dc7a3Sopenharmony_ci         int m = 1 << (FAST_BITS-s);
2038cc1dc7a3Sopenharmony_ci         for (j=0; j < m; ++j) {
2039cc1dc7a3Sopenharmony_ci            h->fast[c+j] = (stbi_uc) i;
2040cc1dc7a3Sopenharmony_ci         }
2041cc1dc7a3Sopenharmony_ci      }
2042cc1dc7a3Sopenharmony_ci   }
2043cc1dc7a3Sopenharmony_ci   return 1;
2044cc1dc7a3Sopenharmony_ci}
2045cc1dc7a3Sopenharmony_ci
2046cc1dc7a3Sopenharmony_ci// build a table that decodes both magnitude and value of small ACs in
2047cc1dc7a3Sopenharmony_ci// one go.
2048cc1dc7a3Sopenharmony_cistatic void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h)
2049cc1dc7a3Sopenharmony_ci{
2050cc1dc7a3Sopenharmony_ci   int i;
2051cc1dc7a3Sopenharmony_ci   for (i=0; i < (1 << FAST_BITS); ++i) {
2052cc1dc7a3Sopenharmony_ci      stbi_uc fast = h->fast[i];
2053cc1dc7a3Sopenharmony_ci      fast_ac[i] = 0;
2054cc1dc7a3Sopenharmony_ci      if (fast < 255) {
2055cc1dc7a3Sopenharmony_ci         int rs = h->values[fast];
2056cc1dc7a3Sopenharmony_ci         int run = (rs >> 4) & 15;
2057cc1dc7a3Sopenharmony_ci         int magbits = rs & 15;
2058cc1dc7a3Sopenharmony_ci         int len = h->size[fast];
2059cc1dc7a3Sopenharmony_ci
2060cc1dc7a3Sopenharmony_ci         if (magbits && len + magbits <= FAST_BITS) {
2061cc1dc7a3Sopenharmony_ci            // magnitude code followed by receive_extend code
2062cc1dc7a3Sopenharmony_ci            int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits);
2063cc1dc7a3Sopenharmony_ci            int m = 1 << (magbits - 1);
2064cc1dc7a3Sopenharmony_ci            if (k < m) k += (~0U << magbits) + 1;
2065cc1dc7a3Sopenharmony_ci            // if the result is small enough, we can fit it in fast_ac table
2066cc1dc7a3Sopenharmony_ci            if (k >= -128 && k <= 127)
2067cc1dc7a3Sopenharmony_ci               fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits));
2068cc1dc7a3Sopenharmony_ci         }
2069cc1dc7a3Sopenharmony_ci      }
2070cc1dc7a3Sopenharmony_ci   }
2071cc1dc7a3Sopenharmony_ci}
2072cc1dc7a3Sopenharmony_ci
2073cc1dc7a3Sopenharmony_cistatic void stbi__grow_buffer_unsafe(stbi__jpeg *j)
2074cc1dc7a3Sopenharmony_ci{
2075cc1dc7a3Sopenharmony_ci   do {
2076cc1dc7a3Sopenharmony_ci      unsigned int b = j->nomore ? 0 : stbi__get8(j->s);
2077cc1dc7a3Sopenharmony_ci      if (b == 0xff) {
2078cc1dc7a3Sopenharmony_ci         int c = stbi__get8(j->s);
2079cc1dc7a3Sopenharmony_ci         while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes
2080cc1dc7a3Sopenharmony_ci         if (c != 0) {
2081cc1dc7a3Sopenharmony_ci            j->marker = (unsigned char) c;
2082cc1dc7a3Sopenharmony_ci            j->nomore = 1;
2083cc1dc7a3Sopenharmony_ci            return;
2084cc1dc7a3Sopenharmony_ci         }
2085cc1dc7a3Sopenharmony_ci      }
2086cc1dc7a3Sopenharmony_ci      j->code_buffer |= b << (24 - j->code_bits);
2087cc1dc7a3Sopenharmony_ci      j->code_bits += 8;
2088cc1dc7a3Sopenharmony_ci   } while (j->code_bits <= 24);
2089cc1dc7a3Sopenharmony_ci}
2090cc1dc7a3Sopenharmony_ci
2091cc1dc7a3Sopenharmony_ci// (1 << n) - 1
2092cc1dc7a3Sopenharmony_cistatic const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535};
2093cc1dc7a3Sopenharmony_ci
2094cc1dc7a3Sopenharmony_ci// decode a jpeg huffman value from the bitstream
2095cc1dc7a3Sopenharmony_cistbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h)
2096cc1dc7a3Sopenharmony_ci{
2097cc1dc7a3Sopenharmony_ci   unsigned int temp;
2098cc1dc7a3Sopenharmony_ci   int c,k;
2099cc1dc7a3Sopenharmony_ci
2100cc1dc7a3Sopenharmony_ci   if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
2101cc1dc7a3Sopenharmony_ci
2102cc1dc7a3Sopenharmony_ci   // look at the top FAST_BITS and determine what symbol ID it is,
2103cc1dc7a3Sopenharmony_ci   // if the code is <= FAST_BITS
2104cc1dc7a3Sopenharmony_ci   c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
2105cc1dc7a3Sopenharmony_ci   k = h->fast[c];
2106cc1dc7a3Sopenharmony_ci   if (k < 255) {
2107cc1dc7a3Sopenharmony_ci      int s = h->size[k];
2108cc1dc7a3Sopenharmony_ci      if (s > j->code_bits)
2109cc1dc7a3Sopenharmony_ci         return -1;
2110cc1dc7a3Sopenharmony_ci      j->code_buffer <<= s;
2111cc1dc7a3Sopenharmony_ci      j->code_bits -= s;
2112cc1dc7a3Sopenharmony_ci      return h->values[k];
2113cc1dc7a3Sopenharmony_ci   }
2114cc1dc7a3Sopenharmony_ci
2115cc1dc7a3Sopenharmony_ci   // naive test is to shift the code_buffer down so k bits are
2116cc1dc7a3Sopenharmony_ci   // valid, then test against maxcode. To speed this up, we've
2117cc1dc7a3Sopenharmony_ci   // preshifted maxcode left so that it has (16-k) 0s at the
2118cc1dc7a3Sopenharmony_ci   // end; in other words, regardless of the number of bits, it
2119cc1dc7a3Sopenharmony_ci   // wants to be compared against something shifted to have 16;
2120cc1dc7a3Sopenharmony_ci   // that way we don't need to shift inside the loop.
2121cc1dc7a3Sopenharmony_ci   temp = j->code_buffer >> 16;
2122cc1dc7a3Sopenharmony_ci   for (k=FAST_BITS+1 ; ; ++k)
2123cc1dc7a3Sopenharmony_ci      if (temp < h->maxcode[k])
2124cc1dc7a3Sopenharmony_ci         break;
2125cc1dc7a3Sopenharmony_ci   if (k == 17) {
2126cc1dc7a3Sopenharmony_ci      // error! code not found
2127cc1dc7a3Sopenharmony_ci      j->code_bits -= 16;
2128cc1dc7a3Sopenharmony_ci      return -1;
2129cc1dc7a3Sopenharmony_ci   }
2130cc1dc7a3Sopenharmony_ci
2131cc1dc7a3Sopenharmony_ci   if (k > j->code_bits)
2132cc1dc7a3Sopenharmony_ci      return -1;
2133cc1dc7a3Sopenharmony_ci
2134cc1dc7a3Sopenharmony_ci   // convert the huffman code to the symbol id
2135cc1dc7a3Sopenharmony_ci   c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k];
2136cc1dc7a3Sopenharmony_ci   if(c < 0 || c >= 256) // symbol id out of bounds!
2137cc1dc7a3Sopenharmony_ci       return -1;
2138cc1dc7a3Sopenharmony_ci   STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]);
2139cc1dc7a3Sopenharmony_ci
2140cc1dc7a3Sopenharmony_ci   // convert the id to a symbol
2141cc1dc7a3Sopenharmony_ci   j->code_bits -= k;
2142cc1dc7a3Sopenharmony_ci   j->code_buffer <<= k;
2143cc1dc7a3Sopenharmony_ci   return h->values[c];
2144cc1dc7a3Sopenharmony_ci}
2145cc1dc7a3Sopenharmony_ci
2146cc1dc7a3Sopenharmony_ci// bias[n] = (-1<<n) + 1
2147cc1dc7a3Sopenharmony_cistatic const int stbi__jbias[16] = {0,-1,-3,-7,-15,-31,-63,-127,-255,-511,-1023,-2047,-4095,-8191,-16383,-32767};
2148cc1dc7a3Sopenharmony_ci
2149cc1dc7a3Sopenharmony_ci// combined JPEG 'receive' and JPEG 'extend', since baseline
2150cc1dc7a3Sopenharmony_ci// always extends everything it receives.
2151cc1dc7a3Sopenharmony_cistbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
2152cc1dc7a3Sopenharmony_ci{
2153cc1dc7a3Sopenharmony_ci   unsigned int k;
2154cc1dc7a3Sopenharmony_ci   int sgn;
2155cc1dc7a3Sopenharmony_ci   if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
2156cc1dc7a3Sopenharmony_ci   if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing
2157cc1dc7a3Sopenharmony_ci
2158cc1dc7a3Sopenharmony_ci   sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative)
2159cc1dc7a3Sopenharmony_ci   k = stbi_lrot(j->code_buffer, n);
2160cc1dc7a3Sopenharmony_ci   j->code_buffer = k & ~stbi__bmask[n];
2161cc1dc7a3Sopenharmony_ci   k &= stbi__bmask[n];
2162cc1dc7a3Sopenharmony_ci   j->code_bits -= n;
2163cc1dc7a3Sopenharmony_ci   return k + (stbi__jbias[n] & (sgn - 1));
2164cc1dc7a3Sopenharmony_ci}
2165cc1dc7a3Sopenharmony_ci
2166cc1dc7a3Sopenharmony_ci// get some unsigned bits
2167cc1dc7a3Sopenharmony_cistbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n)
2168cc1dc7a3Sopenharmony_ci{
2169cc1dc7a3Sopenharmony_ci   unsigned int k;
2170cc1dc7a3Sopenharmony_ci   if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
2171cc1dc7a3Sopenharmony_ci   if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing
2172cc1dc7a3Sopenharmony_ci   k = stbi_lrot(j->code_buffer, n);
2173cc1dc7a3Sopenharmony_ci   j->code_buffer = k & ~stbi__bmask[n];
2174cc1dc7a3Sopenharmony_ci   k &= stbi__bmask[n];
2175cc1dc7a3Sopenharmony_ci   j->code_bits -= n;
2176cc1dc7a3Sopenharmony_ci   return k;
2177cc1dc7a3Sopenharmony_ci}
2178cc1dc7a3Sopenharmony_ci
2179cc1dc7a3Sopenharmony_cistbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j)
2180cc1dc7a3Sopenharmony_ci{
2181cc1dc7a3Sopenharmony_ci   unsigned int k;
2182cc1dc7a3Sopenharmony_ci   if (j->code_bits < 1) stbi__grow_buffer_unsafe(j);
2183cc1dc7a3Sopenharmony_ci   if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing
2184cc1dc7a3Sopenharmony_ci   k = j->code_buffer;
2185cc1dc7a3Sopenharmony_ci   j->code_buffer <<= 1;
2186cc1dc7a3Sopenharmony_ci   --j->code_bits;
2187cc1dc7a3Sopenharmony_ci   return k & 0x80000000;
2188cc1dc7a3Sopenharmony_ci}
2189cc1dc7a3Sopenharmony_ci
2190cc1dc7a3Sopenharmony_ci// given a value that's at position X in the zigzag stream,
2191cc1dc7a3Sopenharmony_ci// where does it appear in the 8x8 matrix coded as row-major?
2192cc1dc7a3Sopenharmony_cistatic const stbi_uc stbi__jpeg_dezigzag[64+15] =
2193cc1dc7a3Sopenharmony_ci{
2194cc1dc7a3Sopenharmony_ci    0,  1,  8, 16,  9,  2,  3, 10,
2195cc1dc7a3Sopenharmony_ci   17, 24, 32, 25, 18, 11,  4,  5,
2196cc1dc7a3Sopenharmony_ci   12, 19, 26, 33, 40, 48, 41, 34,
2197cc1dc7a3Sopenharmony_ci   27, 20, 13,  6,  7, 14, 21, 28,
2198cc1dc7a3Sopenharmony_ci   35, 42, 49, 56, 57, 50, 43, 36,
2199cc1dc7a3Sopenharmony_ci   29, 22, 15, 23, 30, 37, 44, 51,
2200cc1dc7a3Sopenharmony_ci   58, 59, 52, 45, 38, 31, 39, 46,
2201cc1dc7a3Sopenharmony_ci   53, 60, 61, 54, 47, 55, 62, 63,
2202cc1dc7a3Sopenharmony_ci   // let corrupt input sample past end
2203cc1dc7a3Sopenharmony_ci   63, 63, 63, 63, 63, 63, 63, 63,
2204cc1dc7a3Sopenharmony_ci   63, 63, 63, 63, 63, 63, 63
2205cc1dc7a3Sopenharmony_ci};
2206cc1dc7a3Sopenharmony_ci
2207cc1dc7a3Sopenharmony_ci// decode one 64-entry block--
2208cc1dc7a3Sopenharmony_cistatic int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant)
2209cc1dc7a3Sopenharmony_ci{
2210cc1dc7a3Sopenharmony_ci   int diff,dc,k;
2211cc1dc7a3Sopenharmony_ci   int t;
2212cc1dc7a3Sopenharmony_ci
2213cc1dc7a3Sopenharmony_ci   if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
2214cc1dc7a3Sopenharmony_ci   t = stbi__jpeg_huff_decode(j, hdc);
2215cc1dc7a3Sopenharmony_ci   if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG");
2216cc1dc7a3Sopenharmony_ci
2217cc1dc7a3Sopenharmony_ci   // 0 all the ac values now so we can do it 32-bits at a time
2218cc1dc7a3Sopenharmony_ci   memset(data,0,64*sizeof(data[0]));
2219cc1dc7a3Sopenharmony_ci
2220cc1dc7a3Sopenharmony_ci   diff = t ? stbi__extend_receive(j, t) : 0;
2221cc1dc7a3Sopenharmony_ci   if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG");
2222cc1dc7a3Sopenharmony_ci   dc = j->img_comp[b].dc_pred + diff;
2223cc1dc7a3Sopenharmony_ci   j->img_comp[b].dc_pred = dc;
2224cc1dc7a3Sopenharmony_ci   if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
2225cc1dc7a3Sopenharmony_ci   data[0] = (short) (dc * dequant[0]);
2226cc1dc7a3Sopenharmony_ci
2227cc1dc7a3Sopenharmony_ci   // decode AC components, see JPEG spec
2228cc1dc7a3Sopenharmony_ci   k = 1;
2229cc1dc7a3Sopenharmony_ci   do {
2230cc1dc7a3Sopenharmony_ci      unsigned int zig;
2231cc1dc7a3Sopenharmony_ci      int c,r,s;
2232cc1dc7a3Sopenharmony_ci      if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
2233cc1dc7a3Sopenharmony_ci      c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
2234cc1dc7a3Sopenharmony_ci      r = fac[c];
2235cc1dc7a3Sopenharmony_ci      if (r) { // fast-AC path
2236cc1dc7a3Sopenharmony_ci         k += (r >> 4) & 15; // run
2237cc1dc7a3Sopenharmony_ci         s = r & 15; // combined length
2238cc1dc7a3Sopenharmony_ci         if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");
2239cc1dc7a3Sopenharmony_ci         j->code_buffer <<= s;
2240cc1dc7a3Sopenharmony_ci         j->code_bits -= s;
2241cc1dc7a3Sopenharmony_ci         // decode into unzigzag'd location
2242cc1dc7a3Sopenharmony_ci         zig = stbi__jpeg_dezigzag[k++];
2243cc1dc7a3Sopenharmony_ci         data[zig] = (short) ((r >> 8) * dequant[zig]);
2244cc1dc7a3Sopenharmony_ci      } else {
2245cc1dc7a3Sopenharmony_ci         int rs = stbi__jpeg_huff_decode(j, hac);
2246cc1dc7a3Sopenharmony_ci         if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
2247cc1dc7a3Sopenharmony_ci         s = rs & 15;
2248cc1dc7a3Sopenharmony_ci         r = rs >> 4;
2249cc1dc7a3Sopenharmony_ci         if (s == 0) {
2250cc1dc7a3Sopenharmony_ci            if (rs != 0xf0) break; // end block
2251cc1dc7a3Sopenharmony_ci            k += 16;
2252cc1dc7a3Sopenharmony_ci         } else {
2253cc1dc7a3Sopenharmony_ci            k += r;
2254cc1dc7a3Sopenharmony_ci            // decode into unzigzag'd location
2255cc1dc7a3Sopenharmony_ci            zig = stbi__jpeg_dezigzag[k++];
2256cc1dc7a3Sopenharmony_ci            data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]);
2257cc1dc7a3Sopenharmony_ci         }
2258cc1dc7a3Sopenharmony_ci      }
2259cc1dc7a3Sopenharmony_ci   } while (k < 64);
2260cc1dc7a3Sopenharmony_ci   return 1;
2261cc1dc7a3Sopenharmony_ci}
2262cc1dc7a3Sopenharmony_ci
2263cc1dc7a3Sopenharmony_cistatic int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b)
2264cc1dc7a3Sopenharmony_ci{
2265cc1dc7a3Sopenharmony_ci   int diff,dc;
2266cc1dc7a3Sopenharmony_ci   int t;
2267cc1dc7a3Sopenharmony_ci   if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
2268cc1dc7a3Sopenharmony_ci
2269cc1dc7a3Sopenharmony_ci   if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
2270cc1dc7a3Sopenharmony_ci
2271cc1dc7a3Sopenharmony_ci   if (j->succ_high == 0) {
2272cc1dc7a3Sopenharmony_ci      // first scan for DC coefficient, must be first
2273cc1dc7a3Sopenharmony_ci      memset(data,0,64*sizeof(data[0])); // 0 all the ac values now
2274cc1dc7a3Sopenharmony_ci      t = stbi__jpeg_huff_decode(j, hdc);
2275cc1dc7a3Sopenharmony_ci      if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
2276cc1dc7a3Sopenharmony_ci      diff = t ? stbi__extend_receive(j, t) : 0;
2277cc1dc7a3Sopenharmony_ci
2278cc1dc7a3Sopenharmony_ci      if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG");
2279cc1dc7a3Sopenharmony_ci      dc = j->img_comp[b].dc_pred + diff;
2280cc1dc7a3Sopenharmony_ci      j->img_comp[b].dc_pred = dc;
2281cc1dc7a3Sopenharmony_ci      if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
2282cc1dc7a3Sopenharmony_ci      data[0] = (short) (dc * (1 << j->succ_low));
2283cc1dc7a3Sopenharmony_ci   } else {
2284cc1dc7a3Sopenharmony_ci      // refinement scan for DC coefficient
2285cc1dc7a3Sopenharmony_ci      if (stbi__jpeg_get_bit(j))
2286cc1dc7a3Sopenharmony_ci         data[0] += (short) (1 << j->succ_low);
2287cc1dc7a3Sopenharmony_ci   }
2288cc1dc7a3Sopenharmony_ci   return 1;
2289cc1dc7a3Sopenharmony_ci}
2290cc1dc7a3Sopenharmony_ci
2291cc1dc7a3Sopenharmony_ci// @OPTIMIZE: store non-zigzagged during the decode passes,
2292cc1dc7a3Sopenharmony_ci// and only de-zigzag when dequantizing
2293cc1dc7a3Sopenharmony_cistatic int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac)
2294cc1dc7a3Sopenharmony_ci{
2295cc1dc7a3Sopenharmony_ci   int k;
2296cc1dc7a3Sopenharmony_ci   if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
2297cc1dc7a3Sopenharmony_ci
2298cc1dc7a3Sopenharmony_ci   if (j->succ_high == 0) {
2299cc1dc7a3Sopenharmony_ci      int shift = j->succ_low;
2300cc1dc7a3Sopenharmony_ci
2301cc1dc7a3Sopenharmony_ci      if (j->eob_run) {
2302cc1dc7a3Sopenharmony_ci         --j->eob_run;
2303cc1dc7a3Sopenharmony_ci         return 1;
2304cc1dc7a3Sopenharmony_ci      }
2305cc1dc7a3Sopenharmony_ci
2306cc1dc7a3Sopenharmony_ci      k = j->spec_start;
2307cc1dc7a3Sopenharmony_ci      do {
2308cc1dc7a3Sopenharmony_ci         unsigned int zig;
2309cc1dc7a3Sopenharmony_ci         int c,r,s;
2310cc1dc7a3Sopenharmony_ci         if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);
2311cc1dc7a3Sopenharmony_ci         c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);
2312cc1dc7a3Sopenharmony_ci         r = fac[c];
2313cc1dc7a3Sopenharmony_ci         if (r) { // fast-AC path
2314cc1dc7a3Sopenharmony_ci            k += (r >> 4) & 15; // run
2315cc1dc7a3Sopenharmony_ci            s = r & 15; // combined length
2316cc1dc7a3Sopenharmony_ci            if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");
2317cc1dc7a3Sopenharmony_ci            j->code_buffer <<= s;
2318cc1dc7a3Sopenharmony_ci            j->code_bits -= s;
2319cc1dc7a3Sopenharmony_ci            zig = stbi__jpeg_dezigzag[k++];
2320cc1dc7a3Sopenharmony_ci            data[zig] = (short) ((r >> 8) * (1 << shift));
2321cc1dc7a3Sopenharmony_ci         } else {
2322cc1dc7a3Sopenharmony_ci            int rs = stbi__jpeg_huff_decode(j, hac);
2323cc1dc7a3Sopenharmony_ci            if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
2324cc1dc7a3Sopenharmony_ci            s = rs & 15;
2325cc1dc7a3Sopenharmony_ci            r = rs >> 4;
2326cc1dc7a3Sopenharmony_ci            if (s == 0) {
2327cc1dc7a3Sopenharmony_ci               if (r < 15) {
2328cc1dc7a3Sopenharmony_ci                  j->eob_run = (1 << r);
2329cc1dc7a3Sopenharmony_ci                  if (r)
2330cc1dc7a3Sopenharmony_ci                     j->eob_run += stbi__jpeg_get_bits(j, r);
2331cc1dc7a3Sopenharmony_ci                  --j->eob_run;
2332cc1dc7a3Sopenharmony_ci                  break;
2333cc1dc7a3Sopenharmony_ci               }
2334cc1dc7a3Sopenharmony_ci               k += 16;
2335cc1dc7a3Sopenharmony_ci            } else {
2336cc1dc7a3Sopenharmony_ci               k += r;
2337cc1dc7a3Sopenharmony_ci               zig = stbi__jpeg_dezigzag[k++];
2338cc1dc7a3Sopenharmony_ci               data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift));
2339cc1dc7a3Sopenharmony_ci            }
2340cc1dc7a3Sopenharmony_ci         }
2341cc1dc7a3Sopenharmony_ci      } while (k <= j->spec_end);
2342cc1dc7a3Sopenharmony_ci   } else {
2343cc1dc7a3Sopenharmony_ci      // refinement scan for these AC coefficients
2344cc1dc7a3Sopenharmony_ci
2345cc1dc7a3Sopenharmony_ci      short bit = (short) (1 << j->succ_low);
2346cc1dc7a3Sopenharmony_ci
2347cc1dc7a3Sopenharmony_ci      if (j->eob_run) {
2348cc1dc7a3Sopenharmony_ci         --j->eob_run;
2349cc1dc7a3Sopenharmony_ci         for (k = j->spec_start; k <= j->spec_end; ++k) {
2350cc1dc7a3Sopenharmony_ci            short *p = &data[stbi__jpeg_dezigzag[k]];
2351cc1dc7a3Sopenharmony_ci            if (*p != 0)
2352cc1dc7a3Sopenharmony_ci               if (stbi__jpeg_get_bit(j))
2353cc1dc7a3Sopenharmony_ci                  if ((*p & bit)==0) {
2354cc1dc7a3Sopenharmony_ci                     if (*p > 0)
2355cc1dc7a3Sopenharmony_ci                        *p += bit;
2356cc1dc7a3Sopenharmony_ci                     else
2357cc1dc7a3Sopenharmony_ci                        *p -= bit;
2358cc1dc7a3Sopenharmony_ci                  }
2359cc1dc7a3Sopenharmony_ci         }
2360cc1dc7a3Sopenharmony_ci      } else {
2361cc1dc7a3Sopenharmony_ci         k = j->spec_start;
2362cc1dc7a3Sopenharmony_ci         do {
2363cc1dc7a3Sopenharmony_ci            int r,s;
2364cc1dc7a3Sopenharmony_ci            int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh
2365cc1dc7a3Sopenharmony_ci            if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");
2366cc1dc7a3Sopenharmony_ci            s = rs & 15;
2367cc1dc7a3Sopenharmony_ci            r = rs >> 4;
2368cc1dc7a3Sopenharmony_ci            if (s == 0) {
2369cc1dc7a3Sopenharmony_ci               if (r < 15) {
2370cc1dc7a3Sopenharmony_ci                  j->eob_run = (1 << r) - 1;
2371cc1dc7a3Sopenharmony_ci                  if (r)
2372cc1dc7a3Sopenharmony_ci                     j->eob_run += stbi__jpeg_get_bits(j, r);
2373cc1dc7a3Sopenharmony_ci                  r = 64; // force end of block
2374cc1dc7a3Sopenharmony_ci               } else {
2375cc1dc7a3Sopenharmony_ci                  // r=15 s=0 should write 16 0s, so we just do
2376cc1dc7a3Sopenharmony_ci                  // a run of 15 0s and then write s (which is 0),
2377cc1dc7a3Sopenharmony_ci                  // so we don't have to do anything special here
2378cc1dc7a3Sopenharmony_ci               }
2379cc1dc7a3Sopenharmony_ci            } else {
2380cc1dc7a3Sopenharmony_ci               if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG");
2381cc1dc7a3Sopenharmony_ci               // sign bit
2382cc1dc7a3Sopenharmony_ci               if (stbi__jpeg_get_bit(j))
2383cc1dc7a3Sopenharmony_ci                  s = bit;
2384cc1dc7a3Sopenharmony_ci               else
2385cc1dc7a3Sopenharmony_ci                  s = -bit;
2386cc1dc7a3Sopenharmony_ci            }
2387cc1dc7a3Sopenharmony_ci
2388cc1dc7a3Sopenharmony_ci            // advance by r
2389cc1dc7a3Sopenharmony_ci            while (k <= j->spec_end) {
2390cc1dc7a3Sopenharmony_ci               short *p = &data[stbi__jpeg_dezigzag[k++]];
2391cc1dc7a3Sopenharmony_ci               if (*p != 0) {
2392cc1dc7a3Sopenharmony_ci                  if (stbi__jpeg_get_bit(j))
2393cc1dc7a3Sopenharmony_ci                     if ((*p & bit)==0) {
2394cc1dc7a3Sopenharmony_ci                        if (*p > 0)
2395cc1dc7a3Sopenharmony_ci                           *p += bit;
2396cc1dc7a3Sopenharmony_ci                        else
2397cc1dc7a3Sopenharmony_ci                           *p -= bit;
2398cc1dc7a3Sopenharmony_ci                     }
2399cc1dc7a3Sopenharmony_ci               } else {
2400cc1dc7a3Sopenharmony_ci                  if (r == 0) {
2401cc1dc7a3Sopenharmony_ci                     *p = (short) s;
2402cc1dc7a3Sopenharmony_ci                     break;
2403cc1dc7a3Sopenharmony_ci                  }
2404cc1dc7a3Sopenharmony_ci                  --r;
2405cc1dc7a3Sopenharmony_ci               }
2406cc1dc7a3Sopenharmony_ci            }
2407cc1dc7a3Sopenharmony_ci         } while (k <= j->spec_end);
2408cc1dc7a3Sopenharmony_ci      }
2409cc1dc7a3Sopenharmony_ci   }
2410cc1dc7a3Sopenharmony_ci   return 1;
2411cc1dc7a3Sopenharmony_ci}
2412cc1dc7a3Sopenharmony_ci
2413cc1dc7a3Sopenharmony_ci// take a -128..127 value and stbi__clamp it and convert to 0..255
2414cc1dc7a3Sopenharmony_cistbi_inline static stbi_uc stbi__clamp(int x)
2415cc1dc7a3Sopenharmony_ci{
2416cc1dc7a3Sopenharmony_ci   // trick to use a single test to catch both cases
2417cc1dc7a3Sopenharmony_ci   if ((unsigned int) x > 255) {
2418cc1dc7a3Sopenharmony_ci      if (x < 0) return 0;
2419cc1dc7a3Sopenharmony_ci      if (x > 255) return 255;
2420cc1dc7a3Sopenharmony_ci   }
2421cc1dc7a3Sopenharmony_ci   return (stbi_uc) x;
2422cc1dc7a3Sopenharmony_ci}
2423cc1dc7a3Sopenharmony_ci
2424cc1dc7a3Sopenharmony_ci#define stbi__f2f(x)  ((int) (((x) * 4096 + 0.5)))
2425cc1dc7a3Sopenharmony_ci#define stbi__fsh(x)  ((x) * 4096)
2426cc1dc7a3Sopenharmony_ci
2427cc1dc7a3Sopenharmony_ci// derived from jidctint -- DCT_ISLOW
2428cc1dc7a3Sopenharmony_ci#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \
2429cc1dc7a3Sopenharmony_ci   int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \
2430cc1dc7a3Sopenharmony_ci   p2 = s2;                                    \
2431cc1dc7a3Sopenharmony_ci   p3 = s6;                                    \
2432cc1dc7a3Sopenharmony_ci   p1 = (p2+p3) * stbi__f2f(0.5411961f);       \
2433cc1dc7a3Sopenharmony_ci   t2 = p1 + p3*stbi__f2f(-1.847759065f);      \
2434cc1dc7a3Sopenharmony_ci   t3 = p1 + p2*stbi__f2f( 0.765366865f);      \
2435cc1dc7a3Sopenharmony_ci   p2 = s0;                                    \
2436cc1dc7a3Sopenharmony_ci   p3 = s4;                                    \
2437cc1dc7a3Sopenharmony_ci   t0 = stbi__fsh(p2+p3);                      \
2438cc1dc7a3Sopenharmony_ci   t1 = stbi__fsh(p2-p3);                      \
2439cc1dc7a3Sopenharmony_ci   x0 = t0+t3;                                 \
2440cc1dc7a3Sopenharmony_ci   x3 = t0-t3;                                 \
2441cc1dc7a3Sopenharmony_ci   x1 = t1+t2;                                 \
2442cc1dc7a3Sopenharmony_ci   x2 = t1-t2;                                 \
2443cc1dc7a3Sopenharmony_ci   t0 = s7;                                    \
2444cc1dc7a3Sopenharmony_ci   t1 = s5;                                    \
2445cc1dc7a3Sopenharmony_ci   t2 = s3;                                    \
2446cc1dc7a3Sopenharmony_ci   t3 = s1;                                    \
2447cc1dc7a3Sopenharmony_ci   p3 = t0+t2;                                 \
2448cc1dc7a3Sopenharmony_ci   p4 = t1+t3;                                 \
2449cc1dc7a3Sopenharmony_ci   p1 = t0+t3;                                 \
2450cc1dc7a3Sopenharmony_ci   p2 = t1+t2;                                 \
2451cc1dc7a3Sopenharmony_ci   p5 = (p3+p4)*stbi__f2f( 1.175875602f);      \
2452cc1dc7a3Sopenharmony_ci   t0 = t0*stbi__f2f( 0.298631336f);           \
2453cc1dc7a3Sopenharmony_ci   t1 = t1*stbi__f2f( 2.053119869f);           \
2454cc1dc7a3Sopenharmony_ci   t2 = t2*stbi__f2f( 3.072711026f);           \
2455cc1dc7a3Sopenharmony_ci   t3 = t3*stbi__f2f( 1.501321110f);           \
2456cc1dc7a3Sopenharmony_ci   p1 = p5 + p1*stbi__f2f(-0.899976223f);      \
2457cc1dc7a3Sopenharmony_ci   p2 = p5 + p2*stbi__f2f(-2.562915447f);      \
2458cc1dc7a3Sopenharmony_ci   p3 = p3*stbi__f2f(-1.961570560f);           \
2459cc1dc7a3Sopenharmony_ci   p4 = p4*stbi__f2f(-0.390180644f);           \
2460cc1dc7a3Sopenharmony_ci   t3 += p1+p4;                                \
2461cc1dc7a3Sopenharmony_ci   t2 += p2+p3;                                \
2462cc1dc7a3Sopenharmony_ci   t1 += p2+p4;                                \
2463cc1dc7a3Sopenharmony_ci   t0 += p1+p3;
2464cc1dc7a3Sopenharmony_ci
2465cc1dc7a3Sopenharmony_cistatic void stbi__idct_block(stbi_uc *out, int out_stride, short data[64])
2466cc1dc7a3Sopenharmony_ci{
2467cc1dc7a3Sopenharmony_ci   int i,val[64],*v=val;
2468cc1dc7a3Sopenharmony_ci   stbi_uc *o;
2469cc1dc7a3Sopenharmony_ci   short *d = data;
2470cc1dc7a3Sopenharmony_ci
2471cc1dc7a3Sopenharmony_ci   // columns
2472cc1dc7a3Sopenharmony_ci   for (i=0; i < 8; ++i,++d, ++v) {
2473cc1dc7a3Sopenharmony_ci      // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing
2474cc1dc7a3Sopenharmony_ci      if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0
2475cc1dc7a3Sopenharmony_ci           && d[40]==0 && d[48]==0 && d[56]==0) {
2476cc1dc7a3Sopenharmony_ci         //    no shortcut                 0     seconds
2477cc1dc7a3Sopenharmony_ci         //    (1|2|3|4|5|6|7)==0          0     seconds
2478cc1dc7a3Sopenharmony_ci         //    all separate               -0.047 seconds
2479cc1dc7a3Sopenharmony_ci         //    1 && 2|3 && 4|5 && 6|7:    -0.047 seconds
2480cc1dc7a3Sopenharmony_ci         int dcterm = d[0]*4;
2481cc1dc7a3Sopenharmony_ci         v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm;
2482cc1dc7a3Sopenharmony_ci      } else {
2483cc1dc7a3Sopenharmony_ci         STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56])
2484cc1dc7a3Sopenharmony_ci         // constants scaled things up by 1<<12; let's bring them back
2485cc1dc7a3Sopenharmony_ci         // down, but keep 2 extra bits of precision
2486cc1dc7a3Sopenharmony_ci         x0 += 512; x1 += 512; x2 += 512; x3 += 512;
2487cc1dc7a3Sopenharmony_ci         v[ 0] = (x0+t3) >> 10;
2488cc1dc7a3Sopenharmony_ci         v[56] = (x0-t3) >> 10;
2489cc1dc7a3Sopenharmony_ci         v[ 8] = (x1+t2) >> 10;
2490cc1dc7a3Sopenharmony_ci         v[48] = (x1-t2) >> 10;
2491cc1dc7a3Sopenharmony_ci         v[16] = (x2+t1) >> 10;
2492cc1dc7a3Sopenharmony_ci         v[40] = (x2-t1) >> 10;
2493cc1dc7a3Sopenharmony_ci         v[24] = (x3+t0) >> 10;
2494cc1dc7a3Sopenharmony_ci         v[32] = (x3-t0) >> 10;
2495cc1dc7a3Sopenharmony_ci      }
2496cc1dc7a3Sopenharmony_ci   }
2497cc1dc7a3Sopenharmony_ci
2498cc1dc7a3Sopenharmony_ci   for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) {
2499cc1dc7a3Sopenharmony_ci      // no fast case since the first 1D IDCT spread components out
2500cc1dc7a3Sopenharmony_ci      STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7])
2501cc1dc7a3Sopenharmony_ci      // constants scaled things up by 1<<12, plus we had 1<<2 from first
2502cc1dc7a3Sopenharmony_ci      // loop, plus horizontal and vertical each scale by sqrt(8) so together
2503cc1dc7a3Sopenharmony_ci      // we've got an extra 1<<3, so 1<<17 total we need to remove.
2504cc1dc7a3Sopenharmony_ci      // so we want to round that, which means adding 0.5 * 1<<17,
2505cc1dc7a3Sopenharmony_ci      // aka 65536. Also, we'll end up with -128 to 127 that we want
2506cc1dc7a3Sopenharmony_ci      // to encode as 0..255 by adding 128, so we'll add that before the shift
2507cc1dc7a3Sopenharmony_ci      x0 += 65536 + (128<<17);
2508cc1dc7a3Sopenharmony_ci      x1 += 65536 + (128<<17);
2509cc1dc7a3Sopenharmony_ci      x2 += 65536 + (128<<17);
2510cc1dc7a3Sopenharmony_ci      x3 += 65536 + (128<<17);
2511cc1dc7a3Sopenharmony_ci      // tried computing the shifts into temps, or'ing the temps to see
2512cc1dc7a3Sopenharmony_ci      // if any were out of range, but that was slower
2513cc1dc7a3Sopenharmony_ci      o[0] = stbi__clamp((x0+t3) >> 17);
2514cc1dc7a3Sopenharmony_ci      o[7] = stbi__clamp((x0-t3) >> 17);
2515cc1dc7a3Sopenharmony_ci      o[1] = stbi__clamp((x1+t2) >> 17);
2516cc1dc7a3Sopenharmony_ci      o[6] = stbi__clamp((x1-t2) >> 17);
2517cc1dc7a3Sopenharmony_ci      o[2] = stbi__clamp((x2+t1) >> 17);
2518cc1dc7a3Sopenharmony_ci      o[5] = stbi__clamp((x2-t1) >> 17);
2519cc1dc7a3Sopenharmony_ci      o[3] = stbi__clamp((x3+t0) >> 17);
2520cc1dc7a3Sopenharmony_ci      o[4] = stbi__clamp((x3-t0) >> 17);
2521cc1dc7a3Sopenharmony_ci   }
2522cc1dc7a3Sopenharmony_ci}
2523cc1dc7a3Sopenharmony_ci
2524cc1dc7a3Sopenharmony_ci#ifdef STBI_SSE2
2525cc1dc7a3Sopenharmony_ci// sse2 integer IDCT. not the fastest possible implementation but it
2526cc1dc7a3Sopenharmony_ci// produces bit-identical results to the generic C version so it's
2527cc1dc7a3Sopenharmony_ci// fully "transparent".
2528cc1dc7a3Sopenharmony_cistatic void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
2529cc1dc7a3Sopenharmony_ci{
2530cc1dc7a3Sopenharmony_ci   // This is constructed to match our regular (generic) integer IDCT exactly.
2531cc1dc7a3Sopenharmony_ci   __m128i row0, row1, row2, row3, row4, row5, row6, row7;
2532cc1dc7a3Sopenharmony_ci   __m128i tmp;
2533cc1dc7a3Sopenharmony_ci
2534cc1dc7a3Sopenharmony_ci   // dot product constant: even elems=x, odd elems=y
2535cc1dc7a3Sopenharmony_ci   #define dct_const(x,y)  _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y))
2536cc1dc7a3Sopenharmony_ci
2537cc1dc7a3Sopenharmony_ci   // out(0) = c0[even]*x + c0[odd]*y   (c0, x, y 16-bit, out 32-bit)
2538cc1dc7a3Sopenharmony_ci   // out(1) = c1[even]*x + c1[odd]*y
2539cc1dc7a3Sopenharmony_ci   #define dct_rot(out0,out1, x,y,c0,c1) \
2540cc1dc7a3Sopenharmony_ci      __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \
2541cc1dc7a3Sopenharmony_ci      __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \
2542cc1dc7a3Sopenharmony_ci      __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \
2543cc1dc7a3Sopenharmony_ci      __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \
2544cc1dc7a3Sopenharmony_ci      __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \
2545cc1dc7a3Sopenharmony_ci      __m128i out1##_h = _mm_madd_epi16(c0##hi, c1)
2546cc1dc7a3Sopenharmony_ci
2547cc1dc7a3Sopenharmony_ci   // out = in << 12  (in 16-bit, out 32-bit)
2548cc1dc7a3Sopenharmony_ci   #define dct_widen(out, in) \
2549cc1dc7a3Sopenharmony_ci      __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \
2550cc1dc7a3Sopenharmony_ci      __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4)
2551cc1dc7a3Sopenharmony_ci
2552cc1dc7a3Sopenharmony_ci   // wide add
2553cc1dc7a3Sopenharmony_ci   #define dct_wadd(out, a, b) \
2554cc1dc7a3Sopenharmony_ci      __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \
2555cc1dc7a3Sopenharmony_ci      __m128i out##_h = _mm_add_epi32(a##_h, b##_h)
2556cc1dc7a3Sopenharmony_ci
2557cc1dc7a3Sopenharmony_ci   // wide sub
2558cc1dc7a3Sopenharmony_ci   #define dct_wsub(out, a, b) \
2559cc1dc7a3Sopenharmony_ci      __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \
2560cc1dc7a3Sopenharmony_ci      __m128i out##_h = _mm_sub_epi32(a##_h, b##_h)
2561cc1dc7a3Sopenharmony_ci
2562cc1dc7a3Sopenharmony_ci   // butterfly a/b, add bias, then shift by "s" and pack
2563cc1dc7a3Sopenharmony_ci   #define dct_bfly32o(out0, out1, a,b,bias,s) \
2564cc1dc7a3Sopenharmony_ci      { \
2565cc1dc7a3Sopenharmony_ci         __m128i abiased_l = _mm_add_epi32(a##_l, bias); \
2566cc1dc7a3Sopenharmony_ci         __m128i abiased_h = _mm_add_epi32(a##_h, bias); \
2567cc1dc7a3Sopenharmony_ci         dct_wadd(sum, abiased, b); \
2568cc1dc7a3Sopenharmony_ci         dct_wsub(dif, abiased, b); \
2569cc1dc7a3Sopenharmony_ci         out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \
2570cc1dc7a3Sopenharmony_ci         out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \
2571cc1dc7a3Sopenharmony_ci      }
2572cc1dc7a3Sopenharmony_ci
2573cc1dc7a3Sopenharmony_ci   // 8-bit interleave step (for transposes)
2574cc1dc7a3Sopenharmony_ci   #define dct_interleave8(a, b) \
2575cc1dc7a3Sopenharmony_ci      tmp = a; \
2576cc1dc7a3Sopenharmony_ci      a = _mm_unpacklo_epi8(a, b); \
2577cc1dc7a3Sopenharmony_ci      b = _mm_unpackhi_epi8(tmp, b)
2578cc1dc7a3Sopenharmony_ci
2579cc1dc7a3Sopenharmony_ci   // 16-bit interleave step (for transposes)
2580cc1dc7a3Sopenharmony_ci   #define dct_interleave16(a, b) \
2581cc1dc7a3Sopenharmony_ci      tmp = a; \
2582cc1dc7a3Sopenharmony_ci      a = _mm_unpacklo_epi16(a, b); \
2583cc1dc7a3Sopenharmony_ci      b = _mm_unpackhi_epi16(tmp, b)
2584cc1dc7a3Sopenharmony_ci
2585cc1dc7a3Sopenharmony_ci   #define dct_pass(bias,shift) \
2586cc1dc7a3Sopenharmony_ci      { \
2587cc1dc7a3Sopenharmony_ci         /* even part */ \
2588cc1dc7a3Sopenharmony_ci         dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \
2589cc1dc7a3Sopenharmony_ci         __m128i sum04 = _mm_add_epi16(row0, row4); \
2590cc1dc7a3Sopenharmony_ci         __m128i dif04 = _mm_sub_epi16(row0, row4); \
2591cc1dc7a3Sopenharmony_ci         dct_widen(t0e, sum04); \
2592cc1dc7a3Sopenharmony_ci         dct_widen(t1e, dif04); \
2593cc1dc7a3Sopenharmony_ci         dct_wadd(x0, t0e, t3e); \
2594cc1dc7a3Sopenharmony_ci         dct_wsub(x3, t0e, t3e); \
2595cc1dc7a3Sopenharmony_ci         dct_wadd(x1, t1e, t2e); \
2596cc1dc7a3Sopenharmony_ci         dct_wsub(x2, t1e, t2e); \
2597cc1dc7a3Sopenharmony_ci         /* odd part */ \
2598cc1dc7a3Sopenharmony_ci         dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \
2599cc1dc7a3Sopenharmony_ci         dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \
2600cc1dc7a3Sopenharmony_ci         __m128i sum17 = _mm_add_epi16(row1, row7); \
2601cc1dc7a3Sopenharmony_ci         __m128i sum35 = _mm_add_epi16(row3, row5); \
2602cc1dc7a3Sopenharmony_ci         dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \
2603cc1dc7a3Sopenharmony_ci         dct_wadd(x4, y0o, y4o); \
2604cc1dc7a3Sopenharmony_ci         dct_wadd(x5, y1o, y5o); \
2605cc1dc7a3Sopenharmony_ci         dct_wadd(x6, y2o, y5o); \
2606cc1dc7a3Sopenharmony_ci         dct_wadd(x7, y3o, y4o); \
2607cc1dc7a3Sopenharmony_ci         dct_bfly32o(row0,row7, x0,x7,bias,shift); \
2608cc1dc7a3Sopenharmony_ci         dct_bfly32o(row1,row6, x1,x6,bias,shift); \
2609cc1dc7a3Sopenharmony_ci         dct_bfly32o(row2,row5, x2,x5,bias,shift); \
2610cc1dc7a3Sopenharmony_ci         dct_bfly32o(row3,row4, x3,x4,bias,shift); \
2611cc1dc7a3Sopenharmony_ci      }
2612cc1dc7a3Sopenharmony_ci
2613cc1dc7a3Sopenharmony_ci   __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f));
2614cc1dc7a3Sopenharmony_ci   __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f));
2615cc1dc7a3Sopenharmony_ci   __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f));
2616cc1dc7a3Sopenharmony_ci   __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f));
2617cc1dc7a3Sopenharmony_ci   __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f));
2618cc1dc7a3Sopenharmony_ci   __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f));
2619cc1dc7a3Sopenharmony_ci   __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f));
2620cc1dc7a3Sopenharmony_ci   __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f));
2621cc1dc7a3Sopenharmony_ci
2622cc1dc7a3Sopenharmony_ci   // rounding biases in column/row passes, see stbi__idct_block for explanation.
2623cc1dc7a3Sopenharmony_ci   __m128i bias_0 = _mm_set1_epi32(512);
2624cc1dc7a3Sopenharmony_ci   __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17));
2625cc1dc7a3Sopenharmony_ci
2626cc1dc7a3Sopenharmony_ci   // load
2627cc1dc7a3Sopenharmony_ci   row0 = _mm_load_si128((const __m128i *) (data + 0*8));
2628cc1dc7a3Sopenharmony_ci   row1 = _mm_load_si128((const __m128i *) (data + 1*8));
2629cc1dc7a3Sopenharmony_ci   row2 = _mm_load_si128((const __m128i *) (data + 2*8));
2630cc1dc7a3Sopenharmony_ci   row3 = _mm_load_si128((const __m128i *) (data + 3*8));
2631cc1dc7a3Sopenharmony_ci   row4 = _mm_load_si128((const __m128i *) (data + 4*8));
2632cc1dc7a3Sopenharmony_ci   row5 = _mm_load_si128((const __m128i *) (data + 5*8));
2633cc1dc7a3Sopenharmony_ci   row6 = _mm_load_si128((const __m128i *) (data + 6*8));
2634cc1dc7a3Sopenharmony_ci   row7 = _mm_load_si128((const __m128i *) (data + 7*8));
2635cc1dc7a3Sopenharmony_ci
2636cc1dc7a3Sopenharmony_ci   // column pass
2637cc1dc7a3Sopenharmony_ci   dct_pass(bias_0, 10);
2638cc1dc7a3Sopenharmony_ci
2639cc1dc7a3Sopenharmony_ci   {
2640cc1dc7a3Sopenharmony_ci      // 16bit 8x8 transpose pass 1
2641cc1dc7a3Sopenharmony_ci      dct_interleave16(row0, row4);
2642cc1dc7a3Sopenharmony_ci      dct_interleave16(row1, row5);
2643cc1dc7a3Sopenharmony_ci      dct_interleave16(row2, row6);
2644cc1dc7a3Sopenharmony_ci      dct_interleave16(row3, row7);
2645cc1dc7a3Sopenharmony_ci
2646cc1dc7a3Sopenharmony_ci      // transpose pass 2
2647cc1dc7a3Sopenharmony_ci      dct_interleave16(row0, row2);
2648cc1dc7a3Sopenharmony_ci      dct_interleave16(row1, row3);
2649cc1dc7a3Sopenharmony_ci      dct_interleave16(row4, row6);
2650cc1dc7a3Sopenharmony_ci      dct_interleave16(row5, row7);
2651cc1dc7a3Sopenharmony_ci
2652cc1dc7a3Sopenharmony_ci      // transpose pass 3
2653cc1dc7a3Sopenharmony_ci      dct_interleave16(row0, row1);
2654cc1dc7a3Sopenharmony_ci      dct_interleave16(row2, row3);
2655cc1dc7a3Sopenharmony_ci      dct_interleave16(row4, row5);
2656cc1dc7a3Sopenharmony_ci      dct_interleave16(row6, row7);
2657cc1dc7a3Sopenharmony_ci   }
2658cc1dc7a3Sopenharmony_ci
2659cc1dc7a3Sopenharmony_ci   // row pass
2660cc1dc7a3Sopenharmony_ci   dct_pass(bias_1, 17);
2661cc1dc7a3Sopenharmony_ci
2662cc1dc7a3Sopenharmony_ci   {
2663cc1dc7a3Sopenharmony_ci      // pack
2664cc1dc7a3Sopenharmony_ci      __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7
2665cc1dc7a3Sopenharmony_ci      __m128i p1 = _mm_packus_epi16(row2, row3);
2666cc1dc7a3Sopenharmony_ci      __m128i p2 = _mm_packus_epi16(row4, row5);
2667cc1dc7a3Sopenharmony_ci      __m128i p3 = _mm_packus_epi16(row6, row7);
2668cc1dc7a3Sopenharmony_ci
2669cc1dc7a3Sopenharmony_ci      // 8bit 8x8 transpose pass 1
2670cc1dc7a3Sopenharmony_ci      dct_interleave8(p0, p2); // a0e0a1e1...
2671cc1dc7a3Sopenharmony_ci      dct_interleave8(p1, p3); // c0g0c1g1...
2672cc1dc7a3Sopenharmony_ci
2673cc1dc7a3Sopenharmony_ci      // transpose pass 2
2674cc1dc7a3Sopenharmony_ci      dct_interleave8(p0, p1); // a0c0e0g0...
2675cc1dc7a3Sopenharmony_ci      dct_interleave8(p2, p3); // b0d0f0h0...
2676cc1dc7a3Sopenharmony_ci
2677cc1dc7a3Sopenharmony_ci      // transpose pass 3
2678cc1dc7a3Sopenharmony_ci      dct_interleave8(p0, p2); // a0b0c0d0...
2679cc1dc7a3Sopenharmony_ci      dct_interleave8(p1, p3); // a4b4c4d4...
2680cc1dc7a3Sopenharmony_ci
2681cc1dc7a3Sopenharmony_ci      // store
2682cc1dc7a3Sopenharmony_ci      _mm_storel_epi64((__m128i *) out, p0); out += out_stride;
2683cc1dc7a3Sopenharmony_ci      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride;
2684cc1dc7a3Sopenharmony_ci      _mm_storel_epi64((__m128i *) out, p2); out += out_stride;
2685cc1dc7a3Sopenharmony_ci      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride;
2686cc1dc7a3Sopenharmony_ci      _mm_storel_epi64((__m128i *) out, p1); out += out_stride;
2687cc1dc7a3Sopenharmony_ci      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride;
2688cc1dc7a3Sopenharmony_ci      _mm_storel_epi64((__m128i *) out, p3); out += out_stride;
2689cc1dc7a3Sopenharmony_ci      _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e));
2690cc1dc7a3Sopenharmony_ci   }
2691cc1dc7a3Sopenharmony_ci
2692cc1dc7a3Sopenharmony_ci#undef dct_const
2693cc1dc7a3Sopenharmony_ci#undef dct_rot
2694cc1dc7a3Sopenharmony_ci#undef dct_widen
2695cc1dc7a3Sopenharmony_ci#undef dct_wadd
2696cc1dc7a3Sopenharmony_ci#undef dct_wsub
2697cc1dc7a3Sopenharmony_ci#undef dct_bfly32o
2698cc1dc7a3Sopenharmony_ci#undef dct_interleave8
2699cc1dc7a3Sopenharmony_ci#undef dct_interleave16
2700cc1dc7a3Sopenharmony_ci#undef dct_pass
2701cc1dc7a3Sopenharmony_ci}
2702cc1dc7a3Sopenharmony_ci
2703cc1dc7a3Sopenharmony_ci#endif // STBI_SSE2
2704cc1dc7a3Sopenharmony_ci
2705cc1dc7a3Sopenharmony_ci#ifdef STBI_NEON
2706cc1dc7a3Sopenharmony_ci
2707cc1dc7a3Sopenharmony_ci// NEON integer IDCT. should produce bit-identical
2708cc1dc7a3Sopenharmony_ci// results to the generic C version.
2709cc1dc7a3Sopenharmony_cistatic void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
2710cc1dc7a3Sopenharmony_ci{
2711cc1dc7a3Sopenharmony_ci   int16x8_t row0, row1, row2, row3, row4, row5, row6, row7;
2712cc1dc7a3Sopenharmony_ci
2713cc1dc7a3Sopenharmony_ci   int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f));
2714cc1dc7a3Sopenharmony_ci   int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f));
2715cc1dc7a3Sopenharmony_ci   int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f));
2716cc1dc7a3Sopenharmony_ci   int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f));
2717cc1dc7a3Sopenharmony_ci   int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f));
2718cc1dc7a3Sopenharmony_ci   int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f));
2719cc1dc7a3Sopenharmony_ci   int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f));
2720cc1dc7a3Sopenharmony_ci   int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f));
2721cc1dc7a3Sopenharmony_ci   int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f));
2722cc1dc7a3Sopenharmony_ci   int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f));
2723cc1dc7a3Sopenharmony_ci   int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f));
2724cc1dc7a3Sopenharmony_ci   int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f));
2725cc1dc7a3Sopenharmony_ci
2726cc1dc7a3Sopenharmony_ci#define dct_long_mul(out, inq, coeff) \
2727cc1dc7a3Sopenharmony_ci   int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \
2728cc1dc7a3Sopenharmony_ci   int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff)
2729cc1dc7a3Sopenharmony_ci
2730cc1dc7a3Sopenharmony_ci#define dct_long_mac(out, acc, inq, coeff) \
2731cc1dc7a3Sopenharmony_ci   int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \
2732cc1dc7a3Sopenharmony_ci   int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff)
2733cc1dc7a3Sopenharmony_ci
2734cc1dc7a3Sopenharmony_ci#define dct_widen(out, inq) \
2735cc1dc7a3Sopenharmony_ci   int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \
2736cc1dc7a3Sopenharmony_ci   int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12)
2737cc1dc7a3Sopenharmony_ci
2738cc1dc7a3Sopenharmony_ci// wide add
2739cc1dc7a3Sopenharmony_ci#define dct_wadd(out, a, b) \
2740cc1dc7a3Sopenharmony_ci   int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \
2741cc1dc7a3Sopenharmony_ci   int32x4_t out##_h = vaddq_s32(a##_h, b##_h)
2742cc1dc7a3Sopenharmony_ci
2743cc1dc7a3Sopenharmony_ci// wide sub
2744cc1dc7a3Sopenharmony_ci#define dct_wsub(out, a, b) \
2745cc1dc7a3Sopenharmony_ci   int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \
2746cc1dc7a3Sopenharmony_ci   int32x4_t out##_h = vsubq_s32(a##_h, b##_h)
2747cc1dc7a3Sopenharmony_ci
2748cc1dc7a3Sopenharmony_ci// butterfly a/b, then shift using "shiftop" by "s" and pack
2749cc1dc7a3Sopenharmony_ci#define dct_bfly32o(out0,out1, a,b,shiftop,s) \
2750cc1dc7a3Sopenharmony_ci   { \
2751cc1dc7a3Sopenharmony_ci      dct_wadd(sum, a, b); \
2752cc1dc7a3Sopenharmony_ci      dct_wsub(dif, a, b); \
2753cc1dc7a3Sopenharmony_ci      out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \
2754cc1dc7a3Sopenharmony_ci      out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \
2755cc1dc7a3Sopenharmony_ci   }
2756cc1dc7a3Sopenharmony_ci
2757cc1dc7a3Sopenharmony_ci#define dct_pass(shiftop, shift) \
2758cc1dc7a3Sopenharmony_ci   { \
2759cc1dc7a3Sopenharmony_ci      /* even part */ \
2760cc1dc7a3Sopenharmony_ci      int16x8_t sum26 = vaddq_s16(row2, row6); \
2761cc1dc7a3Sopenharmony_ci      dct_long_mul(p1e, sum26, rot0_0); \
2762cc1dc7a3Sopenharmony_ci      dct_long_mac(t2e, p1e, row6, rot0_1); \
2763cc1dc7a3Sopenharmony_ci      dct_long_mac(t3e, p1e, row2, rot0_2); \
2764cc1dc7a3Sopenharmony_ci      int16x8_t sum04 = vaddq_s16(row0, row4); \
2765cc1dc7a3Sopenharmony_ci      int16x8_t dif04 = vsubq_s16(row0, row4); \
2766cc1dc7a3Sopenharmony_ci      dct_widen(t0e, sum04); \
2767cc1dc7a3Sopenharmony_ci      dct_widen(t1e, dif04); \
2768cc1dc7a3Sopenharmony_ci      dct_wadd(x0, t0e, t3e); \
2769cc1dc7a3Sopenharmony_ci      dct_wsub(x3, t0e, t3e); \
2770cc1dc7a3Sopenharmony_ci      dct_wadd(x1, t1e, t2e); \
2771cc1dc7a3Sopenharmony_ci      dct_wsub(x2, t1e, t2e); \
2772cc1dc7a3Sopenharmony_ci      /* odd part */ \
2773cc1dc7a3Sopenharmony_ci      int16x8_t sum15 = vaddq_s16(row1, row5); \
2774cc1dc7a3Sopenharmony_ci      int16x8_t sum17 = vaddq_s16(row1, row7); \
2775cc1dc7a3Sopenharmony_ci      int16x8_t sum35 = vaddq_s16(row3, row5); \
2776cc1dc7a3Sopenharmony_ci      int16x8_t sum37 = vaddq_s16(row3, row7); \
2777cc1dc7a3Sopenharmony_ci      int16x8_t sumodd = vaddq_s16(sum17, sum35); \
2778cc1dc7a3Sopenharmony_ci      dct_long_mul(p5o, sumodd, rot1_0); \
2779cc1dc7a3Sopenharmony_ci      dct_long_mac(p1o, p5o, sum17, rot1_1); \
2780cc1dc7a3Sopenharmony_ci      dct_long_mac(p2o, p5o, sum35, rot1_2); \
2781cc1dc7a3Sopenharmony_ci      dct_long_mul(p3o, sum37, rot2_0); \
2782cc1dc7a3Sopenharmony_ci      dct_long_mul(p4o, sum15, rot2_1); \
2783cc1dc7a3Sopenharmony_ci      dct_wadd(sump13o, p1o, p3o); \
2784cc1dc7a3Sopenharmony_ci      dct_wadd(sump24o, p2o, p4o); \
2785cc1dc7a3Sopenharmony_ci      dct_wadd(sump23o, p2o, p3o); \
2786cc1dc7a3Sopenharmony_ci      dct_wadd(sump14o, p1o, p4o); \
2787cc1dc7a3Sopenharmony_ci      dct_long_mac(x4, sump13o, row7, rot3_0); \
2788cc1dc7a3Sopenharmony_ci      dct_long_mac(x5, sump24o, row5, rot3_1); \
2789cc1dc7a3Sopenharmony_ci      dct_long_mac(x6, sump23o, row3, rot3_2); \
2790cc1dc7a3Sopenharmony_ci      dct_long_mac(x7, sump14o, row1, rot3_3); \
2791cc1dc7a3Sopenharmony_ci      dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \
2792cc1dc7a3Sopenharmony_ci      dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \
2793cc1dc7a3Sopenharmony_ci      dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \
2794cc1dc7a3Sopenharmony_ci      dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \
2795cc1dc7a3Sopenharmony_ci   }
2796cc1dc7a3Sopenharmony_ci
2797cc1dc7a3Sopenharmony_ci   // load
2798cc1dc7a3Sopenharmony_ci   row0 = vld1q_s16(data + 0*8);
2799cc1dc7a3Sopenharmony_ci   row1 = vld1q_s16(data + 1*8);
2800cc1dc7a3Sopenharmony_ci   row2 = vld1q_s16(data + 2*8);
2801cc1dc7a3Sopenharmony_ci   row3 = vld1q_s16(data + 3*8);
2802cc1dc7a3Sopenharmony_ci   row4 = vld1q_s16(data + 4*8);
2803cc1dc7a3Sopenharmony_ci   row5 = vld1q_s16(data + 5*8);
2804cc1dc7a3Sopenharmony_ci   row6 = vld1q_s16(data + 6*8);
2805cc1dc7a3Sopenharmony_ci   row7 = vld1q_s16(data + 7*8);
2806cc1dc7a3Sopenharmony_ci
2807cc1dc7a3Sopenharmony_ci   // add DC bias
2808cc1dc7a3Sopenharmony_ci   row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0));
2809cc1dc7a3Sopenharmony_ci
2810cc1dc7a3Sopenharmony_ci   // column pass
2811cc1dc7a3Sopenharmony_ci   dct_pass(vrshrn_n_s32, 10);
2812cc1dc7a3Sopenharmony_ci
2813cc1dc7a3Sopenharmony_ci   // 16bit 8x8 transpose
2814cc1dc7a3Sopenharmony_ci   {
2815cc1dc7a3Sopenharmony_ci// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively.
2816cc1dc7a3Sopenharmony_ci// whether compilers actually get this is another story, sadly.
2817cc1dc7a3Sopenharmony_ci#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; }
2818cc1dc7a3Sopenharmony_ci#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); }
2819cc1dc7a3Sopenharmony_ci#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); }
2820cc1dc7a3Sopenharmony_ci
2821cc1dc7a3Sopenharmony_ci      // pass 1
2822cc1dc7a3Sopenharmony_ci      dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6
2823cc1dc7a3Sopenharmony_ci      dct_trn16(row2, row3);
2824cc1dc7a3Sopenharmony_ci      dct_trn16(row4, row5);
2825cc1dc7a3Sopenharmony_ci      dct_trn16(row6, row7);
2826cc1dc7a3Sopenharmony_ci
2827cc1dc7a3Sopenharmony_ci      // pass 2
2828cc1dc7a3Sopenharmony_ci      dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4
2829cc1dc7a3Sopenharmony_ci      dct_trn32(row1, row3);
2830cc1dc7a3Sopenharmony_ci      dct_trn32(row4, row6);
2831cc1dc7a3Sopenharmony_ci      dct_trn32(row5, row7);
2832cc1dc7a3Sopenharmony_ci
2833cc1dc7a3Sopenharmony_ci      // pass 3
2834cc1dc7a3Sopenharmony_ci      dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0
2835cc1dc7a3Sopenharmony_ci      dct_trn64(row1, row5);
2836cc1dc7a3Sopenharmony_ci      dct_trn64(row2, row6);
2837cc1dc7a3Sopenharmony_ci      dct_trn64(row3, row7);
2838cc1dc7a3Sopenharmony_ci
2839cc1dc7a3Sopenharmony_ci#undef dct_trn16
2840cc1dc7a3Sopenharmony_ci#undef dct_trn32
2841cc1dc7a3Sopenharmony_ci#undef dct_trn64
2842cc1dc7a3Sopenharmony_ci   }
2843cc1dc7a3Sopenharmony_ci
2844cc1dc7a3Sopenharmony_ci   // row pass
2845cc1dc7a3Sopenharmony_ci   // vrshrn_n_s32 only supports shifts up to 16, we need
2846cc1dc7a3Sopenharmony_ci   // 17. so do a non-rounding shift of 16 first then follow
2847cc1dc7a3Sopenharmony_ci   // up with a rounding shift by 1.
2848cc1dc7a3Sopenharmony_ci   dct_pass(vshrn_n_s32, 16);
2849cc1dc7a3Sopenharmony_ci
2850cc1dc7a3Sopenharmony_ci   {
2851cc1dc7a3Sopenharmony_ci      // pack and round
2852cc1dc7a3Sopenharmony_ci      uint8x8_t p0 = vqrshrun_n_s16(row0, 1);
2853cc1dc7a3Sopenharmony_ci      uint8x8_t p1 = vqrshrun_n_s16(row1, 1);
2854cc1dc7a3Sopenharmony_ci      uint8x8_t p2 = vqrshrun_n_s16(row2, 1);
2855cc1dc7a3Sopenharmony_ci      uint8x8_t p3 = vqrshrun_n_s16(row3, 1);
2856cc1dc7a3Sopenharmony_ci      uint8x8_t p4 = vqrshrun_n_s16(row4, 1);
2857cc1dc7a3Sopenharmony_ci      uint8x8_t p5 = vqrshrun_n_s16(row5, 1);
2858cc1dc7a3Sopenharmony_ci      uint8x8_t p6 = vqrshrun_n_s16(row6, 1);
2859cc1dc7a3Sopenharmony_ci      uint8x8_t p7 = vqrshrun_n_s16(row7, 1);
2860cc1dc7a3Sopenharmony_ci
2861cc1dc7a3Sopenharmony_ci      // again, these can translate into one instruction, but often don't.
2862cc1dc7a3Sopenharmony_ci#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; }
2863cc1dc7a3Sopenharmony_ci#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); }
2864cc1dc7a3Sopenharmony_ci#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); }
2865cc1dc7a3Sopenharmony_ci
2866cc1dc7a3Sopenharmony_ci      // sadly can't use interleaved stores here since we only write
2867cc1dc7a3Sopenharmony_ci      // 8 bytes to each scan line!
2868cc1dc7a3Sopenharmony_ci
2869cc1dc7a3Sopenharmony_ci      // 8x8 8-bit transpose pass 1
2870cc1dc7a3Sopenharmony_ci      dct_trn8_8(p0, p1);
2871cc1dc7a3Sopenharmony_ci      dct_trn8_8(p2, p3);
2872cc1dc7a3Sopenharmony_ci      dct_trn8_8(p4, p5);
2873cc1dc7a3Sopenharmony_ci      dct_trn8_8(p6, p7);
2874cc1dc7a3Sopenharmony_ci
2875cc1dc7a3Sopenharmony_ci      // pass 2
2876cc1dc7a3Sopenharmony_ci      dct_trn8_16(p0, p2);
2877cc1dc7a3Sopenharmony_ci      dct_trn8_16(p1, p3);
2878cc1dc7a3Sopenharmony_ci      dct_trn8_16(p4, p6);
2879cc1dc7a3Sopenharmony_ci      dct_trn8_16(p5, p7);
2880cc1dc7a3Sopenharmony_ci
2881cc1dc7a3Sopenharmony_ci      // pass 3
2882cc1dc7a3Sopenharmony_ci      dct_trn8_32(p0, p4);
2883cc1dc7a3Sopenharmony_ci      dct_trn8_32(p1, p5);
2884cc1dc7a3Sopenharmony_ci      dct_trn8_32(p2, p6);
2885cc1dc7a3Sopenharmony_ci      dct_trn8_32(p3, p7);
2886cc1dc7a3Sopenharmony_ci
2887cc1dc7a3Sopenharmony_ci      // store
2888cc1dc7a3Sopenharmony_ci      vst1_u8(out, p0); out += out_stride;
2889cc1dc7a3Sopenharmony_ci      vst1_u8(out, p1); out += out_stride;
2890cc1dc7a3Sopenharmony_ci      vst1_u8(out, p2); out += out_stride;
2891cc1dc7a3Sopenharmony_ci      vst1_u8(out, p3); out += out_stride;
2892cc1dc7a3Sopenharmony_ci      vst1_u8(out, p4); out += out_stride;
2893cc1dc7a3Sopenharmony_ci      vst1_u8(out, p5); out += out_stride;
2894cc1dc7a3Sopenharmony_ci      vst1_u8(out, p6); out += out_stride;
2895cc1dc7a3Sopenharmony_ci      vst1_u8(out, p7);
2896cc1dc7a3Sopenharmony_ci
2897cc1dc7a3Sopenharmony_ci#undef dct_trn8_8
2898cc1dc7a3Sopenharmony_ci#undef dct_trn8_16
2899cc1dc7a3Sopenharmony_ci#undef dct_trn8_32
2900cc1dc7a3Sopenharmony_ci   }
2901cc1dc7a3Sopenharmony_ci
2902cc1dc7a3Sopenharmony_ci#undef dct_long_mul
2903cc1dc7a3Sopenharmony_ci#undef dct_long_mac
2904cc1dc7a3Sopenharmony_ci#undef dct_widen
2905cc1dc7a3Sopenharmony_ci#undef dct_wadd
2906cc1dc7a3Sopenharmony_ci#undef dct_wsub
2907cc1dc7a3Sopenharmony_ci#undef dct_bfly32o
2908cc1dc7a3Sopenharmony_ci#undef dct_pass
2909cc1dc7a3Sopenharmony_ci}
2910cc1dc7a3Sopenharmony_ci
2911cc1dc7a3Sopenharmony_ci#endif // STBI_NEON
2912cc1dc7a3Sopenharmony_ci
2913cc1dc7a3Sopenharmony_ci#define STBI__MARKER_none  0xff
2914cc1dc7a3Sopenharmony_ci// if there's a pending marker from the entropy stream, return that
2915cc1dc7a3Sopenharmony_ci// otherwise, fetch from the stream and get a marker. if there's no
2916cc1dc7a3Sopenharmony_ci// marker, return 0xff, which is never a valid marker value
2917cc1dc7a3Sopenharmony_cistatic stbi_uc stbi__get_marker(stbi__jpeg *j)
2918cc1dc7a3Sopenharmony_ci{
2919cc1dc7a3Sopenharmony_ci   stbi_uc x;
2920cc1dc7a3Sopenharmony_ci   if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; }
2921cc1dc7a3Sopenharmony_ci   x = stbi__get8(j->s);
2922cc1dc7a3Sopenharmony_ci   if (x != 0xff) return STBI__MARKER_none;
2923cc1dc7a3Sopenharmony_ci   while (x == 0xff)
2924cc1dc7a3Sopenharmony_ci      x = stbi__get8(j->s); // consume repeated 0xff fill bytes
2925cc1dc7a3Sopenharmony_ci   return x;
2926cc1dc7a3Sopenharmony_ci}
2927cc1dc7a3Sopenharmony_ci
2928cc1dc7a3Sopenharmony_ci// in each scan, we'll have scan_n components, and the order
2929cc1dc7a3Sopenharmony_ci// of the components is specified by order[]
2930cc1dc7a3Sopenharmony_ci#define STBI__RESTART(x)     ((x) >= 0xd0 && (x) <= 0xd7)
2931cc1dc7a3Sopenharmony_ci
2932cc1dc7a3Sopenharmony_ci// after a restart interval, stbi__jpeg_reset the entropy decoder and
2933cc1dc7a3Sopenharmony_ci// the dc prediction
2934cc1dc7a3Sopenharmony_cistatic void stbi__jpeg_reset(stbi__jpeg *j)
2935cc1dc7a3Sopenharmony_ci{
2936cc1dc7a3Sopenharmony_ci   j->code_bits = 0;
2937cc1dc7a3Sopenharmony_ci   j->code_buffer = 0;
2938cc1dc7a3Sopenharmony_ci   j->nomore = 0;
2939cc1dc7a3Sopenharmony_ci   j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0;
2940cc1dc7a3Sopenharmony_ci   j->marker = STBI__MARKER_none;
2941cc1dc7a3Sopenharmony_ci   j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff;
2942cc1dc7a3Sopenharmony_ci   j->eob_run = 0;
2943cc1dc7a3Sopenharmony_ci   // no more than 1<<31 MCUs if no restart_interal? that's plenty safe,
2944cc1dc7a3Sopenharmony_ci   // since we don't even allow 1<<30 pixels
2945cc1dc7a3Sopenharmony_ci}
2946cc1dc7a3Sopenharmony_ci
2947cc1dc7a3Sopenharmony_cistatic int stbi__parse_entropy_coded_data(stbi__jpeg *z)
2948cc1dc7a3Sopenharmony_ci{
2949cc1dc7a3Sopenharmony_ci   stbi__jpeg_reset(z);
2950cc1dc7a3Sopenharmony_ci   if (!z->progressive) {
2951cc1dc7a3Sopenharmony_ci      if (z->scan_n == 1) {
2952cc1dc7a3Sopenharmony_ci         int i,j;
2953cc1dc7a3Sopenharmony_ci         STBI_SIMD_ALIGN(short, data[64]);
2954cc1dc7a3Sopenharmony_ci         int n = z->order[0];
2955cc1dc7a3Sopenharmony_ci         // non-interleaved data, we just need to process one block at a time,
2956cc1dc7a3Sopenharmony_ci         // in trivial scanline order
2957cc1dc7a3Sopenharmony_ci         // number of blocks to do just depends on how many actual "pixels" this
2958cc1dc7a3Sopenharmony_ci         // component has, independent of interleaved MCU blocking and such
2959cc1dc7a3Sopenharmony_ci         int w = (z->img_comp[n].x+7) >> 3;
2960cc1dc7a3Sopenharmony_ci         int h = (z->img_comp[n].y+7) >> 3;
2961cc1dc7a3Sopenharmony_ci         for (j=0; j < h; ++j) {
2962cc1dc7a3Sopenharmony_ci            for (i=0; i < w; ++i) {
2963cc1dc7a3Sopenharmony_ci               int ha = z->img_comp[n].ha;
2964cc1dc7a3Sopenharmony_ci               if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0;
2965cc1dc7a3Sopenharmony_ci               z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data);
2966cc1dc7a3Sopenharmony_ci               // every data block is an MCU, so countdown the restart interval
2967cc1dc7a3Sopenharmony_ci               if (--z->todo <= 0) {
2968cc1dc7a3Sopenharmony_ci                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
2969cc1dc7a3Sopenharmony_ci                  // if it's NOT a restart, then just bail, so we get corrupt data
2970cc1dc7a3Sopenharmony_ci                  // rather than no data
2971cc1dc7a3Sopenharmony_ci                  if (!STBI__RESTART(z->marker)) return 1;
2972cc1dc7a3Sopenharmony_ci                  stbi__jpeg_reset(z);
2973cc1dc7a3Sopenharmony_ci               }
2974cc1dc7a3Sopenharmony_ci            }
2975cc1dc7a3Sopenharmony_ci         }
2976cc1dc7a3Sopenharmony_ci         return 1;
2977cc1dc7a3Sopenharmony_ci      } else { // interleaved
2978cc1dc7a3Sopenharmony_ci         int i,j,k,x,y;
2979cc1dc7a3Sopenharmony_ci         STBI_SIMD_ALIGN(short, data[64]);
2980cc1dc7a3Sopenharmony_ci         for (j=0; j < z->img_mcu_y; ++j) {
2981cc1dc7a3Sopenharmony_ci            for (i=0; i < z->img_mcu_x; ++i) {
2982cc1dc7a3Sopenharmony_ci               // scan an interleaved mcu... process scan_n components in order
2983cc1dc7a3Sopenharmony_ci               for (k=0; k < z->scan_n; ++k) {
2984cc1dc7a3Sopenharmony_ci                  int n = z->order[k];
2985cc1dc7a3Sopenharmony_ci                  // scan out an mcu's worth of this component; that's just determined
2986cc1dc7a3Sopenharmony_ci                  // by the basic H and V specified for the component
2987cc1dc7a3Sopenharmony_ci                  for (y=0; y < z->img_comp[n].v; ++y) {
2988cc1dc7a3Sopenharmony_ci                     for (x=0; x < z->img_comp[n].h; ++x) {
2989cc1dc7a3Sopenharmony_ci                        int x2 = (i*z->img_comp[n].h + x)*8;
2990cc1dc7a3Sopenharmony_ci                        int y2 = (j*z->img_comp[n].v + y)*8;
2991cc1dc7a3Sopenharmony_ci                        int ha = z->img_comp[n].ha;
2992cc1dc7a3Sopenharmony_ci                        if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0;
2993cc1dc7a3Sopenharmony_ci                        z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data);
2994cc1dc7a3Sopenharmony_ci                     }
2995cc1dc7a3Sopenharmony_ci                  }
2996cc1dc7a3Sopenharmony_ci               }
2997cc1dc7a3Sopenharmony_ci               // after all interleaved components, that's an interleaved MCU,
2998cc1dc7a3Sopenharmony_ci               // so now count down the restart interval
2999cc1dc7a3Sopenharmony_ci               if (--z->todo <= 0) {
3000cc1dc7a3Sopenharmony_ci                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
3001cc1dc7a3Sopenharmony_ci                  if (!STBI__RESTART(z->marker)) return 1;
3002cc1dc7a3Sopenharmony_ci                  stbi__jpeg_reset(z);
3003cc1dc7a3Sopenharmony_ci               }
3004cc1dc7a3Sopenharmony_ci            }
3005cc1dc7a3Sopenharmony_ci         }
3006cc1dc7a3Sopenharmony_ci         return 1;
3007cc1dc7a3Sopenharmony_ci      }
3008cc1dc7a3Sopenharmony_ci   } else {
3009cc1dc7a3Sopenharmony_ci      if (z->scan_n == 1) {
3010cc1dc7a3Sopenharmony_ci         int i,j;
3011cc1dc7a3Sopenharmony_ci         int n = z->order[0];
3012cc1dc7a3Sopenharmony_ci         // non-interleaved data, we just need to process one block at a time,
3013cc1dc7a3Sopenharmony_ci         // in trivial scanline order
3014cc1dc7a3Sopenharmony_ci         // number of blocks to do just depends on how many actual "pixels" this
3015cc1dc7a3Sopenharmony_ci         // component has, independent of interleaved MCU blocking and such
3016cc1dc7a3Sopenharmony_ci         int w = (z->img_comp[n].x+7) >> 3;
3017cc1dc7a3Sopenharmony_ci         int h = (z->img_comp[n].y+7) >> 3;
3018cc1dc7a3Sopenharmony_ci         for (j=0; j < h; ++j) {
3019cc1dc7a3Sopenharmony_ci            for (i=0; i < w; ++i) {
3020cc1dc7a3Sopenharmony_ci               short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);
3021cc1dc7a3Sopenharmony_ci               if (z->spec_start == 0) {
3022cc1dc7a3Sopenharmony_ci                  if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))
3023cc1dc7a3Sopenharmony_ci                     return 0;
3024cc1dc7a3Sopenharmony_ci               } else {
3025cc1dc7a3Sopenharmony_ci                  int ha = z->img_comp[n].ha;
3026cc1dc7a3Sopenharmony_ci                  if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha]))
3027cc1dc7a3Sopenharmony_ci                     return 0;
3028cc1dc7a3Sopenharmony_ci               }
3029cc1dc7a3Sopenharmony_ci               // every data block is an MCU, so countdown the restart interval
3030cc1dc7a3Sopenharmony_ci               if (--z->todo <= 0) {
3031cc1dc7a3Sopenharmony_ci                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
3032cc1dc7a3Sopenharmony_ci                  if (!STBI__RESTART(z->marker)) return 1;
3033cc1dc7a3Sopenharmony_ci                  stbi__jpeg_reset(z);
3034cc1dc7a3Sopenharmony_ci               }
3035cc1dc7a3Sopenharmony_ci            }
3036cc1dc7a3Sopenharmony_ci         }
3037cc1dc7a3Sopenharmony_ci         return 1;
3038cc1dc7a3Sopenharmony_ci      } else { // interleaved
3039cc1dc7a3Sopenharmony_ci         int i,j,k,x,y;
3040cc1dc7a3Sopenharmony_ci         for (j=0; j < z->img_mcu_y; ++j) {
3041cc1dc7a3Sopenharmony_ci            for (i=0; i < z->img_mcu_x; ++i) {
3042cc1dc7a3Sopenharmony_ci               // scan an interleaved mcu... process scan_n components in order
3043cc1dc7a3Sopenharmony_ci               for (k=0; k < z->scan_n; ++k) {
3044cc1dc7a3Sopenharmony_ci                  int n = z->order[k];
3045cc1dc7a3Sopenharmony_ci                  // scan out an mcu's worth of this component; that's just determined
3046cc1dc7a3Sopenharmony_ci                  // by the basic H and V specified for the component
3047cc1dc7a3Sopenharmony_ci                  for (y=0; y < z->img_comp[n].v; ++y) {
3048cc1dc7a3Sopenharmony_ci                     for (x=0; x < z->img_comp[n].h; ++x) {
3049cc1dc7a3Sopenharmony_ci                        int x2 = (i*z->img_comp[n].h + x);
3050cc1dc7a3Sopenharmony_ci                        int y2 = (j*z->img_comp[n].v + y);
3051cc1dc7a3Sopenharmony_ci                        short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w);
3052cc1dc7a3Sopenharmony_ci                        if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))
3053cc1dc7a3Sopenharmony_ci                           return 0;
3054cc1dc7a3Sopenharmony_ci                     }
3055cc1dc7a3Sopenharmony_ci                  }
3056cc1dc7a3Sopenharmony_ci               }
3057cc1dc7a3Sopenharmony_ci               // after all interleaved components, that's an interleaved MCU,
3058cc1dc7a3Sopenharmony_ci               // so now count down the restart interval
3059cc1dc7a3Sopenharmony_ci               if (--z->todo <= 0) {
3060cc1dc7a3Sopenharmony_ci                  if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);
3061cc1dc7a3Sopenharmony_ci                  if (!STBI__RESTART(z->marker)) return 1;
3062cc1dc7a3Sopenharmony_ci                  stbi__jpeg_reset(z);
3063cc1dc7a3Sopenharmony_ci               }
3064cc1dc7a3Sopenharmony_ci            }
3065cc1dc7a3Sopenharmony_ci         }
3066cc1dc7a3Sopenharmony_ci         return 1;
3067cc1dc7a3Sopenharmony_ci      }
3068cc1dc7a3Sopenharmony_ci   }
3069cc1dc7a3Sopenharmony_ci}
3070cc1dc7a3Sopenharmony_ci
3071cc1dc7a3Sopenharmony_cistatic void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant)
3072cc1dc7a3Sopenharmony_ci{
3073cc1dc7a3Sopenharmony_ci   int i;
3074cc1dc7a3Sopenharmony_ci   for (i=0; i < 64; ++i)
3075cc1dc7a3Sopenharmony_ci      data[i] *= dequant[i];
3076cc1dc7a3Sopenharmony_ci}
3077cc1dc7a3Sopenharmony_ci
3078cc1dc7a3Sopenharmony_cistatic void stbi__jpeg_finish(stbi__jpeg *z)
3079cc1dc7a3Sopenharmony_ci{
3080cc1dc7a3Sopenharmony_ci   if (z->progressive) {
3081cc1dc7a3Sopenharmony_ci      // dequantize and idct the data
3082cc1dc7a3Sopenharmony_ci      int i,j,n;
3083cc1dc7a3Sopenharmony_ci      for (n=0; n < z->s->img_n; ++n) {
3084cc1dc7a3Sopenharmony_ci         int w = (z->img_comp[n].x+7) >> 3;
3085cc1dc7a3Sopenharmony_ci         int h = (z->img_comp[n].y+7) >> 3;
3086cc1dc7a3Sopenharmony_ci         for (j=0; j < h; ++j) {
3087cc1dc7a3Sopenharmony_ci            for (i=0; i < w; ++i) {
3088cc1dc7a3Sopenharmony_ci               short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);
3089cc1dc7a3Sopenharmony_ci               stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]);
3090cc1dc7a3Sopenharmony_ci               z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data);
3091cc1dc7a3Sopenharmony_ci            }
3092cc1dc7a3Sopenharmony_ci         }
3093cc1dc7a3Sopenharmony_ci      }
3094cc1dc7a3Sopenharmony_ci   }
3095cc1dc7a3Sopenharmony_ci}
3096cc1dc7a3Sopenharmony_ci
3097cc1dc7a3Sopenharmony_cistatic int stbi__process_marker(stbi__jpeg *z, int m)
3098cc1dc7a3Sopenharmony_ci{
3099cc1dc7a3Sopenharmony_ci   int L;
3100cc1dc7a3Sopenharmony_ci   switch (m) {
3101cc1dc7a3Sopenharmony_ci      case STBI__MARKER_none: // no marker found
3102cc1dc7a3Sopenharmony_ci         return stbi__err("expected marker","Corrupt JPEG");
3103cc1dc7a3Sopenharmony_ci
3104cc1dc7a3Sopenharmony_ci      case 0xDD: // DRI - specify restart interval
3105cc1dc7a3Sopenharmony_ci         if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG");
3106cc1dc7a3Sopenharmony_ci         z->restart_interval = stbi__get16be(z->s);
3107cc1dc7a3Sopenharmony_ci         return 1;
3108cc1dc7a3Sopenharmony_ci
3109cc1dc7a3Sopenharmony_ci      case 0xDB: // DQT - define quantization table
3110cc1dc7a3Sopenharmony_ci         L = stbi__get16be(z->s)-2;
3111cc1dc7a3Sopenharmony_ci         while (L > 0) {
3112cc1dc7a3Sopenharmony_ci            int q = stbi__get8(z->s);
3113cc1dc7a3Sopenharmony_ci            int p = q >> 4, sixteen = (p != 0);
3114cc1dc7a3Sopenharmony_ci            int t = q & 15,i;
3115cc1dc7a3Sopenharmony_ci            if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG");
3116cc1dc7a3Sopenharmony_ci            if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG");
3117cc1dc7a3Sopenharmony_ci
3118cc1dc7a3Sopenharmony_ci            for (i=0; i < 64; ++i)
3119cc1dc7a3Sopenharmony_ci               z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s));
3120cc1dc7a3Sopenharmony_ci            L -= (sixteen ? 129 : 65);
3121cc1dc7a3Sopenharmony_ci         }
3122cc1dc7a3Sopenharmony_ci         return L==0;
3123cc1dc7a3Sopenharmony_ci
3124cc1dc7a3Sopenharmony_ci      case 0xC4: // DHT - define huffman table
3125cc1dc7a3Sopenharmony_ci         L = stbi__get16be(z->s)-2;
3126cc1dc7a3Sopenharmony_ci         while (L > 0) {
3127cc1dc7a3Sopenharmony_ci            stbi_uc *v;
3128cc1dc7a3Sopenharmony_ci            int sizes[16],i,n=0;
3129cc1dc7a3Sopenharmony_ci            int q = stbi__get8(z->s);
3130cc1dc7a3Sopenharmony_ci            int tc = q >> 4;
3131cc1dc7a3Sopenharmony_ci            int th = q & 15;
3132cc1dc7a3Sopenharmony_ci            if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG");
3133cc1dc7a3Sopenharmony_ci            for (i=0; i < 16; ++i) {
3134cc1dc7a3Sopenharmony_ci               sizes[i] = stbi__get8(z->s);
3135cc1dc7a3Sopenharmony_ci               n += sizes[i];
3136cc1dc7a3Sopenharmony_ci            }
3137cc1dc7a3Sopenharmony_ci            if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values!
3138cc1dc7a3Sopenharmony_ci            L -= 17;
3139cc1dc7a3Sopenharmony_ci            if (tc == 0) {
3140cc1dc7a3Sopenharmony_ci               if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0;
3141cc1dc7a3Sopenharmony_ci               v = z->huff_dc[th].values;
3142cc1dc7a3Sopenharmony_ci            } else {
3143cc1dc7a3Sopenharmony_ci               if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0;
3144cc1dc7a3Sopenharmony_ci               v = z->huff_ac[th].values;
3145cc1dc7a3Sopenharmony_ci            }
3146cc1dc7a3Sopenharmony_ci            for (i=0; i < n; ++i)
3147cc1dc7a3Sopenharmony_ci               v[i] = stbi__get8(z->s);
3148cc1dc7a3Sopenharmony_ci            if (tc != 0)
3149cc1dc7a3Sopenharmony_ci               stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th);
3150cc1dc7a3Sopenharmony_ci            L -= n;
3151cc1dc7a3Sopenharmony_ci         }
3152cc1dc7a3Sopenharmony_ci         return L==0;
3153cc1dc7a3Sopenharmony_ci   }
3154cc1dc7a3Sopenharmony_ci
3155cc1dc7a3Sopenharmony_ci   // check for comment block or APP blocks
3156cc1dc7a3Sopenharmony_ci   if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) {
3157cc1dc7a3Sopenharmony_ci      L = stbi__get16be(z->s);
3158cc1dc7a3Sopenharmony_ci      if (L < 2) {
3159cc1dc7a3Sopenharmony_ci         if (m == 0xFE)
3160cc1dc7a3Sopenharmony_ci            return stbi__err("bad COM len","Corrupt JPEG");
3161cc1dc7a3Sopenharmony_ci         else
3162cc1dc7a3Sopenharmony_ci            return stbi__err("bad APP len","Corrupt JPEG");
3163cc1dc7a3Sopenharmony_ci      }
3164cc1dc7a3Sopenharmony_ci      L -= 2;
3165cc1dc7a3Sopenharmony_ci
3166cc1dc7a3Sopenharmony_ci      if (m == 0xE0 && L >= 5) { // JFIF APP0 segment
3167cc1dc7a3Sopenharmony_ci         static const unsigned char tag[5] = {'J','F','I','F','\0'};
3168cc1dc7a3Sopenharmony_ci         int ok = 1;
3169cc1dc7a3Sopenharmony_ci         int i;
3170cc1dc7a3Sopenharmony_ci         for (i=0; i < 5; ++i)
3171cc1dc7a3Sopenharmony_ci            if (stbi__get8(z->s) != tag[i])
3172cc1dc7a3Sopenharmony_ci               ok = 0;
3173cc1dc7a3Sopenharmony_ci         L -= 5;
3174cc1dc7a3Sopenharmony_ci         if (ok)
3175cc1dc7a3Sopenharmony_ci            z->jfif = 1;
3176cc1dc7a3Sopenharmony_ci      } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment
3177cc1dc7a3Sopenharmony_ci         static const unsigned char tag[6] = {'A','d','o','b','e','\0'};
3178cc1dc7a3Sopenharmony_ci         int ok = 1;
3179cc1dc7a3Sopenharmony_ci         int i;
3180cc1dc7a3Sopenharmony_ci         for (i=0; i < 6; ++i)
3181cc1dc7a3Sopenharmony_ci            if (stbi__get8(z->s) != tag[i])
3182cc1dc7a3Sopenharmony_ci               ok = 0;
3183cc1dc7a3Sopenharmony_ci         L -= 6;
3184cc1dc7a3Sopenharmony_ci         if (ok) {
3185cc1dc7a3Sopenharmony_ci            stbi__get8(z->s); // version
3186cc1dc7a3Sopenharmony_ci            stbi__get16be(z->s); // flags0
3187cc1dc7a3Sopenharmony_ci            stbi__get16be(z->s); // flags1
3188cc1dc7a3Sopenharmony_ci            z->app14_color_transform = stbi__get8(z->s); // color transform
3189cc1dc7a3Sopenharmony_ci            L -= 6;
3190cc1dc7a3Sopenharmony_ci         }
3191cc1dc7a3Sopenharmony_ci      }
3192cc1dc7a3Sopenharmony_ci
3193cc1dc7a3Sopenharmony_ci      stbi__skip(z->s, L);
3194cc1dc7a3Sopenharmony_ci      return 1;
3195cc1dc7a3Sopenharmony_ci   }
3196cc1dc7a3Sopenharmony_ci
3197cc1dc7a3Sopenharmony_ci   return stbi__err("unknown marker","Corrupt JPEG");
3198cc1dc7a3Sopenharmony_ci}
3199cc1dc7a3Sopenharmony_ci
3200cc1dc7a3Sopenharmony_ci// after we see SOS
3201cc1dc7a3Sopenharmony_cistatic int stbi__process_scan_header(stbi__jpeg *z)
3202cc1dc7a3Sopenharmony_ci{
3203cc1dc7a3Sopenharmony_ci   int i;
3204cc1dc7a3Sopenharmony_ci   int Ls = stbi__get16be(z->s);
3205cc1dc7a3Sopenharmony_ci   z->scan_n = stbi__get8(z->s);
3206cc1dc7a3Sopenharmony_ci   if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG");
3207cc1dc7a3Sopenharmony_ci   if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG");
3208cc1dc7a3Sopenharmony_ci   for (i=0; i < z->scan_n; ++i) {
3209cc1dc7a3Sopenharmony_ci      int id = stbi__get8(z->s), which;
3210cc1dc7a3Sopenharmony_ci      int q = stbi__get8(z->s);
3211cc1dc7a3Sopenharmony_ci      for (which = 0; which < z->s->img_n; ++which)
3212cc1dc7a3Sopenharmony_ci         if (z->img_comp[which].id == id)
3213cc1dc7a3Sopenharmony_ci            break;
3214cc1dc7a3Sopenharmony_ci      if (which == z->s->img_n) return 0; // no match
3215cc1dc7a3Sopenharmony_ci      z->img_comp[which].hd = q >> 4;   if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG");
3216cc1dc7a3Sopenharmony_ci      z->img_comp[which].ha = q & 15;   if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG");
3217cc1dc7a3Sopenharmony_ci      z->order[i] = which;
3218cc1dc7a3Sopenharmony_ci   }
3219cc1dc7a3Sopenharmony_ci
3220cc1dc7a3Sopenharmony_ci   {
3221cc1dc7a3Sopenharmony_ci      int aa;
3222cc1dc7a3Sopenharmony_ci      z->spec_start = stbi__get8(z->s);
3223cc1dc7a3Sopenharmony_ci      z->spec_end   = stbi__get8(z->s); // should be 63, but might be 0
3224cc1dc7a3Sopenharmony_ci      aa = stbi__get8(z->s);
3225cc1dc7a3Sopenharmony_ci      z->succ_high = (aa >> 4);
3226cc1dc7a3Sopenharmony_ci      z->succ_low  = (aa & 15);
3227cc1dc7a3Sopenharmony_ci      if (z->progressive) {
3228cc1dc7a3Sopenharmony_ci         if (z->spec_start > 63 || z->spec_end > 63  || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13)
3229cc1dc7a3Sopenharmony_ci            return stbi__err("bad SOS", "Corrupt JPEG");
3230cc1dc7a3Sopenharmony_ci      } else {
3231cc1dc7a3Sopenharmony_ci         if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG");
3232cc1dc7a3Sopenharmony_ci         if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG");
3233cc1dc7a3Sopenharmony_ci         z->spec_end = 63;
3234cc1dc7a3Sopenharmony_ci      }
3235cc1dc7a3Sopenharmony_ci   }
3236cc1dc7a3Sopenharmony_ci
3237cc1dc7a3Sopenharmony_ci   return 1;
3238cc1dc7a3Sopenharmony_ci}
3239cc1dc7a3Sopenharmony_ci
3240cc1dc7a3Sopenharmony_cistatic int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why)
3241cc1dc7a3Sopenharmony_ci{
3242cc1dc7a3Sopenharmony_ci   int i;
3243cc1dc7a3Sopenharmony_ci   for (i=0; i < ncomp; ++i) {
3244cc1dc7a3Sopenharmony_ci      if (z->img_comp[i].raw_data) {
3245cc1dc7a3Sopenharmony_ci         STBI_FREE(z->img_comp[i].raw_data);
3246cc1dc7a3Sopenharmony_ci         z->img_comp[i].raw_data = NULL;
3247cc1dc7a3Sopenharmony_ci         z->img_comp[i].data = NULL;
3248cc1dc7a3Sopenharmony_ci      }
3249cc1dc7a3Sopenharmony_ci      if (z->img_comp[i].raw_coeff) {
3250cc1dc7a3Sopenharmony_ci         STBI_FREE(z->img_comp[i].raw_coeff);
3251cc1dc7a3Sopenharmony_ci         z->img_comp[i].raw_coeff = 0;
3252cc1dc7a3Sopenharmony_ci         z->img_comp[i].coeff = 0;
3253cc1dc7a3Sopenharmony_ci      }
3254cc1dc7a3Sopenharmony_ci      if (z->img_comp[i].linebuf) {
3255cc1dc7a3Sopenharmony_ci         STBI_FREE(z->img_comp[i].linebuf);
3256cc1dc7a3Sopenharmony_ci         z->img_comp[i].linebuf = NULL;
3257cc1dc7a3Sopenharmony_ci      }
3258cc1dc7a3Sopenharmony_ci   }
3259cc1dc7a3Sopenharmony_ci   return why;
3260cc1dc7a3Sopenharmony_ci}
3261cc1dc7a3Sopenharmony_ci
3262cc1dc7a3Sopenharmony_cistatic int stbi__process_frame_header(stbi__jpeg *z, int scan)
3263cc1dc7a3Sopenharmony_ci{
3264cc1dc7a3Sopenharmony_ci   stbi__context *s = z->s;
3265cc1dc7a3Sopenharmony_ci   int Lf,p,i,q, h_max=1,v_max=1,c;
3266cc1dc7a3Sopenharmony_ci   Lf = stbi__get16be(s);         if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG
3267cc1dc7a3Sopenharmony_ci   p  = stbi__get8(s);            if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline
3268cc1dc7a3Sopenharmony_ci   s->img_y = stbi__get16be(s);   if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG
3269cc1dc7a3Sopenharmony_ci   s->img_x = stbi__get16be(s);   if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires
3270cc1dc7a3Sopenharmony_ci   if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
3271cc1dc7a3Sopenharmony_ci   if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
3272cc1dc7a3Sopenharmony_ci   c = stbi__get8(s);
3273cc1dc7a3Sopenharmony_ci   if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG");
3274cc1dc7a3Sopenharmony_ci   s->img_n = c;
3275cc1dc7a3Sopenharmony_ci   for (i=0; i < c; ++i) {
3276cc1dc7a3Sopenharmony_ci      z->img_comp[i].data = NULL;
3277cc1dc7a3Sopenharmony_ci      z->img_comp[i].linebuf = NULL;
3278cc1dc7a3Sopenharmony_ci   }
3279cc1dc7a3Sopenharmony_ci
3280cc1dc7a3Sopenharmony_ci   if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG");
3281cc1dc7a3Sopenharmony_ci
3282cc1dc7a3Sopenharmony_ci   z->rgb = 0;
3283cc1dc7a3Sopenharmony_ci   for (i=0; i < s->img_n; ++i) {
3284cc1dc7a3Sopenharmony_ci      static const unsigned char rgb[3] = { 'R', 'G', 'B' };
3285cc1dc7a3Sopenharmony_ci      z->img_comp[i].id = stbi__get8(s);
3286cc1dc7a3Sopenharmony_ci      if (s->img_n == 3 && z->img_comp[i].id == rgb[i])
3287cc1dc7a3Sopenharmony_ci         ++z->rgb;
3288cc1dc7a3Sopenharmony_ci      q = stbi__get8(s);
3289cc1dc7a3Sopenharmony_ci      z->img_comp[i].h = (q >> 4);  if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG");
3290cc1dc7a3Sopenharmony_ci      z->img_comp[i].v = q & 15;    if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG");
3291cc1dc7a3Sopenharmony_ci      z->img_comp[i].tq = stbi__get8(s);  if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG");
3292cc1dc7a3Sopenharmony_ci   }
3293cc1dc7a3Sopenharmony_ci
3294cc1dc7a3Sopenharmony_ci   if (scan != STBI__SCAN_load) return 1;
3295cc1dc7a3Sopenharmony_ci
3296cc1dc7a3Sopenharmony_ci   if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode");
3297cc1dc7a3Sopenharmony_ci
3298cc1dc7a3Sopenharmony_ci   for (i=0; i < s->img_n; ++i) {
3299cc1dc7a3Sopenharmony_ci      if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h;
3300cc1dc7a3Sopenharmony_ci      if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v;
3301cc1dc7a3Sopenharmony_ci   }
3302cc1dc7a3Sopenharmony_ci
3303cc1dc7a3Sopenharmony_ci   // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios
3304cc1dc7a3Sopenharmony_ci   // and I've never seen a non-corrupted JPEG file actually use them
3305cc1dc7a3Sopenharmony_ci   for (i=0; i < s->img_n; ++i) {
3306cc1dc7a3Sopenharmony_ci      if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG");
3307cc1dc7a3Sopenharmony_ci      if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG");
3308cc1dc7a3Sopenharmony_ci   }
3309cc1dc7a3Sopenharmony_ci
3310cc1dc7a3Sopenharmony_ci   // compute interleaved mcu info
3311cc1dc7a3Sopenharmony_ci   z->img_h_max = h_max;
3312cc1dc7a3Sopenharmony_ci   z->img_v_max = v_max;
3313cc1dc7a3Sopenharmony_ci   z->img_mcu_w = h_max * 8;
3314cc1dc7a3Sopenharmony_ci   z->img_mcu_h = v_max * 8;
3315cc1dc7a3Sopenharmony_ci   // these sizes can't be more than 17 bits
3316cc1dc7a3Sopenharmony_ci   z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w;
3317cc1dc7a3Sopenharmony_ci   z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h;
3318cc1dc7a3Sopenharmony_ci
3319cc1dc7a3Sopenharmony_ci   for (i=0; i < s->img_n; ++i) {
3320cc1dc7a3Sopenharmony_ci      // number of effective pixels (e.g. for non-interleaved MCU)
3321cc1dc7a3Sopenharmony_ci      z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max;
3322cc1dc7a3Sopenharmony_ci      z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max;
3323cc1dc7a3Sopenharmony_ci      // to simplify generation, we'll allocate enough memory to decode
3324cc1dc7a3Sopenharmony_ci      // the bogus oversized data from using interleaved MCUs and their
3325cc1dc7a3Sopenharmony_ci      // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't
3326cc1dc7a3Sopenharmony_ci      // discard the extra data until colorspace conversion
3327cc1dc7a3Sopenharmony_ci      //
3328cc1dc7a3Sopenharmony_ci      // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier)
3329cc1dc7a3Sopenharmony_ci      // so these muls can't overflow with 32-bit ints (which we require)
3330cc1dc7a3Sopenharmony_ci      z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8;
3331cc1dc7a3Sopenharmony_ci      z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8;
3332cc1dc7a3Sopenharmony_ci      z->img_comp[i].coeff = 0;
3333cc1dc7a3Sopenharmony_ci      z->img_comp[i].raw_coeff = 0;
3334cc1dc7a3Sopenharmony_ci      z->img_comp[i].linebuf = NULL;
3335cc1dc7a3Sopenharmony_ci      z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15);
3336cc1dc7a3Sopenharmony_ci      if (z->img_comp[i].raw_data == NULL)
3337cc1dc7a3Sopenharmony_ci         return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
3338cc1dc7a3Sopenharmony_ci      // align blocks for idct using mmx/sse
3339cc1dc7a3Sopenharmony_ci      z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15);
3340cc1dc7a3Sopenharmony_ci      if (z->progressive) {
3341cc1dc7a3Sopenharmony_ci         // w2, h2 are multiples of 8 (see above)
3342cc1dc7a3Sopenharmony_ci         z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8;
3343cc1dc7a3Sopenharmony_ci         z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8;
3344cc1dc7a3Sopenharmony_ci         z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15);
3345cc1dc7a3Sopenharmony_ci         if (z->img_comp[i].raw_coeff == NULL)
3346cc1dc7a3Sopenharmony_ci            return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
3347cc1dc7a3Sopenharmony_ci         z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15);
3348cc1dc7a3Sopenharmony_ci      }
3349cc1dc7a3Sopenharmony_ci   }
3350cc1dc7a3Sopenharmony_ci
3351cc1dc7a3Sopenharmony_ci   return 1;
3352cc1dc7a3Sopenharmony_ci}
3353cc1dc7a3Sopenharmony_ci
3354cc1dc7a3Sopenharmony_ci// use comparisons since in some cases we handle more than one case (e.g. SOF)
3355cc1dc7a3Sopenharmony_ci#define stbi__DNL(x)         ((x) == 0xdc)
3356cc1dc7a3Sopenharmony_ci#define stbi__SOI(x)         ((x) == 0xd8)
3357cc1dc7a3Sopenharmony_ci#define stbi__EOI(x)         ((x) == 0xd9)
3358cc1dc7a3Sopenharmony_ci#define stbi__SOF(x)         ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2)
3359cc1dc7a3Sopenharmony_ci#define stbi__SOS(x)         ((x) == 0xda)
3360cc1dc7a3Sopenharmony_ci
3361cc1dc7a3Sopenharmony_ci#define stbi__SOF_progressive(x)   ((x) == 0xc2)
3362cc1dc7a3Sopenharmony_ci
3363cc1dc7a3Sopenharmony_cistatic int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
3364cc1dc7a3Sopenharmony_ci{
3365cc1dc7a3Sopenharmony_ci   int m;
3366cc1dc7a3Sopenharmony_ci   z->jfif = 0;
3367cc1dc7a3Sopenharmony_ci   z->app14_color_transform = -1; // valid values are 0,1,2
3368cc1dc7a3Sopenharmony_ci   z->marker = STBI__MARKER_none; // initialize cached marker to empty
3369cc1dc7a3Sopenharmony_ci   m = stbi__get_marker(z);
3370cc1dc7a3Sopenharmony_ci   if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG");
3371cc1dc7a3Sopenharmony_ci   if (scan == STBI__SCAN_type) return 1;
3372cc1dc7a3Sopenharmony_ci   m = stbi__get_marker(z);
3373cc1dc7a3Sopenharmony_ci   while (!stbi__SOF(m)) {
3374cc1dc7a3Sopenharmony_ci      if (!stbi__process_marker(z,m)) return 0;
3375cc1dc7a3Sopenharmony_ci      m = stbi__get_marker(z);
3376cc1dc7a3Sopenharmony_ci      while (m == STBI__MARKER_none) {
3377cc1dc7a3Sopenharmony_ci         // some files have extra padding after their blocks, so ok, we'll scan
3378cc1dc7a3Sopenharmony_ci         if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG");
3379cc1dc7a3Sopenharmony_ci         m = stbi__get_marker(z);
3380cc1dc7a3Sopenharmony_ci      }
3381cc1dc7a3Sopenharmony_ci   }
3382cc1dc7a3Sopenharmony_ci   z->progressive = stbi__SOF_progressive(m);
3383cc1dc7a3Sopenharmony_ci   if (!stbi__process_frame_header(z, scan)) return 0;
3384cc1dc7a3Sopenharmony_ci   return 1;
3385cc1dc7a3Sopenharmony_ci}
3386cc1dc7a3Sopenharmony_ci
3387cc1dc7a3Sopenharmony_cistatic int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j)
3388cc1dc7a3Sopenharmony_ci{
3389cc1dc7a3Sopenharmony_ci   // some JPEGs have junk at end, skip over it but if we find what looks
3390cc1dc7a3Sopenharmony_ci   // like a valid marker, resume there
3391cc1dc7a3Sopenharmony_ci   while (!stbi__at_eof(j->s)) {
3392cc1dc7a3Sopenharmony_ci      int x = stbi__get8(j->s);
3393cc1dc7a3Sopenharmony_ci      while (x == 255) { // might be a marker
3394cc1dc7a3Sopenharmony_ci         if (stbi__at_eof(j->s)) return STBI__MARKER_none;
3395cc1dc7a3Sopenharmony_ci         x = stbi__get8(j->s);
3396cc1dc7a3Sopenharmony_ci         if (x != 0x00 && x != 0xff) {
3397cc1dc7a3Sopenharmony_ci            // not a stuffed zero or lead-in to another marker, looks
3398cc1dc7a3Sopenharmony_ci            // like an actual marker, return it
3399cc1dc7a3Sopenharmony_ci            return x;
3400cc1dc7a3Sopenharmony_ci         }
3401cc1dc7a3Sopenharmony_ci         // stuffed zero has x=0 now which ends the loop, meaning we go
3402cc1dc7a3Sopenharmony_ci         // back to regular scan loop.
3403cc1dc7a3Sopenharmony_ci         // repeated 0xff keeps trying to read the next byte of the marker.
3404cc1dc7a3Sopenharmony_ci      }
3405cc1dc7a3Sopenharmony_ci   }
3406cc1dc7a3Sopenharmony_ci   return STBI__MARKER_none;
3407cc1dc7a3Sopenharmony_ci}
3408cc1dc7a3Sopenharmony_ci
3409cc1dc7a3Sopenharmony_ci// decode image to YCbCr format
3410cc1dc7a3Sopenharmony_cistatic int stbi__decode_jpeg_image(stbi__jpeg *j)
3411cc1dc7a3Sopenharmony_ci{
3412cc1dc7a3Sopenharmony_ci   int m;
3413cc1dc7a3Sopenharmony_ci   for (m = 0; m < 4; m++) {
3414cc1dc7a3Sopenharmony_ci      j->img_comp[m].raw_data = NULL;
3415cc1dc7a3Sopenharmony_ci      j->img_comp[m].raw_coeff = NULL;
3416cc1dc7a3Sopenharmony_ci   }
3417cc1dc7a3Sopenharmony_ci   j->restart_interval = 0;
3418cc1dc7a3Sopenharmony_ci   if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0;
3419cc1dc7a3Sopenharmony_ci   m = stbi__get_marker(j);
3420cc1dc7a3Sopenharmony_ci   while (!stbi__EOI(m)) {
3421cc1dc7a3Sopenharmony_ci      if (stbi__SOS(m)) {
3422cc1dc7a3Sopenharmony_ci         if (!stbi__process_scan_header(j)) return 0;
3423cc1dc7a3Sopenharmony_ci         if (!stbi__parse_entropy_coded_data(j)) return 0;
3424cc1dc7a3Sopenharmony_ci         if (j->marker == STBI__MARKER_none ) {
3425cc1dc7a3Sopenharmony_ci         j->marker = stbi__skip_jpeg_junk_at_end(j);
3426cc1dc7a3Sopenharmony_ci            // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0
3427cc1dc7a3Sopenharmony_ci         }
3428cc1dc7a3Sopenharmony_ci         m = stbi__get_marker(j);
3429cc1dc7a3Sopenharmony_ci         if (STBI__RESTART(m))
3430cc1dc7a3Sopenharmony_ci            m = stbi__get_marker(j);
3431cc1dc7a3Sopenharmony_ci      } else if (stbi__DNL(m)) {
3432cc1dc7a3Sopenharmony_ci         int Ld = stbi__get16be(j->s);
3433cc1dc7a3Sopenharmony_ci         stbi__uint32 NL = stbi__get16be(j->s);
3434cc1dc7a3Sopenharmony_ci         if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG");
3435cc1dc7a3Sopenharmony_ci         if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG");
3436cc1dc7a3Sopenharmony_ci         m = stbi__get_marker(j);
3437cc1dc7a3Sopenharmony_ci      } else {
3438cc1dc7a3Sopenharmony_ci         if (!stbi__process_marker(j, m)) return 1;
3439cc1dc7a3Sopenharmony_ci         m = stbi__get_marker(j);
3440cc1dc7a3Sopenharmony_ci      }
3441cc1dc7a3Sopenharmony_ci   }
3442cc1dc7a3Sopenharmony_ci   if (j->progressive)
3443cc1dc7a3Sopenharmony_ci      stbi__jpeg_finish(j);
3444cc1dc7a3Sopenharmony_ci   return 1;
3445cc1dc7a3Sopenharmony_ci}
3446cc1dc7a3Sopenharmony_ci
3447cc1dc7a3Sopenharmony_ci// static jfif-centered resampling (across block boundaries)
3448cc1dc7a3Sopenharmony_ci
3449cc1dc7a3Sopenharmony_citypedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1,
3450cc1dc7a3Sopenharmony_ci                                    int w, int hs);
3451cc1dc7a3Sopenharmony_ci
3452cc1dc7a3Sopenharmony_ci#define stbi__div4(x) ((stbi_uc) ((x) >> 2))
3453cc1dc7a3Sopenharmony_ci
3454cc1dc7a3Sopenharmony_cistatic stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
3455cc1dc7a3Sopenharmony_ci{
3456cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(out);
3457cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(in_far);
3458cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(w);
3459cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(hs);
3460cc1dc7a3Sopenharmony_ci   return in_near;
3461cc1dc7a3Sopenharmony_ci}
3462cc1dc7a3Sopenharmony_ci
3463cc1dc7a3Sopenharmony_cistatic stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
3464cc1dc7a3Sopenharmony_ci{
3465cc1dc7a3Sopenharmony_ci   // need to generate two samples vertically for every one in input
3466cc1dc7a3Sopenharmony_ci   int i;
3467cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(hs);
3468cc1dc7a3Sopenharmony_ci   for (i=0; i < w; ++i)
3469cc1dc7a3Sopenharmony_ci      out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2);
3470cc1dc7a3Sopenharmony_ci   return out;
3471cc1dc7a3Sopenharmony_ci}
3472cc1dc7a3Sopenharmony_ci
3473cc1dc7a3Sopenharmony_cistatic stbi_uc*  stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
3474cc1dc7a3Sopenharmony_ci{
3475cc1dc7a3Sopenharmony_ci   // need to generate two samples horizontally for every one in input
3476cc1dc7a3Sopenharmony_ci   int i;
3477cc1dc7a3Sopenharmony_ci   stbi_uc *input = in_near;
3478cc1dc7a3Sopenharmony_ci
3479cc1dc7a3Sopenharmony_ci   if (w == 1) {
3480cc1dc7a3Sopenharmony_ci      // if only one sample, can't do any interpolation
3481cc1dc7a3Sopenharmony_ci      out[0] = out[1] = input[0];
3482cc1dc7a3Sopenharmony_ci      return out;
3483cc1dc7a3Sopenharmony_ci   }
3484cc1dc7a3Sopenharmony_ci
3485cc1dc7a3Sopenharmony_ci   out[0] = input[0];
3486cc1dc7a3Sopenharmony_ci   out[1] = stbi__div4(input[0]*3 + input[1] + 2);
3487cc1dc7a3Sopenharmony_ci   for (i=1; i < w-1; ++i) {
3488cc1dc7a3Sopenharmony_ci      int n = 3*input[i]+2;
3489cc1dc7a3Sopenharmony_ci      out[i*2+0] = stbi__div4(n+input[i-1]);
3490cc1dc7a3Sopenharmony_ci      out[i*2+1] = stbi__div4(n+input[i+1]);
3491cc1dc7a3Sopenharmony_ci   }
3492cc1dc7a3Sopenharmony_ci   out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2);
3493cc1dc7a3Sopenharmony_ci   out[i*2+1] = input[w-1];
3494cc1dc7a3Sopenharmony_ci
3495cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(in_far);
3496cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(hs);
3497cc1dc7a3Sopenharmony_ci
3498cc1dc7a3Sopenharmony_ci   return out;
3499cc1dc7a3Sopenharmony_ci}
3500cc1dc7a3Sopenharmony_ci
3501cc1dc7a3Sopenharmony_ci#define stbi__div16(x) ((stbi_uc) ((x) >> 4))
3502cc1dc7a3Sopenharmony_ci
3503cc1dc7a3Sopenharmony_cistatic stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
3504cc1dc7a3Sopenharmony_ci{
3505cc1dc7a3Sopenharmony_ci   // need to generate 2x2 samples for every one in input
3506cc1dc7a3Sopenharmony_ci   int i,t0,t1;
3507cc1dc7a3Sopenharmony_ci   if (w == 1) {
3508cc1dc7a3Sopenharmony_ci      out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2);
3509cc1dc7a3Sopenharmony_ci      return out;
3510cc1dc7a3Sopenharmony_ci   }
3511cc1dc7a3Sopenharmony_ci
3512cc1dc7a3Sopenharmony_ci   t1 = 3*in_near[0] + in_far[0];
3513cc1dc7a3Sopenharmony_ci   out[0] = stbi__div4(t1+2);
3514cc1dc7a3Sopenharmony_ci   for (i=1; i < w; ++i) {
3515cc1dc7a3Sopenharmony_ci      t0 = t1;
3516cc1dc7a3Sopenharmony_ci      t1 = 3*in_near[i]+in_far[i];
3517cc1dc7a3Sopenharmony_ci      out[i*2-1] = stbi__div16(3*t0 + t1 + 8);
3518cc1dc7a3Sopenharmony_ci      out[i*2  ] = stbi__div16(3*t1 + t0 + 8);
3519cc1dc7a3Sopenharmony_ci   }
3520cc1dc7a3Sopenharmony_ci   out[w*2-1] = stbi__div4(t1+2);
3521cc1dc7a3Sopenharmony_ci
3522cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(hs);
3523cc1dc7a3Sopenharmony_ci
3524cc1dc7a3Sopenharmony_ci   return out;
3525cc1dc7a3Sopenharmony_ci}
3526cc1dc7a3Sopenharmony_ci
3527cc1dc7a3Sopenharmony_ci#if defined(STBI_SSE2) || defined(STBI_NEON)
3528cc1dc7a3Sopenharmony_cistatic stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
3529cc1dc7a3Sopenharmony_ci{
3530cc1dc7a3Sopenharmony_ci   // need to generate 2x2 samples for every one in input
3531cc1dc7a3Sopenharmony_ci   int i=0,t0,t1;
3532cc1dc7a3Sopenharmony_ci
3533cc1dc7a3Sopenharmony_ci   if (w == 1) {
3534cc1dc7a3Sopenharmony_ci      out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2);
3535cc1dc7a3Sopenharmony_ci      return out;
3536cc1dc7a3Sopenharmony_ci   }
3537cc1dc7a3Sopenharmony_ci
3538cc1dc7a3Sopenharmony_ci   t1 = 3*in_near[0] + in_far[0];
3539cc1dc7a3Sopenharmony_ci   // process groups of 8 pixels for as long as we can.
3540cc1dc7a3Sopenharmony_ci   // note we can't handle the last pixel in a row in this loop
3541cc1dc7a3Sopenharmony_ci   // because we need to handle the filter boundary conditions.
3542cc1dc7a3Sopenharmony_ci   for (; i < ((w-1) & ~7); i += 8) {
3543cc1dc7a3Sopenharmony_ci#if defined(STBI_SSE2)
3544cc1dc7a3Sopenharmony_ci      // load and perform the vertical filtering pass
3545cc1dc7a3Sopenharmony_ci      // this uses 3*x + y = 4*x + (y - x)
3546cc1dc7a3Sopenharmony_ci      __m128i zero  = _mm_setzero_si128();
3547cc1dc7a3Sopenharmony_ci      __m128i farb  = _mm_loadl_epi64((__m128i *) (in_far + i));
3548cc1dc7a3Sopenharmony_ci      __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i));
3549cc1dc7a3Sopenharmony_ci      __m128i farw  = _mm_unpacklo_epi8(farb, zero);
3550cc1dc7a3Sopenharmony_ci      __m128i nearw = _mm_unpacklo_epi8(nearb, zero);
3551cc1dc7a3Sopenharmony_ci      __m128i diff  = _mm_sub_epi16(farw, nearw);
3552cc1dc7a3Sopenharmony_ci      __m128i nears = _mm_slli_epi16(nearw, 2);
3553cc1dc7a3Sopenharmony_ci      __m128i curr  = _mm_add_epi16(nears, diff); // current row
3554cc1dc7a3Sopenharmony_ci
3555cc1dc7a3Sopenharmony_ci      // horizontal filter works the same based on shifted vers of current
3556cc1dc7a3Sopenharmony_ci      // row. "prev" is current row shifted right by 1 pixel; we need to
3557cc1dc7a3Sopenharmony_ci      // insert the previous pixel value (from t1).
3558cc1dc7a3Sopenharmony_ci      // "next" is current row shifted left by 1 pixel, with first pixel
3559cc1dc7a3Sopenharmony_ci      // of next block of 8 pixels added in.
3560cc1dc7a3Sopenharmony_ci      __m128i prv0 = _mm_slli_si128(curr, 2);
3561cc1dc7a3Sopenharmony_ci      __m128i nxt0 = _mm_srli_si128(curr, 2);
3562cc1dc7a3Sopenharmony_ci      __m128i prev = _mm_insert_epi16(prv0, t1, 0);
3563cc1dc7a3Sopenharmony_ci      __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7);
3564cc1dc7a3Sopenharmony_ci
3565cc1dc7a3Sopenharmony_ci      // horizontal filter, polyphase implementation since it's convenient:
3566cc1dc7a3Sopenharmony_ci      // even pixels = 3*cur + prev = cur*4 + (prev - cur)
3567cc1dc7a3Sopenharmony_ci      // odd  pixels = 3*cur + next = cur*4 + (next - cur)
3568cc1dc7a3Sopenharmony_ci      // note the shared term.
3569cc1dc7a3Sopenharmony_ci      __m128i bias  = _mm_set1_epi16(8);
3570cc1dc7a3Sopenharmony_ci      __m128i curs = _mm_slli_epi16(curr, 2);
3571cc1dc7a3Sopenharmony_ci      __m128i prvd = _mm_sub_epi16(prev, curr);
3572cc1dc7a3Sopenharmony_ci      __m128i nxtd = _mm_sub_epi16(next, curr);
3573cc1dc7a3Sopenharmony_ci      __m128i curb = _mm_add_epi16(curs, bias);
3574cc1dc7a3Sopenharmony_ci      __m128i even = _mm_add_epi16(prvd, curb);
3575cc1dc7a3Sopenharmony_ci      __m128i odd  = _mm_add_epi16(nxtd, curb);
3576cc1dc7a3Sopenharmony_ci
3577cc1dc7a3Sopenharmony_ci      // interleave even and odd pixels, then undo scaling.
3578cc1dc7a3Sopenharmony_ci      __m128i int0 = _mm_unpacklo_epi16(even, odd);
3579cc1dc7a3Sopenharmony_ci      __m128i int1 = _mm_unpackhi_epi16(even, odd);
3580cc1dc7a3Sopenharmony_ci      __m128i de0  = _mm_srli_epi16(int0, 4);
3581cc1dc7a3Sopenharmony_ci      __m128i de1  = _mm_srli_epi16(int1, 4);
3582cc1dc7a3Sopenharmony_ci
3583cc1dc7a3Sopenharmony_ci      // pack and write output
3584cc1dc7a3Sopenharmony_ci      __m128i outv = _mm_packus_epi16(de0, de1);
3585cc1dc7a3Sopenharmony_ci      _mm_storeu_si128((__m128i *) (out + i*2), outv);
3586cc1dc7a3Sopenharmony_ci#elif defined(STBI_NEON)
3587cc1dc7a3Sopenharmony_ci      // load and perform the vertical filtering pass
3588cc1dc7a3Sopenharmony_ci      // this uses 3*x + y = 4*x + (y - x)
3589cc1dc7a3Sopenharmony_ci      uint8x8_t farb  = vld1_u8(in_far + i);
3590cc1dc7a3Sopenharmony_ci      uint8x8_t nearb = vld1_u8(in_near + i);
3591cc1dc7a3Sopenharmony_ci      int16x8_t diff  = vreinterpretq_s16_u16(vsubl_u8(farb, nearb));
3592cc1dc7a3Sopenharmony_ci      int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2));
3593cc1dc7a3Sopenharmony_ci      int16x8_t curr  = vaddq_s16(nears, diff); // current row
3594cc1dc7a3Sopenharmony_ci
3595cc1dc7a3Sopenharmony_ci      // horizontal filter works the same based on shifted vers of current
3596cc1dc7a3Sopenharmony_ci      // row. "prev" is current row shifted right by 1 pixel; we need to
3597cc1dc7a3Sopenharmony_ci      // insert the previous pixel value (from t1).
3598cc1dc7a3Sopenharmony_ci      // "next" is current row shifted left by 1 pixel, with first pixel
3599cc1dc7a3Sopenharmony_ci      // of next block of 8 pixels added in.
3600cc1dc7a3Sopenharmony_ci      int16x8_t prv0 = vextq_s16(curr, curr, 7);
3601cc1dc7a3Sopenharmony_ci      int16x8_t nxt0 = vextq_s16(curr, curr, 1);
3602cc1dc7a3Sopenharmony_ci      int16x8_t prev = vsetq_lane_s16(t1, prv0, 0);
3603cc1dc7a3Sopenharmony_ci      int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7);
3604cc1dc7a3Sopenharmony_ci
3605cc1dc7a3Sopenharmony_ci      // horizontal filter, polyphase implementation since it's convenient:
3606cc1dc7a3Sopenharmony_ci      // even pixels = 3*cur + prev = cur*4 + (prev - cur)
3607cc1dc7a3Sopenharmony_ci      // odd  pixels = 3*cur + next = cur*4 + (next - cur)
3608cc1dc7a3Sopenharmony_ci      // note the shared term.
3609cc1dc7a3Sopenharmony_ci      int16x8_t curs = vshlq_n_s16(curr, 2);
3610cc1dc7a3Sopenharmony_ci      int16x8_t prvd = vsubq_s16(prev, curr);
3611cc1dc7a3Sopenharmony_ci      int16x8_t nxtd = vsubq_s16(next, curr);
3612cc1dc7a3Sopenharmony_ci      int16x8_t even = vaddq_s16(curs, prvd);
3613cc1dc7a3Sopenharmony_ci      int16x8_t odd  = vaddq_s16(curs, nxtd);
3614cc1dc7a3Sopenharmony_ci
3615cc1dc7a3Sopenharmony_ci      // undo scaling and round, then store with even/odd phases interleaved
3616cc1dc7a3Sopenharmony_ci      uint8x8x2_t o;
3617cc1dc7a3Sopenharmony_ci      o.val[0] = vqrshrun_n_s16(even, 4);
3618cc1dc7a3Sopenharmony_ci      o.val[1] = vqrshrun_n_s16(odd,  4);
3619cc1dc7a3Sopenharmony_ci      vst2_u8(out + i*2, o);
3620cc1dc7a3Sopenharmony_ci#endif
3621cc1dc7a3Sopenharmony_ci
3622cc1dc7a3Sopenharmony_ci      // "previous" value for next iter
3623cc1dc7a3Sopenharmony_ci      t1 = 3*in_near[i+7] + in_far[i+7];
3624cc1dc7a3Sopenharmony_ci   }
3625cc1dc7a3Sopenharmony_ci
3626cc1dc7a3Sopenharmony_ci   t0 = t1;
3627cc1dc7a3Sopenharmony_ci   t1 = 3*in_near[i] + in_far[i];
3628cc1dc7a3Sopenharmony_ci   out[i*2] = stbi__div16(3*t1 + t0 + 8);
3629cc1dc7a3Sopenharmony_ci
3630cc1dc7a3Sopenharmony_ci   for (++i; i < w; ++i) {
3631cc1dc7a3Sopenharmony_ci      t0 = t1;
3632cc1dc7a3Sopenharmony_ci      t1 = 3*in_near[i]+in_far[i];
3633cc1dc7a3Sopenharmony_ci      out[i*2-1] = stbi__div16(3*t0 + t1 + 8);
3634cc1dc7a3Sopenharmony_ci      out[i*2  ] = stbi__div16(3*t1 + t0 + 8);
3635cc1dc7a3Sopenharmony_ci   }
3636cc1dc7a3Sopenharmony_ci   out[w*2-1] = stbi__div4(t1+2);
3637cc1dc7a3Sopenharmony_ci
3638cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(hs);
3639cc1dc7a3Sopenharmony_ci
3640cc1dc7a3Sopenharmony_ci   return out;
3641cc1dc7a3Sopenharmony_ci}
3642cc1dc7a3Sopenharmony_ci#endif
3643cc1dc7a3Sopenharmony_ci
3644cc1dc7a3Sopenharmony_cistatic stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)
3645cc1dc7a3Sopenharmony_ci{
3646cc1dc7a3Sopenharmony_ci   // resample with nearest-neighbor
3647cc1dc7a3Sopenharmony_ci   int i,j;
3648cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(in_far);
3649cc1dc7a3Sopenharmony_ci   for (i=0; i < w; ++i)
3650cc1dc7a3Sopenharmony_ci      for (j=0; j < hs; ++j)
3651cc1dc7a3Sopenharmony_ci         out[i*hs+j] = in_near[i];
3652cc1dc7a3Sopenharmony_ci   return out;
3653cc1dc7a3Sopenharmony_ci}
3654cc1dc7a3Sopenharmony_ci
3655cc1dc7a3Sopenharmony_ci// this is a reduced-precision calculation of YCbCr-to-RGB introduced
3656cc1dc7a3Sopenharmony_ci// to make sure the code produces the same results in both SIMD and scalar
3657cc1dc7a3Sopenharmony_ci#define stbi__float2fixed(x)  (((int) ((x) * 4096.0f + 0.5f)) << 8)
3658cc1dc7a3Sopenharmony_cistatic void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step)
3659cc1dc7a3Sopenharmony_ci{
3660cc1dc7a3Sopenharmony_ci   int i;
3661cc1dc7a3Sopenharmony_ci   for (i=0; i < count; ++i) {
3662cc1dc7a3Sopenharmony_ci      int y_fixed = (y[i] << 20) + (1<<19); // rounding
3663cc1dc7a3Sopenharmony_ci      int r,g,b;
3664cc1dc7a3Sopenharmony_ci      int cr = pcr[i] - 128;
3665cc1dc7a3Sopenharmony_ci      int cb = pcb[i] - 128;
3666cc1dc7a3Sopenharmony_ci      r = y_fixed +  cr* stbi__float2fixed(1.40200f);
3667cc1dc7a3Sopenharmony_ci      g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);
3668cc1dc7a3Sopenharmony_ci      b = y_fixed                                     +   cb* stbi__float2fixed(1.77200f);
3669cc1dc7a3Sopenharmony_ci      r >>= 20;
3670cc1dc7a3Sopenharmony_ci      g >>= 20;
3671cc1dc7a3Sopenharmony_ci      b >>= 20;
3672cc1dc7a3Sopenharmony_ci      if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }
3673cc1dc7a3Sopenharmony_ci      if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }
3674cc1dc7a3Sopenharmony_ci      if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }
3675cc1dc7a3Sopenharmony_ci      out[0] = (stbi_uc)r;
3676cc1dc7a3Sopenharmony_ci      out[1] = (stbi_uc)g;
3677cc1dc7a3Sopenharmony_ci      out[2] = (stbi_uc)b;
3678cc1dc7a3Sopenharmony_ci      out[3] = 255;
3679cc1dc7a3Sopenharmony_ci      out += step;
3680cc1dc7a3Sopenharmony_ci   }
3681cc1dc7a3Sopenharmony_ci}
3682cc1dc7a3Sopenharmony_ci
3683cc1dc7a3Sopenharmony_ci#if defined(STBI_SSE2) || defined(STBI_NEON)
3684cc1dc7a3Sopenharmony_cistatic void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step)
3685cc1dc7a3Sopenharmony_ci{
3686cc1dc7a3Sopenharmony_ci   int i = 0;
3687cc1dc7a3Sopenharmony_ci
3688cc1dc7a3Sopenharmony_ci#ifdef STBI_SSE2
3689cc1dc7a3Sopenharmony_ci   // step == 3 is pretty ugly on the final interleave, and i'm not convinced
3690cc1dc7a3Sopenharmony_ci   // it's useful in practice (you wouldn't use it for textures, for example).
3691cc1dc7a3Sopenharmony_ci   // so just accelerate step == 4 case.
3692cc1dc7a3Sopenharmony_ci   if (step == 4) {
3693cc1dc7a3Sopenharmony_ci      // this is a fairly straightforward implementation and not super-optimized.
3694cc1dc7a3Sopenharmony_ci      __m128i signflip  = _mm_set1_epi8(-0x80);
3695cc1dc7a3Sopenharmony_ci      __m128i cr_const0 = _mm_set1_epi16(   (short) ( 1.40200f*4096.0f+0.5f));
3696cc1dc7a3Sopenharmony_ci      __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f));
3697cc1dc7a3Sopenharmony_ci      __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f));
3698cc1dc7a3Sopenharmony_ci      __m128i cb_const1 = _mm_set1_epi16(   (short) ( 1.77200f*4096.0f+0.5f));
3699cc1dc7a3Sopenharmony_ci      __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128);
3700cc1dc7a3Sopenharmony_ci      __m128i xw = _mm_set1_epi16(255); // alpha channel
3701cc1dc7a3Sopenharmony_ci
3702cc1dc7a3Sopenharmony_ci      for (; i+7 < count; i += 8) {
3703cc1dc7a3Sopenharmony_ci         // load
3704cc1dc7a3Sopenharmony_ci         __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i));
3705cc1dc7a3Sopenharmony_ci         __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i));
3706cc1dc7a3Sopenharmony_ci         __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i));
3707cc1dc7a3Sopenharmony_ci         __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128
3708cc1dc7a3Sopenharmony_ci         __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128
3709cc1dc7a3Sopenharmony_ci
3710cc1dc7a3Sopenharmony_ci         // unpack to short (and left-shift cr, cb by 8)
3711cc1dc7a3Sopenharmony_ci         __m128i yw  = _mm_unpacklo_epi8(y_bias, y_bytes);
3712cc1dc7a3Sopenharmony_ci         __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased);
3713cc1dc7a3Sopenharmony_ci         __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased);
3714cc1dc7a3Sopenharmony_ci
3715cc1dc7a3Sopenharmony_ci         // color transform
3716cc1dc7a3Sopenharmony_ci         __m128i yws = _mm_srli_epi16(yw, 4);
3717cc1dc7a3Sopenharmony_ci         __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw);
3718cc1dc7a3Sopenharmony_ci         __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw);
3719cc1dc7a3Sopenharmony_ci         __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1);
3720cc1dc7a3Sopenharmony_ci         __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1);
3721cc1dc7a3Sopenharmony_ci         __m128i rws = _mm_add_epi16(cr0, yws);
3722cc1dc7a3Sopenharmony_ci         __m128i gwt = _mm_add_epi16(cb0, yws);
3723cc1dc7a3Sopenharmony_ci         __m128i bws = _mm_add_epi16(yws, cb1);
3724cc1dc7a3Sopenharmony_ci         __m128i gws = _mm_add_epi16(gwt, cr1);
3725cc1dc7a3Sopenharmony_ci
3726cc1dc7a3Sopenharmony_ci         // descale
3727cc1dc7a3Sopenharmony_ci         __m128i rw = _mm_srai_epi16(rws, 4);
3728cc1dc7a3Sopenharmony_ci         __m128i bw = _mm_srai_epi16(bws, 4);
3729cc1dc7a3Sopenharmony_ci         __m128i gw = _mm_srai_epi16(gws, 4);
3730cc1dc7a3Sopenharmony_ci
3731cc1dc7a3Sopenharmony_ci         // back to byte, set up for transpose
3732cc1dc7a3Sopenharmony_ci         __m128i brb = _mm_packus_epi16(rw, bw);
3733cc1dc7a3Sopenharmony_ci         __m128i gxb = _mm_packus_epi16(gw, xw);
3734cc1dc7a3Sopenharmony_ci
3735cc1dc7a3Sopenharmony_ci         // transpose to interleave channels
3736cc1dc7a3Sopenharmony_ci         __m128i t0 = _mm_unpacklo_epi8(brb, gxb);
3737cc1dc7a3Sopenharmony_ci         __m128i t1 = _mm_unpackhi_epi8(brb, gxb);
3738cc1dc7a3Sopenharmony_ci         __m128i o0 = _mm_unpacklo_epi16(t0, t1);
3739cc1dc7a3Sopenharmony_ci         __m128i o1 = _mm_unpackhi_epi16(t0, t1);
3740cc1dc7a3Sopenharmony_ci
3741cc1dc7a3Sopenharmony_ci         // store
3742cc1dc7a3Sopenharmony_ci         _mm_storeu_si128((__m128i *) (out + 0), o0);
3743cc1dc7a3Sopenharmony_ci         _mm_storeu_si128((__m128i *) (out + 16), o1);
3744cc1dc7a3Sopenharmony_ci         out += 32;
3745cc1dc7a3Sopenharmony_ci      }
3746cc1dc7a3Sopenharmony_ci   }
3747cc1dc7a3Sopenharmony_ci#endif
3748cc1dc7a3Sopenharmony_ci
3749cc1dc7a3Sopenharmony_ci#ifdef STBI_NEON
3750cc1dc7a3Sopenharmony_ci   // in this version, step=3 support would be easy to add. but is there demand?
3751cc1dc7a3Sopenharmony_ci   if (step == 4) {
3752cc1dc7a3Sopenharmony_ci      // this is a fairly straightforward implementation and not super-optimized.
3753cc1dc7a3Sopenharmony_ci      uint8x8_t signflip = vdup_n_u8(0x80);
3754cc1dc7a3Sopenharmony_ci      int16x8_t cr_const0 = vdupq_n_s16(   (short) ( 1.40200f*4096.0f+0.5f));
3755cc1dc7a3Sopenharmony_ci      int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f));
3756cc1dc7a3Sopenharmony_ci      int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f));
3757cc1dc7a3Sopenharmony_ci      int16x8_t cb_const1 = vdupq_n_s16(   (short) ( 1.77200f*4096.0f+0.5f));
3758cc1dc7a3Sopenharmony_ci
3759cc1dc7a3Sopenharmony_ci      for (; i+7 < count; i += 8) {
3760cc1dc7a3Sopenharmony_ci         // load
3761cc1dc7a3Sopenharmony_ci         uint8x8_t y_bytes  = vld1_u8(y + i);
3762cc1dc7a3Sopenharmony_ci         uint8x8_t cr_bytes = vld1_u8(pcr + i);
3763cc1dc7a3Sopenharmony_ci         uint8x8_t cb_bytes = vld1_u8(pcb + i);
3764cc1dc7a3Sopenharmony_ci         int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip));
3765cc1dc7a3Sopenharmony_ci         int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip));
3766cc1dc7a3Sopenharmony_ci
3767cc1dc7a3Sopenharmony_ci         // expand to s16
3768cc1dc7a3Sopenharmony_ci         int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4));
3769cc1dc7a3Sopenharmony_ci         int16x8_t crw = vshll_n_s8(cr_biased, 7);
3770cc1dc7a3Sopenharmony_ci         int16x8_t cbw = vshll_n_s8(cb_biased, 7);
3771cc1dc7a3Sopenharmony_ci
3772cc1dc7a3Sopenharmony_ci         // color transform
3773cc1dc7a3Sopenharmony_ci         int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0);
3774cc1dc7a3Sopenharmony_ci         int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0);
3775cc1dc7a3Sopenharmony_ci         int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1);
3776cc1dc7a3Sopenharmony_ci         int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1);
3777cc1dc7a3Sopenharmony_ci         int16x8_t rws = vaddq_s16(yws, cr0);
3778cc1dc7a3Sopenharmony_ci         int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1);
3779cc1dc7a3Sopenharmony_ci         int16x8_t bws = vaddq_s16(yws, cb1);
3780cc1dc7a3Sopenharmony_ci
3781cc1dc7a3Sopenharmony_ci         // undo scaling, round, convert to byte
3782cc1dc7a3Sopenharmony_ci         uint8x8x4_t o;
3783cc1dc7a3Sopenharmony_ci         o.val[0] = vqrshrun_n_s16(rws, 4);
3784cc1dc7a3Sopenharmony_ci         o.val[1] = vqrshrun_n_s16(gws, 4);
3785cc1dc7a3Sopenharmony_ci         o.val[2] = vqrshrun_n_s16(bws, 4);
3786cc1dc7a3Sopenharmony_ci         o.val[3] = vdup_n_u8(255);
3787cc1dc7a3Sopenharmony_ci
3788cc1dc7a3Sopenharmony_ci         // store, interleaving r/g/b/a
3789cc1dc7a3Sopenharmony_ci         vst4_u8(out, o);
3790cc1dc7a3Sopenharmony_ci         out += 8*4;
3791cc1dc7a3Sopenharmony_ci      }
3792cc1dc7a3Sopenharmony_ci   }
3793cc1dc7a3Sopenharmony_ci#endif
3794cc1dc7a3Sopenharmony_ci
3795cc1dc7a3Sopenharmony_ci   for (; i < count; ++i) {
3796cc1dc7a3Sopenharmony_ci      int y_fixed = (y[i] << 20) + (1<<19); // rounding
3797cc1dc7a3Sopenharmony_ci      int r,g,b;
3798cc1dc7a3Sopenharmony_ci      int cr = pcr[i] - 128;
3799cc1dc7a3Sopenharmony_ci      int cb = pcb[i] - 128;
3800cc1dc7a3Sopenharmony_ci      r = y_fixed + cr* stbi__float2fixed(1.40200f);
3801cc1dc7a3Sopenharmony_ci      g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);
3802cc1dc7a3Sopenharmony_ci      b = y_fixed                                   +   cb* stbi__float2fixed(1.77200f);
3803cc1dc7a3Sopenharmony_ci      r >>= 20;
3804cc1dc7a3Sopenharmony_ci      g >>= 20;
3805cc1dc7a3Sopenharmony_ci      b >>= 20;
3806cc1dc7a3Sopenharmony_ci      if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }
3807cc1dc7a3Sopenharmony_ci      if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }
3808cc1dc7a3Sopenharmony_ci      if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }
3809cc1dc7a3Sopenharmony_ci      out[0] = (stbi_uc)r;
3810cc1dc7a3Sopenharmony_ci      out[1] = (stbi_uc)g;
3811cc1dc7a3Sopenharmony_ci      out[2] = (stbi_uc)b;
3812cc1dc7a3Sopenharmony_ci      out[3] = 255;
3813cc1dc7a3Sopenharmony_ci      out += step;
3814cc1dc7a3Sopenharmony_ci   }
3815cc1dc7a3Sopenharmony_ci}
3816cc1dc7a3Sopenharmony_ci#endif
3817cc1dc7a3Sopenharmony_ci
3818cc1dc7a3Sopenharmony_ci// set up the kernels
3819cc1dc7a3Sopenharmony_cistatic void stbi__setup_jpeg(stbi__jpeg *j)
3820cc1dc7a3Sopenharmony_ci{
3821cc1dc7a3Sopenharmony_ci   j->idct_block_kernel = stbi__idct_block;
3822cc1dc7a3Sopenharmony_ci   j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row;
3823cc1dc7a3Sopenharmony_ci   j->resample_row_hv_2_kernel = stbi__resample_row_hv_2;
3824cc1dc7a3Sopenharmony_ci
3825cc1dc7a3Sopenharmony_ci#ifdef STBI_SSE2
3826cc1dc7a3Sopenharmony_ci   if (stbi__sse2_available()) {
3827cc1dc7a3Sopenharmony_ci      j->idct_block_kernel = stbi__idct_simd;
3828cc1dc7a3Sopenharmony_ci      j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
3829cc1dc7a3Sopenharmony_ci      j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
3830cc1dc7a3Sopenharmony_ci   }
3831cc1dc7a3Sopenharmony_ci#endif
3832cc1dc7a3Sopenharmony_ci
3833cc1dc7a3Sopenharmony_ci#ifdef STBI_NEON
3834cc1dc7a3Sopenharmony_ci   j->idct_block_kernel = stbi__idct_simd;
3835cc1dc7a3Sopenharmony_ci   j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;
3836cc1dc7a3Sopenharmony_ci   j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;
3837cc1dc7a3Sopenharmony_ci#endif
3838cc1dc7a3Sopenharmony_ci}
3839cc1dc7a3Sopenharmony_ci
3840cc1dc7a3Sopenharmony_ci// clean up the temporary component buffers
3841cc1dc7a3Sopenharmony_cistatic void stbi__cleanup_jpeg(stbi__jpeg *j)
3842cc1dc7a3Sopenharmony_ci{
3843cc1dc7a3Sopenharmony_ci   stbi__free_jpeg_components(j, j->s->img_n, 0);
3844cc1dc7a3Sopenharmony_ci}
3845cc1dc7a3Sopenharmony_ci
3846cc1dc7a3Sopenharmony_citypedef struct
3847cc1dc7a3Sopenharmony_ci{
3848cc1dc7a3Sopenharmony_ci   resample_row_func resample;
3849cc1dc7a3Sopenharmony_ci   stbi_uc *line0,*line1;
3850cc1dc7a3Sopenharmony_ci   int hs,vs;   // expansion factor in each axis
3851cc1dc7a3Sopenharmony_ci   int w_lores; // horizontal pixels pre-expansion
3852cc1dc7a3Sopenharmony_ci   int ystep;   // how far through vertical expansion we are
3853cc1dc7a3Sopenharmony_ci   int ypos;    // which pre-expansion row we're on
3854cc1dc7a3Sopenharmony_ci} stbi__resample;
3855cc1dc7a3Sopenharmony_ci
3856cc1dc7a3Sopenharmony_ci// fast 0..255 * 0..255 => 0..255 rounded multiplication
3857cc1dc7a3Sopenharmony_cistatic stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y)
3858cc1dc7a3Sopenharmony_ci{
3859cc1dc7a3Sopenharmony_ci   unsigned int t = x*y + 128;
3860cc1dc7a3Sopenharmony_ci   return (stbi_uc) ((t + (t >>8)) >> 8);
3861cc1dc7a3Sopenharmony_ci}
3862cc1dc7a3Sopenharmony_ci
3863cc1dc7a3Sopenharmony_cistatic stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp)
3864cc1dc7a3Sopenharmony_ci{
3865cc1dc7a3Sopenharmony_ci   int n, decode_n, is_rgb;
3866cc1dc7a3Sopenharmony_ci   z->s->img_n = 0; // make stbi__cleanup_jpeg safe
3867cc1dc7a3Sopenharmony_ci
3868cc1dc7a3Sopenharmony_ci   // validate req_comp
3869cc1dc7a3Sopenharmony_ci   if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
3870cc1dc7a3Sopenharmony_ci
3871cc1dc7a3Sopenharmony_ci   // load a jpeg image from whichever source, but leave in YCbCr format
3872cc1dc7a3Sopenharmony_ci   if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; }
3873cc1dc7a3Sopenharmony_ci
3874cc1dc7a3Sopenharmony_ci   // determine actual number of components to generate
3875cc1dc7a3Sopenharmony_ci   n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1;
3876cc1dc7a3Sopenharmony_ci
3877cc1dc7a3Sopenharmony_ci   is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif));
3878cc1dc7a3Sopenharmony_ci
3879cc1dc7a3Sopenharmony_ci   if (z->s->img_n == 3 && n < 3 && !is_rgb)
3880cc1dc7a3Sopenharmony_ci      decode_n = 1;
3881cc1dc7a3Sopenharmony_ci   else
3882cc1dc7a3Sopenharmony_ci      decode_n = z->s->img_n;
3883cc1dc7a3Sopenharmony_ci
3884cc1dc7a3Sopenharmony_ci   // nothing to do if no components requested; check this now to avoid
3885cc1dc7a3Sopenharmony_ci   // accessing uninitialized coutput[0] later
3886cc1dc7a3Sopenharmony_ci   if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; }
3887cc1dc7a3Sopenharmony_ci
3888cc1dc7a3Sopenharmony_ci   // resample and color-convert
3889cc1dc7a3Sopenharmony_ci   {
3890cc1dc7a3Sopenharmony_ci      int k;
3891cc1dc7a3Sopenharmony_ci      unsigned int i,j;
3892cc1dc7a3Sopenharmony_ci      stbi_uc *output;
3893cc1dc7a3Sopenharmony_ci      stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL };
3894cc1dc7a3Sopenharmony_ci
3895cc1dc7a3Sopenharmony_ci      stbi__resample res_comp[4];
3896cc1dc7a3Sopenharmony_ci
3897cc1dc7a3Sopenharmony_ci      for (k=0; k < decode_n; ++k) {
3898cc1dc7a3Sopenharmony_ci         stbi__resample *r = &res_comp[k];
3899cc1dc7a3Sopenharmony_ci
3900cc1dc7a3Sopenharmony_ci         // allocate line buffer big enough for upsampling off the edges
3901cc1dc7a3Sopenharmony_ci         // with upsample factor of 4
3902cc1dc7a3Sopenharmony_ci         z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3);
3903cc1dc7a3Sopenharmony_ci         if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
3904cc1dc7a3Sopenharmony_ci
3905cc1dc7a3Sopenharmony_ci         r->hs      = z->img_h_max / z->img_comp[k].h;
3906cc1dc7a3Sopenharmony_ci         r->vs      = z->img_v_max / z->img_comp[k].v;
3907cc1dc7a3Sopenharmony_ci         r->ystep   = r->vs >> 1;
3908cc1dc7a3Sopenharmony_ci         r->w_lores = (z->s->img_x + r->hs-1) / r->hs;
3909cc1dc7a3Sopenharmony_ci         r->ypos    = 0;
3910cc1dc7a3Sopenharmony_ci         r->line0   = r->line1 = z->img_comp[k].data;
3911cc1dc7a3Sopenharmony_ci
3912cc1dc7a3Sopenharmony_ci         if      (r->hs == 1 && r->vs == 1) r->resample = resample_row_1;
3913cc1dc7a3Sopenharmony_ci         else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2;
3914cc1dc7a3Sopenharmony_ci         else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2;
3915cc1dc7a3Sopenharmony_ci         else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel;
3916cc1dc7a3Sopenharmony_ci         else                               r->resample = stbi__resample_row_generic;
3917cc1dc7a3Sopenharmony_ci      }
3918cc1dc7a3Sopenharmony_ci
3919cc1dc7a3Sopenharmony_ci      // can't error after this so, this is safe
3920cc1dc7a3Sopenharmony_ci      output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1);
3921cc1dc7a3Sopenharmony_ci      if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
3922cc1dc7a3Sopenharmony_ci
3923cc1dc7a3Sopenharmony_ci      // now go ahead and resample
3924cc1dc7a3Sopenharmony_ci      for (j=0; j < z->s->img_y; ++j) {
3925cc1dc7a3Sopenharmony_ci         stbi_uc *out = output + n * z->s->img_x * j;
3926cc1dc7a3Sopenharmony_ci         for (k=0; k < decode_n; ++k) {
3927cc1dc7a3Sopenharmony_ci            stbi__resample *r = &res_comp[k];
3928cc1dc7a3Sopenharmony_ci            int y_bot = r->ystep >= (r->vs >> 1);
3929cc1dc7a3Sopenharmony_ci            coutput[k] = r->resample(z->img_comp[k].linebuf,
3930cc1dc7a3Sopenharmony_ci                                     y_bot ? r->line1 : r->line0,
3931cc1dc7a3Sopenharmony_ci                                     y_bot ? r->line0 : r->line1,
3932cc1dc7a3Sopenharmony_ci                                     r->w_lores, r->hs);
3933cc1dc7a3Sopenharmony_ci            if (++r->ystep >= r->vs) {
3934cc1dc7a3Sopenharmony_ci               r->ystep = 0;
3935cc1dc7a3Sopenharmony_ci               r->line0 = r->line1;
3936cc1dc7a3Sopenharmony_ci               if (++r->ypos < z->img_comp[k].y)
3937cc1dc7a3Sopenharmony_ci                  r->line1 += z->img_comp[k].w2;
3938cc1dc7a3Sopenharmony_ci            }
3939cc1dc7a3Sopenharmony_ci         }
3940cc1dc7a3Sopenharmony_ci         if (n >= 3) {
3941cc1dc7a3Sopenharmony_ci            stbi_uc *y = coutput[0];
3942cc1dc7a3Sopenharmony_ci            if (z->s->img_n == 3) {
3943cc1dc7a3Sopenharmony_ci               if (is_rgb) {
3944cc1dc7a3Sopenharmony_ci                  for (i=0; i < z->s->img_x; ++i) {
3945cc1dc7a3Sopenharmony_ci                     out[0] = y[i];
3946cc1dc7a3Sopenharmony_ci                     out[1] = coutput[1][i];
3947cc1dc7a3Sopenharmony_ci                     out[2] = coutput[2][i];
3948cc1dc7a3Sopenharmony_ci                     out[3] = 255;
3949cc1dc7a3Sopenharmony_ci                     out += n;
3950cc1dc7a3Sopenharmony_ci                  }
3951cc1dc7a3Sopenharmony_ci               } else {
3952cc1dc7a3Sopenharmony_ci                  z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
3953cc1dc7a3Sopenharmony_ci               }
3954cc1dc7a3Sopenharmony_ci            } else if (z->s->img_n == 4) {
3955cc1dc7a3Sopenharmony_ci               if (z->app14_color_transform == 0) { // CMYK
3956cc1dc7a3Sopenharmony_ci                  for (i=0; i < z->s->img_x; ++i) {
3957cc1dc7a3Sopenharmony_ci                     stbi_uc m = coutput[3][i];
3958cc1dc7a3Sopenharmony_ci                     out[0] = stbi__blinn_8x8(coutput[0][i], m);
3959cc1dc7a3Sopenharmony_ci                     out[1] = stbi__blinn_8x8(coutput[1][i], m);
3960cc1dc7a3Sopenharmony_ci                     out[2] = stbi__blinn_8x8(coutput[2][i], m);
3961cc1dc7a3Sopenharmony_ci                     out[3] = 255;
3962cc1dc7a3Sopenharmony_ci                     out += n;
3963cc1dc7a3Sopenharmony_ci                  }
3964cc1dc7a3Sopenharmony_ci               } else if (z->app14_color_transform == 2) { // YCCK
3965cc1dc7a3Sopenharmony_ci                  z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
3966cc1dc7a3Sopenharmony_ci                  for (i=0; i < z->s->img_x; ++i) {
3967cc1dc7a3Sopenharmony_ci                     stbi_uc m = coutput[3][i];
3968cc1dc7a3Sopenharmony_ci                     out[0] = stbi__blinn_8x8(255 - out[0], m);
3969cc1dc7a3Sopenharmony_ci                     out[1] = stbi__blinn_8x8(255 - out[1], m);
3970cc1dc7a3Sopenharmony_ci                     out[2] = stbi__blinn_8x8(255 - out[2], m);
3971cc1dc7a3Sopenharmony_ci                     out += n;
3972cc1dc7a3Sopenharmony_ci                  }
3973cc1dc7a3Sopenharmony_ci               } else { // YCbCr + alpha?  Ignore the fourth channel for now
3974cc1dc7a3Sopenharmony_ci                  z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
3975cc1dc7a3Sopenharmony_ci               }
3976cc1dc7a3Sopenharmony_ci            } else
3977cc1dc7a3Sopenharmony_ci               for (i=0; i < z->s->img_x; ++i) {
3978cc1dc7a3Sopenharmony_ci                  out[0] = out[1] = out[2] = y[i];
3979cc1dc7a3Sopenharmony_ci                  out[3] = 255; // not used if n==3
3980cc1dc7a3Sopenharmony_ci                  out += n;
3981cc1dc7a3Sopenharmony_ci               }
3982cc1dc7a3Sopenharmony_ci         } else {
3983cc1dc7a3Sopenharmony_ci            if (is_rgb) {
3984cc1dc7a3Sopenharmony_ci               if (n == 1)
3985cc1dc7a3Sopenharmony_ci                  for (i=0; i < z->s->img_x; ++i)
3986cc1dc7a3Sopenharmony_ci                     *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
3987cc1dc7a3Sopenharmony_ci               else {
3988cc1dc7a3Sopenharmony_ci                  for (i=0; i < z->s->img_x; ++i, out += 2) {
3989cc1dc7a3Sopenharmony_ci                     out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);
3990cc1dc7a3Sopenharmony_ci                     out[1] = 255;
3991cc1dc7a3Sopenharmony_ci                  }
3992cc1dc7a3Sopenharmony_ci               }
3993cc1dc7a3Sopenharmony_ci            } else if (z->s->img_n == 4 && z->app14_color_transform == 0) {
3994cc1dc7a3Sopenharmony_ci               for (i=0; i < z->s->img_x; ++i) {
3995cc1dc7a3Sopenharmony_ci                  stbi_uc m = coutput[3][i];
3996cc1dc7a3Sopenharmony_ci                  stbi_uc r = stbi__blinn_8x8(coutput[0][i], m);
3997cc1dc7a3Sopenharmony_ci                  stbi_uc g = stbi__blinn_8x8(coutput[1][i], m);
3998cc1dc7a3Sopenharmony_ci                  stbi_uc b = stbi__blinn_8x8(coutput[2][i], m);
3999cc1dc7a3Sopenharmony_ci                  out[0] = stbi__compute_y(r, g, b);
4000cc1dc7a3Sopenharmony_ci                  out[1] = 255;
4001cc1dc7a3Sopenharmony_ci                  out += n;
4002cc1dc7a3Sopenharmony_ci               }
4003cc1dc7a3Sopenharmony_ci            } else if (z->s->img_n == 4 && z->app14_color_transform == 2) {
4004cc1dc7a3Sopenharmony_ci               for (i=0; i < z->s->img_x; ++i) {
4005cc1dc7a3Sopenharmony_ci                  out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]);
4006cc1dc7a3Sopenharmony_ci                  out[1] = 255;
4007cc1dc7a3Sopenharmony_ci                  out += n;
4008cc1dc7a3Sopenharmony_ci               }
4009cc1dc7a3Sopenharmony_ci            } else {
4010cc1dc7a3Sopenharmony_ci               stbi_uc *y = coutput[0];
4011cc1dc7a3Sopenharmony_ci               if (n == 1)
4012cc1dc7a3Sopenharmony_ci                  for (i=0; i < z->s->img_x; ++i) out[i] = y[i];
4013cc1dc7a3Sopenharmony_ci               else
4014cc1dc7a3Sopenharmony_ci                  for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; }
4015cc1dc7a3Sopenharmony_ci            }
4016cc1dc7a3Sopenharmony_ci         }
4017cc1dc7a3Sopenharmony_ci      }
4018cc1dc7a3Sopenharmony_ci      stbi__cleanup_jpeg(z);
4019cc1dc7a3Sopenharmony_ci      *out_x = z->s->img_x;
4020cc1dc7a3Sopenharmony_ci      *out_y = z->s->img_y;
4021cc1dc7a3Sopenharmony_ci      if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output
4022cc1dc7a3Sopenharmony_ci      return output;
4023cc1dc7a3Sopenharmony_ci   }
4024cc1dc7a3Sopenharmony_ci}
4025cc1dc7a3Sopenharmony_ci
4026cc1dc7a3Sopenharmony_cistatic void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
4027cc1dc7a3Sopenharmony_ci{
4028cc1dc7a3Sopenharmony_ci   unsigned char* result;
4029cc1dc7a3Sopenharmony_ci   stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
4030cc1dc7a3Sopenharmony_ci   if (!j) return stbi__errpuc("outofmem", "Out of memory");
4031cc1dc7a3Sopenharmony_ci   memset(j, 0, sizeof(stbi__jpeg));
4032cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(ri);
4033cc1dc7a3Sopenharmony_ci   j->s = s;
4034cc1dc7a3Sopenharmony_ci   stbi__setup_jpeg(j);
4035cc1dc7a3Sopenharmony_ci   result = load_jpeg_image(j, x,y,comp,req_comp);
4036cc1dc7a3Sopenharmony_ci   STBI_FREE(j);
4037cc1dc7a3Sopenharmony_ci   return result;
4038cc1dc7a3Sopenharmony_ci}
4039cc1dc7a3Sopenharmony_ci
4040cc1dc7a3Sopenharmony_cistatic int stbi__jpeg_test(stbi__context *s)
4041cc1dc7a3Sopenharmony_ci{
4042cc1dc7a3Sopenharmony_ci   int r;
4043cc1dc7a3Sopenharmony_ci   stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg));
4044cc1dc7a3Sopenharmony_ci   if (!j) return stbi__err("outofmem", "Out of memory");
4045cc1dc7a3Sopenharmony_ci   memset(j, 0, sizeof(stbi__jpeg));
4046cc1dc7a3Sopenharmony_ci   j->s = s;
4047cc1dc7a3Sopenharmony_ci   stbi__setup_jpeg(j);
4048cc1dc7a3Sopenharmony_ci   r = stbi__decode_jpeg_header(j, STBI__SCAN_type);
4049cc1dc7a3Sopenharmony_ci   stbi__rewind(s);
4050cc1dc7a3Sopenharmony_ci   STBI_FREE(j);
4051cc1dc7a3Sopenharmony_ci   return r;
4052cc1dc7a3Sopenharmony_ci}
4053cc1dc7a3Sopenharmony_ci
4054cc1dc7a3Sopenharmony_cistatic int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp)
4055cc1dc7a3Sopenharmony_ci{
4056cc1dc7a3Sopenharmony_ci   if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) {
4057cc1dc7a3Sopenharmony_ci      stbi__rewind( j->s );
4058cc1dc7a3Sopenharmony_ci      return 0;
4059cc1dc7a3Sopenharmony_ci   }
4060cc1dc7a3Sopenharmony_ci   if (x) *x = j->s->img_x;
4061cc1dc7a3Sopenharmony_ci   if (y) *y = j->s->img_y;
4062cc1dc7a3Sopenharmony_ci   if (comp) *comp = j->s->img_n >= 3 ? 3 : 1;
4063cc1dc7a3Sopenharmony_ci   return 1;
4064cc1dc7a3Sopenharmony_ci}
4065cc1dc7a3Sopenharmony_ci
4066cc1dc7a3Sopenharmony_cistatic int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
4067cc1dc7a3Sopenharmony_ci{
4068cc1dc7a3Sopenharmony_ci   int result;
4069cc1dc7a3Sopenharmony_ci   stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
4070cc1dc7a3Sopenharmony_ci   if (!j) return stbi__err("outofmem", "Out of memory");
4071cc1dc7a3Sopenharmony_ci   memset(j, 0, sizeof(stbi__jpeg));
4072cc1dc7a3Sopenharmony_ci   j->s = s;
4073cc1dc7a3Sopenharmony_ci   result = stbi__jpeg_info_raw(j, x, y, comp);
4074cc1dc7a3Sopenharmony_ci   STBI_FREE(j);
4075cc1dc7a3Sopenharmony_ci   return result;
4076cc1dc7a3Sopenharmony_ci}
4077cc1dc7a3Sopenharmony_ci#endif
4078cc1dc7a3Sopenharmony_ci
4079cc1dc7a3Sopenharmony_ci// public domain zlib decode    v0.2  Sean Barrett 2006-11-18
4080cc1dc7a3Sopenharmony_ci//    simple implementation
4081cc1dc7a3Sopenharmony_ci//      - all input must be provided in an upfront buffer
4082cc1dc7a3Sopenharmony_ci//      - all output is written to a single output buffer (can malloc/realloc)
4083cc1dc7a3Sopenharmony_ci//    performance
4084cc1dc7a3Sopenharmony_ci//      - fast huffman
4085cc1dc7a3Sopenharmony_ci
4086cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_ZLIB
4087cc1dc7a3Sopenharmony_ci
4088cc1dc7a3Sopenharmony_ci// fast-way is faster to check than jpeg huffman, but slow way is slower
4089cc1dc7a3Sopenharmony_ci#define STBI__ZFAST_BITS  9 // accelerate all cases in default tables
4090cc1dc7a3Sopenharmony_ci#define STBI__ZFAST_MASK  ((1 << STBI__ZFAST_BITS) - 1)
4091cc1dc7a3Sopenharmony_ci#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet
4092cc1dc7a3Sopenharmony_ci
4093cc1dc7a3Sopenharmony_ci// zlib-style huffman encoding
4094cc1dc7a3Sopenharmony_ci// (jpegs packs from left, zlib from right, so can't share code)
4095cc1dc7a3Sopenharmony_citypedef struct
4096cc1dc7a3Sopenharmony_ci{
4097cc1dc7a3Sopenharmony_ci   stbi__uint16 fast[1 << STBI__ZFAST_BITS];
4098cc1dc7a3Sopenharmony_ci   stbi__uint16 firstcode[16];
4099cc1dc7a3Sopenharmony_ci   int maxcode[17];
4100cc1dc7a3Sopenharmony_ci   stbi__uint16 firstsymbol[16];
4101cc1dc7a3Sopenharmony_ci   stbi_uc  size[STBI__ZNSYMS];
4102cc1dc7a3Sopenharmony_ci   stbi__uint16 value[STBI__ZNSYMS];
4103cc1dc7a3Sopenharmony_ci} stbi__zhuffman;
4104cc1dc7a3Sopenharmony_ci
4105cc1dc7a3Sopenharmony_cistbi_inline static int stbi__bitreverse16(int n)
4106cc1dc7a3Sopenharmony_ci{
4107cc1dc7a3Sopenharmony_ci  n = ((n & 0xAAAA) >>  1) | ((n & 0x5555) << 1);
4108cc1dc7a3Sopenharmony_ci  n = ((n & 0xCCCC) >>  2) | ((n & 0x3333) << 2);
4109cc1dc7a3Sopenharmony_ci  n = ((n & 0xF0F0) >>  4) | ((n & 0x0F0F) << 4);
4110cc1dc7a3Sopenharmony_ci  n = ((n & 0xFF00) >>  8) | ((n & 0x00FF) << 8);
4111cc1dc7a3Sopenharmony_ci  return n;
4112cc1dc7a3Sopenharmony_ci}
4113cc1dc7a3Sopenharmony_ci
4114cc1dc7a3Sopenharmony_cistbi_inline static int stbi__bit_reverse(int v, int bits)
4115cc1dc7a3Sopenharmony_ci{
4116cc1dc7a3Sopenharmony_ci   STBI_ASSERT(bits <= 16);
4117cc1dc7a3Sopenharmony_ci   // to bit reverse n bits, reverse 16 and shift
4118cc1dc7a3Sopenharmony_ci   // e.g. 11 bits, bit reverse and shift away 5
4119cc1dc7a3Sopenharmony_ci   return stbi__bitreverse16(v) >> (16-bits);
4120cc1dc7a3Sopenharmony_ci}
4121cc1dc7a3Sopenharmony_ci
4122cc1dc7a3Sopenharmony_cistatic int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num)
4123cc1dc7a3Sopenharmony_ci{
4124cc1dc7a3Sopenharmony_ci   int i,k=0;
4125cc1dc7a3Sopenharmony_ci   int code, next_code[16], sizes[17];
4126cc1dc7a3Sopenharmony_ci
4127cc1dc7a3Sopenharmony_ci   // DEFLATE spec for generating codes
4128cc1dc7a3Sopenharmony_ci   memset(sizes, 0, sizeof(sizes));
4129cc1dc7a3Sopenharmony_ci   memset(z->fast, 0, sizeof(z->fast));
4130cc1dc7a3Sopenharmony_ci   for (i=0; i < num; ++i)
4131cc1dc7a3Sopenharmony_ci      ++sizes[sizelist[i]];
4132cc1dc7a3Sopenharmony_ci   sizes[0] = 0;
4133cc1dc7a3Sopenharmony_ci   for (i=1; i < 16; ++i)
4134cc1dc7a3Sopenharmony_ci      if (sizes[i] > (1 << i))
4135cc1dc7a3Sopenharmony_ci         return stbi__err("bad sizes", "Corrupt PNG");
4136cc1dc7a3Sopenharmony_ci   code = 0;
4137cc1dc7a3Sopenharmony_ci   for (i=1; i < 16; ++i) {
4138cc1dc7a3Sopenharmony_ci      next_code[i] = code;
4139cc1dc7a3Sopenharmony_ci      z->firstcode[i] = (stbi__uint16) code;
4140cc1dc7a3Sopenharmony_ci      z->firstsymbol[i] = (stbi__uint16) k;
4141cc1dc7a3Sopenharmony_ci      code = (code + sizes[i]);
4142cc1dc7a3Sopenharmony_ci      if (sizes[i])
4143cc1dc7a3Sopenharmony_ci         if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG");
4144cc1dc7a3Sopenharmony_ci      z->maxcode[i] = code << (16-i); // preshift for inner loop
4145cc1dc7a3Sopenharmony_ci      code <<= 1;
4146cc1dc7a3Sopenharmony_ci      k += sizes[i];
4147cc1dc7a3Sopenharmony_ci   }
4148cc1dc7a3Sopenharmony_ci   z->maxcode[16] = 0x10000; // sentinel
4149cc1dc7a3Sopenharmony_ci   for (i=0; i < num; ++i) {
4150cc1dc7a3Sopenharmony_ci      int s = sizelist[i];
4151cc1dc7a3Sopenharmony_ci      if (s) {
4152cc1dc7a3Sopenharmony_ci         int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s];
4153cc1dc7a3Sopenharmony_ci         stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i);
4154cc1dc7a3Sopenharmony_ci         z->size [c] = (stbi_uc     ) s;
4155cc1dc7a3Sopenharmony_ci         z->value[c] = (stbi__uint16) i;
4156cc1dc7a3Sopenharmony_ci         if (s <= STBI__ZFAST_BITS) {
4157cc1dc7a3Sopenharmony_ci            int j = stbi__bit_reverse(next_code[s],s);
4158cc1dc7a3Sopenharmony_ci            while (j < (1 << STBI__ZFAST_BITS)) {
4159cc1dc7a3Sopenharmony_ci               z->fast[j] = fastv;
4160cc1dc7a3Sopenharmony_ci               j += (1 << s);
4161cc1dc7a3Sopenharmony_ci            }
4162cc1dc7a3Sopenharmony_ci         }
4163cc1dc7a3Sopenharmony_ci         ++next_code[s];
4164cc1dc7a3Sopenharmony_ci      }
4165cc1dc7a3Sopenharmony_ci   }
4166cc1dc7a3Sopenharmony_ci   return 1;
4167cc1dc7a3Sopenharmony_ci}
4168cc1dc7a3Sopenharmony_ci
4169cc1dc7a3Sopenharmony_ci// zlib-from-memory implementation for PNG reading
4170cc1dc7a3Sopenharmony_ci//    because PNG allows splitting the zlib stream arbitrarily,
4171cc1dc7a3Sopenharmony_ci//    and it's annoying structurally to have PNG call ZLIB call PNG,
4172cc1dc7a3Sopenharmony_ci//    we require PNG read all the IDATs and combine them into a single
4173cc1dc7a3Sopenharmony_ci//    memory buffer
4174cc1dc7a3Sopenharmony_ci
4175cc1dc7a3Sopenharmony_citypedef struct
4176cc1dc7a3Sopenharmony_ci{
4177cc1dc7a3Sopenharmony_ci   stbi_uc *zbuffer, *zbuffer_end;
4178cc1dc7a3Sopenharmony_ci   int num_bits;
4179cc1dc7a3Sopenharmony_ci   stbi__uint32 code_buffer;
4180cc1dc7a3Sopenharmony_ci
4181cc1dc7a3Sopenharmony_ci   char *zout;
4182cc1dc7a3Sopenharmony_ci   char *zout_start;
4183cc1dc7a3Sopenharmony_ci   char *zout_end;
4184cc1dc7a3Sopenharmony_ci   int   z_expandable;
4185cc1dc7a3Sopenharmony_ci
4186cc1dc7a3Sopenharmony_ci   stbi__zhuffman z_length, z_distance;
4187cc1dc7a3Sopenharmony_ci} stbi__zbuf;
4188cc1dc7a3Sopenharmony_ci
4189cc1dc7a3Sopenharmony_cistbi_inline static int stbi__zeof(stbi__zbuf *z)
4190cc1dc7a3Sopenharmony_ci{
4191cc1dc7a3Sopenharmony_ci   return (z->zbuffer >= z->zbuffer_end);
4192cc1dc7a3Sopenharmony_ci}
4193cc1dc7a3Sopenharmony_ci
4194cc1dc7a3Sopenharmony_cistbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z)
4195cc1dc7a3Sopenharmony_ci{
4196cc1dc7a3Sopenharmony_ci   return stbi__zeof(z) ? 0 : *z->zbuffer++;
4197cc1dc7a3Sopenharmony_ci}
4198cc1dc7a3Sopenharmony_ci
4199cc1dc7a3Sopenharmony_cistatic void stbi__fill_bits(stbi__zbuf *z)
4200cc1dc7a3Sopenharmony_ci{
4201cc1dc7a3Sopenharmony_ci   do {
4202cc1dc7a3Sopenharmony_ci      if (z->code_buffer >= (1U << z->num_bits)) {
4203cc1dc7a3Sopenharmony_ci        z->zbuffer = z->zbuffer_end;  /* treat this as EOF so we fail. */
4204cc1dc7a3Sopenharmony_ci        return;
4205cc1dc7a3Sopenharmony_ci      }
4206cc1dc7a3Sopenharmony_ci      z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits;
4207cc1dc7a3Sopenharmony_ci      z->num_bits += 8;
4208cc1dc7a3Sopenharmony_ci   } while (z->num_bits <= 24);
4209cc1dc7a3Sopenharmony_ci}
4210cc1dc7a3Sopenharmony_ci
4211cc1dc7a3Sopenharmony_cistbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n)
4212cc1dc7a3Sopenharmony_ci{
4213cc1dc7a3Sopenharmony_ci   unsigned int k;
4214cc1dc7a3Sopenharmony_ci   if (z->num_bits < n) stbi__fill_bits(z);
4215cc1dc7a3Sopenharmony_ci   k = z->code_buffer & ((1 << n) - 1);
4216cc1dc7a3Sopenharmony_ci   z->code_buffer >>= n;
4217cc1dc7a3Sopenharmony_ci   z->num_bits -= n;
4218cc1dc7a3Sopenharmony_ci   return k;
4219cc1dc7a3Sopenharmony_ci}
4220cc1dc7a3Sopenharmony_ci
4221cc1dc7a3Sopenharmony_cistatic int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
4222cc1dc7a3Sopenharmony_ci{
4223cc1dc7a3Sopenharmony_ci   int b,s,k;
4224cc1dc7a3Sopenharmony_ci   // not resolved by fast table, so compute it the slow way
4225cc1dc7a3Sopenharmony_ci   // use jpeg approach, which requires MSbits at top
4226cc1dc7a3Sopenharmony_ci   k = stbi__bit_reverse(a->code_buffer, 16);
4227cc1dc7a3Sopenharmony_ci   for (s=STBI__ZFAST_BITS+1; ; ++s)
4228cc1dc7a3Sopenharmony_ci      if (k < z->maxcode[s])
4229cc1dc7a3Sopenharmony_ci         break;
4230cc1dc7a3Sopenharmony_ci   if (s >= 16) return -1; // invalid code!
4231cc1dc7a3Sopenharmony_ci   // code size is s, so:
4232cc1dc7a3Sopenharmony_ci   b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
4233cc1dc7a3Sopenharmony_ci   if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere!
4234cc1dc7a3Sopenharmony_ci   if (z->size[b] != s) return -1;  // was originally an assert, but report failure instead.
4235cc1dc7a3Sopenharmony_ci   a->code_buffer >>= s;
4236cc1dc7a3Sopenharmony_ci   a->num_bits -= s;
4237cc1dc7a3Sopenharmony_ci   return z->value[b];
4238cc1dc7a3Sopenharmony_ci}
4239cc1dc7a3Sopenharmony_ci
4240cc1dc7a3Sopenharmony_cistbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
4241cc1dc7a3Sopenharmony_ci{
4242cc1dc7a3Sopenharmony_ci   int b,s;
4243cc1dc7a3Sopenharmony_ci   if (a->num_bits < 16) {
4244cc1dc7a3Sopenharmony_ci      if (stbi__zeof(a)) {
4245cc1dc7a3Sopenharmony_ci         return -1;   /* report error for unexpected end of data. */
4246cc1dc7a3Sopenharmony_ci      }
4247cc1dc7a3Sopenharmony_ci      stbi__fill_bits(a);
4248cc1dc7a3Sopenharmony_ci   }
4249cc1dc7a3Sopenharmony_ci   b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
4250cc1dc7a3Sopenharmony_ci   if (b) {
4251cc1dc7a3Sopenharmony_ci      s = b >> 9;
4252cc1dc7a3Sopenharmony_ci      a->code_buffer >>= s;
4253cc1dc7a3Sopenharmony_ci      a->num_bits -= s;
4254cc1dc7a3Sopenharmony_ci      return b & 511;
4255cc1dc7a3Sopenharmony_ci   }
4256cc1dc7a3Sopenharmony_ci   return stbi__zhuffman_decode_slowpath(a, z);
4257cc1dc7a3Sopenharmony_ci}
4258cc1dc7a3Sopenharmony_ci
4259cc1dc7a3Sopenharmony_cistatic int stbi__zexpand(stbi__zbuf *z, char *zout, int n)  // need to make room for n bytes
4260cc1dc7a3Sopenharmony_ci{
4261cc1dc7a3Sopenharmony_ci   char *q;
4262cc1dc7a3Sopenharmony_ci   unsigned int cur, limit, old_limit;
4263cc1dc7a3Sopenharmony_ci   z->zout = zout;
4264cc1dc7a3Sopenharmony_ci   if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
4265cc1dc7a3Sopenharmony_ci   cur   = (unsigned int) (z->zout - z->zout_start);
4266cc1dc7a3Sopenharmony_ci   limit = old_limit = (unsigned) (z->zout_end - z->zout_start);
4267cc1dc7a3Sopenharmony_ci   if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory");
4268cc1dc7a3Sopenharmony_ci   while (cur + n > limit) {
4269cc1dc7a3Sopenharmony_ci      if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory");
4270cc1dc7a3Sopenharmony_ci      limit *= 2;
4271cc1dc7a3Sopenharmony_ci   }
4272cc1dc7a3Sopenharmony_ci   q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
4273cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(old_limit);
4274cc1dc7a3Sopenharmony_ci   if (q == NULL) return stbi__err("outofmem", "Out of memory");
4275cc1dc7a3Sopenharmony_ci   z->zout_start = q;
4276cc1dc7a3Sopenharmony_ci   z->zout       = q + cur;
4277cc1dc7a3Sopenharmony_ci   z->zout_end   = q + limit;
4278cc1dc7a3Sopenharmony_ci   return 1;
4279cc1dc7a3Sopenharmony_ci}
4280cc1dc7a3Sopenharmony_ci
4281cc1dc7a3Sopenharmony_cistatic const int stbi__zlength_base[31] = {
4282cc1dc7a3Sopenharmony_ci   3,4,5,6,7,8,9,10,11,13,
4283cc1dc7a3Sopenharmony_ci   15,17,19,23,27,31,35,43,51,59,
4284cc1dc7a3Sopenharmony_ci   67,83,99,115,131,163,195,227,258,0,0 };
4285cc1dc7a3Sopenharmony_ci
4286cc1dc7a3Sopenharmony_cistatic const int stbi__zlength_extra[31]=
4287cc1dc7a3Sopenharmony_ci{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 };
4288cc1dc7a3Sopenharmony_ci
4289cc1dc7a3Sopenharmony_cistatic const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,
4290cc1dc7a3Sopenharmony_ci257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
4291cc1dc7a3Sopenharmony_ci
4292cc1dc7a3Sopenharmony_cistatic const int stbi__zdist_extra[32] =
4293cc1dc7a3Sopenharmony_ci{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
4294cc1dc7a3Sopenharmony_ci
4295cc1dc7a3Sopenharmony_cistatic int stbi__parse_huffman_block(stbi__zbuf *a)
4296cc1dc7a3Sopenharmony_ci{
4297cc1dc7a3Sopenharmony_ci   char *zout = a->zout;
4298cc1dc7a3Sopenharmony_ci   for(;;) {
4299cc1dc7a3Sopenharmony_ci      int z = stbi__zhuffman_decode(a, &a->z_length);
4300cc1dc7a3Sopenharmony_ci      if (z < 256) {
4301cc1dc7a3Sopenharmony_ci         if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes
4302cc1dc7a3Sopenharmony_ci         if (zout >= a->zout_end) {
4303cc1dc7a3Sopenharmony_ci            if (!stbi__zexpand(a, zout, 1)) return 0;
4304cc1dc7a3Sopenharmony_ci            zout = a->zout;
4305cc1dc7a3Sopenharmony_ci         }
4306cc1dc7a3Sopenharmony_ci         *zout++ = (char) z;
4307cc1dc7a3Sopenharmony_ci      } else {
4308cc1dc7a3Sopenharmony_ci         stbi_uc *p;
4309cc1dc7a3Sopenharmony_ci         int len,dist;
4310cc1dc7a3Sopenharmony_ci         if (z == 256) {
4311cc1dc7a3Sopenharmony_ci            a->zout = zout;
4312cc1dc7a3Sopenharmony_ci            return 1;
4313cc1dc7a3Sopenharmony_ci         }
4314cc1dc7a3Sopenharmony_ci         if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data
4315cc1dc7a3Sopenharmony_ci         z -= 257;
4316cc1dc7a3Sopenharmony_ci         len = stbi__zlength_base[z];
4317cc1dc7a3Sopenharmony_ci         if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]);
4318cc1dc7a3Sopenharmony_ci         z = stbi__zhuffman_decode(a, &a->z_distance);
4319cc1dc7a3Sopenharmony_ci         if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data
4320cc1dc7a3Sopenharmony_ci         dist = stbi__zdist_base[z];
4321cc1dc7a3Sopenharmony_ci         if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);
4322cc1dc7a3Sopenharmony_ci         if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");
4323cc1dc7a3Sopenharmony_ci         if (zout + len > a->zout_end) {
4324cc1dc7a3Sopenharmony_ci            if (!stbi__zexpand(a, zout, len)) return 0;
4325cc1dc7a3Sopenharmony_ci            zout = a->zout;
4326cc1dc7a3Sopenharmony_ci         }
4327cc1dc7a3Sopenharmony_ci         p = (stbi_uc *) (zout - dist);
4328cc1dc7a3Sopenharmony_ci         if (dist == 1) { // run of one byte; common in images.
4329cc1dc7a3Sopenharmony_ci            stbi_uc v = *p;
4330cc1dc7a3Sopenharmony_ci            if (len) { do *zout++ = v; while (--len); }
4331cc1dc7a3Sopenharmony_ci         } else {
4332cc1dc7a3Sopenharmony_ci            if (len) { do *zout++ = *p++; while (--len); }
4333cc1dc7a3Sopenharmony_ci         }
4334cc1dc7a3Sopenharmony_ci      }
4335cc1dc7a3Sopenharmony_ci   }
4336cc1dc7a3Sopenharmony_ci}
4337cc1dc7a3Sopenharmony_ci
4338cc1dc7a3Sopenharmony_cistatic int stbi__compute_huffman_codes(stbi__zbuf *a)
4339cc1dc7a3Sopenharmony_ci{
4340cc1dc7a3Sopenharmony_ci   static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
4341cc1dc7a3Sopenharmony_ci   stbi__zhuffman z_codelength;
4342cc1dc7a3Sopenharmony_ci   stbi_uc lencodes[286+32+137];//padding for maximum single op
4343cc1dc7a3Sopenharmony_ci   stbi_uc codelength_sizes[19];
4344cc1dc7a3Sopenharmony_ci   int i,n;
4345cc1dc7a3Sopenharmony_ci
4346cc1dc7a3Sopenharmony_ci   int hlit  = stbi__zreceive(a,5) + 257;
4347cc1dc7a3Sopenharmony_ci   int hdist = stbi__zreceive(a,5) + 1;
4348cc1dc7a3Sopenharmony_ci   int hclen = stbi__zreceive(a,4) + 4;
4349cc1dc7a3Sopenharmony_ci   int ntot  = hlit + hdist;
4350cc1dc7a3Sopenharmony_ci
4351cc1dc7a3Sopenharmony_ci   memset(codelength_sizes, 0, sizeof(codelength_sizes));
4352cc1dc7a3Sopenharmony_ci   for (i=0; i < hclen; ++i) {
4353cc1dc7a3Sopenharmony_ci      int s = stbi__zreceive(a,3);
4354cc1dc7a3Sopenharmony_ci      codelength_sizes[length_dezigzag[i]] = (stbi_uc) s;
4355cc1dc7a3Sopenharmony_ci   }
4356cc1dc7a3Sopenharmony_ci   if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0;
4357cc1dc7a3Sopenharmony_ci
4358cc1dc7a3Sopenharmony_ci   n = 0;
4359cc1dc7a3Sopenharmony_ci   while (n < ntot) {
4360cc1dc7a3Sopenharmony_ci      int c = stbi__zhuffman_decode(a, &z_codelength);
4361cc1dc7a3Sopenharmony_ci      if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG");
4362cc1dc7a3Sopenharmony_ci      if (c < 16)
4363cc1dc7a3Sopenharmony_ci         lencodes[n++] = (stbi_uc) c;
4364cc1dc7a3Sopenharmony_ci      else {
4365cc1dc7a3Sopenharmony_ci         stbi_uc fill = 0;
4366cc1dc7a3Sopenharmony_ci         if (c == 16) {
4367cc1dc7a3Sopenharmony_ci            c = stbi__zreceive(a,2)+3;
4368cc1dc7a3Sopenharmony_ci            if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");
4369cc1dc7a3Sopenharmony_ci            fill = lencodes[n-1];
4370cc1dc7a3Sopenharmony_ci         } else if (c == 17) {
4371cc1dc7a3Sopenharmony_ci            c = stbi__zreceive(a,3)+3;
4372cc1dc7a3Sopenharmony_ci         } else if (c == 18) {
4373cc1dc7a3Sopenharmony_ci            c = stbi__zreceive(a,7)+11;
4374cc1dc7a3Sopenharmony_ci         } else {
4375cc1dc7a3Sopenharmony_ci            return stbi__err("bad codelengths", "Corrupt PNG");
4376cc1dc7a3Sopenharmony_ci         }
4377cc1dc7a3Sopenharmony_ci         if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG");
4378cc1dc7a3Sopenharmony_ci         memset(lencodes+n, fill, c);
4379cc1dc7a3Sopenharmony_ci         n += c;
4380cc1dc7a3Sopenharmony_ci      }
4381cc1dc7a3Sopenharmony_ci   }
4382cc1dc7a3Sopenharmony_ci   if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG");
4383cc1dc7a3Sopenharmony_ci   if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0;
4384cc1dc7a3Sopenharmony_ci   if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0;
4385cc1dc7a3Sopenharmony_ci   return 1;
4386cc1dc7a3Sopenharmony_ci}
4387cc1dc7a3Sopenharmony_ci
4388cc1dc7a3Sopenharmony_cistatic int stbi__parse_uncompressed_block(stbi__zbuf *a)
4389cc1dc7a3Sopenharmony_ci{
4390cc1dc7a3Sopenharmony_ci   stbi_uc header[4];
4391cc1dc7a3Sopenharmony_ci   int len,nlen,k;
4392cc1dc7a3Sopenharmony_ci   if (a->num_bits & 7)
4393cc1dc7a3Sopenharmony_ci      stbi__zreceive(a, a->num_bits & 7); // discard
4394cc1dc7a3Sopenharmony_ci   // drain the bit-packed data into header
4395cc1dc7a3Sopenharmony_ci   k = 0;
4396cc1dc7a3Sopenharmony_ci   while (a->num_bits > 0) {
4397cc1dc7a3Sopenharmony_ci      header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check
4398cc1dc7a3Sopenharmony_ci      a->code_buffer >>= 8;
4399cc1dc7a3Sopenharmony_ci      a->num_bits -= 8;
4400cc1dc7a3Sopenharmony_ci   }
4401cc1dc7a3Sopenharmony_ci   if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG");
4402cc1dc7a3Sopenharmony_ci   // now fill header the normal way
4403cc1dc7a3Sopenharmony_ci   while (k < 4)
4404cc1dc7a3Sopenharmony_ci      header[k++] = stbi__zget8(a);
4405cc1dc7a3Sopenharmony_ci   len  = header[1] * 256 + header[0];
4406cc1dc7a3Sopenharmony_ci   nlen = header[3] * 256 + header[2];
4407cc1dc7a3Sopenharmony_ci   if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG");
4408cc1dc7a3Sopenharmony_ci   if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG");
4409cc1dc7a3Sopenharmony_ci   if (a->zout + len > a->zout_end)
4410cc1dc7a3Sopenharmony_ci      if (!stbi__zexpand(a, a->zout, len)) return 0;
4411cc1dc7a3Sopenharmony_ci   memcpy(a->zout, a->zbuffer, len);
4412cc1dc7a3Sopenharmony_ci   a->zbuffer += len;
4413cc1dc7a3Sopenharmony_ci   a->zout += len;
4414cc1dc7a3Sopenharmony_ci   return 1;
4415cc1dc7a3Sopenharmony_ci}
4416cc1dc7a3Sopenharmony_ci
4417cc1dc7a3Sopenharmony_cistatic int stbi__parse_zlib_header(stbi__zbuf *a)
4418cc1dc7a3Sopenharmony_ci{
4419cc1dc7a3Sopenharmony_ci   int cmf   = stbi__zget8(a);
4420cc1dc7a3Sopenharmony_ci   int cm    = cmf & 15;
4421cc1dc7a3Sopenharmony_ci   /* int cinfo = cmf >> 4; */
4422cc1dc7a3Sopenharmony_ci   int flg   = stbi__zget8(a);
4423cc1dc7a3Sopenharmony_ci   if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
4424cc1dc7a3Sopenharmony_ci   if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
4425cc1dc7a3Sopenharmony_ci   if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png
4426cc1dc7a3Sopenharmony_ci   if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png
4427cc1dc7a3Sopenharmony_ci   // window = 1 << (8 + cinfo)... but who cares, we fully buffer output
4428cc1dc7a3Sopenharmony_ci   return 1;
4429cc1dc7a3Sopenharmony_ci}
4430cc1dc7a3Sopenharmony_ci
4431cc1dc7a3Sopenharmony_cistatic const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] =
4432cc1dc7a3Sopenharmony_ci{
4433cc1dc7a3Sopenharmony_ci   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4434cc1dc7a3Sopenharmony_ci   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4435cc1dc7a3Sopenharmony_ci   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4436cc1dc7a3Sopenharmony_ci   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4437cc1dc7a3Sopenharmony_ci   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
4438cc1dc7a3Sopenharmony_ci   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
4439cc1dc7a3Sopenharmony_ci   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
4440cc1dc7a3Sopenharmony_ci   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
4441cc1dc7a3Sopenharmony_ci   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8
4442cc1dc7a3Sopenharmony_ci};
4443cc1dc7a3Sopenharmony_cistatic const stbi_uc stbi__zdefault_distance[32] =
4444cc1dc7a3Sopenharmony_ci{
4445cc1dc7a3Sopenharmony_ci   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,5,5,5,5,5,5,5
4446cc1dc7a3Sopenharmony_ci};
4447cc1dc7a3Sopenharmony_ci/*
4448cc1dc7a3Sopenharmony_ciInit algorithm:
4449cc1dc7a3Sopenharmony_ci{
4450cc1dc7a3Sopenharmony_ci   int i;   // use <= to match clearly with spec
4451cc1dc7a3Sopenharmony_ci   for (i=0; i <= 143; ++i)     stbi__zdefault_length[i]   = 8;
4452cc1dc7a3Sopenharmony_ci   for (   ; i <= 255; ++i)     stbi__zdefault_length[i]   = 9;
4453cc1dc7a3Sopenharmony_ci   for (   ; i <= 279; ++i)     stbi__zdefault_length[i]   = 7;
4454cc1dc7a3Sopenharmony_ci   for (   ; i <= 287; ++i)     stbi__zdefault_length[i]   = 8;
4455cc1dc7a3Sopenharmony_ci
4456cc1dc7a3Sopenharmony_ci   for (i=0; i <=  31; ++i)     stbi__zdefault_distance[i] = 5;
4457cc1dc7a3Sopenharmony_ci}
4458cc1dc7a3Sopenharmony_ci*/
4459cc1dc7a3Sopenharmony_ci
4460cc1dc7a3Sopenharmony_cistatic int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
4461cc1dc7a3Sopenharmony_ci{
4462cc1dc7a3Sopenharmony_ci   int final, type;
4463cc1dc7a3Sopenharmony_ci   if (parse_header)
4464cc1dc7a3Sopenharmony_ci      if (!stbi__parse_zlib_header(a)) return 0;
4465cc1dc7a3Sopenharmony_ci   a->num_bits = 0;
4466cc1dc7a3Sopenharmony_ci   a->code_buffer = 0;
4467cc1dc7a3Sopenharmony_ci   do {
4468cc1dc7a3Sopenharmony_ci      final = stbi__zreceive(a,1);
4469cc1dc7a3Sopenharmony_ci      type = stbi__zreceive(a,2);
4470cc1dc7a3Sopenharmony_ci      if (type == 0) {
4471cc1dc7a3Sopenharmony_ci         if (!stbi__parse_uncompressed_block(a)) return 0;
4472cc1dc7a3Sopenharmony_ci      } else if (type == 3) {
4473cc1dc7a3Sopenharmony_ci         return 0;
4474cc1dc7a3Sopenharmony_ci      } else {
4475cc1dc7a3Sopenharmony_ci         if (type == 1) {
4476cc1dc7a3Sopenharmony_ci            // use fixed code lengths
4477cc1dc7a3Sopenharmony_ci            if (!stbi__zbuild_huffman(&a->z_length  , stbi__zdefault_length  , STBI__ZNSYMS)) return 0;
4478cc1dc7a3Sopenharmony_ci            if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance,  32)) return 0;
4479cc1dc7a3Sopenharmony_ci         } else {
4480cc1dc7a3Sopenharmony_ci            if (!stbi__compute_huffman_codes(a)) return 0;
4481cc1dc7a3Sopenharmony_ci         }
4482cc1dc7a3Sopenharmony_ci         if (!stbi__parse_huffman_block(a)) return 0;
4483cc1dc7a3Sopenharmony_ci      }
4484cc1dc7a3Sopenharmony_ci   } while (!final);
4485cc1dc7a3Sopenharmony_ci   return 1;
4486cc1dc7a3Sopenharmony_ci}
4487cc1dc7a3Sopenharmony_ci
4488cc1dc7a3Sopenharmony_cistatic int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header)
4489cc1dc7a3Sopenharmony_ci{
4490cc1dc7a3Sopenharmony_ci   a->zout_start = obuf;
4491cc1dc7a3Sopenharmony_ci   a->zout       = obuf;
4492cc1dc7a3Sopenharmony_ci   a->zout_end   = obuf + olen;
4493cc1dc7a3Sopenharmony_ci   a->z_expandable = exp;
4494cc1dc7a3Sopenharmony_ci
4495cc1dc7a3Sopenharmony_ci   return stbi__parse_zlib(a, parse_header);
4496cc1dc7a3Sopenharmony_ci}
4497cc1dc7a3Sopenharmony_ci
4498cc1dc7a3Sopenharmony_ciSTBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen)
4499cc1dc7a3Sopenharmony_ci{
4500cc1dc7a3Sopenharmony_ci   stbi__zbuf a;
4501cc1dc7a3Sopenharmony_ci   char *p = (char *) stbi__malloc(initial_size);
4502cc1dc7a3Sopenharmony_ci   if (p == NULL) return NULL;
4503cc1dc7a3Sopenharmony_ci   a.zbuffer = (stbi_uc *) buffer;
4504cc1dc7a3Sopenharmony_ci   a.zbuffer_end = (stbi_uc *) buffer + len;
4505cc1dc7a3Sopenharmony_ci   if (stbi__do_zlib(&a, p, initial_size, 1, 1)) {
4506cc1dc7a3Sopenharmony_ci      if (outlen) *outlen = (int) (a.zout - a.zout_start);
4507cc1dc7a3Sopenharmony_ci      return a.zout_start;
4508cc1dc7a3Sopenharmony_ci   } else {
4509cc1dc7a3Sopenharmony_ci      STBI_FREE(a.zout_start);
4510cc1dc7a3Sopenharmony_ci      return NULL;
4511cc1dc7a3Sopenharmony_ci   }
4512cc1dc7a3Sopenharmony_ci}
4513cc1dc7a3Sopenharmony_ci
4514cc1dc7a3Sopenharmony_ciSTBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen)
4515cc1dc7a3Sopenharmony_ci{
4516cc1dc7a3Sopenharmony_ci   return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen);
4517cc1dc7a3Sopenharmony_ci}
4518cc1dc7a3Sopenharmony_ci
4519cc1dc7a3Sopenharmony_ciSTBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header)
4520cc1dc7a3Sopenharmony_ci{
4521cc1dc7a3Sopenharmony_ci   stbi__zbuf a;
4522cc1dc7a3Sopenharmony_ci   char *p = (char *) stbi__malloc(initial_size);
4523cc1dc7a3Sopenharmony_ci   if (p == NULL) return NULL;
4524cc1dc7a3Sopenharmony_ci   a.zbuffer = (stbi_uc *) buffer;
4525cc1dc7a3Sopenharmony_ci   a.zbuffer_end = (stbi_uc *) buffer + len;
4526cc1dc7a3Sopenharmony_ci   if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) {
4527cc1dc7a3Sopenharmony_ci      if (outlen) *outlen = (int) (a.zout - a.zout_start);
4528cc1dc7a3Sopenharmony_ci      return a.zout_start;
4529cc1dc7a3Sopenharmony_ci   } else {
4530cc1dc7a3Sopenharmony_ci      STBI_FREE(a.zout_start);
4531cc1dc7a3Sopenharmony_ci      return NULL;
4532cc1dc7a3Sopenharmony_ci   }
4533cc1dc7a3Sopenharmony_ci}
4534cc1dc7a3Sopenharmony_ci
4535cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen)
4536cc1dc7a3Sopenharmony_ci{
4537cc1dc7a3Sopenharmony_ci   stbi__zbuf a;
4538cc1dc7a3Sopenharmony_ci   a.zbuffer = (stbi_uc *) ibuffer;
4539cc1dc7a3Sopenharmony_ci   a.zbuffer_end = (stbi_uc *) ibuffer + ilen;
4540cc1dc7a3Sopenharmony_ci   if (stbi__do_zlib(&a, obuffer, olen, 0, 1))
4541cc1dc7a3Sopenharmony_ci      return (int) (a.zout - a.zout_start);
4542cc1dc7a3Sopenharmony_ci   else
4543cc1dc7a3Sopenharmony_ci      return -1;
4544cc1dc7a3Sopenharmony_ci}
4545cc1dc7a3Sopenharmony_ci
4546cc1dc7a3Sopenharmony_ciSTBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen)
4547cc1dc7a3Sopenharmony_ci{
4548cc1dc7a3Sopenharmony_ci   stbi__zbuf a;
4549cc1dc7a3Sopenharmony_ci   char *p = (char *) stbi__malloc(16384);
4550cc1dc7a3Sopenharmony_ci   if (p == NULL) return NULL;
4551cc1dc7a3Sopenharmony_ci   a.zbuffer = (stbi_uc *) buffer;
4552cc1dc7a3Sopenharmony_ci   a.zbuffer_end = (stbi_uc *) buffer+len;
4553cc1dc7a3Sopenharmony_ci   if (stbi__do_zlib(&a, p, 16384, 1, 0)) {
4554cc1dc7a3Sopenharmony_ci      if (outlen) *outlen = (int) (a.zout - a.zout_start);
4555cc1dc7a3Sopenharmony_ci      return a.zout_start;
4556cc1dc7a3Sopenharmony_ci   } else {
4557cc1dc7a3Sopenharmony_ci      STBI_FREE(a.zout_start);
4558cc1dc7a3Sopenharmony_ci      return NULL;
4559cc1dc7a3Sopenharmony_ci   }
4560cc1dc7a3Sopenharmony_ci}
4561cc1dc7a3Sopenharmony_ci
4562cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen)
4563cc1dc7a3Sopenharmony_ci{
4564cc1dc7a3Sopenharmony_ci   stbi__zbuf a;
4565cc1dc7a3Sopenharmony_ci   a.zbuffer = (stbi_uc *) ibuffer;
4566cc1dc7a3Sopenharmony_ci   a.zbuffer_end = (stbi_uc *) ibuffer + ilen;
4567cc1dc7a3Sopenharmony_ci   if (stbi__do_zlib(&a, obuffer, olen, 0, 0))
4568cc1dc7a3Sopenharmony_ci      return (int) (a.zout - a.zout_start);
4569cc1dc7a3Sopenharmony_ci   else
4570cc1dc7a3Sopenharmony_ci      return -1;
4571cc1dc7a3Sopenharmony_ci}
4572cc1dc7a3Sopenharmony_ci#endif
4573cc1dc7a3Sopenharmony_ci
4574cc1dc7a3Sopenharmony_ci// public domain "baseline" PNG decoder   v0.10  Sean Barrett 2006-11-18
4575cc1dc7a3Sopenharmony_ci//    simple implementation
4576cc1dc7a3Sopenharmony_ci//      - only 8-bit samples
4577cc1dc7a3Sopenharmony_ci//      - no CRC checking
4578cc1dc7a3Sopenharmony_ci//      - allocates lots of intermediate memory
4579cc1dc7a3Sopenharmony_ci//        - avoids problem of streaming data between subsystems
4580cc1dc7a3Sopenharmony_ci//        - avoids explicit window management
4581cc1dc7a3Sopenharmony_ci//    performance
4582cc1dc7a3Sopenharmony_ci//      - uses stb_zlib, a PD zlib implementation with fast huffman decoding
4583cc1dc7a3Sopenharmony_ci
4584cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_PNG
4585cc1dc7a3Sopenharmony_citypedef struct
4586cc1dc7a3Sopenharmony_ci{
4587cc1dc7a3Sopenharmony_ci   stbi__uint32 length;
4588cc1dc7a3Sopenharmony_ci   stbi__uint32 type;
4589cc1dc7a3Sopenharmony_ci} stbi__pngchunk;
4590cc1dc7a3Sopenharmony_ci
4591cc1dc7a3Sopenharmony_cistatic stbi__pngchunk stbi__get_chunk_header(stbi__context *s)
4592cc1dc7a3Sopenharmony_ci{
4593cc1dc7a3Sopenharmony_ci   stbi__pngchunk c;
4594cc1dc7a3Sopenharmony_ci   c.length = stbi__get32be(s);
4595cc1dc7a3Sopenharmony_ci   c.type   = stbi__get32be(s);
4596cc1dc7a3Sopenharmony_ci   return c;
4597cc1dc7a3Sopenharmony_ci}
4598cc1dc7a3Sopenharmony_ci
4599cc1dc7a3Sopenharmony_cistatic int stbi__check_png_header(stbi__context *s)
4600cc1dc7a3Sopenharmony_ci{
4601cc1dc7a3Sopenharmony_ci   static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 };
4602cc1dc7a3Sopenharmony_ci   int i;
4603cc1dc7a3Sopenharmony_ci   for (i=0; i < 8; ++i)
4604cc1dc7a3Sopenharmony_ci      if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG");
4605cc1dc7a3Sopenharmony_ci   return 1;
4606cc1dc7a3Sopenharmony_ci}
4607cc1dc7a3Sopenharmony_ci
4608cc1dc7a3Sopenharmony_citypedef struct
4609cc1dc7a3Sopenharmony_ci{
4610cc1dc7a3Sopenharmony_ci   stbi__context *s;
4611cc1dc7a3Sopenharmony_ci   stbi_uc *idata, *expanded, *out;
4612cc1dc7a3Sopenharmony_ci   int depth;
4613cc1dc7a3Sopenharmony_ci} stbi__png;
4614cc1dc7a3Sopenharmony_ci
4615cc1dc7a3Sopenharmony_ci
4616cc1dc7a3Sopenharmony_cienum {
4617cc1dc7a3Sopenharmony_ci   STBI__F_none=0,
4618cc1dc7a3Sopenharmony_ci   STBI__F_sub=1,
4619cc1dc7a3Sopenharmony_ci   STBI__F_up=2,
4620cc1dc7a3Sopenharmony_ci   STBI__F_avg=3,
4621cc1dc7a3Sopenharmony_ci   STBI__F_paeth=4,
4622cc1dc7a3Sopenharmony_ci   // synthetic filters used for first scanline to avoid needing a dummy row of 0s
4623cc1dc7a3Sopenharmony_ci   STBI__F_avg_first,
4624cc1dc7a3Sopenharmony_ci   STBI__F_paeth_first
4625cc1dc7a3Sopenharmony_ci};
4626cc1dc7a3Sopenharmony_ci
4627cc1dc7a3Sopenharmony_cistatic stbi_uc first_row_filter[5] =
4628cc1dc7a3Sopenharmony_ci{
4629cc1dc7a3Sopenharmony_ci   STBI__F_none,
4630cc1dc7a3Sopenharmony_ci   STBI__F_sub,
4631cc1dc7a3Sopenharmony_ci   STBI__F_none,
4632cc1dc7a3Sopenharmony_ci   STBI__F_avg_first,
4633cc1dc7a3Sopenharmony_ci   STBI__F_paeth_first
4634cc1dc7a3Sopenharmony_ci};
4635cc1dc7a3Sopenharmony_ci
4636cc1dc7a3Sopenharmony_cistatic int stbi__paeth(int a, int b, int c)
4637cc1dc7a3Sopenharmony_ci{
4638cc1dc7a3Sopenharmony_ci   int p = a + b - c;
4639cc1dc7a3Sopenharmony_ci   int pa = abs(p-a);
4640cc1dc7a3Sopenharmony_ci   int pb = abs(p-b);
4641cc1dc7a3Sopenharmony_ci   int pc = abs(p-c);
4642cc1dc7a3Sopenharmony_ci   if (pa <= pb && pa <= pc) return a;
4643cc1dc7a3Sopenharmony_ci   if (pb <= pc) return b;
4644cc1dc7a3Sopenharmony_ci   return c;
4645cc1dc7a3Sopenharmony_ci}
4646cc1dc7a3Sopenharmony_ci
4647cc1dc7a3Sopenharmony_cistatic const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 };
4648cc1dc7a3Sopenharmony_ci
4649cc1dc7a3Sopenharmony_ci// create the png data from post-deflated data
4650cc1dc7a3Sopenharmony_cistatic int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
4651cc1dc7a3Sopenharmony_ci{
4652cc1dc7a3Sopenharmony_ci   int bytes = (depth == 16? 2 : 1);
4653cc1dc7a3Sopenharmony_ci   stbi__context *s = a->s;
4654cc1dc7a3Sopenharmony_ci   stbi__uint32 i,j,stride = x*out_n*bytes;
4655cc1dc7a3Sopenharmony_ci   stbi__uint32 img_len, img_width_bytes;
4656cc1dc7a3Sopenharmony_ci   int k;
4657cc1dc7a3Sopenharmony_ci   int img_n = s->img_n; // copy it into a local for later
4658cc1dc7a3Sopenharmony_ci
4659cc1dc7a3Sopenharmony_ci   int output_bytes = out_n*bytes;
4660cc1dc7a3Sopenharmony_ci   int filter_bytes = img_n*bytes;
4661cc1dc7a3Sopenharmony_ci   int width = x;
4662cc1dc7a3Sopenharmony_ci
4663cc1dc7a3Sopenharmony_ci   STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
4664cc1dc7a3Sopenharmony_ci   a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
4665cc1dc7a3Sopenharmony_ci   if (!a->out) return stbi__err("outofmem", "Out of memory");
4666cc1dc7a3Sopenharmony_ci
4667cc1dc7a3Sopenharmony_ci   if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG");
4668cc1dc7a3Sopenharmony_ci   img_width_bytes = (((img_n * x * depth) + 7) >> 3);
4669cc1dc7a3Sopenharmony_ci   img_len = (img_width_bytes + 1) * y;
4670cc1dc7a3Sopenharmony_ci
4671cc1dc7a3Sopenharmony_ci   // we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
4672cc1dc7a3Sopenharmony_ci   // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros),
4673cc1dc7a3Sopenharmony_ci   // so just check for raw_len < img_len always.
4674cc1dc7a3Sopenharmony_ci   if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
4675cc1dc7a3Sopenharmony_ci
4676cc1dc7a3Sopenharmony_ci   for (j=0; j < y; ++j) {
4677cc1dc7a3Sopenharmony_ci      stbi_uc *cur = a->out + stride*j;
4678cc1dc7a3Sopenharmony_ci      stbi_uc *prior;
4679cc1dc7a3Sopenharmony_ci      int filter = *raw++;
4680cc1dc7a3Sopenharmony_ci
4681cc1dc7a3Sopenharmony_ci      if (filter > 4)
4682cc1dc7a3Sopenharmony_ci         return stbi__err("invalid filter","Corrupt PNG");
4683cc1dc7a3Sopenharmony_ci
4684cc1dc7a3Sopenharmony_ci      if (depth < 8) {
4685cc1dc7a3Sopenharmony_ci         if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG");
4686cc1dc7a3Sopenharmony_ci         cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
4687cc1dc7a3Sopenharmony_ci         filter_bytes = 1;
4688cc1dc7a3Sopenharmony_ci         width = img_width_bytes;
4689cc1dc7a3Sopenharmony_ci      }
4690cc1dc7a3Sopenharmony_ci      prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above
4691cc1dc7a3Sopenharmony_ci
4692cc1dc7a3Sopenharmony_ci      // if first row, use special filter that doesn't sample previous row
4693cc1dc7a3Sopenharmony_ci      if (j == 0) filter = first_row_filter[filter];
4694cc1dc7a3Sopenharmony_ci
4695cc1dc7a3Sopenharmony_ci      // handle first byte explicitly
4696cc1dc7a3Sopenharmony_ci      for (k=0; k < filter_bytes; ++k) {
4697cc1dc7a3Sopenharmony_ci         switch (filter) {
4698cc1dc7a3Sopenharmony_ci            case STBI__F_none       : cur[k] = raw[k]; break;
4699cc1dc7a3Sopenharmony_ci            case STBI__F_sub        : cur[k] = raw[k]; break;
4700cc1dc7a3Sopenharmony_ci            case STBI__F_up         : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
4701cc1dc7a3Sopenharmony_ci            case STBI__F_avg        : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break;
4702cc1dc7a3Sopenharmony_ci            case STBI__F_paeth      : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break;
4703cc1dc7a3Sopenharmony_ci            case STBI__F_avg_first  : cur[k] = raw[k]; break;
4704cc1dc7a3Sopenharmony_ci            case STBI__F_paeth_first: cur[k] = raw[k]; break;
4705cc1dc7a3Sopenharmony_ci         }
4706cc1dc7a3Sopenharmony_ci      }
4707cc1dc7a3Sopenharmony_ci
4708cc1dc7a3Sopenharmony_ci      if (depth == 8) {
4709cc1dc7a3Sopenharmony_ci         if (img_n != out_n)
4710cc1dc7a3Sopenharmony_ci            cur[img_n] = 255; // first pixel
4711cc1dc7a3Sopenharmony_ci         raw += img_n;
4712cc1dc7a3Sopenharmony_ci         cur += out_n;
4713cc1dc7a3Sopenharmony_ci         prior += out_n;
4714cc1dc7a3Sopenharmony_ci      } else if (depth == 16) {
4715cc1dc7a3Sopenharmony_ci         if (img_n != out_n) {
4716cc1dc7a3Sopenharmony_ci            cur[filter_bytes]   = 255; // first pixel top byte
4717cc1dc7a3Sopenharmony_ci            cur[filter_bytes+1] = 255; // first pixel bottom byte
4718cc1dc7a3Sopenharmony_ci         }
4719cc1dc7a3Sopenharmony_ci         raw += filter_bytes;
4720cc1dc7a3Sopenharmony_ci         cur += output_bytes;
4721cc1dc7a3Sopenharmony_ci         prior += output_bytes;
4722cc1dc7a3Sopenharmony_ci      } else {
4723cc1dc7a3Sopenharmony_ci         raw += 1;
4724cc1dc7a3Sopenharmony_ci         cur += 1;
4725cc1dc7a3Sopenharmony_ci         prior += 1;
4726cc1dc7a3Sopenharmony_ci      }
4727cc1dc7a3Sopenharmony_ci
4728cc1dc7a3Sopenharmony_ci      // this is a little gross, so that we don't switch per-pixel or per-component
4729cc1dc7a3Sopenharmony_ci      if (depth < 8 || img_n == out_n) {
4730cc1dc7a3Sopenharmony_ci         int nk = (width - 1)*filter_bytes;
4731cc1dc7a3Sopenharmony_ci         #define STBI__CASE(f) \
4732cc1dc7a3Sopenharmony_ci             case f:     \
4733cc1dc7a3Sopenharmony_ci                for (k=0; k < nk; ++k)
4734cc1dc7a3Sopenharmony_ci         switch (filter) {
4735cc1dc7a3Sopenharmony_ci            // "none" filter turns into a memcpy here; make that explicit.
4736cc1dc7a3Sopenharmony_ci            case STBI__F_none:         memcpy(cur, raw, nk); break;
4737cc1dc7a3Sopenharmony_ci            STBI__CASE(STBI__F_sub)          { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break;
4738cc1dc7a3Sopenharmony_ci            STBI__CASE(STBI__F_up)           { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
4739cc1dc7a3Sopenharmony_ci            STBI__CASE(STBI__F_avg)          { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break;
4740cc1dc7a3Sopenharmony_ci            STBI__CASE(STBI__F_paeth)        { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break;
4741cc1dc7a3Sopenharmony_ci            STBI__CASE(STBI__F_avg_first)    { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break;
4742cc1dc7a3Sopenharmony_ci            STBI__CASE(STBI__F_paeth_first)  { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break;
4743cc1dc7a3Sopenharmony_ci         }
4744cc1dc7a3Sopenharmony_ci         #undef STBI__CASE
4745cc1dc7a3Sopenharmony_ci         raw += nk;
4746cc1dc7a3Sopenharmony_ci      } else {
4747cc1dc7a3Sopenharmony_ci         STBI_ASSERT(img_n+1 == out_n);
4748cc1dc7a3Sopenharmony_ci         #define STBI__CASE(f) \
4749cc1dc7a3Sopenharmony_ci             case f:     \
4750cc1dc7a3Sopenharmony_ci                for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
4751cc1dc7a3Sopenharmony_ci                   for (k=0; k < filter_bytes; ++k)
4752cc1dc7a3Sopenharmony_ci         switch (filter) {
4753cc1dc7a3Sopenharmony_ci            STBI__CASE(STBI__F_none)         { cur[k] = raw[k]; } break;
4754cc1dc7a3Sopenharmony_ci            STBI__CASE(STBI__F_sub)          { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break;
4755cc1dc7a3Sopenharmony_ci            STBI__CASE(STBI__F_up)           { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
4756cc1dc7a3Sopenharmony_ci            STBI__CASE(STBI__F_avg)          { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break;
4757cc1dc7a3Sopenharmony_ci            STBI__CASE(STBI__F_paeth)        { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break;
4758cc1dc7a3Sopenharmony_ci            STBI__CASE(STBI__F_avg_first)    { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break;
4759cc1dc7a3Sopenharmony_ci            STBI__CASE(STBI__F_paeth_first)  { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break;
4760cc1dc7a3Sopenharmony_ci         }
4761cc1dc7a3Sopenharmony_ci         #undef STBI__CASE
4762cc1dc7a3Sopenharmony_ci
4763cc1dc7a3Sopenharmony_ci         // the loop above sets the high byte of the pixels' alpha, but for
4764cc1dc7a3Sopenharmony_ci         // 16 bit png files we also need the low byte set. we'll do that here.
4765cc1dc7a3Sopenharmony_ci         if (depth == 16) {
4766cc1dc7a3Sopenharmony_ci            cur = a->out + stride*j; // start at the beginning of the row again
4767cc1dc7a3Sopenharmony_ci            for (i=0; i < x; ++i,cur+=output_bytes) {
4768cc1dc7a3Sopenharmony_ci               cur[filter_bytes+1] = 255;
4769cc1dc7a3Sopenharmony_ci            }
4770cc1dc7a3Sopenharmony_ci         }
4771cc1dc7a3Sopenharmony_ci      }
4772cc1dc7a3Sopenharmony_ci   }
4773cc1dc7a3Sopenharmony_ci
4774cc1dc7a3Sopenharmony_ci   // we make a separate pass to expand bits to pixels; for performance,
4775cc1dc7a3Sopenharmony_ci   // this could run two scanlines behind the above code, so it won't
4776cc1dc7a3Sopenharmony_ci   // intefere with filtering but will still be in the cache.
4777cc1dc7a3Sopenharmony_ci   if (depth < 8) {
4778cc1dc7a3Sopenharmony_ci      for (j=0; j < y; ++j) {
4779cc1dc7a3Sopenharmony_ci         stbi_uc *cur = a->out + stride*j;
4780cc1dc7a3Sopenharmony_ci         stbi_uc *in  = a->out + stride*j + x*out_n - img_width_bytes;
4781cc1dc7a3Sopenharmony_ci         // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit
4782cc1dc7a3Sopenharmony_ci         // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop
4783cc1dc7a3Sopenharmony_ci         stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
4784cc1dc7a3Sopenharmony_ci
4785cc1dc7a3Sopenharmony_ci         // note that the final byte might overshoot and write more data than desired.
4786cc1dc7a3Sopenharmony_ci         // we can allocate enough data that this never writes out of memory, but it
4787cc1dc7a3Sopenharmony_ci         // could also overwrite the next scanline. can it overwrite non-empty data
4788cc1dc7a3Sopenharmony_ci         // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel.
4789cc1dc7a3Sopenharmony_ci         // so we need to explicitly clamp the final ones
4790cc1dc7a3Sopenharmony_ci
4791cc1dc7a3Sopenharmony_ci         if (depth == 4) {
4792cc1dc7a3Sopenharmony_ci            for (k=x*img_n; k >= 2; k-=2, ++in) {
4793cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in >> 4)       );
4794cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in     ) & 0x0f);
4795cc1dc7a3Sopenharmony_ci            }
4796cc1dc7a3Sopenharmony_ci            if (k > 0) *cur++ = scale * ((*in >> 4)       );
4797cc1dc7a3Sopenharmony_ci         } else if (depth == 2) {
4798cc1dc7a3Sopenharmony_ci            for (k=x*img_n; k >= 4; k-=4, ++in) {
4799cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in >> 6)       );
4800cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in >> 4) & 0x03);
4801cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in >> 2) & 0x03);
4802cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in     ) & 0x03);
4803cc1dc7a3Sopenharmony_ci            }
4804cc1dc7a3Sopenharmony_ci            if (k > 0) *cur++ = scale * ((*in >> 6)       );
4805cc1dc7a3Sopenharmony_ci            if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03);
4806cc1dc7a3Sopenharmony_ci            if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03);
4807cc1dc7a3Sopenharmony_ci         } else if (depth == 1) {
4808cc1dc7a3Sopenharmony_ci            for (k=x*img_n; k >= 8; k-=8, ++in) {
4809cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in >> 7)       );
4810cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in >> 6) & 0x01);
4811cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in >> 5) & 0x01);
4812cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in >> 4) & 0x01);
4813cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in >> 3) & 0x01);
4814cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in >> 2) & 0x01);
4815cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in >> 1) & 0x01);
4816cc1dc7a3Sopenharmony_ci               *cur++ = scale * ((*in     ) & 0x01);
4817cc1dc7a3Sopenharmony_ci            }
4818cc1dc7a3Sopenharmony_ci            if (k > 0) *cur++ = scale * ((*in >> 7)       );
4819cc1dc7a3Sopenharmony_ci            if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01);
4820cc1dc7a3Sopenharmony_ci            if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01);
4821cc1dc7a3Sopenharmony_ci            if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01);
4822cc1dc7a3Sopenharmony_ci            if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01);
4823cc1dc7a3Sopenharmony_ci            if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01);
4824cc1dc7a3Sopenharmony_ci            if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01);
4825cc1dc7a3Sopenharmony_ci         }
4826cc1dc7a3Sopenharmony_ci         if (img_n != out_n) {
4827cc1dc7a3Sopenharmony_ci            int q;
4828cc1dc7a3Sopenharmony_ci            // insert alpha = 255
4829cc1dc7a3Sopenharmony_ci            cur = a->out + stride*j;
4830cc1dc7a3Sopenharmony_ci            if (img_n == 1) {
4831cc1dc7a3Sopenharmony_ci               for (q=x-1; q >= 0; --q) {
4832cc1dc7a3Sopenharmony_ci                  cur[q*2+1] = 255;
4833cc1dc7a3Sopenharmony_ci                  cur[q*2+0] = cur[q];
4834cc1dc7a3Sopenharmony_ci               }
4835cc1dc7a3Sopenharmony_ci            } else {
4836cc1dc7a3Sopenharmony_ci               STBI_ASSERT(img_n == 3);
4837cc1dc7a3Sopenharmony_ci               for (q=x-1; q >= 0; --q) {
4838cc1dc7a3Sopenharmony_ci                  cur[q*4+3] = 255;
4839cc1dc7a3Sopenharmony_ci                  cur[q*4+2] = cur[q*3+2];
4840cc1dc7a3Sopenharmony_ci                  cur[q*4+1] = cur[q*3+1];
4841cc1dc7a3Sopenharmony_ci                  cur[q*4+0] = cur[q*3+0];
4842cc1dc7a3Sopenharmony_ci               }
4843cc1dc7a3Sopenharmony_ci            }
4844cc1dc7a3Sopenharmony_ci         }
4845cc1dc7a3Sopenharmony_ci      }
4846cc1dc7a3Sopenharmony_ci   } else if (depth == 16) {
4847cc1dc7a3Sopenharmony_ci      // force the image data from big-endian to platform-native.
4848cc1dc7a3Sopenharmony_ci      // this is done in a separate pass due to the decoding relying
4849cc1dc7a3Sopenharmony_ci      // on the data being untouched, but could probably be done
4850cc1dc7a3Sopenharmony_ci      // per-line during decode if care is taken.
4851cc1dc7a3Sopenharmony_ci      stbi_uc *cur = a->out;
4852cc1dc7a3Sopenharmony_ci      stbi__uint16 *cur16 = (stbi__uint16*)cur;
4853cc1dc7a3Sopenharmony_ci
4854cc1dc7a3Sopenharmony_ci      for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) {
4855cc1dc7a3Sopenharmony_ci         *cur16 = (cur[0] << 8) | cur[1];
4856cc1dc7a3Sopenharmony_ci      }
4857cc1dc7a3Sopenharmony_ci   }
4858cc1dc7a3Sopenharmony_ci
4859cc1dc7a3Sopenharmony_ci   return 1;
4860cc1dc7a3Sopenharmony_ci}
4861cc1dc7a3Sopenharmony_ci
4862cc1dc7a3Sopenharmony_cistatic int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced)
4863cc1dc7a3Sopenharmony_ci{
4864cc1dc7a3Sopenharmony_ci   int bytes = (depth == 16 ? 2 : 1);
4865cc1dc7a3Sopenharmony_ci   int out_bytes = out_n * bytes;
4866cc1dc7a3Sopenharmony_ci   stbi_uc *final;
4867cc1dc7a3Sopenharmony_ci   int p;
4868cc1dc7a3Sopenharmony_ci   if (!interlaced)
4869cc1dc7a3Sopenharmony_ci      return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color);
4870cc1dc7a3Sopenharmony_ci
4871cc1dc7a3Sopenharmony_ci   // de-interlacing
4872cc1dc7a3Sopenharmony_ci   final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0);
4873cc1dc7a3Sopenharmony_ci   if (!final) return stbi__err("outofmem", "Out of memory");
4874cc1dc7a3Sopenharmony_ci   for (p=0; p < 7; ++p) {
4875cc1dc7a3Sopenharmony_ci      int xorig[] = { 0,4,0,2,0,1,0 };
4876cc1dc7a3Sopenharmony_ci      int yorig[] = { 0,0,4,0,2,0,1 };
4877cc1dc7a3Sopenharmony_ci      int xspc[]  = { 8,8,4,4,2,2,1 };
4878cc1dc7a3Sopenharmony_ci      int yspc[]  = { 8,8,8,4,4,2,2 };
4879cc1dc7a3Sopenharmony_ci      int i,j,x,y;
4880cc1dc7a3Sopenharmony_ci      // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1
4881cc1dc7a3Sopenharmony_ci      x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p];
4882cc1dc7a3Sopenharmony_ci      y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p];
4883cc1dc7a3Sopenharmony_ci      if (x && y) {
4884cc1dc7a3Sopenharmony_ci         stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y;
4885cc1dc7a3Sopenharmony_ci         if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) {
4886cc1dc7a3Sopenharmony_ci            STBI_FREE(final);
4887cc1dc7a3Sopenharmony_ci            return 0;
4888cc1dc7a3Sopenharmony_ci         }
4889cc1dc7a3Sopenharmony_ci         for (j=0; j < y; ++j) {
4890cc1dc7a3Sopenharmony_ci            for (i=0; i < x; ++i) {
4891cc1dc7a3Sopenharmony_ci               int out_y = j*yspc[p]+yorig[p];
4892cc1dc7a3Sopenharmony_ci               int out_x = i*xspc[p]+xorig[p];
4893cc1dc7a3Sopenharmony_ci               memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes,
4894cc1dc7a3Sopenharmony_ci                      a->out + (j*x+i)*out_bytes, out_bytes);
4895cc1dc7a3Sopenharmony_ci            }
4896cc1dc7a3Sopenharmony_ci         }
4897cc1dc7a3Sopenharmony_ci         STBI_FREE(a->out);
4898cc1dc7a3Sopenharmony_ci         image_data += img_len;
4899cc1dc7a3Sopenharmony_ci         image_data_len -= img_len;
4900cc1dc7a3Sopenharmony_ci      }
4901cc1dc7a3Sopenharmony_ci   }
4902cc1dc7a3Sopenharmony_ci   a->out = final;
4903cc1dc7a3Sopenharmony_ci
4904cc1dc7a3Sopenharmony_ci   return 1;
4905cc1dc7a3Sopenharmony_ci}
4906cc1dc7a3Sopenharmony_ci
4907cc1dc7a3Sopenharmony_cistatic int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n)
4908cc1dc7a3Sopenharmony_ci{
4909cc1dc7a3Sopenharmony_ci   stbi__context *s = z->s;
4910cc1dc7a3Sopenharmony_ci   stbi__uint32 i, pixel_count = s->img_x * s->img_y;
4911cc1dc7a3Sopenharmony_ci   stbi_uc *p = z->out;
4912cc1dc7a3Sopenharmony_ci
4913cc1dc7a3Sopenharmony_ci   // compute color-based transparency, assuming we've
4914cc1dc7a3Sopenharmony_ci   // already got 255 as the alpha value in the output
4915cc1dc7a3Sopenharmony_ci   STBI_ASSERT(out_n == 2 || out_n == 4);
4916cc1dc7a3Sopenharmony_ci
4917cc1dc7a3Sopenharmony_ci   if (out_n == 2) {
4918cc1dc7a3Sopenharmony_ci      for (i=0; i < pixel_count; ++i) {
4919cc1dc7a3Sopenharmony_ci         p[1] = (p[0] == tc[0] ? 0 : 255);
4920cc1dc7a3Sopenharmony_ci         p += 2;
4921cc1dc7a3Sopenharmony_ci      }
4922cc1dc7a3Sopenharmony_ci   } else {
4923cc1dc7a3Sopenharmony_ci      for (i=0; i < pixel_count; ++i) {
4924cc1dc7a3Sopenharmony_ci         if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
4925cc1dc7a3Sopenharmony_ci            p[3] = 0;
4926cc1dc7a3Sopenharmony_ci         p += 4;
4927cc1dc7a3Sopenharmony_ci      }
4928cc1dc7a3Sopenharmony_ci   }
4929cc1dc7a3Sopenharmony_ci   return 1;
4930cc1dc7a3Sopenharmony_ci}
4931cc1dc7a3Sopenharmony_ci
4932cc1dc7a3Sopenharmony_cistatic int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n)
4933cc1dc7a3Sopenharmony_ci{
4934cc1dc7a3Sopenharmony_ci   stbi__context *s = z->s;
4935cc1dc7a3Sopenharmony_ci   stbi__uint32 i, pixel_count = s->img_x * s->img_y;
4936cc1dc7a3Sopenharmony_ci   stbi__uint16 *p = (stbi__uint16*) z->out;
4937cc1dc7a3Sopenharmony_ci
4938cc1dc7a3Sopenharmony_ci   // compute color-based transparency, assuming we've
4939cc1dc7a3Sopenharmony_ci   // already got 65535 as the alpha value in the output
4940cc1dc7a3Sopenharmony_ci   STBI_ASSERT(out_n == 2 || out_n == 4);
4941cc1dc7a3Sopenharmony_ci
4942cc1dc7a3Sopenharmony_ci   if (out_n == 2) {
4943cc1dc7a3Sopenharmony_ci      for (i = 0; i < pixel_count; ++i) {
4944cc1dc7a3Sopenharmony_ci         p[1] = (p[0] == tc[0] ? 0 : 65535);
4945cc1dc7a3Sopenharmony_ci         p += 2;
4946cc1dc7a3Sopenharmony_ci      }
4947cc1dc7a3Sopenharmony_ci   } else {
4948cc1dc7a3Sopenharmony_ci      for (i = 0; i < pixel_count; ++i) {
4949cc1dc7a3Sopenharmony_ci         if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
4950cc1dc7a3Sopenharmony_ci            p[3] = 0;
4951cc1dc7a3Sopenharmony_ci         p += 4;
4952cc1dc7a3Sopenharmony_ci      }
4953cc1dc7a3Sopenharmony_ci   }
4954cc1dc7a3Sopenharmony_ci   return 1;
4955cc1dc7a3Sopenharmony_ci}
4956cc1dc7a3Sopenharmony_ci
4957cc1dc7a3Sopenharmony_cistatic int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n)
4958cc1dc7a3Sopenharmony_ci{
4959cc1dc7a3Sopenharmony_ci   stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
4960cc1dc7a3Sopenharmony_ci   stbi_uc *p, *temp_out, *orig = a->out;
4961cc1dc7a3Sopenharmony_ci
4962cc1dc7a3Sopenharmony_ci   p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0);
4963cc1dc7a3Sopenharmony_ci   if (p == NULL) return stbi__err("outofmem", "Out of memory");
4964cc1dc7a3Sopenharmony_ci
4965cc1dc7a3Sopenharmony_ci   // between here and free(out) below, exitting would leak
4966cc1dc7a3Sopenharmony_ci   temp_out = p;
4967cc1dc7a3Sopenharmony_ci
4968cc1dc7a3Sopenharmony_ci   if (pal_img_n == 3) {
4969cc1dc7a3Sopenharmony_ci      for (i=0; i < pixel_count; ++i) {
4970cc1dc7a3Sopenharmony_ci         int n = orig[i]*4;
4971cc1dc7a3Sopenharmony_ci         p[0] = palette[n  ];
4972cc1dc7a3Sopenharmony_ci         p[1] = palette[n+1];
4973cc1dc7a3Sopenharmony_ci         p[2] = palette[n+2];
4974cc1dc7a3Sopenharmony_ci         p += 3;
4975cc1dc7a3Sopenharmony_ci      }
4976cc1dc7a3Sopenharmony_ci   } else {
4977cc1dc7a3Sopenharmony_ci      for (i=0; i < pixel_count; ++i) {
4978cc1dc7a3Sopenharmony_ci         int n = orig[i]*4;
4979cc1dc7a3Sopenharmony_ci         p[0] = palette[n  ];
4980cc1dc7a3Sopenharmony_ci         p[1] = palette[n+1];
4981cc1dc7a3Sopenharmony_ci         p[2] = palette[n+2];
4982cc1dc7a3Sopenharmony_ci         p[3] = palette[n+3];
4983cc1dc7a3Sopenharmony_ci         p += 4;
4984cc1dc7a3Sopenharmony_ci      }
4985cc1dc7a3Sopenharmony_ci   }
4986cc1dc7a3Sopenharmony_ci   STBI_FREE(a->out);
4987cc1dc7a3Sopenharmony_ci   a->out = temp_out;
4988cc1dc7a3Sopenharmony_ci
4989cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(len);
4990cc1dc7a3Sopenharmony_ci
4991cc1dc7a3Sopenharmony_ci   return 1;
4992cc1dc7a3Sopenharmony_ci}
4993cc1dc7a3Sopenharmony_ci
4994cc1dc7a3Sopenharmony_cistatic int stbi__unpremultiply_on_load_global = 0;
4995cc1dc7a3Sopenharmony_cistatic int stbi__de_iphone_flag_global = 0;
4996cc1dc7a3Sopenharmony_ci
4997cc1dc7a3Sopenharmony_ciSTBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply)
4998cc1dc7a3Sopenharmony_ci{
4999cc1dc7a3Sopenharmony_ci   stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply;
5000cc1dc7a3Sopenharmony_ci}
5001cc1dc7a3Sopenharmony_ci
5002cc1dc7a3Sopenharmony_ciSTBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)
5003cc1dc7a3Sopenharmony_ci{
5004cc1dc7a3Sopenharmony_ci   stbi__de_iphone_flag_global = flag_true_if_should_convert;
5005cc1dc7a3Sopenharmony_ci}
5006cc1dc7a3Sopenharmony_ci
5007cc1dc7a3Sopenharmony_ci#ifndef STBI_THREAD_LOCAL
5008cc1dc7a3Sopenharmony_ci#define stbi__unpremultiply_on_load  stbi__unpremultiply_on_load_global
5009cc1dc7a3Sopenharmony_ci#define stbi__de_iphone_flag  stbi__de_iphone_flag_global
5010cc1dc7a3Sopenharmony_ci#else
5011cc1dc7a3Sopenharmony_cistatic STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set;
5012cc1dc7a3Sopenharmony_cistatic STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set;
5013cc1dc7a3Sopenharmony_ci
5014cc1dc7a3Sopenharmony_ciSTBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply)
5015cc1dc7a3Sopenharmony_ci{
5016cc1dc7a3Sopenharmony_ci   stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply;
5017cc1dc7a3Sopenharmony_ci   stbi__unpremultiply_on_load_set = 1;
5018cc1dc7a3Sopenharmony_ci}
5019cc1dc7a3Sopenharmony_ci
5020cc1dc7a3Sopenharmony_ciSTBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert)
5021cc1dc7a3Sopenharmony_ci{
5022cc1dc7a3Sopenharmony_ci   stbi__de_iphone_flag_local = flag_true_if_should_convert;
5023cc1dc7a3Sopenharmony_ci   stbi__de_iphone_flag_set = 1;
5024cc1dc7a3Sopenharmony_ci}
5025cc1dc7a3Sopenharmony_ci
5026cc1dc7a3Sopenharmony_ci#define stbi__unpremultiply_on_load  (stbi__unpremultiply_on_load_set           \
5027cc1dc7a3Sopenharmony_ci                                       ? stbi__unpremultiply_on_load_local      \
5028cc1dc7a3Sopenharmony_ci                                       : stbi__unpremultiply_on_load_global)
5029cc1dc7a3Sopenharmony_ci#define stbi__de_iphone_flag  (stbi__de_iphone_flag_set                         \
5030cc1dc7a3Sopenharmony_ci                                ? stbi__de_iphone_flag_local                    \
5031cc1dc7a3Sopenharmony_ci                                : stbi__de_iphone_flag_global)
5032cc1dc7a3Sopenharmony_ci#endif // STBI_THREAD_LOCAL
5033cc1dc7a3Sopenharmony_ci
5034cc1dc7a3Sopenharmony_cistatic void stbi__de_iphone(stbi__png *z)
5035cc1dc7a3Sopenharmony_ci{
5036cc1dc7a3Sopenharmony_ci   stbi__context *s = z->s;
5037cc1dc7a3Sopenharmony_ci   stbi__uint32 i, pixel_count = s->img_x * s->img_y;
5038cc1dc7a3Sopenharmony_ci   stbi_uc *p = z->out;
5039cc1dc7a3Sopenharmony_ci
5040cc1dc7a3Sopenharmony_ci   if (s->img_out_n == 3) {  // convert bgr to rgb
5041cc1dc7a3Sopenharmony_ci      for (i=0; i < pixel_count; ++i) {
5042cc1dc7a3Sopenharmony_ci         stbi_uc t = p[0];
5043cc1dc7a3Sopenharmony_ci         p[0] = p[2];
5044cc1dc7a3Sopenharmony_ci         p[2] = t;
5045cc1dc7a3Sopenharmony_ci         p += 3;
5046cc1dc7a3Sopenharmony_ci      }
5047cc1dc7a3Sopenharmony_ci   } else {
5048cc1dc7a3Sopenharmony_ci      STBI_ASSERT(s->img_out_n == 4);
5049cc1dc7a3Sopenharmony_ci      if (stbi__unpremultiply_on_load) {
5050cc1dc7a3Sopenharmony_ci         // convert bgr to rgb and unpremultiply
5051cc1dc7a3Sopenharmony_ci         for (i=0; i < pixel_count; ++i) {
5052cc1dc7a3Sopenharmony_ci            stbi_uc a = p[3];
5053cc1dc7a3Sopenharmony_ci            stbi_uc t = p[0];
5054cc1dc7a3Sopenharmony_ci            if (a) {
5055cc1dc7a3Sopenharmony_ci               stbi_uc half = a / 2;
5056cc1dc7a3Sopenharmony_ci               p[0] = (p[2] * 255 + half) / a;
5057cc1dc7a3Sopenharmony_ci               p[1] = (p[1] * 255 + half) / a;
5058cc1dc7a3Sopenharmony_ci               p[2] = ( t   * 255 + half) / a;
5059cc1dc7a3Sopenharmony_ci            } else {
5060cc1dc7a3Sopenharmony_ci               p[0] = p[2];
5061cc1dc7a3Sopenharmony_ci               p[2] = t;
5062cc1dc7a3Sopenharmony_ci            }
5063cc1dc7a3Sopenharmony_ci            p += 4;
5064cc1dc7a3Sopenharmony_ci         }
5065cc1dc7a3Sopenharmony_ci      } else {
5066cc1dc7a3Sopenharmony_ci         // convert bgr to rgb
5067cc1dc7a3Sopenharmony_ci         for (i=0; i < pixel_count; ++i) {
5068cc1dc7a3Sopenharmony_ci            stbi_uc t = p[0];
5069cc1dc7a3Sopenharmony_ci            p[0] = p[2];
5070cc1dc7a3Sopenharmony_ci            p[2] = t;
5071cc1dc7a3Sopenharmony_ci            p += 4;
5072cc1dc7a3Sopenharmony_ci         }
5073cc1dc7a3Sopenharmony_ci      }
5074cc1dc7a3Sopenharmony_ci   }
5075cc1dc7a3Sopenharmony_ci}
5076cc1dc7a3Sopenharmony_ci
5077cc1dc7a3Sopenharmony_ci#define STBI__PNG_TYPE(a,b,c,d)  (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d))
5078cc1dc7a3Sopenharmony_ci
5079cc1dc7a3Sopenharmony_cistatic int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
5080cc1dc7a3Sopenharmony_ci{
5081cc1dc7a3Sopenharmony_ci   stbi_uc palette[1024], pal_img_n=0;
5082cc1dc7a3Sopenharmony_ci   stbi_uc has_trans=0, tc[3]={0};
5083cc1dc7a3Sopenharmony_ci   stbi__uint16 tc16[3];
5084cc1dc7a3Sopenharmony_ci   stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
5085cc1dc7a3Sopenharmony_ci   int first=1,k,interlace=0, color=0, is_iphone=0;
5086cc1dc7a3Sopenharmony_ci   stbi__context *s = z->s;
5087cc1dc7a3Sopenharmony_ci
5088cc1dc7a3Sopenharmony_ci   z->expanded = NULL;
5089cc1dc7a3Sopenharmony_ci   z->idata = NULL;
5090cc1dc7a3Sopenharmony_ci   z->out = NULL;
5091cc1dc7a3Sopenharmony_ci
5092cc1dc7a3Sopenharmony_ci   if (!stbi__check_png_header(s)) return 0;
5093cc1dc7a3Sopenharmony_ci
5094cc1dc7a3Sopenharmony_ci   if (scan == STBI__SCAN_type) return 1;
5095cc1dc7a3Sopenharmony_ci
5096cc1dc7a3Sopenharmony_ci   for (;;) {
5097cc1dc7a3Sopenharmony_ci      stbi__pngchunk c = stbi__get_chunk_header(s);
5098cc1dc7a3Sopenharmony_ci      switch (c.type) {
5099cc1dc7a3Sopenharmony_ci         case STBI__PNG_TYPE('C','g','B','I'):
5100cc1dc7a3Sopenharmony_ci            is_iphone = 1;
5101cc1dc7a3Sopenharmony_ci            stbi__skip(s, c.length);
5102cc1dc7a3Sopenharmony_ci            break;
5103cc1dc7a3Sopenharmony_ci         case STBI__PNG_TYPE('I','H','D','R'): {
5104cc1dc7a3Sopenharmony_ci            int comp,filter;
5105cc1dc7a3Sopenharmony_ci            if (!first) return stbi__err("multiple IHDR","Corrupt PNG");
5106cc1dc7a3Sopenharmony_ci            first = 0;
5107cc1dc7a3Sopenharmony_ci            if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
5108cc1dc7a3Sopenharmony_ci            s->img_x = stbi__get32be(s);
5109cc1dc7a3Sopenharmony_ci            s->img_y = stbi__get32be(s);
5110cc1dc7a3Sopenharmony_ci            if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
5111cc1dc7a3Sopenharmony_ci            if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
5112cc1dc7a3Sopenharmony_ci            z->depth = stbi__get8(s);  if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16)  return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");
5113cc1dc7a3Sopenharmony_ci            color = stbi__get8(s);  if (color > 6)         return stbi__err("bad ctype","Corrupt PNG");
5114cc1dc7a3Sopenharmony_ci            if (color == 3 && z->depth == 16)                  return stbi__err("bad ctype","Corrupt PNG");
5115cc1dc7a3Sopenharmony_ci            if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG");
5116cc1dc7a3Sopenharmony_ci            comp  = stbi__get8(s);  if (comp) return stbi__err("bad comp method","Corrupt PNG");
5117cc1dc7a3Sopenharmony_ci            filter= stbi__get8(s);  if (filter) return stbi__err("bad filter method","Corrupt PNG");
5118cc1dc7a3Sopenharmony_ci            interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG");
5119cc1dc7a3Sopenharmony_ci            if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG");
5120cc1dc7a3Sopenharmony_ci            if (!pal_img_n) {
5121cc1dc7a3Sopenharmony_ci               s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0);
5122cc1dc7a3Sopenharmony_ci               if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode");
5123cc1dc7a3Sopenharmony_ci            } else {
5124cc1dc7a3Sopenharmony_ci               // if paletted, then pal_n is our final components, and
5125cc1dc7a3Sopenharmony_ci               // img_n is # components to decompress/filter.
5126cc1dc7a3Sopenharmony_ci               s->img_n = 1;
5127cc1dc7a3Sopenharmony_ci               if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG");
5128cc1dc7a3Sopenharmony_ci            }
5129cc1dc7a3Sopenharmony_ci            // even with SCAN_header, have to scan to see if we have a tRNS
5130cc1dc7a3Sopenharmony_ci            break;
5131cc1dc7a3Sopenharmony_ci         }
5132cc1dc7a3Sopenharmony_ci
5133cc1dc7a3Sopenharmony_ci         case STBI__PNG_TYPE('P','L','T','E'):  {
5134cc1dc7a3Sopenharmony_ci            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
5135cc1dc7a3Sopenharmony_ci            if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG");
5136cc1dc7a3Sopenharmony_ci            pal_len = c.length / 3;
5137cc1dc7a3Sopenharmony_ci            if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG");
5138cc1dc7a3Sopenharmony_ci            for (i=0; i < pal_len; ++i) {
5139cc1dc7a3Sopenharmony_ci               palette[i*4+0] = stbi__get8(s);
5140cc1dc7a3Sopenharmony_ci               palette[i*4+1] = stbi__get8(s);
5141cc1dc7a3Sopenharmony_ci               palette[i*4+2] = stbi__get8(s);
5142cc1dc7a3Sopenharmony_ci               palette[i*4+3] = 255;
5143cc1dc7a3Sopenharmony_ci            }
5144cc1dc7a3Sopenharmony_ci            break;
5145cc1dc7a3Sopenharmony_ci         }
5146cc1dc7a3Sopenharmony_ci
5147cc1dc7a3Sopenharmony_ci         case STBI__PNG_TYPE('t','R','N','S'): {
5148cc1dc7a3Sopenharmony_ci            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
5149cc1dc7a3Sopenharmony_ci            if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG");
5150cc1dc7a3Sopenharmony_ci            if (pal_img_n) {
5151cc1dc7a3Sopenharmony_ci               if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; }
5152cc1dc7a3Sopenharmony_ci               if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG");
5153cc1dc7a3Sopenharmony_ci               if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG");
5154cc1dc7a3Sopenharmony_ci               pal_img_n = 4;
5155cc1dc7a3Sopenharmony_ci               for (i=0; i < c.length; ++i)
5156cc1dc7a3Sopenharmony_ci                  palette[i*4+3] = stbi__get8(s);
5157cc1dc7a3Sopenharmony_ci            } else {
5158cc1dc7a3Sopenharmony_ci               if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
5159cc1dc7a3Sopenharmony_ci               if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
5160cc1dc7a3Sopenharmony_ci               has_trans = 1;
5161cc1dc7a3Sopenharmony_ci               // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now.
5162cc1dc7a3Sopenharmony_ci               if (scan == STBI__SCAN_header) { ++s->img_n; return 1; }
5163cc1dc7a3Sopenharmony_ci               if (z->depth == 16) {
5164cc1dc7a3Sopenharmony_ci                  for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
5165cc1dc7a3Sopenharmony_ci               } else {
5166cc1dc7a3Sopenharmony_ci                  for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
5167cc1dc7a3Sopenharmony_ci               }
5168cc1dc7a3Sopenharmony_ci            }
5169cc1dc7a3Sopenharmony_ci            break;
5170cc1dc7a3Sopenharmony_ci         }
5171cc1dc7a3Sopenharmony_ci
5172cc1dc7a3Sopenharmony_ci         case STBI__PNG_TYPE('I','D','A','T'): {
5173cc1dc7a3Sopenharmony_ci            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
5174cc1dc7a3Sopenharmony_ci            if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG");
5175cc1dc7a3Sopenharmony_ci            if (scan == STBI__SCAN_header) {
5176cc1dc7a3Sopenharmony_ci               // header scan definitely stops at first IDAT
5177cc1dc7a3Sopenharmony_ci               if (pal_img_n)
5178cc1dc7a3Sopenharmony_ci                  s->img_n = pal_img_n;
5179cc1dc7a3Sopenharmony_ci               return 1;
5180cc1dc7a3Sopenharmony_ci            }
5181cc1dc7a3Sopenharmony_ci            if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes");
5182cc1dc7a3Sopenharmony_ci            if ((int)(ioff + c.length) < (int)ioff) return 0;
5183cc1dc7a3Sopenharmony_ci            if (ioff + c.length > idata_limit) {
5184cc1dc7a3Sopenharmony_ci               stbi__uint32 idata_limit_old = idata_limit;
5185cc1dc7a3Sopenharmony_ci               stbi_uc *p;
5186cc1dc7a3Sopenharmony_ci               if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096;
5187cc1dc7a3Sopenharmony_ci               while (ioff + c.length > idata_limit)
5188cc1dc7a3Sopenharmony_ci                  idata_limit *= 2;
5189cc1dc7a3Sopenharmony_ci               STBI_NOTUSED(idata_limit_old);
5190cc1dc7a3Sopenharmony_ci               p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory");
5191cc1dc7a3Sopenharmony_ci               z->idata = p;
5192cc1dc7a3Sopenharmony_ci            }
5193cc1dc7a3Sopenharmony_ci            if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG");
5194cc1dc7a3Sopenharmony_ci            ioff += c.length;
5195cc1dc7a3Sopenharmony_ci            break;
5196cc1dc7a3Sopenharmony_ci         }
5197cc1dc7a3Sopenharmony_ci
5198cc1dc7a3Sopenharmony_ci         case STBI__PNG_TYPE('I','E','N','D'): {
5199cc1dc7a3Sopenharmony_ci            stbi__uint32 raw_len, bpl;
5200cc1dc7a3Sopenharmony_ci            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
5201cc1dc7a3Sopenharmony_ci            if (scan != STBI__SCAN_load) return 1;
5202cc1dc7a3Sopenharmony_ci            if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG");
5203cc1dc7a3Sopenharmony_ci            // initial guess for decoded data size to avoid unnecessary reallocs
5204cc1dc7a3Sopenharmony_ci            bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component
5205cc1dc7a3Sopenharmony_ci            raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;
5206cc1dc7a3Sopenharmony_ci            z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone);
5207cc1dc7a3Sopenharmony_ci            if (z->expanded == NULL) return 0; // zlib should set error
5208cc1dc7a3Sopenharmony_ci            STBI_FREE(z->idata); z->idata = NULL;
5209cc1dc7a3Sopenharmony_ci            if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans)
5210cc1dc7a3Sopenharmony_ci               s->img_out_n = s->img_n+1;
5211cc1dc7a3Sopenharmony_ci            else
5212cc1dc7a3Sopenharmony_ci               s->img_out_n = s->img_n;
5213cc1dc7a3Sopenharmony_ci            if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0;
5214cc1dc7a3Sopenharmony_ci            if (has_trans) {
5215cc1dc7a3Sopenharmony_ci               if (z->depth == 16) {
5216cc1dc7a3Sopenharmony_ci                  if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0;
5217cc1dc7a3Sopenharmony_ci               } else {
5218cc1dc7a3Sopenharmony_ci                  if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
5219cc1dc7a3Sopenharmony_ci               }
5220cc1dc7a3Sopenharmony_ci            }
5221cc1dc7a3Sopenharmony_ci            if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
5222cc1dc7a3Sopenharmony_ci               stbi__de_iphone(z);
5223cc1dc7a3Sopenharmony_ci            if (pal_img_n) {
5224cc1dc7a3Sopenharmony_ci               // pal_img_n == 3 or 4
5225cc1dc7a3Sopenharmony_ci               s->img_n = pal_img_n; // record the actual colors we had
5226cc1dc7a3Sopenharmony_ci               s->img_out_n = pal_img_n;
5227cc1dc7a3Sopenharmony_ci               if (req_comp >= 3) s->img_out_n = req_comp;
5228cc1dc7a3Sopenharmony_ci               if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n))
5229cc1dc7a3Sopenharmony_ci                  return 0;
5230cc1dc7a3Sopenharmony_ci            } else if (has_trans) {
5231cc1dc7a3Sopenharmony_ci               // non-paletted image with tRNS -> source image has (constant) alpha
5232cc1dc7a3Sopenharmony_ci               ++s->img_n;
5233cc1dc7a3Sopenharmony_ci            }
5234cc1dc7a3Sopenharmony_ci            STBI_FREE(z->expanded); z->expanded = NULL;
5235cc1dc7a3Sopenharmony_ci            // end of PNG chunk, read and skip CRC
5236cc1dc7a3Sopenharmony_ci            stbi__get32be(s);
5237cc1dc7a3Sopenharmony_ci            return 1;
5238cc1dc7a3Sopenharmony_ci         }
5239cc1dc7a3Sopenharmony_ci
5240cc1dc7a3Sopenharmony_ci         default:
5241cc1dc7a3Sopenharmony_ci            // if critical, fail
5242cc1dc7a3Sopenharmony_ci            if (first) return stbi__err("first not IHDR", "Corrupt PNG");
5243cc1dc7a3Sopenharmony_ci            if ((c.type & (1 << 29)) == 0) {
5244cc1dc7a3Sopenharmony_ci               #ifndef STBI_NO_FAILURE_STRINGS
5245cc1dc7a3Sopenharmony_ci               // not threadsafe
5246cc1dc7a3Sopenharmony_ci               static char invalid_chunk[] = "XXXX PNG chunk not known";
5247cc1dc7a3Sopenharmony_ci               invalid_chunk[0] = STBI__BYTECAST(c.type >> 24);
5248cc1dc7a3Sopenharmony_ci               invalid_chunk[1] = STBI__BYTECAST(c.type >> 16);
5249cc1dc7a3Sopenharmony_ci               invalid_chunk[2] = STBI__BYTECAST(c.type >>  8);
5250cc1dc7a3Sopenharmony_ci               invalid_chunk[3] = STBI__BYTECAST(c.type >>  0);
5251cc1dc7a3Sopenharmony_ci               #endif
5252cc1dc7a3Sopenharmony_ci               return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type");
5253cc1dc7a3Sopenharmony_ci            }
5254cc1dc7a3Sopenharmony_ci            stbi__skip(s, c.length);
5255cc1dc7a3Sopenharmony_ci            break;
5256cc1dc7a3Sopenharmony_ci      }
5257cc1dc7a3Sopenharmony_ci      // end of PNG chunk, read and skip CRC
5258cc1dc7a3Sopenharmony_ci      stbi__get32be(s);
5259cc1dc7a3Sopenharmony_ci   }
5260cc1dc7a3Sopenharmony_ci}
5261cc1dc7a3Sopenharmony_ci
5262cc1dc7a3Sopenharmony_cistatic void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri)
5263cc1dc7a3Sopenharmony_ci{
5264cc1dc7a3Sopenharmony_ci   void *result=NULL;
5265cc1dc7a3Sopenharmony_ci   if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
5266cc1dc7a3Sopenharmony_ci   if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
5267cc1dc7a3Sopenharmony_ci      if (p->depth <= 8)
5268cc1dc7a3Sopenharmony_ci         ri->bits_per_channel = 8;
5269cc1dc7a3Sopenharmony_ci      else if (p->depth == 16)
5270cc1dc7a3Sopenharmony_ci         ri->bits_per_channel = 16;
5271cc1dc7a3Sopenharmony_ci      else
5272cc1dc7a3Sopenharmony_ci         return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth");
5273cc1dc7a3Sopenharmony_ci      result = p->out;
5274cc1dc7a3Sopenharmony_ci      p->out = NULL;
5275cc1dc7a3Sopenharmony_ci      if (req_comp && req_comp != p->s->img_out_n) {
5276cc1dc7a3Sopenharmony_ci         if (ri->bits_per_channel == 8)
5277cc1dc7a3Sopenharmony_ci            result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
5278cc1dc7a3Sopenharmony_ci         else
5279cc1dc7a3Sopenharmony_ci            result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
5280cc1dc7a3Sopenharmony_ci         p->s->img_out_n = req_comp;
5281cc1dc7a3Sopenharmony_ci         if (result == NULL) return result;
5282cc1dc7a3Sopenharmony_ci      }
5283cc1dc7a3Sopenharmony_ci      *x = p->s->img_x;
5284cc1dc7a3Sopenharmony_ci      *y = p->s->img_y;
5285cc1dc7a3Sopenharmony_ci      if (n) *n = p->s->img_n;
5286cc1dc7a3Sopenharmony_ci   }
5287cc1dc7a3Sopenharmony_ci   STBI_FREE(p->out);      p->out      = NULL;
5288cc1dc7a3Sopenharmony_ci   STBI_FREE(p->expanded); p->expanded = NULL;
5289cc1dc7a3Sopenharmony_ci   STBI_FREE(p->idata);    p->idata    = NULL;
5290cc1dc7a3Sopenharmony_ci
5291cc1dc7a3Sopenharmony_ci   return result;
5292cc1dc7a3Sopenharmony_ci}
5293cc1dc7a3Sopenharmony_ci
5294cc1dc7a3Sopenharmony_cistatic void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
5295cc1dc7a3Sopenharmony_ci{
5296cc1dc7a3Sopenharmony_ci   stbi__png p;
5297cc1dc7a3Sopenharmony_ci   p.s = s;
5298cc1dc7a3Sopenharmony_ci   return stbi__do_png(&p, x,y,comp,req_comp, ri);
5299cc1dc7a3Sopenharmony_ci}
5300cc1dc7a3Sopenharmony_ci
5301cc1dc7a3Sopenharmony_cistatic int stbi__png_test(stbi__context *s)
5302cc1dc7a3Sopenharmony_ci{
5303cc1dc7a3Sopenharmony_ci   int r;
5304cc1dc7a3Sopenharmony_ci   r = stbi__check_png_header(s);
5305cc1dc7a3Sopenharmony_ci   stbi__rewind(s);
5306cc1dc7a3Sopenharmony_ci   return r;
5307cc1dc7a3Sopenharmony_ci}
5308cc1dc7a3Sopenharmony_ci
5309cc1dc7a3Sopenharmony_cistatic int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp)
5310cc1dc7a3Sopenharmony_ci{
5311cc1dc7a3Sopenharmony_ci   if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) {
5312cc1dc7a3Sopenharmony_ci      stbi__rewind( p->s );
5313cc1dc7a3Sopenharmony_ci      return 0;
5314cc1dc7a3Sopenharmony_ci   }
5315cc1dc7a3Sopenharmony_ci   if (x) *x = p->s->img_x;
5316cc1dc7a3Sopenharmony_ci   if (y) *y = p->s->img_y;
5317cc1dc7a3Sopenharmony_ci   if (comp) *comp = p->s->img_n;
5318cc1dc7a3Sopenharmony_ci   return 1;
5319cc1dc7a3Sopenharmony_ci}
5320cc1dc7a3Sopenharmony_ci
5321cc1dc7a3Sopenharmony_cistatic int stbi__png_info(stbi__context *s, int *x, int *y, int *comp)
5322cc1dc7a3Sopenharmony_ci{
5323cc1dc7a3Sopenharmony_ci   stbi__png p;
5324cc1dc7a3Sopenharmony_ci   p.s = s;
5325cc1dc7a3Sopenharmony_ci   return stbi__png_info_raw(&p, x, y, comp);
5326cc1dc7a3Sopenharmony_ci}
5327cc1dc7a3Sopenharmony_ci
5328cc1dc7a3Sopenharmony_cistatic int stbi__png_is16(stbi__context *s)
5329cc1dc7a3Sopenharmony_ci{
5330cc1dc7a3Sopenharmony_ci   stbi__png p;
5331cc1dc7a3Sopenharmony_ci   p.s = s;
5332cc1dc7a3Sopenharmony_ci   if (!stbi__png_info_raw(&p, NULL, NULL, NULL))
5333cc1dc7a3Sopenharmony_ci	   return 0;
5334cc1dc7a3Sopenharmony_ci   if (p.depth != 16) {
5335cc1dc7a3Sopenharmony_ci      stbi__rewind(p.s);
5336cc1dc7a3Sopenharmony_ci      return 0;
5337cc1dc7a3Sopenharmony_ci   }
5338cc1dc7a3Sopenharmony_ci   return 1;
5339cc1dc7a3Sopenharmony_ci}
5340cc1dc7a3Sopenharmony_ci#endif
5341cc1dc7a3Sopenharmony_ci
5342cc1dc7a3Sopenharmony_ci// Microsoft/Windows BMP image
5343cc1dc7a3Sopenharmony_ci
5344cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_BMP
5345cc1dc7a3Sopenharmony_cistatic int stbi__bmp_test_raw(stbi__context *s)
5346cc1dc7a3Sopenharmony_ci{
5347cc1dc7a3Sopenharmony_ci   int r;
5348cc1dc7a3Sopenharmony_ci   int sz;
5349cc1dc7a3Sopenharmony_ci   if (stbi__get8(s) != 'B') return 0;
5350cc1dc7a3Sopenharmony_ci   if (stbi__get8(s) != 'M') return 0;
5351cc1dc7a3Sopenharmony_ci   stbi__get32le(s); // discard filesize
5352cc1dc7a3Sopenharmony_ci   stbi__get16le(s); // discard reserved
5353cc1dc7a3Sopenharmony_ci   stbi__get16le(s); // discard reserved
5354cc1dc7a3Sopenharmony_ci   stbi__get32le(s); // discard data offset
5355cc1dc7a3Sopenharmony_ci   sz = stbi__get32le(s);
5356cc1dc7a3Sopenharmony_ci   r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124);
5357cc1dc7a3Sopenharmony_ci   return r;
5358cc1dc7a3Sopenharmony_ci}
5359cc1dc7a3Sopenharmony_ci
5360cc1dc7a3Sopenharmony_cistatic int stbi__bmp_test(stbi__context *s)
5361cc1dc7a3Sopenharmony_ci{
5362cc1dc7a3Sopenharmony_ci   int r = stbi__bmp_test_raw(s);
5363cc1dc7a3Sopenharmony_ci   stbi__rewind(s);
5364cc1dc7a3Sopenharmony_ci   return r;
5365cc1dc7a3Sopenharmony_ci}
5366cc1dc7a3Sopenharmony_ci
5367cc1dc7a3Sopenharmony_ci
5368cc1dc7a3Sopenharmony_ci// returns 0..31 for the highest set bit
5369cc1dc7a3Sopenharmony_cistatic int stbi__high_bit(unsigned int z)
5370cc1dc7a3Sopenharmony_ci{
5371cc1dc7a3Sopenharmony_ci   int n=0;
5372cc1dc7a3Sopenharmony_ci   if (z == 0) return -1;
5373cc1dc7a3Sopenharmony_ci   if (z >= 0x10000) { n += 16; z >>= 16; }
5374cc1dc7a3Sopenharmony_ci   if (z >= 0x00100) { n +=  8; z >>=  8; }
5375cc1dc7a3Sopenharmony_ci   if (z >= 0x00010) { n +=  4; z >>=  4; }
5376cc1dc7a3Sopenharmony_ci   if (z >= 0x00004) { n +=  2; z >>=  2; }
5377cc1dc7a3Sopenharmony_ci   if (z >= 0x00002) { n +=  1;/* >>=  1;*/ }
5378cc1dc7a3Sopenharmony_ci   return n;
5379cc1dc7a3Sopenharmony_ci}
5380cc1dc7a3Sopenharmony_ci
5381cc1dc7a3Sopenharmony_cistatic int stbi__bitcount(unsigned int a)
5382cc1dc7a3Sopenharmony_ci{
5383cc1dc7a3Sopenharmony_ci   a = (a & 0x55555555) + ((a >>  1) & 0x55555555); // max 2
5384cc1dc7a3Sopenharmony_ci   a = (a & 0x33333333) + ((a >>  2) & 0x33333333); // max 4
5385cc1dc7a3Sopenharmony_ci   a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits
5386cc1dc7a3Sopenharmony_ci   a = (a + (a >> 8)); // max 16 per 8 bits
5387cc1dc7a3Sopenharmony_ci   a = (a + (a >> 16)); // max 32 per 8 bits
5388cc1dc7a3Sopenharmony_ci   return a & 0xff;
5389cc1dc7a3Sopenharmony_ci}
5390cc1dc7a3Sopenharmony_ci
5391cc1dc7a3Sopenharmony_ci// extract an arbitrarily-aligned N-bit value (N=bits)
5392cc1dc7a3Sopenharmony_ci// from v, and then make it 8-bits long and fractionally
5393cc1dc7a3Sopenharmony_ci// extend it to full full range.
5394cc1dc7a3Sopenharmony_cistatic int stbi__shiftsigned(unsigned int v, int shift, int bits)
5395cc1dc7a3Sopenharmony_ci{
5396cc1dc7a3Sopenharmony_ci   static unsigned int mul_table[9] = {
5397cc1dc7a3Sopenharmony_ci      0,
5398cc1dc7a3Sopenharmony_ci      0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/,
5399cc1dc7a3Sopenharmony_ci      0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/,
5400cc1dc7a3Sopenharmony_ci   };
5401cc1dc7a3Sopenharmony_ci   static unsigned int shift_table[9] = {
5402cc1dc7a3Sopenharmony_ci      0, 0,0,1,0,2,4,6,0,
5403cc1dc7a3Sopenharmony_ci   };
5404cc1dc7a3Sopenharmony_ci   if (shift < 0)
5405cc1dc7a3Sopenharmony_ci      v <<= -shift;
5406cc1dc7a3Sopenharmony_ci   else
5407cc1dc7a3Sopenharmony_ci      v >>= shift;
5408cc1dc7a3Sopenharmony_ci   STBI_ASSERT(v < 256);
5409cc1dc7a3Sopenharmony_ci   v >>= (8-bits);
5410cc1dc7a3Sopenharmony_ci   STBI_ASSERT(bits >= 0 && bits <= 8);
5411cc1dc7a3Sopenharmony_ci   return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits];
5412cc1dc7a3Sopenharmony_ci}
5413cc1dc7a3Sopenharmony_ci
5414cc1dc7a3Sopenharmony_citypedef struct
5415cc1dc7a3Sopenharmony_ci{
5416cc1dc7a3Sopenharmony_ci   int bpp, offset, hsz;
5417cc1dc7a3Sopenharmony_ci   unsigned int mr,mg,mb,ma, all_a;
5418cc1dc7a3Sopenharmony_ci   int extra_read;
5419cc1dc7a3Sopenharmony_ci} stbi__bmp_data;
5420cc1dc7a3Sopenharmony_ci
5421cc1dc7a3Sopenharmony_cistatic int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress)
5422cc1dc7a3Sopenharmony_ci{
5423cc1dc7a3Sopenharmony_ci   // BI_BITFIELDS specifies masks explicitly, don't override
5424cc1dc7a3Sopenharmony_ci   if (compress == 3)
5425cc1dc7a3Sopenharmony_ci      return 1;
5426cc1dc7a3Sopenharmony_ci
5427cc1dc7a3Sopenharmony_ci   if (compress == 0) {
5428cc1dc7a3Sopenharmony_ci      if (info->bpp == 16) {
5429cc1dc7a3Sopenharmony_ci         info->mr = 31u << 10;
5430cc1dc7a3Sopenharmony_ci         info->mg = 31u <<  5;
5431cc1dc7a3Sopenharmony_ci         info->mb = 31u <<  0;
5432cc1dc7a3Sopenharmony_ci      } else if (info->bpp == 32) {
5433cc1dc7a3Sopenharmony_ci         info->mr = 0xffu << 16;
5434cc1dc7a3Sopenharmony_ci         info->mg = 0xffu <<  8;
5435cc1dc7a3Sopenharmony_ci         info->mb = 0xffu <<  0;
5436cc1dc7a3Sopenharmony_ci         info->ma = 0xffu << 24;
5437cc1dc7a3Sopenharmony_ci         info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
5438cc1dc7a3Sopenharmony_ci      } else {
5439cc1dc7a3Sopenharmony_ci         // otherwise, use defaults, which is all-0
5440cc1dc7a3Sopenharmony_ci         info->mr = info->mg = info->mb = info->ma = 0;
5441cc1dc7a3Sopenharmony_ci      }
5442cc1dc7a3Sopenharmony_ci      return 1;
5443cc1dc7a3Sopenharmony_ci   }
5444cc1dc7a3Sopenharmony_ci   return 0; // error
5445cc1dc7a3Sopenharmony_ci}
5446cc1dc7a3Sopenharmony_ci
5447cc1dc7a3Sopenharmony_cistatic void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
5448cc1dc7a3Sopenharmony_ci{
5449cc1dc7a3Sopenharmony_ci   int hsz;
5450cc1dc7a3Sopenharmony_ci   if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP");
5451cc1dc7a3Sopenharmony_ci   stbi__get32le(s); // discard filesize
5452cc1dc7a3Sopenharmony_ci   stbi__get16le(s); // discard reserved
5453cc1dc7a3Sopenharmony_ci   stbi__get16le(s); // discard reserved
5454cc1dc7a3Sopenharmony_ci   info->offset = stbi__get32le(s);
5455cc1dc7a3Sopenharmony_ci   info->hsz = hsz = stbi__get32le(s);
5456cc1dc7a3Sopenharmony_ci   info->mr = info->mg = info->mb = info->ma = 0;
5457cc1dc7a3Sopenharmony_ci   info->extra_read = 14;
5458cc1dc7a3Sopenharmony_ci
5459cc1dc7a3Sopenharmony_ci   if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP");
5460cc1dc7a3Sopenharmony_ci
5461cc1dc7a3Sopenharmony_ci   if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
5462cc1dc7a3Sopenharmony_ci   if (hsz == 12) {
5463cc1dc7a3Sopenharmony_ci      s->img_x = stbi__get16le(s);
5464cc1dc7a3Sopenharmony_ci      s->img_y = stbi__get16le(s);
5465cc1dc7a3Sopenharmony_ci   } else {
5466cc1dc7a3Sopenharmony_ci      s->img_x = stbi__get32le(s);
5467cc1dc7a3Sopenharmony_ci      s->img_y = stbi__get32le(s);
5468cc1dc7a3Sopenharmony_ci   }
5469cc1dc7a3Sopenharmony_ci   if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP");
5470cc1dc7a3Sopenharmony_ci   info->bpp = stbi__get16le(s);
5471cc1dc7a3Sopenharmony_ci   if (hsz != 12) {
5472cc1dc7a3Sopenharmony_ci      int compress = stbi__get32le(s);
5473cc1dc7a3Sopenharmony_ci      if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");
5474cc1dc7a3Sopenharmony_ci      if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes
5475cc1dc7a3Sopenharmony_ci      if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel
5476cc1dc7a3Sopenharmony_ci      stbi__get32le(s); // discard sizeof
5477cc1dc7a3Sopenharmony_ci      stbi__get32le(s); // discard hres
5478cc1dc7a3Sopenharmony_ci      stbi__get32le(s); // discard vres
5479cc1dc7a3Sopenharmony_ci      stbi__get32le(s); // discard colorsused
5480cc1dc7a3Sopenharmony_ci      stbi__get32le(s); // discard max important
5481cc1dc7a3Sopenharmony_ci      if (hsz == 40 || hsz == 56) {
5482cc1dc7a3Sopenharmony_ci         if (hsz == 56) {
5483cc1dc7a3Sopenharmony_ci            stbi__get32le(s);
5484cc1dc7a3Sopenharmony_ci            stbi__get32le(s);
5485cc1dc7a3Sopenharmony_ci            stbi__get32le(s);
5486cc1dc7a3Sopenharmony_ci            stbi__get32le(s);
5487cc1dc7a3Sopenharmony_ci         }
5488cc1dc7a3Sopenharmony_ci         if (info->bpp == 16 || info->bpp == 32) {
5489cc1dc7a3Sopenharmony_ci            if (compress == 0) {
5490cc1dc7a3Sopenharmony_ci               stbi__bmp_set_mask_defaults(info, compress);
5491cc1dc7a3Sopenharmony_ci            } else if (compress == 3) {
5492cc1dc7a3Sopenharmony_ci               info->mr = stbi__get32le(s);
5493cc1dc7a3Sopenharmony_ci               info->mg = stbi__get32le(s);
5494cc1dc7a3Sopenharmony_ci               info->mb = stbi__get32le(s);
5495cc1dc7a3Sopenharmony_ci               info->extra_read += 12;
5496cc1dc7a3Sopenharmony_ci               // not documented, but generated by photoshop and handled by mspaint
5497cc1dc7a3Sopenharmony_ci               if (info->mr == info->mg && info->mg == info->mb) {
5498cc1dc7a3Sopenharmony_ci                  // ?!?!?
5499cc1dc7a3Sopenharmony_ci                  return stbi__errpuc("bad BMP", "bad BMP");
5500cc1dc7a3Sopenharmony_ci               }
5501cc1dc7a3Sopenharmony_ci            } else
5502cc1dc7a3Sopenharmony_ci               return stbi__errpuc("bad BMP", "bad BMP");
5503cc1dc7a3Sopenharmony_ci         }
5504cc1dc7a3Sopenharmony_ci      } else {
5505cc1dc7a3Sopenharmony_ci         // V4/V5 header
5506cc1dc7a3Sopenharmony_ci         int i;
5507cc1dc7a3Sopenharmony_ci         if (hsz != 108 && hsz != 124)
5508cc1dc7a3Sopenharmony_ci            return stbi__errpuc("bad BMP", "bad BMP");
5509cc1dc7a3Sopenharmony_ci         info->mr = stbi__get32le(s);
5510cc1dc7a3Sopenharmony_ci         info->mg = stbi__get32le(s);
5511cc1dc7a3Sopenharmony_ci         info->mb = stbi__get32le(s);
5512cc1dc7a3Sopenharmony_ci         info->ma = stbi__get32le(s);
5513cc1dc7a3Sopenharmony_ci         if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs
5514cc1dc7a3Sopenharmony_ci            stbi__bmp_set_mask_defaults(info, compress);
5515cc1dc7a3Sopenharmony_ci         stbi__get32le(s); // discard color space
5516cc1dc7a3Sopenharmony_ci         for (i=0; i < 12; ++i)
5517cc1dc7a3Sopenharmony_ci            stbi__get32le(s); // discard color space parameters
5518cc1dc7a3Sopenharmony_ci         if (hsz == 124) {
5519cc1dc7a3Sopenharmony_ci            stbi__get32le(s); // discard rendering intent
5520cc1dc7a3Sopenharmony_ci            stbi__get32le(s); // discard offset of profile data
5521cc1dc7a3Sopenharmony_ci            stbi__get32le(s); // discard size of profile data
5522cc1dc7a3Sopenharmony_ci            stbi__get32le(s); // discard reserved
5523cc1dc7a3Sopenharmony_ci         }
5524cc1dc7a3Sopenharmony_ci      }
5525cc1dc7a3Sopenharmony_ci   }
5526cc1dc7a3Sopenharmony_ci   return (void *) 1;
5527cc1dc7a3Sopenharmony_ci}
5528cc1dc7a3Sopenharmony_ci
5529cc1dc7a3Sopenharmony_ci
5530cc1dc7a3Sopenharmony_cistatic void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
5531cc1dc7a3Sopenharmony_ci{
5532cc1dc7a3Sopenharmony_ci   stbi_uc *out;
5533cc1dc7a3Sopenharmony_ci   unsigned int mr=0,mg=0,mb=0,ma=0, all_a;
5534cc1dc7a3Sopenharmony_ci   stbi_uc pal[256][4];
5535cc1dc7a3Sopenharmony_ci   int psize=0,i,j,width;
5536cc1dc7a3Sopenharmony_ci   int flip_vertically, pad, target;
5537cc1dc7a3Sopenharmony_ci   stbi__bmp_data info;
5538cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(ri);
5539cc1dc7a3Sopenharmony_ci
5540cc1dc7a3Sopenharmony_ci   info.all_a = 255;
5541cc1dc7a3Sopenharmony_ci   if (stbi__bmp_parse_header(s, &info) == NULL)
5542cc1dc7a3Sopenharmony_ci      return NULL; // error code already set
5543cc1dc7a3Sopenharmony_ci
5544cc1dc7a3Sopenharmony_ci   flip_vertically = ((int) s->img_y) > 0;
5545cc1dc7a3Sopenharmony_ci   s->img_y = abs((int) s->img_y);
5546cc1dc7a3Sopenharmony_ci
5547cc1dc7a3Sopenharmony_ci   if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
5548cc1dc7a3Sopenharmony_ci   if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
5549cc1dc7a3Sopenharmony_ci
5550cc1dc7a3Sopenharmony_ci   mr = info.mr;
5551cc1dc7a3Sopenharmony_ci   mg = info.mg;
5552cc1dc7a3Sopenharmony_ci   mb = info.mb;
5553cc1dc7a3Sopenharmony_ci   ma = info.ma;
5554cc1dc7a3Sopenharmony_ci   all_a = info.all_a;
5555cc1dc7a3Sopenharmony_ci
5556cc1dc7a3Sopenharmony_ci   if (info.hsz == 12) {
5557cc1dc7a3Sopenharmony_ci      if (info.bpp < 24)
5558cc1dc7a3Sopenharmony_ci         psize = (info.offset - info.extra_read - 24) / 3;
5559cc1dc7a3Sopenharmony_ci   } else {
5560cc1dc7a3Sopenharmony_ci      if (info.bpp < 16)
5561cc1dc7a3Sopenharmony_ci         psize = (info.offset - info.extra_read - info.hsz) >> 2;
5562cc1dc7a3Sopenharmony_ci   }
5563cc1dc7a3Sopenharmony_ci   if (psize == 0) {
5564cc1dc7a3Sopenharmony_ci      // accept some number of extra bytes after the header, but if the offset points either to before
5565cc1dc7a3Sopenharmony_ci      // the header ends or implies a large amount of extra data, reject the file as malformed
5566cc1dc7a3Sopenharmony_ci      int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original);
5567cc1dc7a3Sopenharmony_ci      int header_limit = 1024; // max we actually read is below 256 bytes currently.
5568cc1dc7a3Sopenharmony_ci      int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size.
5569cc1dc7a3Sopenharmony_ci      if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) {
5570cc1dc7a3Sopenharmony_ci         return stbi__errpuc("bad header", "Corrupt BMP");
5571cc1dc7a3Sopenharmony_ci      }
5572cc1dc7a3Sopenharmony_ci      // we established that bytes_read_so_far is positive and sensible.
5573cc1dc7a3Sopenharmony_ci      // the first half of this test rejects offsets that are either too small positives, or
5574cc1dc7a3Sopenharmony_ci      // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn
5575cc1dc7a3Sopenharmony_ci      // ensures the number computed in the second half of the test can't overflow.
5576cc1dc7a3Sopenharmony_ci      if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) {
5577cc1dc7a3Sopenharmony_ci         return stbi__errpuc("bad offset", "Corrupt BMP");
5578cc1dc7a3Sopenharmony_ci      } else {
5579cc1dc7a3Sopenharmony_ci         stbi__skip(s, info.offset - bytes_read_so_far);
5580cc1dc7a3Sopenharmony_ci      }
5581cc1dc7a3Sopenharmony_ci   }
5582cc1dc7a3Sopenharmony_ci
5583cc1dc7a3Sopenharmony_ci   if (info.bpp == 24 && ma == 0xff000000)
5584cc1dc7a3Sopenharmony_ci      s->img_n = 3;
5585cc1dc7a3Sopenharmony_ci   else
5586cc1dc7a3Sopenharmony_ci      s->img_n = ma ? 4 : 3;
5587cc1dc7a3Sopenharmony_ci   if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
5588cc1dc7a3Sopenharmony_ci      target = req_comp;
5589cc1dc7a3Sopenharmony_ci   else
5590cc1dc7a3Sopenharmony_ci      target = s->img_n; // if they want monochrome, we'll post-convert
5591cc1dc7a3Sopenharmony_ci
5592cc1dc7a3Sopenharmony_ci   // sanity-check size
5593cc1dc7a3Sopenharmony_ci   if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0))
5594cc1dc7a3Sopenharmony_ci      return stbi__errpuc("too large", "Corrupt BMP");
5595cc1dc7a3Sopenharmony_ci
5596cc1dc7a3Sopenharmony_ci   out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0);
5597cc1dc7a3Sopenharmony_ci   if (!out) return stbi__errpuc("outofmem", "Out of memory");
5598cc1dc7a3Sopenharmony_ci   if (info.bpp < 16) {
5599cc1dc7a3Sopenharmony_ci      int z=0;
5600cc1dc7a3Sopenharmony_ci      if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); }
5601cc1dc7a3Sopenharmony_ci      for (i=0; i < psize; ++i) {
5602cc1dc7a3Sopenharmony_ci         pal[i][2] = stbi__get8(s);
5603cc1dc7a3Sopenharmony_ci         pal[i][1] = stbi__get8(s);
5604cc1dc7a3Sopenharmony_ci         pal[i][0] = stbi__get8(s);
5605cc1dc7a3Sopenharmony_ci         if (info.hsz != 12) stbi__get8(s);
5606cc1dc7a3Sopenharmony_ci         pal[i][3] = 255;
5607cc1dc7a3Sopenharmony_ci      }
5608cc1dc7a3Sopenharmony_ci      stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
5609cc1dc7a3Sopenharmony_ci      if (info.bpp == 1) width = (s->img_x + 7) >> 3;
5610cc1dc7a3Sopenharmony_ci      else if (info.bpp == 4) width = (s->img_x + 1) >> 1;
5611cc1dc7a3Sopenharmony_ci      else if (info.bpp == 8) width = s->img_x;
5612cc1dc7a3Sopenharmony_ci      else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); }
5613cc1dc7a3Sopenharmony_ci      pad = (-width)&3;
5614cc1dc7a3Sopenharmony_ci      if (info.bpp == 1) {
5615cc1dc7a3Sopenharmony_ci         for (j=0; j < (int) s->img_y; ++j) {
5616cc1dc7a3Sopenharmony_ci            int bit_offset = 7, v = stbi__get8(s);
5617cc1dc7a3Sopenharmony_ci            for (i=0; i < (int) s->img_x; ++i) {
5618cc1dc7a3Sopenharmony_ci               int color = (v>>bit_offset)&0x1;
5619cc1dc7a3Sopenharmony_ci               out[z++] = pal[color][0];
5620cc1dc7a3Sopenharmony_ci               out[z++] = pal[color][1];
5621cc1dc7a3Sopenharmony_ci               out[z++] = pal[color][2];
5622cc1dc7a3Sopenharmony_ci               if (target == 4) out[z++] = 255;
5623cc1dc7a3Sopenharmony_ci               if (i+1 == (int) s->img_x) break;
5624cc1dc7a3Sopenharmony_ci               if((--bit_offset) < 0) {
5625cc1dc7a3Sopenharmony_ci                  bit_offset = 7;
5626cc1dc7a3Sopenharmony_ci                  v = stbi__get8(s);
5627cc1dc7a3Sopenharmony_ci               }
5628cc1dc7a3Sopenharmony_ci            }
5629cc1dc7a3Sopenharmony_ci            stbi__skip(s, pad);
5630cc1dc7a3Sopenharmony_ci         }
5631cc1dc7a3Sopenharmony_ci      } else {
5632cc1dc7a3Sopenharmony_ci         for (j=0; j < (int) s->img_y; ++j) {
5633cc1dc7a3Sopenharmony_ci            for (i=0; i < (int) s->img_x; i += 2) {
5634cc1dc7a3Sopenharmony_ci               int v=stbi__get8(s),v2=0;
5635cc1dc7a3Sopenharmony_ci               if (info.bpp == 4) {
5636cc1dc7a3Sopenharmony_ci                  v2 = v & 15;
5637cc1dc7a3Sopenharmony_ci                  v >>= 4;
5638cc1dc7a3Sopenharmony_ci               }
5639cc1dc7a3Sopenharmony_ci               out[z++] = pal[v][0];
5640cc1dc7a3Sopenharmony_ci               out[z++] = pal[v][1];
5641cc1dc7a3Sopenharmony_ci               out[z++] = pal[v][2];
5642cc1dc7a3Sopenharmony_ci               if (target == 4) out[z++] = 255;
5643cc1dc7a3Sopenharmony_ci               if (i+1 == (int) s->img_x) break;
5644cc1dc7a3Sopenharmony_ci               v = (info.bpp == 8) ? stbi__get8(s) : v2;
5645cc1dc7a3Sopenharmony_ci               out[z++] = pal[v][0];
5646cc1dc7a3Sopenharmony_ci               out[z++] = pal[v][1];
5647cc1dc7a3Sopenharmony_ci               out[z++] = pal[v][2];
5648cc1dc7a3Sopenharmony_ci               if (target == 4) out[z++] = 255;
5649cc1dc7a3Sopenharmony_ci            }
5650cc1dc7a3Sopenharmony_ci            stbi__skip(s, pad);
5651cc1dc7a3Sopenharmony_ci         }
5652cc1dc7a3Sopenharmony_ci      }
5653cc1dc7a3Sopenharmony_ci   } else {
5654cc1dc7a3Sopenharmony_ci      int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
5655cc1dc7a3Sopenharmony_ci      int z = 0;
5656cc1dc7a3Sopenharmony_ci      int easy=0;
5657cc1dc7a3Sopenharmony_ci      stbi__skip(s, info.offset - info.extra_read - info.hsz);
5658cc1dc7a3Sopenharmony_ci      if (info.bpp == 24) width = 3 * s->img_x;
5659cc1dc7a3Sopenharmony_ci      else if (info.bpp == 16) width = 2*s->img_x;
5660cc1dc7a3Sopenharmony_ci      else /* bpp = 32 and pad = 0 */ width=0;
5661cc1dc7a3Sopenharmony_ci      pad = (-width) & 3;
5662cc1dc7a3Sopenharmony_ci      if (info.bpp == 24) {
5663cc1dc7a3Sopenharmony_ci         easy = 1;
5664cc1dc7a3Sopenharmony_ci      } else if (info.bpp == 32) {
5665cc1dc7a3Sopenharmony_ci         if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000)
5666cc1dc7a3Sopenharmony_ci            easy = 2;
5667cc1dc7a3Sopenharmony_ci      }
5668cc1dc7a3Sopenharmony_ci      if (!easy) {
5669cc1dc7a3Sopenharmony_ci         if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); }
5670cc1dc7a3Sopenharmony_ci         // right shift amt to put high bit in position #7
5671cc1dc7a3Sopenharmony_ci         rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr);
5672cc1dc7a3Sopenharmony_ci         gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg);
5673cc1dc7a3Sopenharmony_ci         bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb);
5674cc1dc7a3Sopenharmony_ci         ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma);
5675cc1dc7a3Sopenharmony_ci         if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); }
5676cc1dc7a3Sopenharmony_ci      }
5677cc1dc7a3Sopenharmony_ci      for (j=0; j < (int) s->img_y; ++j) {
5678cc1dc7a3Sopenharmony_ci         if (easy) {
5679cc1dc7a3Sopenharmony_ci            for (i=0; i < (int) s->img_x; ++i) {
5680cc1dc7a3Sopenharmony_ci               unsigned char a;
5681cc1dc7a3Sopenharmony_ci               out[z+2] = stbi__get8(s);
5682cc1dc7a3Sopenharmony_ci               out[z+1] = stbi__get8(s);
5683cc1dc7a3Sopenharmony_ci               out[z+0] = stbi__get8(s);
5684cc1dc7a3Sopenharmony_ci               z += 3;
5685cc1dc7a3Sopenharmony_ci               a = (easy == 2 ? stbi__get8(s) : 255);
5686cc1dc7a3Sopenharmony_ci               all_a |= a;
5687cc1dc7a3Sopenharmony_ci               if (target == 4) out[z++] = a;
5688cc1dc7a3Sopenharmony_ci            }
5689cc1dc7a3Sopenharmony_ci         } else {
5690cc1dc7a3Sopenharmony_ci            int bpp = info.bpp;
5691cc1dc7a3Sopenharmony_ci            for (i=0; i < (int) s->img_x; ++i) {
5692cc1dc7a3Sopenharmony_ci               stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s));
5693cc1dc7a3Sopenharmony_ci               unsigned int a;
5694cc1dc7a3Sopenharmony_ci               out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount));
5695cc1dc7a3Sopenharmony_ci               out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount));
5696cc1dc7a3Sopenharmony_ci               out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount));
5697cc1dc7a3Sopenharmony_ci               a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255);
5698cc1dc7a3Sopenharmony_ci               all_a |= a;
5699cc1dc7a3Sopenharmony_ci               if (target == 4) out[z++] = STBI__BYTECAST(a);
5700cc1dc7a3Sopenharmony_ci            }
5701cc1dc7a3Sopenharmony_ci         }
5702cc1dc7a3Sopenharmony_ci         stbi__skip(s, pad);
5703cc1dc7a3Sopenharmony_ci      }
5704cc1dc7a3Sopenharmony_ci   }
5705cc1dc7a3Sopenharmony_ci
5706cc1dc7a3Sopenharmony_ci   // if alpha channel is all 0s, replace with all 255s
5707cc1dc7a3Sopenharmony_ci   if (target == 4 && all_a == 0)
5708cc1dc7a3Sopenharmony_ci      for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4)
5709cc1dc7a3Sopenharmony_ci         out[i] = 255;
5710cc1dc7a3Sopenharmony_ci
5711cc1dc7a3Sopenharmony_ci   if (flip_vertically) {
5712cc1dc7a3Sopenharmony_ci      stbi_uc t;
5713cc1dc7a3Sopenharmony_ci      for (j=0; j < (int) s->img_y>>1; ++j) {
5714cc1dc7a3Sopenharmony_ci         stbi_uc *p1 = out +      j     *s->img_x*target;
5715cc1dc7a3Sopenharmony_ci         stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target;
5716cc1dc7a3Sopenharmony_ci         for (i=0; i < (int) s->img_x*target; ++i) {
5717cc1dc7a3Sopenharmony_ci            t = p1[i]; p1[i] = p2[i]; p2[i] = t;
5718cc1dc7a3Sopenharmony_ci         }
5719cc1dc7a3Sopenharmony_ci      }
5720cc1dc7a3Sopenharmony_ci   }
5721cc1dc7a3Sopenharmony_ci
5722cc1dc7a3Sopenharmony_ci   if (req_comp && req_comp != target) {
5723cc1dc7a3Sopenharmony_ci      out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y);
5724cc1dc7a3Sopenharmony_ci      if (out == NULL) return out; // stbi__convert_format frees input on failure
5725cc1dc7a3Sopenharmony_ci   }
5726cc1dc7a3Sopenharmony_ci
5727cc1dc7a3Sopenharmony_ci   *x = s->img_x;
5728cc1dc7a3Sopenharmony_ci   *y = s->img_y;
5729cc1dc7a3Sopenharmony_ci   if (comp) *comp = s->img_n;
5730cc1dc7a3Sopenharmony_ci   return out;
5731cc1dc7a3Sopenharmony_ci}
5732cc1dc7a3Sopenharmony_ci#endif
5733cc1dc7a3Sopenharmony_ci
5734cc1dc7a3Sopenharmony_ci// Targa Truevision - TGA
5735cc1dc7a3Sopenharmony_ci// by Jonathan Dummer
5736cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_TGA
5737cc1dc7a3Sopenharmony_ci// returns STBI_rgb or whatever, 0 on error
5738cc1dc7a3Sopenharmony_cistatic int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16)
5739cc1dc7a3Sopenharmony_ci{
5740cc1dc7a3Sopenharmony_ci   // only RGB or RGBA (incl. 16bit) or grey allowed
5741cc1dc7a3Sopenharmony_ci   if (is_rgb16) *is_rgb16 = 0;
5742cc1dc7a3Sopenharmony_ci   switch(bits_per_pixel) {
5743cc1dc7a3Sopenharmony_ci      case 8:  return STBI_grey;
5744cc1dc7a3Sopenharmony_ci      case 16: if(is_grey) return STBI_grey_alpha;
5745cc1dc7a3Sopenharmony_ci               // fallthrough
5746cc1dc7a3Sopenharmony_ci      case 15: if(is_rgb16) *is_rgb16 = 1;
5747cc1dc7a3Sopenharmony_ci               return STBI_rgb;
5748cc1dc7a3Sopenharmony_ci      case 24: // fallthrough
5749cc1dc7a3Sopenharmony_ci      case 32: return bits_per_pixel/8;
5750cc1dc7a3Sopenharmony_ci      default: return 0;
5751cc1dc7a3Sopenharmony_ci   }
5752cc1dc7a3Sopenharmony_ci}
5753cc1dc7a3Sopenharmony_ci
5754cc1dc7a3Sopenharmony_cistatic int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
5755cc1dc7a3Sopenharmony_ci{
5756cc1dc7a3Sopenharmony_ci    int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp;
5757cc1dc7a3Sopenharmony_ci    int sz, tga_colormap_type;
5758cc1dc7a3Sopenharmony_ci    stbi__get8(s);                   // discard Offset
5759cc1dc7a3Sopenharmony_ci    tga_colormap_type = stbi__get8(s); // colormap type
5760cc1dc7a3Sopenharmony_ci    if( tga_colormap_type > 1 ) {
5761cc1dc7a3Sopenharmony_ci        stbi__rewind(s);
5762cc1dc7a3Sopenharmony_ci        return 0;      // only RGB or indexed allowed
5763cc1dc7a3Sopenharmony_ci    }
5764cc1dc7a3Sopenharmony_ci    tga_image_type = stbi__get8(s); // image type
5765cc1dc7a3Sopenharmony_ci    if ( tga_colormap_type == 1 ) { // colormapped (paletted) image
5766cc1dc7a3Sopenharmony_ci        if (tga_image_type != 1 && tga_image_type != 9) {
5767cc1dc7a3Sopenharmony_ci            stbi__rewind(s);
5768cc1dc7a3Sopenharmony_ci            return 0;
5769cc1dc7a3Sopenharmony_ci        }
5770cc1dc7a3Sopenharmony_ci        stbi__skip(s,4);       // skip index of first colormap entry and number of entries
5771cc1dc7a3Sopenharmony_ci        sz = stbi__get8(s);    //   check bits per palette color entry
5772cc1dc7a3Sopenharmony_ci        if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) {
5773cc1dc7a3Sopenharmony_ci            stbi__rewind(s);
5774cc1dc7a3Sopenharmony_ci            return 0;
5775cc1dc7a3Sopenharmony_ci        }
5776cc1dc7a3Sopenharmony_ci        stbi__skip(s,4);       // skip image x and y origin
5777cc1dc7a3Sopenharmony_ci        tga_colormap_bpp = sz;
5778cc1dc7a3Sopenharmony_ci    } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE
5779cc1dc7a3Sopenharmony_ci        if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) {
5780cc1dc7a3Sopenharmony_ci            stbi__rewind(s);
5781cc1dc7a3Sopenharmony_ci            return 0; // only RGB or grey allowed, +/- RLE
5782cc1dc7a3Sopenharmony_ci        }
5783cc1dc7a3Sopenharmony_ci        stbi__skip(s,9); // skip colormap specification and image x/y origin
5784cc1dc7a3Sopenharmony_ci        tga_colormap_bpp = 0;
5785cc1dc7a3Sopenharmony_ci    }
5786cc1dc7a3Sopenharmony_ci    tga_w = stbi__get16le(s);
5787cc1dc7a3Sopenharmony_ci    if( tga_w < 1 ) {
5788cc1dc7a3Sopenharmony_ci        stbi__rewind(s);
5789cc1dc7a3Sopenharmony_ci        return 0;   // test width
5790cc1dc7a3Sopenharmony_ci    }
5791cc1dc7a3Sopenharmony_ci    tga_h = stbi__get16le(s);
5792cc1dc7a3Sopenharmony_ci    if( tga_h < 1 ) {
5793cc1dc7a3Sopenharmony_ci        stbi__rewind(s);
5794cc1dc7a3Sopenharmony_ci        return 0;   // test height
5795cc1dc7a3Sopenharmony_ci    }
5796cc1dc7a3Sopenharmony_ci    tga_bits_per_pixel = stbi__get8(s); // bits per pixel
5797cc1dc7a3Sopenharmony_ci    stbi__get8(s); // ignore alpha bits
5798cc1dc7a3Sopenharmony_ci    if (tga_colormap_bpp != 0) {
5799cc1dc7a3Sopenharmony_ci        if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) {
5800cc1dc7a3Sopenharmony_ci            // when using a colormap, tga_bits_per_pixel is the size of the indexes
5801cc1dc7a3Sopenharmony_ci            // I don't think anything but 8 or 16bit indexes makes sense
5802cc1dc7a3Sopenharmony_ci            stbi__rewind(s);
5803cc1dc7a3Sopenharmony_ci            return 0;
5804cc1dc7a3Sopenharmony_ci        }
5805cc1dc7a3Sopenharmony_ci        tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL);
5806cc1dc7a3Sopenharmony_ci    } else {
5807cc1dc7a3Sopenharmony_ci        tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL);
5808cc1dc7a3Sopenharmony_ci    }
5809cc1dc7a3Sopenharmony_ci    if(!tga_comp) {
5810cc1dc7a3Sopenharmony_ci      stbi__rewind(s);
5811cc1dc7a3Sopenharmony_ci      return 0;
5812cc1dc7a3Sopenharmony_ci    }
5813cc1dc7a3Sopenharmony_ci    if (x) *x = tga_w;
5814cc1dc7a3Sopenharmony_ci    if (y) *y = tga_h;
5815cc1dc7a3Sopenharmony_ci    if (comp) *comp = tga_comp;
5816cc1dc7a3Sopenharmony_ci    return 1;                   // seems to have passed everything
5817cc1dc7a3Sopenharmony_ci}
5818cc1dc7a3Sopenharmony_ci
5819cc1dc7a3Sopenharmony_cistatic int stbi__tga_test(stbi__context *s)
5820cc1dc7a3Sopenharmony_ci{
5821cc1dc7a3Sopenharmony_ci   int res = 0;
5822cc1dc7a3Sopenharmony_ci   int sz, tga_color_type;
5823cc1dc7a3Sopenharmony_ci   stbi__get8(s);      //   discard Offset
5824cc1dc7a3Sopenharmony_ci   tga_color_type = stbi__get8(s);   //   color type
5825cc1dc7a3Sopenharmony_ci   if ( tga_color_type > 1 ) goto errorEnd;   //   only RGB or indexed allowed
5826cc1dc7a3Sopenharmony_ci   sz = stbi__get8(s);   //   image type
5827cc1dc7a3Sopenharmony_ci   if ( tga_color_type == 1 ) { // colormapped (paletted) image
5828cc1dc7a3Sopenharmony_ci      if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9
5829cc1dc7a3Sopenharmony_ci      stbi__skip(s,4);       // skip index of first colormap entry and number of entries
5830cc1dc7a3Sopenharmony_ci      sz = stbi__get8(s);    //   check bits per palette color entry
5831cc1dc7a3Sopenharmony_ci      if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
5832cc1dc7a3Sopenharmony_ci      stbi__skip(s,4);       // skip image x and y origin
5833cc1dc7a3Sopenharmony_ci   } else { // "normal" image w/o colormap
5834cc1dc7a3Sopenharmony_ci      if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE
5835cc1dc7a3Sopenharmony_ci      stbi__skip(s,9); // skip colormap specification and image x/y origin
5836cc1dc7a3Sopenharmony_ci   }
5837cc1dc7a3Sopenharmony_ci   if ( stbi__get16le(s) < 1 ) goto errorEnd;      //   test width
5838cc1dc7a3Sopenharmony_ci   if ( stbi__get16le(s) < 1 ) goto errorEnd;      //   test height
5839cc1dc7a3Sopenharmony_ci   sz = stbi__get8(s);   //   bits per pixel
5840cc1dc7a3Sopenharmony_ci   if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index
5841cc1dc7a3Sopenharmony_ci   if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
5842cc1dc7a3Sopenharmony_ci
5843cc1dc7a3Sopenharmony_ci   res = 1; // if we got this far, everything's good and we can return 1 instead of 0
5844cc1dc7a3Sopenharmony_ci
5845cc1dc7a3Sopenharmony_cierrorEnd:
5846cc1dc7a3Sopenharmony_ci   stbi__rewind(s);
5847cc1dc7a3Sopenharmony_ci   return res;
5848cc1dc7a3Sopenharmony_ci}
5849cc1dc7a3Sopenharmony_ci
5850cc1dc7a3Sopenharmony_ci// read 16bit value and convert to 24bit RGB
5851cc1dc7a3Sopenharmony_cistatic void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out)
5852cc1dc7a3Sopenharmony_ci{
5853cc1dc7a3Sopenharmony_ci   stbi__uint16 px = (stbi__uint16)stbi__get16le(s);
5854cc1dc7a3Sopenharmony_ci   stbi__uint16 fiveBitMask = 31;
5855cc1dc7a3Sopenharmony_ci   // we have 3 channels with 5bits each
5856cc1dc7a3Sopenharmony_ci   int r = (px >> 10) & fiveBitMask;
5857cc1dc7a3Sopenharmony_ci   int g = (px >> 5) & fiveBitMask;
5858cc1dc7a3Sopenharmony_ci   int b = px & fiveBitMask;
5859cc1dc7a3Sopenharmony_ci   // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later
5860cc1dc7a3Sopenharmony_ci   out[0] = (stbi_uc)((r * 255)/31);
5861cc1dc7a3Sopenharmony_ci   out[1] = (stbi_uc)((g * 255)/31);
5862cc1dc7a3Sopenharmony_ci   out[2] = (stbi_uc)((b * 255)/31);
5863cc1dc7a3Sopenharmony_ci
5864cc1dc7a3Sopenharmony_ci   // some people claim that the most significant bit might be used for alpha
5865cc1dc7a3Sopenharmony_ci   // (possibly if an alpha-bit is set in the "image descriptor byte")
5866cc1dc7a3Sopenharmony_ci   // but that only made 16bit test images completely translucent..
5867cc1dc7a3Sopenharmony_ci   // so let's treat all 15 and 16bit TGAs as RGB with no alpha.
5868cc1dc7a3Sopenharmony_ci}
5869cc1dc7a3Sopenharmony_ci
5870cc1dc7a3Sopenharmony_cistatic void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
5871cc1dc7a3Sopenharmony_ci{
5872cc1dc7a3Sopenharmony_ci   //   read in the TGA header stuff
5873cc1dc7a3Sopenharmony_ci   int tga_offset = stbi__get8(s);
5874cc1dc7a3Sopenharmony_ci   int tga_indexed = stbi__get8(s);
5875cc1dc7a3Sopenharmony_ci   int tga_image_type = stbi__get8(s);
5876cc1dc7a3Sopenharmony_ci   int tga_is_RLE = 0;
5877cc1dc7a3Sopenharmony_ci   int tga_palette_start = stbi__get16le(s);
5878cc1dc7a3Sopenharmony_ci   int tga_palette_len = stbi__get16le(s);
5879cc1dc7a3Sopenharmony_ci   int tga_palette_bits = stbi__get8(s);
5880cc1dc7a3Sopenharmony_ci   int tga_x_origin = stbi__get16le(s);
5881cc1dc7a3Sopenharmony_ci   int tga_y_origin = stbi__get16le(s);
5882cc1dc7a3Sopenharmony_ci   int tga_width = stbi__get16le(s);
5883cc1dc7a3Sopenharmony_ci   int tga_height = stbi__get16le(s);
5884cc1dc7a3Sopenharmony_ci   int tga_bits_per_pixel = stbi__get8(s);
5885cc1dc7a3Sopenharmony_ci   int tga_comp, tga_rgb16=0;
5886cc1dc7a3Sopenharmony_ci   int tga_inverted = stbi__get8(s);
5887cc1dc7a3Sopenharmony_ci   // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?)
5888cc1dc7a3Sopenharmony_ci   //   image data
5889cc1dc7a3Sopenharmony_ci   unsigned char *tga_data;
5890cc1dc7a3Sopenharmony_ci   unsigned char *tga_palette = NULL;
5891cc1dc7a3Sopenharmony_ci   int i, j;
5892cc1dc7a3Sopenharmony_ci   unsigned char raw_data[4] = {0};
5893cc1dc7a3Sopenharmony_ci   int RLE_count = 0;
5894cc1dc7a3Sopenharmony_ci   int RLE_repeating = 0;
5895cc1dc7a3Sopenharmony_ci   int read_next_pixel = 1;
5896cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(ri);
5897cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(tga_x_origin); // @TODO
5898cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(tga_y_origin); // @TODO
5899cc1dc7a3Sopenharmony_ci
5900cc1dc7a3Sopenharmony_ci   if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
5901cc1dc7a3Sopenharmony_ci   if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
5902cc1dc7a3Sopenharmony_ci
5903cc1dc7a3Sopenharmony_ci   //   do a tiny bit of precessing
5904cc1dc7a3Sopenharmony_ci   if ( tga_image_type >= 8 )
5905cc1dc7a3Sopenharmony_ci   {
5906cc1dc7a3Sopenharmony_ci      tga_image_type -= 8;
5907cc1dc7a3Sopenharmony_ci      tga_is_RLE = 1;
5908cc1dc7a3Sopenharmony_ci   }
5909cc1dc7a3Sopenharmony_ci   tga_inverted = 1 - ((tga_inverted >> 5) & 1);
5910cc1dc7a3Sopenharmony_ci
5911cc1dc7a3Sopenharmony_ci   //   If I'm paletted, then I'll use the number of bits from the palette
5912cc1dc7a3Sopenharmony_ci   if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16);
5913cc1dc7a3Sopenharmony_ci   else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16);
5914cc1dc7a3Sopenharmony_ci
5915cc1dc7a3Sopenharmony_ci   if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency
5916cc1dc7a3Sopenharmony_ci      return stbi__errpuc("bad format", "Can't find out TGA pixelformat");
5917cc1dc7a3Sopenharmony_ci
5918cc1dc7a3Sopenharmony_ci   //   tga info
5919cc1dc7a3Sopenharmony_ci   *x = tga_width;
5920cc1dc7a3Sopenharmony_ci   *y = tga_height;
5921cc1dc7a3Sopenharmony_ci   if (comp) *comp = tga_comp;
5922cc1dc7a3Sopenharmony_ci
5923cc1dc7a3Sopenharmony_ci   if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0))
5924cc1dc7a3Sopenharmony_ci      return stbi__errpuc("too large", "Corrupt TGA");
5925cc1dc7a3Sopenharmony_ci
5926cc1dc7a3Sopenharmony_ci   tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0);
5927cc1dc7a3Sopenharmony_ci   if (!tga_data) return stbi__errpuc("outofmem", "Out of memory");
5928cc1dc7a3Sopenharmony_ci
5929cc1dc7a3Sopenharmony_ci   // skip to the data's starting position (offset usually = 0)
5930cc1dc7a3Sopenharmony_ci   stbi__skip(s, tga_offset );
5931cc1dc7a3Sopenharmony_ci
5932cc1dc7a3Sopenharmony_ci   if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) {
5933cc1dc7a3Sopenharmony_ci      for (i=0; i < tga_height; ++i) {
5934cc1dc7a3Sopenharmony_ci         int row = tga_inverted ? tga_height -i - 1 : i;
5935cc1dc7a3Sopenharmony_ci         stbi_uc *tga_row = tga_data + row*tga_width*tga_comp;
5936cc1dc7a3Sopenharmony_ci         stbi__getn(s, tga_row, tga_width * tga_comp);
5937cc1dc7a3Sopenharmony_ci      }
5938cc1dc7a3Sopenharmony_ci   } else  {
5939cc1dc7a3Sopenharmony_ci      //   do I need to load a palette?
5940cc1dc7a3Sopenharmony_ci      if ( tga_indexed)
5941cc1dc7a3Sopenharmony_ci      {
5942cc1dc7a3Sopenharmony_ci         if (tga_palette_len == 0) {  /* you have to have at least one entry! */
5943cc1dc7a3Sopenharmony_ci            STBI_FREE(tga_data);
5944cc1dc7a3Sopenharmony_ci            return stbi__errpuc("bad palette", "Corrupt TGA");
5945cc1dc7a3Sopenharmony_ci         }
5946cc1dc7a3Sopenharmony_ci
5947cc1dc7a3Sopenharmony_ci         //   any data to skip? (offset usually = 0)
5948cc1dc7a3Sopenharmony_ci         stbi__skip(s, tga_palette_start );
5949cc1dc7a3Sopenharmony_ci         //   load the palette
5950cc1dc7a3Sopenharmony_ci         tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0);
5951cc1dc7a3Sopenharmony_ci         if (!tga_palette) {
5952cc1dc7a3Sopenharmony_ci            STBI_FREE(tga_data);
5953cc1dc7a3Sopenharmony_ci            return stbi__errpuc("outofmem", "Out of memory");
5954cc1dc7a3Sopenharmony_ci         }
5955cc1dc7a3Sopenharmony_ci         if (tga_rgb16) {
5956cc1dc7a3Sopenharmony_ci            stbi_uc *pal_entry = tga_palette;
5957cc1dc7a3Sopenharmony_ci            STBI_ASSERT(tga_comp == STBI_rgb);
5958cc1dc7a3Sopenharmony_ci            for (i=0; i < tga_palette_len; ++i) {
5959cc1dc7a3Sopenharmony_ci               stbi__tga_read_rgb16(s, pal_entry);
5960cc1dc7a3Sopenharmony_ci               pal_entry += tga_comp;
5961cc1dc7a3Sopenharmony_ci            }
5962cc1dc7a3Sopenharmony_ci         } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) {
5963cc1dc7a3Sopenharmony_ci               STBI_FREE(tga_data);
5964cc1dc7a3Sopenharmony_ci               STBI_FREE(tga_palette);
5965cc1dc7a3Sopenharmony_ci               return stbi__errpuc("bad palette", "Corrupt TGA");
5966cc1dc7a3Sopenharmony_ci         }
5967cc1dc7a3Sopenharmony_ci      }
5968cc1dc7a3Sopenharmony_ci      //   load the data
5969cc1dc7a3Sopenharmony_ci      for (i=0; i < tga_width * tga_height; ++i)
5970cc1dc7a3Sopenharmony_ci      {
5971cc1dc7a3Sopenharmony_ci         //   if I'm in RLE mode, do I need to get a RLE stbi__pngchunk?
5972cc1dc7a3Sopenharmony_ci         if ( tga_is_RLE )
5973cc1dc7a3Sopenharmony_ci         {
5974cc1dc7a3Sopenharmony_ci            if ( RLE_count == 0 )
5975cc1dc7a3Sopenharmony_ci            {
5976cc1dc7a3Sopenharmony_ci               //   yep, get the next byte as a RLE command
5977cc1dc7a3Sopenharmony_ci               int RLE_cmd = stbi__get8(s);
5978cc1dc7a3Sopenharmony_ci               RLE_count = 1 + (RLE_cmd & 127);
5979cc1dc7a3Sopenharmony_ci               RLE_repeating = RLE_cmd >> 7;
5980cc1dc7a3Sopenharmony_ci               read_next_pixel = 1;
5981cc1dc7a3Sopenharmony_ci            } else if ( !RLE_repeating )
5982cc1dc7a3Sopenharmony_ci            {
5983cc1dc7a3Sopenharmony_ci               read_next_pixel = 1;
5984cc1dc7a3Sopenharmony_ci            }
5985cc1dc7a3Sopenharmony_ci         } else
5986cc1dc7a3Sopenharmony_ci         {
5987cc1dc7a3Sopenharmony_ci            read_next_pixel = 1;
5988cc1dc7a3Sopenharmony_ci         }
5989cc1dc7a3Sopenharmony_ci         //   OK, if I need to read a pixel, do it now
5990cc1dc7a3Sopenharmony_ci         if ( read_next_pixel )
5991cc1dc7a3Sopenharmony_ci         {
5992cc1dc7a3Sopenharmony_ci            //   load however much data we did have
5993cc1dc7a3Sopenharmony_ci            if ( tga_indexed )
5994cc1dc7a3Sopenharmony_ci            {
5995cc1dc7a3Sopenharmony_ci               // read in index, then perform the lookup
5996cc1dc7a3Sopenharmony_ci               int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s);
5997cc1dc7a3Sopenharmony_ci               if ( pal_idx >= tga_palette_len ) {
5998cc1dc7a3Sopenharmony_ci                  // invalid index
5999cc1dc7a3Sopenharmony_ci                  pal_idx = 0;
6000cc1dc7a3Sopenharmony_ci               }
6001cc1dc7a3Sopenharmony_ci               pal_idx *= tga_comp;
6002cc1dc7a3Sopenharmony_ci               for (j = 0; j < tga_comp; ++j) {
6003cc1dc7a3Sopenharmony_ci                  raw_data[j] = tga_palette[pal_idx+j];
6004cc1dc7a3Sopenharmony_ci               }
6005cc1dc7a3Sopenharmony_ci            } else if(tga_rgb16) {
6006cc1dc7a3Sopenharmony_ci               STBI_ASSERT(tga_comp == STBI_rgb);
6007cc1dc7a3Sopenharmony_ci               stbi__tga_read_rgb16(s, raw_data);
6008cc1dc7a3Sopenharmony_ci            } else {
6009cc1dc7a3Sopenharmony_ci               //   read in the data raw
6010cc1dc7a3Sopenharmony_ci               for (j = 0; j < tga_comp; ++j) {
6011cc1dc7a3Sopenharmony_ci                  raw_data[j] = stbi__get8(s);
6012cc1dc7a3Sopenharmony_ci               }
6013cc1dc7a3Sopenharmony_ci            }
6014cc1dc7a3Sopenharmony_ci            //   clear the reading flag for the next pixel
6015cc1dc7a3Sopenharmony_ci            read_next_pixel = 0;
6016cc1dc7a3Sopenharmony_ci         } // end of reading a pixel
6017cc1dc7a3Sopenharmony_ci
6018cc1dc7a3Sopenharmony_ci         // copy data
6019cc1dc7a3Sopenharmony_ci         for (j = 0; j < tga_comp; ++j)
6020cc1dc7a3Sopenharmony_ci           tga_data[i*tga_comp+j] = raw_data[j];
6021cc1dc7a3Sopenharmony_ci
6022cc1dc7a3Sopenharmony_ci         //   in case we're in RLE mode, keep counting down
6023cc1dc7a3Sopenharmony_ci         --RLE_count;
6024cc1dc7a3Sopenharmony_ci      }
6025cc1dc7a3Sopenharmony_ci      //   do I need to invert the image?
6026cc1dc7a3Sopenharmony_ci      if ( tga_inverted )
6027cc1dc7a3Sopenharmony_ci      {
6028cc1dc7a3Sopenharmony_ci         for (j = 0; j*2 < tga_height; ++j)
6029cc1dc7a3Sopenharmony_ci         {
6030cc1dc7a3Sopenharmony_ci            int index1 = j * tga_width * tga_comp;
6031cc1dc7a3Sopenharmony_ci            int index2 = (tga_height - 1 - j) * tga_width * tga_comp;
6032cc1dc7a3Sopenharmony_ci            for (i = tga_width * tga_comp; i > 0; --i)
6033cc1dc7a3Sopenharmony_ci            {
6034cc1dc7a3Sopenharmony_ci               unsigned char temp = tga_data[index1];
6035cc1dc7a3Sopenharmony_ci               tga_data[index1] = tga_data[index2];
6036cc1dc7a3Sopenharmony_ci               tga_data[index2] = temp;
6037cc1dc7a3Sopenharmony_ci               ++index1;
6038cc1dc7a3Sopenharmony_ci               ++index2;
6039cc1dc7a3Sopenharmony_ci            }
6040cc1dc7a3Sopenharmony_ci         }
6041cc1dc7a3Sopenharmony_ci      }
6042cc1dc7a3Sopenharmony_ci      //   clear my palette, if I had one
6043cc1dc7a3Sopenharmony_ci      if ( tga_palette != NULL )
6044cc1dc7a3Sopenharmony_ci      {
6045cc1dc7a3Sopenharmony_ci         STBI_FREE( tga_palette );
6046cc1dc7a3Sopenharmony_ci      }
6047cc1dc7a3Sopenharmony_ci   }
6048cc1dc7a3Sopenharmony_ci
6049cc1dc7a3Sopenharmony_ci   // swap RGB - if the source data was RGB16, it already is in the right order
6050cc1dc7a3Sopenharmony_ci   if (tga_comp >= 3 && !tga_rgb16)
6051cc1dc7a3Sopenharmony_ci   {
6052cc1dc7a3Sopenharmony_ci      unsigned char* tga_pixel = tga_data;
6053cc1dc7a3Sopenharmony_ci      for (i=0; i < tga_width * tga_height; ++i)
6054cc1dc7a3Sopenharmony_ci      {
6055cc1dc7a3Sopenharmony_ci         unsigned char temp = tga_pixel[0];
6056cc1dc7a3Sopenharmony_ci         tga_pixel[0] = tga_pixel[2];
6057cc1dc7a3Sopenharmony_ci         tga_pixel[2] = temp;
6058cc1dc7a3Sopenharmony_ci         tga_pixel += tga_comp;
6059cc1dc7a3Sopenharmony_ci      }
6060cc1dc7a3Sopenharmony_ci   }
6061cc1dc7a3Sopenharmony_ci
6062cc1dc7a3Sopenharmony_ci   // convert to target component count
6063cc1dc7a3Sopenharmony_ci   if (req_comp && req_comp != tga_comp)
6064cc1dc7a3Sopenharmony_ci      tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height);
6065cc1dc7a3Sopenharmony_ci
6066cc1dc7a3Sopenharmony_ci   //   the things I do to get rid of an error message, and yet keep
6067cc1dc7a3Sopenharmony_ci   //   Microsoft's C compilers happy... [8^(
6068cc1dc7a3Sopenharmony_ci   tga_palette_start = tga_palette_len = tga_palette_bits =
6069cc1dc7a3Sopenharmony_ci         tga_x_origin = tga_y_origin = 0;
6070cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(tga_palette_start);
6071cc1dc7a3Sopenharmony_ci   //   OK, done
6072cc1dc7a3Sopenharmony_ci   return tga_data;
6073cc1dc7a3Sopenharmony_ci}
6074cc1dc7a3Sopenharmony_ci#endif
6075cc1dc7a3Sopenharmony_ci
6076cc1dc7a3Sopenharmony_ci// *************************************************************************************************
6077cc1dc7a3Sopenharmony_ci// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB
6078cc1dc7a3Sopenharmony_ci
6079cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_PSD
6080cc1dc7a3Sopenharmony_cistatic int stbi__psd_test(stbi__context *s)
6081cc1dc7a3Sopenharmony_ci{
6082cc1dc7a3Sopenharmony_ci   int r = (stbi__get32be(s) == 0x38425053);
6083cc1dc7a3Sopenharmony_ci   stbi__rewind(s);
6084cc1dc7a3Sopenharmony_ci   return r;
6085cc1dc7a3Sopenharmony_ci}
6086cc1dc7a3Sopenharmony_ci
6087cc1dc7a3Sopenharmony_cistatic int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount)
6088cc1dc7a3Sopenharmony_ci{
6089cc1dc7a3Sopenharmony_ci   int count, nleft, len;
6090cc1dc7a3Sopenharmony_ci
6091cc1dc7a3Sopenharmony_ci   count = 0;
6092cc1dc7a3Sopenharmony_ci   while ((nleft = pixelCount - count) > 0) {
6093cc1dc7a3Sopenharmony_ci      len = stbi__get8(s);
6094cc1dc7a3Sopenharmony_ci      if (len == 128) {
6095cc1dc7a3Sopenharmony_ci         // No-op.
6096cc1dc7a3Sopenharmony_ci      } else if (len < 128) {
6097cc1dc7a3Sopenharmony_ci         // Copy next len+1 bytes literally.
6098cc1dc7a3Sopenharmony_ci         len++;
6099cc1dc7a3Sopenharmony_ci         if (len > nleft) return 0; // corrupt data
6100cc1dc7a3Sopenharmony_ci         count += len;
6101cc1dc7a3Sopenharmony_ci         while (len) {
6102cc1dc7a3Sopenharmony_ci            *p = stbi__get8(s);
6103cc1dc7a3Sopenharmony_ci            p += 4;
6104cc1dc7a3Sopenharmony_ci            len--;
6105cc1dc7a3Sopenharmony_ci         }
6106cc1dc7a3Sopenharmony_ci      } else if (len > 128) {
6107cc1dc7a3Sopenharmony_ci         stbi_uc   val;
6108cc1dc7a3Sopenharmony_ci         // Next -len+1 bytes in the dest are replicated from next source byte.
6109cc1dc7a3Sopenharmony_ci         // (Interpret len as a negative 8-bit int.)
6110cc1dc7a3Sopenharmony_ci         len = 257 - len;
6111cc1dc7a3Sopenharmony_ci         if (len > nleft) return 0; // corrupt data
6112cc1dc7a3Sopenharmony_ci         val = stbi__get8(s);
6113cc1dc7a3Sopenharmony_ci         count += len;
6114cc1dc7a3Sopenharmony_ci         while (len) {
6115cc1dc7a3Sopenharmony_ci            *p = val;
6116cc1dc7a3Sopenharmony_ci            p += 4;
6117cc1dc7a3Sopenharmony_ci            len--;
6118cc1dc7a3Sopenharmony_ci         }
6119cc1dc7a3Sopenharmony_ci      }
6120cc1dc7a3Sopenharmony_ci   }
6121cc1dc7a3Sopenharmony_ci
6122cc1dc7a3Sopenharmony_ci   return 1;
6123cc1dc7a3Sopenharmony_ci}
6124cc1dc7a3Sopenharmony_ci
6125cc1dc7a3Sopenharmony_cistatic void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
6126cc1dc7a3Sopenharmony_ci{
6127cc1dc7a3Sopenharmony_ci   int pixelCount;
6128cc1dc7a3Sopenharmony_ci   int channelCount, compression;
6129cc1dc7a3Sopenharmony_ci   int channel, i;
6130cc1dc7a3Sopenharmony_ci   int bitdepth;
6131cc1dc7a3Sopenharmony_ci   int w,h;
6132cc1dc7a3Sopenharmony_ci   stbi_uc *out;
6133cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(ri);
6134cc1dc7a3Sopenharmony_ci
6135cc1dc7a3Sopenharmony_ci   // Check identifier
6136cc1dc7a3Sopenharmony_ci   if (stbi__get32be(s) != 0x38425053)   // "8BPS"
6137cc1dc7a3Sopenharmony_ci      return stbi__errpuc("not PSD", "Corrupt PSD image");
6138cc1dc7a3Sopenharmony_ci
6139cc1dc7a3Sopenharmony_ci   // Check file type version.
6140cc1dc7a3Sopenharmony_ci   if (stbi__get16be(s) != 1)
6141cc1dc7a3Sopenharmony_ci      return stbi__errpuc("wrong version", "Unsupported version of PSD image");
6142cc1dc7a3Sopenharmony_ci
6143cc1dc7a3Sopenharmony_ci   // Skip 6 reserved bytes.
6144cc1dc7a3Sopenharmony_ci   stbi__skip(s, 6 );
6145cc1dc7a3Sopenharmony_ci
6146cc1dc7a3Sopenharmony_ci   // Read the number of channels (R, G, B, A, etc).
6147cc1dc7a3Sopenharmony_ci   channelCount = stbi__get16be(s);
6148cc1dc7a3Sopenharmony_ci   if (channelCount < 0 || channelCount > 16)
6149cc1dc7a3Sopenharmony_ci      return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image");
6150cc1dc7a3Sopenharmony_ci
6151cc1dc7a3Sopenharmony_ci   // Read the rows and columns of the image.
6152cc1dc7a3Sopenharmony_ci   h = stbi__get32be(s);
6153cc1dc7a3Sopenharmony_ci   w = stbi__get32be(s);
6154cc1dc7a3Sopenharmony_ci
6155cc1dc7a3Sopenharmony_ci   if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
6156cc1dc7a3Sopenharmony_ci   if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
6157cc1dc7a3Sopenharmony_ci
6158cc1dc7a3Sopenharmony_ci   // Make sure the depth is 8 bits.
6159cc1dc7a3Sopenharmony_ci   bitdepth = stbi__get16be(s);
6160cc1dc7a3Sopenharmony_ci   if (bitdepth != 8 && bitdepth != 16)
6161cc1dc7a3Sopenharmony_ci      return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit");
6162cc1dc7a3Sopenharmony_ci
6163cc1dc7a3Sopenharmony_ci   // Make sure the color mode is RGB.
6164cc1dc7a3Sopenharmony_ci   // Valid options are:
6165cc1dc7a3Sopenharmony_ci   //   0: Bitmap
6166cc1dc7a3Sopenharmony_ci   //   1: Grayscale
6167cc1dc7a3Sopenharmony_ci   //   2: Indexed color
6168cc1dc7a3Sopenharmony_ci   //   3: RGB color
6169cc1dc7a3Sopenharmony_ci   //   4: CMYK color
6170cc1dc7a3Sopenharmony_ci   //   7: Multichannel
6171cc1dc7a3Sopenharmony_ci   //   8: Duotone
6172cc1dc7a3Sopenharmony_ci   //   9: Lab color
6173cc1dc7a3Sopenharmony_ci   if (stbi__get16be(s) != 3)
6174cc1dc7a3Sopenharmony_ci      return stbi__errpuc("wrong color format", "PSD is not in RGB color format");
6175cc1dc7a3Sopenharmony_ci
6176cc1dc7a3Sopenharmony_ci   // Skip the Mode Data.  (It's the palette for indexed color; other info for other modes.)
6177cc1dc7a3Sopenharmony_ci   stbi__skip(s,stbi__get32be(s) );
6178cc1dc7a3Sopenharmony_ci
6179cc1dc7a3Sopenharmony_ci   // Skip the image resources.  (resolution, pen tool paths, etc)
6180cc1dc7a3Sopenharmony_ci   stbi__skip(s, stbi__get32be(s) );
6181cc1dc7a3Sopenharmony_ci
6182cc1dc7a3Sopenharmony_ci   // Skip the reserved data.
6183cc1dc7a3Sopenharmony_ci   stbi__skip(s, stbi__get32be(s) );
6184cc1dc7a3Sopenharmony_ci
6185cc1dc7a3Sopenharmony_ci   // Find out if the data is compressed.
6186cc1dc7a3Sopenharmony_ci   // Known values:
6187cc1dc7a3Sopenharmony_ci   //   0: no compression
6188cc1dc7a3Sopenharmony_ci   //   1: RLE compressed
6189cc1dc7a3Sopenharmony_ci   compression = stbi__get16be(s);
6190cc1dc7a3Sopenharmony_ci   if (compression > 1)
6191cc1dc7a3Sopenharmony_ci      return stbi__errpuc("bad compression", "PSD has an unknown compression format");
6192cc1dc7a3Sopenharmony_ci
6193cc1dc7a3Sopenharmony_ci   // Check size
6194cc1dc7a3Sopenharmony_ci   if (!stbi__mad3sizes_valid(4, w, h, 0))
6195cc1dc7a3Sopenharmony_ci      return stbi__errpuc("too large", "Corrupt PSD");
6196cc1dc7a3Sopenharmony_ci
6197cc1dc7a3Sopenharmony_ci   // Create the destination image.
6198cc1dc7a3Sopenharmony_ci
6199cc1dc7a3Sopenharmony_ci   if (!compression && bitdepth == 16 && bpc == 16) {
6200cc1dc7a3Sopenharmony_ci      out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0);
6201cc1dc7a3Sopenharmony_ci      ri->bits_per_channel = 16;
6202cc1dc7a3Sopenharmony_ci   } else
6203cc1dc7a3Sopenharmony_ci      out = (stbi_uc *) stbi__malloc(4 * w*h);
6204cc1dc7a3Sopenharmony_ci
6205cc1dc7a3Sopenharmony_ci   if (!out) return stbi__errpuc("outofmem", "Out of memory");
6206cc1dc7a3Sopenharmony_ci   pixelCount = w*h;
6207cc1dc7a3Sopenharmony_ci
6208cc1dc7a3Sopenharmony_ci   // Initialize the data to zero.
6209cc1dc7a3Sopenharmony_ci   //memset( out, 0, pixelCount * 4 );
6210cc1dc7a3Sopenharmony_ci
6211cc1dc7a3Sopenharmony_ci   // Finally, the image data.
6212cc1dc7a3Sopenharmony_ci   if (compression) {
6213cc1dc7a3Sopenharmony_ci      // RLE as used by .PSD and .TIFF
6214cc1dc7a3Sopenharmony_ci      // Loop until you get the number of unpacked bytes you are expecting:
6215cc1dc7a3Sopenharmony_ci      //     Read the next source byte into n.
6216cc1dc7a3Sopenharmony_ci      //     If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
6217cc1dc7a3Sopenharmony_ci      //     Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times.
6218cc1dc7a3Sopenharmony_ci      //     Else if n is 128, noop.
6219cc1dc7a3Sopenharmony_ci      // Endloop
6220cc1dc7a3Sopenharmony_ci
6221cc1dc7a3Sopenharmony_ci      // The RLE-compressed data is preceded by a 2-byte data count for each row in the data,
6222cc1dc7a3Sopenharmony_ci      // which we're going to just skip.
6223cc1dc7a3Sopenharmony_ci      stbi__skip(s, h * channelCount * 2 );
6224cc1dc7a3Sopenharmony_ci
6225cc1dc7a3Sopenharmony_ci      // Read the RLE data by channel.
6226cc1dc7a3Sopenharmony_ci      for (channel = 0; channel < 4; channel++) {
6227cc1dc7a3Sopenharmony_ci         stbi_uc *p;
6228cc1dc7a3Sopenharmony_ci
6229cc1dc7a3Sopenharmony_ci         p = out+channel;
6230cc1dc7a3Sopenharmony_ci         if (channel >= channelCount) {
6231cc1dc7a3Sopenharmony_ci            // Fill this channel with default data.
6232cc1dc7a3Sopenharmony_ci            for (i = 0; i < pixelCount; i++, p += 4)
6233cc1dc7a3Sopenharmony_ci               *p = (channel == 3 ? 255 : 0);
6234cc1dc7a3Sopenharmony_ci         } else {
6235cc1dc7a3Sopenharmony_ci            // Read the RLE data.
6236cc1dc7a3Sopenharmony_ci            if (!stbi__psd_decode_rle(s, p, pixelCount)) {
6237cc1dc7a3Sopenharmony_ci               STBI_FREE(out);
6238cc1dc7a3Sopenharmony_ci               return stbi__errpuc("corrupt", "bad RLE data");
6239cc1dc7a3Sopenharmony_ci            }
6240cc1dc7a3Sopenharmony_ci         }
6241cc1dc7a3Sopenharmony_ci      }
6242cc1dc7a3Sopenharmony_ci
6243cc1dc7a3Sopenharmony_ci   } else {
6244cc1dc7a3Sopenharmony_ci      // We're at the raw image data.  It's each channel in order (Red, Green, Blue, Alpha, ...)
6245cc1dc7a3Sopenharmony_ci      // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image.
6246cc1dc7a3Sopenharmony_ci
6247cc1dc7a3Sopenharmony_ci      // Read the data by channel.
6248cc1dc7a3Sopenharmony_ci      for (channel = 0; channel < 4; channel++) {
6249cc1dc7a3Sopenharmony_ci         if (channel >= channelCount) {
6250cc1dc7a3Sopenharmony_ci            // Fill this channel with default data.
6251cc1dc7a3Sopenharmony_ci            if (bitdepth == 16 && bpc == 16) {
6252cc1dc7a3Sopenharmony_ci               stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
6253cc1dc7a3Sopenharmony_ci               stbi__uint16 val = channel == 3 ? 65535 : 0;
6254cc1dc7a3Sopenharmony_ci               for (i = 0; i < pixelCount; i++, q += 4)
6255cc1dc7a3Sopenharmony_ci                  *q = val;
6256cc1dc7a3Sopenharmony_ci            } else {
6257cc1dc7a3Sopenharmony_ci               stbi_uc *p = out+channel;
6258cc1dc7a3Sopenharmony_ci               stbi_uc val = channel == 3 ? 255 : 0;
6259cc1dc7a3Sopenharmony_ci               for (i = 0; i < pixelCount; i++, p += 4)
6260cc1dc7a3Sopenharmony_ci                  *p = val;
6261cc1dc7a3Sopenharmony_ci            }
6262cc1dc7a3Sopenharmony_ci         } else {
6263cc1dc7a3Sopenharmony_ci            if (ri->bits_per_channel == 16) {    // output bpc
6264cc1dc7a3Sopenharmony_ci               stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
6265cc1dc7a3Sopenharmony_ci               for (i = 0; i < pixelCount; i++, q += 4)
6266cc1dc7a3Sopenharmony_ci                  *q = (stbi__uint16) stbi__get16be(s);
6267cc1dc7a3Sopenharmony_ci            } else {
6268cc1dc7a3Sopenharmony_ci               stbi_uc *p = out+channel;
6269cc1dc7a3Sopenharmony_ci               if (bitdepth == 16) {  // input bpc
6270cc1dc7a3Sopenharmony_ci                  for (i = 0; i < pixelCount; i++, p += 4)
6271cc1dc7a3Sopenharmony_ci                     *p = (stbi_uc) (stbi__get16be(s) >> 8);
6272cc1dc7a3Sopenharmony_ci               } else {
6273cc1dc7a3Sopenharmony_ci                  for (i = 0; i < pixelCount; i++, p += 4)
6274cc1dc7a3Sopenharmony_ci                     *p = stbi__get8(s);
6275cc1dc7a3Sopenharmony_ci               }
6276cc1dc7a3Sopenharmony_ci            }
6277cc1dc7a3Sopenharmony_ci         }
6278cc1dc7a3Sopenharmony_ci      }
6279cc1dc7a3Sopenharmony_ci   }
6280cc1dc7a3Sopenharmony_ci
6281cc1dc7a3Sopenharmony_ci   // remove weird white matte from PSD
6282cc1dc7a3Sopenharmony_ci   if (channelCount >= 4) {
6283cc1dc7a3Sopenharmony_ci      if (ri->bits_per_channel == 16) {
6284cc1dc7a3Sopenharmony_ci         for (i=0; i < w*h; ++i) {
6285cc1dc7a3Sopenharmony_ci            stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i;
6286cc1dc7a3Sopenharmony_ci            if (pixel[3] != 0 && pixel[3] != 65535) {
6287cc1dc7a3Sopenharmony_ci               float a = pixel[3] / 65535.0f;
6288cc1dc7a3Sopenharmony_ci               float ra = 1.0f / a;
6289cc1dc7a3Sopenharmony_ci               float inv_a = 65535.0f * (1 - ra);
6290cc1dc7a3Sopenharmony_ci               pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a);
6291cc1dc7a3Sopenharmony_ci               pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a);
6292cc1dc7a3Sopenharmony_ci               pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a);
6293cc1dc7a3Sopenharmony_ci            }
6294cc1dc7a3Sopenharmony_ci         }
6295cc1dc7a3Sopenharmony_ci      } else {
6296cc1dc7a3Sopenharmony_ci         for (i=0; i < w*h; ++i) {
6297cc1dc7a3Sopenharmony_ci            unsigned char *pixel = out + 4*i;
6298cc1dc7a3Sopenharmony_ci            if (pixel[3] != 0 && pixel[3] != 255) {
6299cc1dc7a3Sopenharmony_ci               float a = pixel[3] / 255.0f;
6300cc1dc7a3Sopenharmony_ci               float ra = 1.0f / a;
6301cc1dc7a3Sopenharmony_ci               float inv_a = 255.0f * (1 - ra);
6302cc1dc7a3Sopenharmony_ci               pixel[0] = (unsigned char) (pixel[0]*ra + inv_a);
6303cc1dc7a3Sopenharmony_ci               pixel[1] = (unsigned char) (pixel[1]*ra + inv_a);
6304cc1dc7a3Sopenharmony_ci               pixel[2] = (unsigned char) (pixel[2]*ra + inv_a);
6305cc1dc7a3Sopenharmony_ci            }
6306cc1dc7a3Sopenharmony_ci         }
6307cc1dc7a3Sopenharmony_ci      }
6308cc1dc7a3Sopenharmony_ci   }
6309cc1dc7a3Sopenharmony_ci
6310cc1dc7a3Sopenharmony_ci   // convert to desired output format
6311cc1dc7a3Sopenharmony_ci   if (req_comp && req_comp != 4) {
6312cc1dc7a3Sopenharmony_ci      if (ri->bits_per_channel == 16)
6313cc1dc7a3Sopenharmony_ci         out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h);
6314cc1dc7a3Sopenharmony_ci      else
6315cc1dc7a3Sopenharmony_ci         out = stbi__convert_format(out, 4, req_comp, w, h);
6316cc1dc7a3Sopenharmony_ci      if (out == NULL) return out; // stbi__convert_format frees input on failure
6317cc1dc7a3Sopenharmony_ci   }
6318cc1dc7a3Sopenharmony_ci
6319cc1dc7a3Sopenharmony_ci   if (comp) *comp = 4;
6320cc1dc7a3Sopenharmony_ci   *y = h;
6321cc1dc7a3Sopenharmony_ci   *x = w;
6322cc1dc7a3Sopenharmony_ci
6323cc1dc7a3Sopenharmony_ci   return out;
6324cc1dc7a3Sopenharmony_ci}
6325cc1dc7a3Sopenharmony_ci#endif
6326cc1dc7a3Sopenharmony_ci
6327cc1dc7a3Sopenharmony_ci// *************************************************************************************************
6328cc1dc7a3Sopenharmony_ci// Softimage PIC loader
6329cc1dc7a3Sopenharmony_ci// by Tom Seddon
6330cc1dc7a3Sopenharmony_ci//
6331cc1dc7a3Sopenharmony_ci// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format
6332cc1dc7a3Sopenharmony_ci// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/
6333cc1dc7a3Sopenharmony_ci
6334cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_PIC
6335cc1dc7a3Sopenharmony_cistatic int stbi__pic_is4(stbi__context *s,const char *str)
6336cc1dc7a3Sopenharmony_ci{
6337cc1dc7a3Sopenharmony_ci   int i;
6338cc1dc7a3Sopenharmony_ci   for (i=0; i<4; ++i)
6339cc1dc7a3Sopenharmony_ci      if (stbi__get8(s) != (stbi_uc)str[i])
6340cc1dc7a3Sopenharmony_ci         return 0;
6341cc1dc7a3Sopenharmony_ci
6342cc1dc7a3Sopenharmony_ci   return 1;
6343cc1dc7a3Sopenharmony_ci}
6344cc1dc7a3Sopenharmony_ci
6345cc1dc7a3Sopenharmony_cistatic int stbi__pic_test_core(stbi__context *s)
6346cc1dc7a3Sopenharmony_ci{
6347cc1dc7a3Sopenharmony_ci   int i;
6348cc1dc7a3Sopenharmony_ci
6349cc1dc7a3Sopenharmony_ci   if (!stbi__pic_is4(s,"\x53\x80\xF6\x34"))
6350cc1dc7a3Sopenharmony_ci      return 0;
6351cc1dc7a3Sopenharmony_ci
6352cc1dc7a3Sopenharmony_ci   for(i=0;i<84;++i)
6353cc1dc7a3Sopenharmony_ci      stbi__get8(s);
6354cc1dc7a3Sopenharmony_ci
6355cc1dc7a3Sopenharmony_ci   if (!stbi__pic_is4(s,"PICT"))
6356cc1dc7a3Sopenharmony_ci      return 0;
6357cc1dc7a3Sopenharmony_ci
6358cc1dc7a3Sopenharmony_ci   return 1;
6359cc1dc7a3Sopenharmony_ci}
6360cc1dc7a3Sopenharmony_ci
6361cc1dc7a3Sopenharmony_citypedef struct
6362cc1dc7a3Sopenharmony_ci{
6363cc1dc7a3Sopenharmony_ci   stbi_uc size,type,channel;
6364cc1dc7a3Sopenharmony_ci} stbi__pic_packet;
6365cc1dc7a3Sopenharmony_ci
6366cc1dc7a3Sopenharmony_cistatic stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest)
6367cc1dc7a3Sopenharmony_ci{
6368cc1dc7a3Sopenharmony_ci   int mask=0x80, i;
6369cc1dc7a3Sopenharmony_ci
6370cc1dc7a3Sopenharmony_ci   for (i=0; i<4; ++i, mask>>=1) {
6371cc1dc7a3Sopenharmony_ci      if (channel & mask) {
6372cc1dc7a3Sopenharmony_ci         if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short");
6373cc1dc7a3Sopenharmony_ci         dest[i]=stbi__get8(s);
6374cc1dc7a3Sopenharmony_ci      }
6375cc1dc7a3Sopenharmony_ci   }
6376cc1dc7a3Sopenharmony_ci
6377cc1dc7a3Sopenharmony_ci   return dest;
6378cc1dc7a3Sopenharmony_ci}
6379cc1dc7a3Sopenharmony_ci
6380cc1dc7a3Sopenharmony_cistatic void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src)
6381cc1dc7a3Sopenharmony_ci{
6382cc1dc7a3Sopenharmony_ci   int mask=0x80,i;
6383cc1dc7a3Sopenharmony_ci
6384cc1dc7a3Sopenharmony_ci   for (i=0;i<4; ++i, mask>>=1)
6385cc1dc7a3Sopenharmony_ci      if (channel&mask)
6386cc1dc7a3Sopenharmony_ci         dest[i]=src[i];
6387cc1dc7a3Sopenharmony_ci}
6388cc1dc7a3Sopenharmony_ci
6389cc1dc7a3Sopenharmony_cistatic stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result)
6390cc1dc7a3Sopenharmony_ci{
6391cc1dc7a3Sopenharmony_ci   int act_comp=0,num_packets=0,y,chained;
6392cc1dc7a3Sopenharmony_ci   stbi__pic_packet packets[10];
6393cc1dc7a3Sopenharmony_ci
6394cc1dc7a3Sopenharmony_ci   // this will (should...) cater for even some bizarre stuff like having data
6395cc1dc7a3Sopenharmony_ci    // for the same channel in multiple packets.
6396cc1dc7a3Sopenharmony_ci   do {
6397cc1dc7a3Sopenharmony_ci      stbi__pic_packet *packet;
6398cc1dc7a3Sopenharmony_ci
6399cc1dc7a3Sopenharmony_ci      if (num_packets==sizeof(packets)/sizeof(packets[0]))
6400cc1dc7a3Sopenharmony_ci         return stbi__errpuc("bad format","too many packets");
6401cc1dc7a3Sopenharmony_ci
6402cc1dc7a3Sopenharmony_ci      packet = &packets[num_packets++];
6403cc1dc7a3Sopenharmony_ci
6404cc1dc7a3Sopenharmony_ci      chained = stbi__get8(s);
6405cc1dc7a3Sopenharmony_ci      packet->size    = stbi__get8(s);
6406cc1dc7a3Sopenharmony_ci      packet->type    = stbi__get8(s);
6407cc1dc7a3Sopenharmony_ci      packet->channel = stbi__get8(s);
6408cc1dc7a3Sopenharmony_ci
6409cc1dc7a3Sopenharmony_ci      act_comp |= packet->channel;
6410cc1dc7a3Sopenharmony_ci
6411cc1dc7a3Sopenharmony_ci      if (stbi__at_eof(s))          return stbi__errpuc("bad file","file too short (reading packets)");
6412cc1dc7a3Sopenharmony_ci      if (packet->size != 8)  return stbi__errpuc("bad format","packet isn't 8bpp");
6413cc1dc7a3Sopenharmony_ci   } while (chained);
6414cc1dc7a3Sopenharmony_ci
6415cc1dc7a3Sopenharmony_ci   *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel?
6416cc1dc7a3Sopenharmony_ci
6417cc1dc7a3Sopenharmony_ci   for(y=0; y<height; ++y) {
6418cc1dc7a3Sopenharmony_ci      int packet_idx;
6419cc1dc7a3Sopenharmony_ci
6420cc1dc7a3Sopenharmony_ci      for(packet_idx=0; packet_idx < num_packets; ++packet_idx) {
6421cc1dc7a3Sopenharmony_ci         stbi__pic_packet *packet = &packets[packet_idx];
6422cc1dc7a3Sopenharmony_ci         stbi_uc *dest = result+y*width*4;
6423cc1dc7a3Sopenharmony_ci
6424cc1dc7a3Sopenharmony_ci         switch (packet->type) {
6425cc1dc7a3Sopenharmony_ci            default:
6426cc1dc7a3Sopenharmony_ci               return stbi__errpuc("bad format","packet has bad compression type");
6427cc1dc7a3Sopenharmony_ci
6428cc1dc7a3Sopenharmony_ci            case 0: {//uncompressed
6429cc1dc7a3Sopenharmony_ci               int x;
6430cc1dc7a3Sopenharmony_ci
6431cc1dc7a3Sopenharmony_ci               for(x=0;x<width;++x, dest+=4)
6432cc1dc7a3Sopenharmony_ci                  if (!stbi__readval(s,packet->channel,dest))
6433cc1dc7a3Sopenharmony_ci                     return 0;
6434cc1dc7a3Sopenharmony_ci               break;
6435cc1dc7a3Sopenharmony_ci            }
6436cc1dc7a3Sopenharmony_ci
6437cc1dc7a3Sopenharmony_ci            case 1://Pure RLE
6438cc1dc7a3Sopenharmony_ci               {
6439cc1dc7a3Sopenharmony_ci                  int left=width, i;
6440cc1dc7a3Sopenharmony_ci
6441cc1dc7a3Sopenharmony_ci                  while (left>0) {
6442cc1dc7a3Sopenharmony_ci                     stbi_uc count,value[4];
6443cc1dc7a3Sopenharmony_ci
6444cc1dc7a3Sopenharmony_ci                     count=stbi__get8(s);
6445cc1dc7a3Sopenharmony_ci                     if (stbi__at_eof(s))   return stbi__errpuc("bad file","file too short (pure read count)");
6446cc1dc7a3Sopenharmony_ci
6447cc1dc7a3Sopenharmony_ci                     if (count > left)
6448cc1dc7a3Sopenharmony_ci                        count = (stbi_uc) left;
6449cc1dc7a3Sopenharmony_ci
6450cc1dc7a3Sopenharmony_ci                     if (!stbi__readval(s,packet->channel,value))  return 0;
6451cc1dc7a3Sopenharmony_ci
6452cc1dc7a3Sopenharmony_ci                     for(i=0; i<count; ++i,dest+=4)
6453cc1dc7a3Sopenharmony_ci                        stbi__copyval(packet->channel,dest,value);
6454cc1dc7a3Sopenharmony_ci                     left -= count;
6455cc1dc7a3Sopenharmony_ci                  }
6456cc1dc7a3Sopenharmony_ci               }
6457cc1dc7a3Sopenharmony_ci               break;
6458cc1dc7a3Sopenharmony_ci
6459cc1dc7a3Sopenharmony_ci            case 2: {//Mixed RLE
6460cc1dc7a3Sopenharmony_ci               int left=width;
6461cc1dc7a3Sopenharmony_ci               while (left>0) {
6462cc1dc7a3Sopenharmony_ci                  int count = stbi__get8(s), i;
6463cc1dc7a3Sopenharmony_ci                  if (stbi__at_eof(s))  return stbi__errpuc("bad file","file too short (mixed read count)");
6464cc1dc7a3Sopenharmony_ci
6465cc1dc7a3Sopenharmony_ci                  if (count >= 128) { // Repeated
6466cc1dc7a3Sopenharmony_ci                     stbi_uc value[4];
6467cc1dc7a3Sopenharmony_ci
6468cc1dc7a3Sopenharmony_ci                     if (count==128)
6469cc1dc7a3Sopenharmony_ci                        count = stbi__get16be(s);
6470cc1dc7a3Sopenharmony_ci                     else
6471cc1dc7a3Sopenharmony_ci                        count -= 127;
6472cc1dc7a3Sopenharmony_ci                     if (count > left)
6473cc1dc7a3Sopenharmony_ci                        return stbi__errpuc("bad file","scanline overrun");
6474cc1dc7a3Sopenharmony_ci
6475cc1dc7a3Sopenharmony_ci                     if (!stbi__readval(s,packet->channel,value))
6476cc1dc7a3Sopenharmony_ci                        return 0;
6477cc1dc7a3Sopenharmony_ci
6478cc1dc7a3Sopenharmony_ci                     for(i=0;i<count;++i, dest += 4)
6479cc1dc7a3Sopenharmony_ci                        stbi__copyval(packet->channel,dest,value);
6480cc1dc7a3Sopenharmony_ci                  } else { // Raw
6481cc1dc7a3Sopenharmony_ci                     ++count;
6482cc1dc7a3Sopenharmony_ci                     if (count>left) return stbi__errpuc("bad file","scanline overrun");
6483cc1dc7a3Sopenharmony_ci
6484cc1dc7a3Sopenharmony_ci                     for(i=0;i<count;++i, dest+=4)
6485cc1dc7a3Sopenharmony_ci                        if (!stbi__readval(s,packet->channel,dest))
6486cc1dc7a3Sopenharmony_ci                           return 0;
6487cc1dc7a3Sopenharmony_ci                  }
6488cc1dc7a3Sopenharmony_ci                  left-=count;
6489cc1dc7a3Sopenharmony_ci               }
6490cc1dc7a3Sopenharmony_ci               break;
6491cc1dc7a3Sopenharmony_ci            }
6492cc1dc7a3Sopenharmony_ci         }
6493cc1dc7a3Sopenharmony_ci      }
6494cc1dc7a3Sopenharmony_ci   }
6495cc1dc7a3Sopenharmony_ci
6496cc1dc7a3Sopenharmony_ci   return result;
6497cc1dc7a3Sopenharmony_ci}
6498cc1dc7a3Sopenharmony_ci
6499cc1dc7a3Sopenharmony_cistatic void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri)
6500cc1dc7a3Sopenharmony_ci{
6501cc1dc7a3Sopenharmony_ci   stbi_uc *result;
6502cc1dc7a3Sopenharmony_ci   int i, x,y, internal_comp;
6503cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(ri);
6504cc1dc7a3Sopenharmony_ci
6505cc1dc7a3Sopenharmony_ci   if (!comp) comp = &internal_comp;
6506cc1dc7a3Sopenharmony_ci
6507cc1dc7a3Sopenharmony_ci   for (i=0; i<92; ++i)
6508cc1dc7a3Sopenharmony_ci      stbi__get8(s);
6509cc1dc7a3Sopenharmony_ci
6510cc1dc7a3Sopenharmony_ci   x = stbi__get16be(s);
6511cc1dc7a3Sopenharmony_ci   y = stbi__get16be(s);
6512cc1dc7a3Sopenharmony_ci
6513cc1dc7a3Sopenharmony_ci   if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
6514cc1dc7a3Sopenharmony_ci   if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
6515cc1dc7a3Sopenharmony_ci
6516cc1dc7a3Sopenharmony_ci   if (stbi__at_eof(s))  return stbi__errpuc("bad file","file too short (pic header)");
6517cc1dc7a3Sopenharmony_ci   if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode");
6518cc1dc7a3Sopenharmony_ci
6519cc1dc7a3Sopenharmony_ci   stbi__get32be(s); //skip `ratio'
6520cc1dc7a3Sopenharmony_ci   stbi__get16be(s); //skip `fields'
6521cc1dc7a3Sopenharmony_ci   stbi__get16be(s); //skip `pad'
6522cc1dc7a3Sopenharmony_ci
6523cc1dc7a3Sopenharmony_ci   // intermediate buffer is RGBA
6524cc1dc7a3Sopenharmony_ci   result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0);
6525cc1dc7a3Sopenharmony_ci   if (!result) return stbi__errpuc("outofmem", "Out of memory");
6526cc1dc7a3Sopenharmony_ci   memset(result, 0xff, x*y*4);
6527cc1dc7a3Sopenharmony_ci
6528cc1dc7a3Sopenharmony_ci   if (!stbi__pic_load_core(s,x,y,comp, result)) {
6529cc1dc7a3Sopenharmony_ci      STBI_FREE(result);
6530cc1dc7a3Sopenharmony_ci      result=0;
6531cc1dc7a3Sopenharmony_ci   }
6532cc1dc7a3Sopenharmony_ci   *px = x;
6533cc1dc7a3Sopenharmony_ci   *py = y;
6534cc1dc7a3Sopenharmony_ci   if (req_comp == 0) req_comp = *comp;
6535cc1dc7a3Sopenharmony_ci   result=stbi__convert_format(result,4,req_comp,x,y);
6536cc1dc7a3Sopenharmony_ci
6537cc1dc7a3Sopenharmony_ci   return result;
6538cc1dc7a3Sopenharmony_ci}
6539cc1dc7a3Sopenharmony_ci
6540cc1dc7a3Sopenharmony_cistatic int stbi__pic_test(stbi__context *s)
6541cc1dc7a3Sopenharmony_ci{
6542cc1dc7a3Sopenharmony_ci   int r = stbi__pic_test_core(s);
6543cc1dc7a3Sopenharmony_ci   stbi__rewind(s);
6544cc1dc7a3Sopenharmony_ci   return r;
6545cc1dc7a3Sopenharmony_ci}
6546cc1dc7a3Sopenharmony_ci#endif
6547cc1dc7a3Sopenharmony_ci
6548cc1dc7a3Sopenharmony_ci// *************************************************************************************************
6549cc1dc7a3Sopenharmony_ci// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb
6550cc1dc7a3Sopenharmony_ci
6551cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_GIF
6552cc1dc7a3Sopenharmony_citypedef struct
6553cc1dc7a3Sopenharmony_ci{
6554cc1dc7a3Sopenharmony_ci   stbi__int16 prefix;
6555cc1dc7a3Sopenharmony_ci   stbi_uc first;
6556cc1dc7a3Sopenharmony_ci   stbi_uc suffix;
6557cc1dc7a3Sopenharmony_ci} stbi__gif_lzw;
6558cc1dc7a3Sopenharmony_ci
6559cc1dc7a3Sopenharmony_citypedef struct
6560cc1dc7a3Sopenharmony_ci{
6561cc1dc7a3Sopenharmony_ci   int w,h;
6562cc1dc7a3Sopenharmony_ci   stbi_uc *out;                 // output buffer (always 4 components)
6563cc1dc7a3Sopenharmony_ci   stbi_uc *background;          // The current "background" as far as a gif is concerned
6564cc1dc7a3Sopenharmony_ci   stbi_uc *history;
6565cc1dc7a3Sopenharmony_ci   int flags, bgindex, ratio, transparent, eflags;
6566cc1dc7a3Sopenharmony_ci   stbi_uc  pal[256][4];
6567cc1dc7a3Sopenharmony_ci   stbi_uc lpal[256][4];
6568cc1dc7a3Sopenharmony_ci   stbi__gif_lzw codes[8192];
6569cc1dc7a3Sopenharmony_ci   stbi_uc *color_table;
6570cc1dc7a3Sopenharmony_ci   int parse, step;
6571cc1dc7a3Sopenharmony_ci   int lflags;
6572cc1dc7a3Sopenharmony_ci   int start_x, start_y;
6573cc1dc7a3Sopenharmony_ci   int max_x, max_y;
6574cc1dc7a3Sopenharmony_ci   int cur_x, cur_y;
6575cc1dc7a3Sopenharmony_ci   int line_size;
6576cc1dc7a3Sopenharmony_ci   int delay;
6577cc1dc7a3Sopenharmony_ci} stbi__gif;
6578cc1dc7a3Sopenharmony_ci
6579cc1dc7a3Sopenharmony_cistatic int stbi__gif_test_raw(stbi__context *s)
6580cc1dc7a3Sopenharmony_ci{
6581cc1dc7a3Sopenharmony_ci   int sz;
6582cc1dc7a3Sopenharmony_ci   if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0;
6583cc1dc7a3Sopenharmony_ci   sz = stbi__get8(s);
6584cc1dc7a3Sopenharmony_ci   if (sz != '9' && sz != '7') return 0;
6585cc1dc7a3Sopenharmony_ci   if (stbi__get8(s) != 'a') return 0;
6586cc1dc7a3Sopenharmony_ci   return 1;
6587cc1dc7a3Sopenharmony_ci}
6588cc1dc7a3Sopenharmony_ci
6589cc1dc7a3Sopenharmony_cistatic int stbi__gif_test(stbi__context *s)
6590cc1dc7a3Sopenharmony_ci{
6591cc1dc7a3Sopenharmony_ci   int r = stbi__gif_test_raw(s);
6592cc1dc7a3Sopenharmony_ci   stbi__rewind(s);
6593cc1dc7a3Sopenharmony_ci   return r;
6594cc1dc7a3Sopenharmony_ci}
6595cc1dc7a3Sopenharmony_ci
6596cc1dc7a3Sopenharmony_cistatic void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp)
6597cc1dc7a3Sopenharmony_ci{
6598cc1dc7a3Sopenharmony_ci   int i;
6599cc1dc7a3Sopenharmony_ci   for (i=0; i < num_entries; ++i) {
6600cc1dc7a3Sopenharmony_ci      pal[i][2] = stbi__get8(s);
6601cc1dc7a3Sopenharmony_ci      pal[i][1] = stbi__get8(s);
6602cc1dc7a3Sopenharmony_ci      pal[i][0] = stbi__get8(s);
6603cc1dc7a3Sopenharmony_ci      pal[i][3] = transp == i ? 0 : 255;
6604cc1dc7a3Sopenharmony_ci   }
6605cc1dc7a3Sopenharmony_ci}
6606cc1dc7a3Sopenharmony_ci
6607cc1dc7a3Sopenharmony_cistatic int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info)
6608cc1dc7a3Sopenharmony_ci{
6609cc1dc7a3Sopenharmony_ci   stbi_uc version;
6610cc1dc7a3Sopenharmony_ci   if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8')
6611cc1dc7a3Sopenharmony_ci      return stbi__err("not GIF", "Corrupt GIF");
6612cc1dc7a3Sopenharmony_ci
6613cc1dc7a3Sopenharmony_ci   version = stbi__get8(s);
6614cc1dc7a3Sopenharmony_ci   if (version != '7' && version != '9')    return stbi__err("not GIF", "Corrupt GIF");
6615cc1dc7a3Sopenharmony_ci   if (stbi__get8(s) != 'a')                return stbi__err("not GIF", "Corrupt GIF");
6616cc1dc7a3Sopenharmony_ci
6617cc1dc7a3Sopenharmony_ci   stbi__g_failure_reason = "";
6618cc1dc7a3Sopenharmony_ci   g->w = stbi__get16le(s);
6619cc1dc7a3Sopenharmony_ci   g->h = stbi__get16le(s);
6620cc1dc7a3Sopenharmony_ci   g->flags = stbi__get8(s);
6621cc1dc7a3Sopenharmony_ci   g->bgindex = stbi__get8(s);
6622cc1dc7a3Sopenharmony_ci   g->ratio = stbi__get8(s);
6623cc1dc7a3Sopenharmony_ci   g->transparent = -1;
6624cc1dc7a3Sopenharmony_ci
6625cc1dc7a3Sopenharmony_ci   if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
6626cc1dc7a3Sopenharmony_ci   if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
6627cc1dc7a3Sopenharmony_ci
6628cc1dc7a3Sopenharmony_ci   if (comp != 0) *comp = 4;  // can't actually tell whether it's 3 or 4 until we parse the comments
6629cc1dc7a3Sopenharmony_ci
6630cc1dc7a3Sopenharmony_ci   if (is_info) return 1;
6631cc1dc7a3Sopenharmony_ci
6632cc1dc7a3Sopenharmony_ci   if (g->flags & 0x80)
6633cc1dc7a3Sopenharmony_ci      stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1);
6634cc1dc7a3Sopenharmony_ci
6635cc1dc7a3Sopenharmony_ci   return 1;
6636cc1dc7a3Sopenharmony_ci}
6637cc1dc7a3Sopenharmony_ci
6638cc1dc7a3Sopenharmony_cistatic int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
6639cc1dc7a3Sopenharmony_ci{
6640cc1dc7a3Sopenharmony_ci   stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
6641cc1dc7a3Sopenharmony_ci   if (!g) return stbi__err("outofmem", "Out of memory");
6642cc1dc7a3Sopenharmony_ci   if (!stbi__gif_header(s, g, comp, 1)) {
6643cc1dc7a3Sopenharmony_ci      STBI_FREE(g);
6644cc1dc7a3Sopenharmony_ci      stbi__rewind( s );
6645cc1dc7a3Sopenharmony_ci      return 0;
6646cc1dc7a3Sopenharmony_ci   }
6647cc1dc7a3Sopenharmony_ci   if (x) *x = g->w;
6648cc1dc7a3Sopenharmony_ci   if (y) *y = g->h;
6649cc1dc7a3Sopenharmony_ci   STBI_FREE(g);
6650cc1dc7a3Sopenharmony_ci   return 1;
6651cc1dc7a3Sopenharmony_ci}
6652cc1dc7a3Sopenharmony_ci
6653cc1dc7a3Sopenharmony_cistatic void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code)
6654cc1dc7a3Sopenharmony_ci{
6655cc1dc7a3Sopenharmony_ci   stbi_uc *p, *c;
6656cc1dc7a3Sopenharmony_ci   int idx;
6657cc1dc7a3Sopenharmony_ci
6658cc1dc7a3Sopenharmony_ci   // recurse to decode the prefixes, since the linked-list is backwards,
6659cc1dc7a3Sopenharmony_ci   // and working backwards through an interleaved image would be nasty
6660cc1dc7a3Sopenharmony_ci   if (g->codes[code].prefix >= 0)
6661cc1dc7a3Sopenharmony_ci      stbi__out_gif_code(g, g->codes[code].prefix);
6662cc1dc7a3Sopenharmony_ci
6663cc1dc7a3Sopenharmony_ci   if (g->cur_y >= g->max_y) return;
6664cc1dc7a3Sopenharmony_ci
6665cc1dc7a3Sopenharmony_ci   idx = g->cur_x + g->cur_y;
6666cc1dc7a3Sopenharmony_ci   p = &g->out[idx];
6667cc1dc7a3Sopenharmony_ci   g->history[idx / 4] = 1;
6668cc1dc7a3Sopenharmony_ci
6669cc1dc7a3Sopenharmony_ci   c = &g->color_table[g->codes[code].suffix * 4];
6670cc1dc7a3Sopenharmony_ci   if (c[3] > 128) { // don't render transparent pixels;
6671cc1dc7a3Sopenharmony_ci      p[0] = c[2];
6672cc1dc7a3Sopenharmony_ci      p[1] = c[1];
6673cc1dc7a3Sopenharmony_ci      p[2] = c[0];
6674cc1dc7a3Sopenharmony_ci      p[3] = c[3];
6675cc1dc7a3Sopenharmony_ci   }
6676cc1dc7a3Sopenharmony_ci   g->cur_x += 4;
6677cc1dc7a3Sopenharmony_ci
6678cc1dc7a3Sopenharmony_ci   if (g->cur_x >= g->max_x) {
6679cc1dc7a3Sopenharmony_ci      g->cur_x = g->start_x;
6680cc1dc7a3Sopenharmony_ci      g->cur_y += g->step;
6681cc1dc7a3Sopenharmony_ci
6682cc1dc7a3Sopenharmony_ci      while (g->cur_y >= g->max_y && g->parse > 0) {
6683cc1dc7a3Sopenharmony_ci         g->step = (1 << g->parse) * g->line_size;
6684cc1dc7a3Sopenharmony_ci         g->cur_y = g->start_y + (g->step >> 1);
6685cc1dc7a3Sopenharmony_ci         --g->parse;
6686cc1dc7a3Sopenharmony_ci      }
6687cc1dc7a3Sopenharmony_ci   }
6688cc1dc7a3Sopenharmony_ci}
6689cc1dc7a3Sopenharmony_ci
6690cc1dc7a3Sopenharmony_cistatic stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g)
6691cc1dc7a3Sopenharmony_ci{
6692cc1dc7a3Sopenharmony_ci   stbi_uc lzw_cs;
6693cc1dc7a3Sopenharmony_ci   stbi__int32 len, init_code;
6694cc1dc7a3Sopenharmony_ci   stbi__uint32 first;
6695cc1dc7a3Sopenharmony_ci   stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear;
6696cc1dc7a3Sopenharmony_ci   stbi__gif_lzw *p;
6697cc1dc7a3Sopenharmony_ci
6698cc1dc7a3Sopenharmony_ci   lzw_cs = stbi__get8(s);
6699cc1dc7a3Sopenharmony_ci   if (lzw_cs > 12) return NULL;
6700cc1dc7a3Sopenharmony_ci   clear = 1 << lzw_cs;
6701cc1dc7a3Sopenharmony_ci   first = 1;
6702cc1dc7a3Sopenharmony_ci   codesize = lzw_cs + 1;
6703cc1dc7a3Sopenharmony_ci   codemask = (1 << codesize) - 1;
6704cc1dc7a3Sopenharmony_ci   bits = 0;
6705cc1dc7a3Sopenharmony_ci   valid_bits = 0;
6706cc1dc7a3Sopenharmony_ci   for (init_code = 0; init_code < clear; init_code++) {
6707cc1dc7a3Sopenharmony_ci      g->codes[init_code].prefix = -1;
6708cc1dc7a3Sopenharmony_ci      g->codes[init_code].first = (stbi_uc) init_code;
6709cc1dc7a3Sopenharmony_ci      g->codes[init_code].suffix = (stbi_uc) init_code;
6710cc1dc7a3Sopenharmony_ci   }
6711cc1dc7a3Sopenharmony_ci
6712cc1dc7a3Sopenharmony_ci   // support no starting clear code
6713cc1dc7a3Sopenharmony_ci   avail = clear+2;
6714cc1dc7a3Sopenharmony_ci   oldcode = -1;
6715cc1dc7a3Sopenharmony_ci
6716cc1dc7a3Sopenharmony_ci   len = 0;
6717cc1dc7a3Sopenharmony_ci   for(;;) {
6718cc1dc7a3Sopenharmony_ci      if (valid_bits < codesize) {
6719cc1dc7a3Sopenharmony_ci         if (len == 0) {
6720cc1dc7a3Sopenharmony_ci            len = stbi__get8(s); // start new block
6721cc1dc7a3Sopenharmony_ci            if (len == 0)
6722cc1dc7a3Sopenharmony_ci               return g->out;
6723cc1dc7a3Sopenharmony_ci         }
6724cc1dc7a3Sopenharmony_ci         --len;
6725cc1dc7a3Sopenharmony_ci         bits |= (stbi__int32) stbi__get8(s) << valid_bits;
6726cc1dc7a3Sopenharmony_ci         valid_bits += 8;
6727cc1dc7a3Sopenharmony_ci      } else {
6728cc1dc7a3Sopenharmony_ci         stbi__int32 code = bits & codemask;
6729cc1dc7a3Sopenharmony_ci         bits >>= codesize;
6730cc1dc7a3Sopenharmony_ci         valid_bits -= codesize;
6731cc1dc7a3Sopenharmony_ci         // @OPTIMIZE: is there some way we can accelerate the non-clear path?
6732cc1dc7a3Sopenharmony_ci         if (code == clear) {  // clear code
6733cc1dc7a3Sopenharmony_ci            codesize = lzw_cs + 1;
6734cc1dc7a3Sopenharmony_ci            codemask = (1 << codesize) - 1;
6735cc1dc7a3Sopenharmony_ci            avail = clear + 2;
6736cc1dc7a3Sopenharmony_ci            oldcode = -1;
6737cc1dc7a3Sopenharmony_ci            first = 0;
6738cc1dc7a3Sopenharmony_ci         } else if (code == clear + 1) { // end of stream code
6739cc1dc7a3Sopenharmony_ci            stbi__skip(s, len);
6740cc1dc7a3Sopenharmony_ci            while ((len = stbi__get8(s)) > 0)
6741cc1dc7a3Sopenharmony_ci               stbi__skip(s,len);
6742cc1dc7a3Sopenharmony_ci            return g->out;
6743cc1dc7a3Sopenharmony_ci         } else if (code <= avail) {
6744cc1dc7a3Sopenharmony_ci            if (first) {
6745cc1dc7a3Sopenharmony_ci               return stbi__errpuc("no clear code", "Corrupt GIF");
6746cc1dc7a3Sopenharmony_ci            }
6747cc1dc7a3Sopenharmony_ci
6748cc1dc7a3Sopenharmony_ci            if (oldcode >= 0) {
6749cc1dc7a3Sopenharmony_ci               p = &g->codes[avail++];
6750cc1dc7a3Sopenharmony_ci               if (avail > 8192) {
6751cc1dc7a3Sopenharmony_ci                  return stbi__errpuc("too many codes", "Corrupt GIF");
6752cc1dc7a3Sopenharmony_ci               }
6753cc1dc7a3Sopenharmony_ci
6754cc1dc7a3Sopenharmony_ci               p->prefix = (stbi__int16) oldcode;
6755cc1dc7a3Sopenharmony_ci               p->first = g->codes[oldcode].first;
6756cc1dc7a3Sopenharmony_ci               p->suffix = (code == avail) ? p->first : g->codes[code].first;
6757cc1dc7a3Sopenharmony_ci            } else if (code == avail)
6758cc1dc7a3Sopenharmony_ci               return stbi__errpuc("illegal code in raster", "Corrupt GIF");
6759cc1dc7a3Sopenharmony_ci
6760cc1dc7a3Sopenharmony_ci            stbi__out_gif_code(g, (stbi__uint16) code);
6761cc1dc7a3Sopenharmony_ci
6762cc1dc7a3Sopenharmony_ci            if ((avail & codemask) == 0 && avail <= 0x0FFF) {
6763cc1dc7a3Sopenharmony_ci               codesize++;
6764cc1dc7a3Sopenharmony_ci               codemask = (1 << codesize) - 1;
6765cc1dc7a3Sopenharmony_ci            }
6766cc1dc7a3Sopenharmony_ci
6767cc1dc7a3Sopenharmony_ci            oldcode = code;
6768cc1dc7a3Sopenharmony_ci         } else {
6769cc1dc7a3Sopenharmony_ci            return stbi__errpuc("illegal code in raster", "Corrupt GIF");
6770cc1dc7a3Sopenharmony_ci         }
6771cc1dc7a3Sopenharmony_ci      }
6772cc1dc7a3Sopenharmony_ci   }
6773cc1dc7a3Sopenharmony_ci}
6774cc1dc7a3Sopenharmony_ci
6775cc1dc7a3Sopenharmony_ci// this function is designed to support animated gifs, although stb_image doesn't support it
6776cc1dc7a3Sopenharmony_ci// two back is the image from two frames ago, used for a very specific disposal format
6777cc1dc7a3Sopenharmony_cistatic stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back)
6778cc1dc7a3Sopenharmony_ci{
6779cc1dc7a3Sopenharmony_ci   int dispose;
6780cc1dc7a3Sopenharmony_ci   int first_frame;
6781cc1dc7a3Sopenharmony_ci   int pi;
6782cc1dc7a3Sopenharmony_ci   int pcount;
6783cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(req_comp);
6784cc1dc7a3Sopenharmony_ci
6785cc1dc7a3Sopenharmony_ci   // on first frame, any non-written pixels get the background colour (non-transparent)
6786cc1dc7a3Sopenharmony_ci   first_frame = 0;
6787cc1dc7a3Sopenharmony_ci   if (g->out == 0) {
6788cc1dc7a3Sopenharmony_ci      if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header
6789cc1dc7a3Sopenharmony_ci      if (!stbi__mad3sizes_valid(4, g->w, g->h, 0))
6790cc1dc7a3Sopenharmony_ci         return stbi__errpuc("too large", "GIF image is too large");
6791cc1dc7a3Sopenharmony_ci      pcount = g->w * g->h;
6792cc1dc7a3Sopenharmony_ci      g->out = (stbi_uc *) stbi__malloc(4 * pcount);
6793cc1dc7a3Sopenharmony_ci      g->background = (stbi_uc *) stbi__malloc(4 * pcount);
6794cc1dc7a3Sopenharmony_ci      g->history = (stbi_uc *) stbi__malloc(pcount);
6795cc1dc7a3Sopenharmony_ci      if (!g->out || !g->background || !g->history)
6796cc1dc7a3Sopenharmony_ci         return stbi__errpuc("outofmem", "Out of memory");
6797cc1dc7a3Sopenharmony_ci
6798cc1dc7a3Sopenharmony_ci      // image is treated as "transparent" at the start - ie, nothing overwrites the current background;
6799cc1dc7a3Sopenharmony_ci      // background colour is only used for pixels that are not rendered first frame, after that "background"
6800cc1dc7a3Sopenharmony_ci      // color refers to the color that was there the previous frame.
6801cc1dc7a3Sopenharmony_ci      memset(g->out, 0x00, 4 * pcount);
6802cc1dc7a3Sopenharmony_ci      memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent)
6803cc1dc7a3Sopenharmony_ci      memset(g->history, 0x00, pcount);        // pixels that were affected previous frame
6804cc1dc7a3Sopenharmony_ci      first_frame = 1;
6805cc1dc7a3Sopenharmony_ci   } else {
6806cc1dc7a3Sopenharmony_ci      // second frame - how do we dispose of the previous one?
6807cc1dc7a3Sopenharmony_ci      dispose = (g->eflags & 0x1C) >> 2;
6808cc1dc7a3Sopenharmony_ci      pcount = g->w * g->h;
6809cc1dc7a3Sopenharmony_ci
6810cc1dc7a3Sopenharmony_ci      if ((dispose == 3) && (two_back == 0)) {
6811cc1dc7a3Sopenharmony_ci         dispose = 2; // if I don't have an image to revert back to, default to the old background
6812cc1dc7a3Sopenharmony_ci      }
6813cc1dc7a3Sopenharmony_ci
6814cc1dc7a3Sopenharmony_ci      if (dispose == 3) { // use previous graphic
6815cc1dc7a3Sopenharmony_ci         for (pi = 0; pi < pcount; ++pi) {
6816cc1dc7a3Sopenharmony_ci            if (g->history[pi]) {
6817cc1dc7a3Sopenharmony_ci               memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 );
6818cc1dc7a3Sopenharmony_ci            }
6819cc1dc7a3Sopenharmony_ci         }
6820cc1dc7a3Sopenharmony_ci      } else if (dispose == 2) {
6821cc1dc7a3Sopenharmony_ci         // restore what was changed last frame to background before that frame;
6822cc1dc7a3Sopenharmony_ci         for (pi = 0; pi < pcount; ++pi) {
6823cc1dc7a3Sopenharmony_ci            if (g->history[pi]) {
6824cc1dc7a3Sopenharmony_ci               memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 );
6825cc1dc7a3Sopenharmony_ci            }
6826cc1dc7a3Sopenharmony_ci         }
6827cc1dc7a3Sopenharmony_ci      } else {
6828cc1dc7a3Sopenharmony_ci         // This is a non-disposal case eithe way, so just
6829cc1dc7a3Sopenharmony_ci         // leave the pixels as is, and they will become the new background
6830cc1dc7a3Sopenharmony_ci         // 1: do not dispose
6831cc1dc7a3Sopenharmony_ci         // 0:  not specified.
6832cc1dc7a3Sopenharmony_ci      }
6833cc1dc7a3Sopenharmony_ci
6834cc1dc7a3Sopenharmony_ci      // background is what out is after the undoing of the previou frame;
6835cc1dc7a3Sopenharmony_ci      memcpy( g->background, g->out, 4 * g->w * g->h );
6836cc1dc7a3Sopenharmony_ci   }
6837cc1dc7a3Sopenharmony_ci
6838cc1dc7a3Sopenharmony_ci   // clear my history;
6839cc1dc7a3Sopenharmony_ci   memset( g->history, 0x00, g->w * g->h );        // pixels that were affected previous frame
6840cc1dc7a3Sopenharmony_ci
6841cc1dc7a3Sopenharmony_ci   for (;;) {
6842cc1dc7a3Sopenharmony_ci      int tag = stbi__get8(s);
6843cc1dc7a3Sopenharmony_ci      switch (tag) {
6844cc1dc7a3Sopenharmony_ci         case 0x2C: /* Image Descriptor */
6845cc1dc7a3Sopenharmony_ci         {
6846cc1dc7a3Sopenharmony_ci            stbi__int32 x, y, w, h;
6847cc1dc7a3Sopenharmony_ci            stbi_uc *o;
6848cc1dc7a3Sopenharmony_ci
6849cc1dc7a3Sopenharmony_ci            x = stbi__get16le(s);
6850cc1dc7a3Sopenharmony_ci            y = stbi__get16le(s);
6851cc1dc7a3Sopenharmony_ci            w = stbi__get16le(s);
6852cc1dc7a3Sopenharmony_ci            h = stbi__get16le(s);
6853cc1dc7a3Sopenharmony_ci            if (((x + w) > (g->w)) || ((y + h) > (g->h)))
6854cc1dc7a3Sopenharmony_ci               return stbi__errpuc("bad Image Descriptor", "Corrupt GIF");
6855cc1dc7a3Sopenharmony_ci
6856cc1dc7a3Sopenharmony_ci            g->line_size = g->w * 4;
6857cc1dc7a3Sopenharmony_ci            g->start_x = x * 4;
6858cc1dc7a3Sopenharmony_ci            g->start_y = y * g->line_size;
6859cc1dc7a3Sopenharmony_ci            g->max_x   = g->start_x + w * 4;
6860cc1dc7a3Sopenharmony_ci            g->max_y   = g->start_y + h * g->line_size;
6861cc1dc7a3Sopenharmony_ci            g->cur_x   = g->start_x;
6862cc1dc7a3Sopenharmony_ci            g->cur_y   = g->start_y;
6863cc1dc7a3Sopenharmony_ci
6864cc1dc7a3Sopenharmony_ci            // if the width of the specified rectangle is 0, that means
6865cc1dc7a3Sopenharmony_ci            // we may not see *any* pixels or the image is malformed;
6866cc1dc7a3Sopenharmony_ci            // to make sure this is caught, move the current y down to
6867cc1dc7a3Sopenharmony_ci            // max_y (which is what out_gif_code checks).
6868cc1dc7a3Sopenharmony_ci            if (w == 0)
6869cc1dc7a3Sopenharmony_ci               g->cur_y = g->max_y;
6870cc1dc7a3Sopenharmony_ci
6871cc1dc7a3Sopenharmony_ci            g->lflags = stbi__get8(s);
6872cc1dc7a3Sopenharmony_ci
6873cc1dc7a3Sopenharmony_ci            if (g->lflags & 0x40) {
6874cc1dc7a3Sopenharmony_ci               g->step = 8 * g->line_size; // first interlaced spacing
6875cc1dc7a3Sopenharmony_ci               g->parse = 3;
6876cc1dc7a3Sopenharmony_ci            } else {
6877cc1dc7a3Sopenharmony_ci               g->step = g->line_size;
6878cc1dc7a3Sopenharmony_ci               g->parse = 0;
6879cc1dc7a3Sopenharmony_ci            }
6880cc1dc7a3Sopenharmony_ci
6881cc1dc7a3Sopenharmony_ci            if (g->lflags & 0x80) {
6882cc1dc7a3Sopenharmony_ci               stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1);
6883cc1dc7a3Sopenharmony_ci               g->color_table = (stbi_uc *) g->lpal;
6884cc1dc7a3Sopenharmony_ci            } else if (g->flags & 0x80) {
6885cc1dc7a3Sopenharmony_ci               g->color_table = (stbi_uc *) g->pal;
6886cc1dc7a3Sopenharmony_ci            } else
6887cc1dc7a3Sopenharmony_ci               return stbi__errpuc("missing color table", "Corrupt GIF");
6888cc1dc7a3Sopenharmony_ci
6889cc1dc7a3Sopenharmony_ci            o = stbi__process_gif_raster(s, g);
6890cc1dc7a3Sopenharmony_ci            if (!o) return NULL;
6891cc1dc7a3Sopenharmony_ci
6892cc1dc7a3Sopenharmony_ci            // if this was the first frame,
6893cc1dc7a3Sopenharmony_ci            pcount = g->w * g->h;
6894cc1dc7a3Sopenharmony_ci            if (first_frame && (g->bgindex > 0)) {
6895cc1dc7a3Sopenharmony_ci               // if first frame, any pixel not drawn to gets the background color
6896cc1dc7a3Sopenharmony_ci               for (pi = 0; pi < pcount; ++pi) {
6897cc1dc7a3Sopenharmony_ci                  if (g->history[pi] == 0) {
6898cc1dc7a3Sopenharmony_ci                     g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be;
6899cc1dc7a3Sopenharmony_ci                     memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 );
6900cc1dc7a3Sopenharmony_ci                  }
6901cc1dc7a3Sopenharmony_ci               }
6902cc1dc7a3Sopenharmony_ci            }
6903cc1dc7a3Sopenharmony_ci
6904cc1dc7a3Sopenharmony_ci            return o;
6905cc1dc7a3Sopenharmony_ci         }
6906cc1dc7a3Sopenharmony_ci
6907cc1dc7a3Sopenharmony_ci         case 0x21: // Comment Extension.
6908cc1dc7a3Sopenharmony_ci         {
6909cc1dc7a3Sopenharmony_ci            int len;
6910cc1dc7a3Sopenharmony_ci            int ext = stbi__get8(s);
6911cc1dc7a3Sopenharmony_ci            if (ext == 0xF9) { // Graphic Control Extension.
6912cc1dc7a3Sopenharmony_ci               len = stbi__get8(s);
6913cc1dc7a3Sopenharmony_ci               if (len == 4) {
6914cc1dc7a3Sopenharmony_ci                  g->eflags = stbi__get8(s);
6915cc1dc7a3Sopenharmony_ci                  g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths.
6916cc1dc7a3Sopenharmony_ci
6917cc1dc7a3Sopenharmony_ci                  // unset old transparent
6918cc1dc7a3Sopenharmony_ci                  if (g->transparent >= 0) {
6919cc1dc7a3Sopenharmony_ci                     g->pal[g->transparent][3] = 255;
6920cc1dc7a3Sopenharmony_ci                  }
6921cc1dc7a3Sopenharmony_ci                  if (g->eflags & 0x01) {
6922cc1dc7a3Sopenharmony_ci                     g->transparent = stbi__get8(s);
6923cc1dc7a3Sopenharmony_ci                     if (g->transparent >= 0) {
6924cc1dc7a3Sopenharmony_ci                        g->pal[g->transparent][3] = 0;
6925cc1dc7a3Sopenharmony_ci                     }
6926cc1dc7a3Sopenharmony_ci                  } else {
6927cc1dc7a3Sopenharmony_ci                     // don't need transparent
6928cc1dc7a3Sopenharmony_ci                     stbi__skip(s, 1);
6929cc1dc7a3Sopenharmony_ci                     g->transparent = -1;
6930cc1dc7a3Sopenharmony_ci                  }
6931cc1dc7a3Sopenharmony_ci               } else {
6932cc1dc7a3Sopenharmony_ci                  stbi__skip(s, len);
6933cc1dc7a3Sopenharmony_ci                  break;
6934cc1dc7a3Sopenharmony_ci               }
6935cc1dc7a3Sopenharmony_ci            }
6936cc1dc7a3Sopenharmony_ci            while ((len = stbi__get8(s)) != 0) {
6937cc1dc7a3Sopenharmony_ci               stbi__skip(s, len);
6938cc1dc7a3Sopenharmony_ci            }
6939cc1dc7a3Sopenharmony_ci            break;
6940cc1dc7a3Sopenharmony_ci         }
6941cc1dc7a3Sopenharmony_ci
6942cc1dc7a3Sopenharmony_ci         case 0x3B: // gif stream termination code
6943cc1dc7a3Sopenharmony_ci            return (stbi_uc *) s; // using '1' causes warning on some compilers
6944cc1dc7a3Sopenharmony_ci
6945cc1dc7a3Sopenharmony_ci         default:
6946cc1dc7a3Sopenharmony_ci            return stbi__errpuc("unknown code", "Corrupt GIF");
6947cc1dc7a3Sopenharmony_ci      }
6948cc1dc7a3Sopenharmony_ci   }
6949cc1dc7a3Sopenharmony_ci}
6950cc1dc7a3Sopenharmony_ci
6951cc1dc7a3Sopenharmony_cistatic void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays)
6952cc1dc7a3Sopenharmony_ci{
6953cc1dc7a3Sopenharmony_ci   STBI_FREE(g->out);
6954cc1dc7a3Sopenharmony_ci   STBI_FREE(g->history);
6955cc1dc7a3Sopenharmony_ci   STBI_FREE(g->background);
6956cc1dc7a3Sopenharmony_ci
6957cc1dc7a3Sopenharmony_ci   if (out) STBI_FREE(out);
6958cc1dc7a3Sopenharmony_ci   if (delays && *delays) STBI_FREE(*delays);
6959cc1dc7a3Sopenharmony_ci   return stbi__errpuc("outofmem", "Out of memory");
6960cc1dc7a3Sopenharmony_ci}
6961cc1dc7a3Sopenharmony_ci
6962cc1dc7a3Sopenharmony_cistatic void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
6963cc1dc7a3Sopenharmony_ci{
6964cc1dc7a3Sopenharmony_ci   if (stbi__gif_test(s)) {
6965cc1dc7a3Sopenharmony_ci      int layers = 0;
6966cc1dc7a3Sopenharmony_ci      stbi_uc *u = 0;
6967cc1dc7a3Sopenharmony_ci      stbi_uc *out = 0;
6968cc1dc7a3Sopenharmony_ci      stbi_uc *two_back = 0;
6969cc1dc7a3Sopenharmony_ci      stbi__gif g;
6970cc1dc7a3Sopenharmony_ci      int stride;
6971cc1dc7a3Sopenharmony_ci      int out_size = 0;
6972cc1dc7a3Sopenharmony_ci      int delays_size = 0;
6973cc1dc7a3Sopenharmony_ci
6974cc1dc7a3Sopenharmony_ci      STBI_NOTUSED(out_size);
6975cc1dc7a3Sopenharmony_ci      STBI_NOTUSED(delays_size);
6976cc1dc7a3Sopenharmony_ci
6977cc1dc7a3Sopenharmony_ci      memset(&g, 0, sizeof(g));
6978cc1dc7a3Sopenharmony_ci      if (delays) {
6979cc1dc7a3Sopenharmony_ci         *delays = 0;
6980cc1dc7a3Sopenharmony_ci      }
6981cc1dc7a3Sopenharmony_ci
6982cc1dc7a3Sopenharmony_ci      do {
6983cc1dc7a3Sopenharmony_ci         u = stbi__gif_load_next(s, &g, comp, req_comp, two_back);
6984cc1dc7a3Sopenharmony_ci         if (u == (stbi_uc *) s) u = 0;  // end of animated gif marker
6985cc1dc7a3Sopenharmony_ci
6986cc1dc7a3Sopenharmony_ci         if (u) {
6987cc1dc7a3Sopenharmony_ci            *x = g.w;
6988cc1dc7a3Sopenharmony_ci            *y = g.h;
6989cc1dc7a3Sopenharmony_ci            ++layers;
6990cc1dc7a3Sopenharmony_ci            stride = g.w * g.h * 4;
6991cc1dc7a3Sopenharmony_ci
6992cc1dc7a3Sopenharmony_ci            if (out) {
6993cc1dc7a3Sopenharmony_ci               void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride );
6994cc1dc7a3Sopenharmony_ci               if (!tmp) {
6995cc1dc7a3Sopenharmony_ci                  void *ret = stbi__load_gif_main_outofmem(&g, out, delays);
6996cc1dc7a3Sopenharmony_ci                  if (delays && *delays) *delays = 0;
6997cc1dc7a3Sopenharmony_ci                  return ret;
6998cc1dc7a3Sopenharmony_ci               }
6999cc1dc7a3Sopenharmony_ci               else {
7000cc1dc7a3Sopenharmony_ci                   out = (stbi_uc*) tmp;
7001cc1dc7a3Sopenharmony_ci                   out_size = layers * stride;
7002cc1dc7a3Sopenharmony_ci               }
7003cc1dc7a3Sopenharmony_ci
7004cc1dc7a3Sopenharmony_ci               if (delays) {
7005cc1dc7a3Sopenharmony_ci                  int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers );
7006cc1dc7a3Sopenharmony_ci                  if (!new_delays)
7007cc1dc7a3Sopenharmony_ci                     return stbi__load_gif_main_outofmem(&g, out, delays);
7008cc1dc7a3Sopenharmony_ci                  *delays = new_delays;
7009cc1dc7a3Sopenharmony_ci                  delays_size = layers * sizeof(int);
7010cc1dc7a3Sopenharmony_ci               }
7011cc1dc7a3Sopenharmony_ci            } else {
7012cc1dc7a3Sopenharmony_ci               out = (stbi_uc*)stbi__malloc( layers * stride );
7013cc1dc7a3Sopenharmony_ci               if (!out) {
7014cc1dc7a3Sopenharmony_ci                  void *ret = stbi__load_gif_main_outofmem(&g, out, delays);
7015cc1dc7a3Sopenharmony_ci                  if (delays && *delays) *delays = 0;
7016cc1dc7a3Sopenharmony_ci                  return ret;
7017cc1dc7a3Sopenharmony_ci               }
7018cc1dc7a3Sopenharmony_ci               out_size = layers * stride;
7019cc1dc7a3Sopenharmony_ci               if (delays) {
7020cc1dc7a3Sopenharmony_ci                  *delays = (int*) stbi__malloc( layers * sizeof(int) );
7021cc1dc7a3Sopenharmony_ci                  if (!*delays)
7022cc1dc7a3Sopenharmony_ci                     return stbi__load_gif_main_outofmem(&g, out, delays);
7023cc1dc7a3Sopenharmony_ci                  delays_size = layers * sizeof(int);
7024cc1dc7a3Sopenharmony_ci               }
7025cc1dc7a3Sopenharmony_ci            }
7026cc1dc7a3Sopenharmony_ci            memcpy( out + ((layers - 1) * stride), u, stride );
7027cc1dc7a3Sopenharmony_ci            if (layers >= 2) {
7028cc1dc7a3Sopenharmony_ci               two_back = out + (layers - 2) * stride;
7029cc1dc7a3Sopenharmony_ci            }
7030cc1dc7a3Sopenharmony_ci
7031cc1dc7a3Sopenharmony_ci            if (delays) {
7032cc1dc7a3Sopenharmony_ci               (*delays)[layers - 1U] = g.delay;
7033cc1dc7a3Sopenharmony_ci            }
7034cc1dc7a3Sopenharmony_ci         }
7035cc1dc7a3Sopenharmony_ci      } while (u != 0);
7036cc1dc7a3Sopenharmony_ci
7037cc1dc7a3Sopenharmony_ci      // free temp buffer;
7038cc1dc7a3Sopenharmony_ci      STBI_FREE(g.out);
7039cc1dc7a3Sopenharmony_ci      STBI_FREE(g.history);
7040cc1dc7a3Sopenharmony_ci      STBI_FREE(g.background);
7041cc1dc7a3Sopenharmony_ci
7042cc1dc7a3Sopenharmony_ci      // do the final conversion after loading everything;
7043cc1dc7a3Sopenharmony_ci      if (req_comp && req_comp != 4)
7044cc1dc7a3Sopenharmony_ci         out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h);
7045cc1dc7a3Sopenharmony_ci
7046cc1dc7a3Sopenharmony_ci      *z = layers;
7047cc1dc7a3Sopenharmony_ci      return out;
7048cc1dc7a3Sopenharmony_ci   } else {
7049cc1dc7a3Sopenharmony_ci      return stbi__errpuc("not GIF", "Image was not as a gif type.");
7050cc1dc7a3Sopenharmony_ci   }
7051cc1dc7a3Sopenharmony_ci}
7052cc1dc7a3Sopenharmony_ci
7053cc1dc7a3Sopenharmony_cistatic void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
7054cc1dc7a3Sopenharmony_ci{
7055cc1dc7a3Sopenharmony_ci   stbi_uc *u = 0;
7056cc1dc7a3Sopenharmony_ci   stbi__gif g;
7057cc1dc7a3Sopenharmony_ci   memset(&g, 0, sizeof(g));
7058cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(ri);
7059cc1dc7a3Sopenharmony_ci
7060cc1dc7a3Sopenharmony_ci   u = stbi__gif_load_next(s, &g, comp, req_comp, 0);
7061cc1dc7a3Sopenharmony_ci   if (u == (stbi_uc *) s) u = 0;  // end of animated gif marker
7062cc1dc7a3Sopenharmony_ci   if (u) {
7063cc1dc7a3Sopenharmony_ci      *x = g.w;
7064cc1dc7a3Sopenharmony_ci      *y = g.h;
7065cc1dc7a3Sopenharmony_ci
7066cc1dc7a3Sopenharmony_ci      // moved conversion to after successful load so that the same
7067cc1dc7a3Sopenharmony_ci      // can be done for multiple frames.
7068cc1dc7a3Sopenharmony_ci      if (req_comp && req_comp != 4)
7069cc1dc7a3Sopenharmony_ci         u = stbi__convert_format(u, 4, req_comp, g.w, g.h);
7070cc1dc7a3Sopenharmony_ci   } else if (g.out) {
7071cc1dc7a3Sopenharmony_ci      // if there was an error and we allocated an image buffer, free it!
7072cc1dc7a3Sopenharmony_ci      STBI_FREE(g.out);
7073cc1dc7a3Sopenharmony_ci   }
7074cc1dc7a3Sopenharmony_ci
7075cc1dc7a3Sopenharmony_ci   // free buffers needed for multiple frame loading;
7076cc1dc7a3Sopenharmony_ci   STBI_FREE(g.history);
7077cc1dc7a3Sopenharmony_ci   STBI_FREE(g.background);
7078cc1dc7a3Sopenharmony_ci
7079cc1dc7a3Sopenharmony_ci   return u;
7080cc1dc7a3Sopenharmony_ci}
7081cc1dc7a3Sopenharmony_ci
7082cc1dc7a3Sopenharmony_cistatic int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp)
7083cc1dc7a3Sopenharmony_ci{
7084cc1dc7a3Sopenharmony_ci   return stbi__gif_info_raw(s,x,y,comp);
7085cc1dc7a3Sopenharmony_ci}
7086cc1dc7a3Sopenharmony_ci#endif
7087cc1dc7a3Sopenharmony_ci
7088cc1dc7a3Sopenharmony_ci// *************************************************************************************************
7089cc1dc7a3Sopenharmony_ci// Radiance RGBE HDR loader
7090cc1dc7a3Sopenharmony_ci// originally by Nicolas Schulz
7091cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_HDR
7092cc1dc7a3Sopenharmony_cistatic int stbi__hdr_test_core(stbi__context *s, const char *signature)
7093cc1dc7a3Sopenharmony_ci{
7094cc1dc7a3Sopenharmony_ci   int i;
7095cc1dc7a3Sopenharmony_ci   for (i=0; signature[i]; ++i)
7096cc1dc7a3Sopenharmony_ci      if (stbi__get8(s) != signature[i])
7097cc1dc7a3Sopenharmony_ci          return 0;
7098cc1dc7a3Sopenharmony_ci   stbi__rewind(s);
7099cc1dc7a3Sopenharmony_ci   return 1;
7100cc1dc7a3Sopenharmony_ci}
7101cc1dc7a3Sopenharmony_ci
7102cc1dc7a3Sopenharmony_cistatic int stbi__hdr_test(stbi__context* s)
7103cc1dc7a3Sopenharmony_ci{
7104cc1dc7a3Sopenharmony_ci   int r = stbi__hdr_test_core(s, "#?RADIANCE\n");
7105cc1dc7a3Sopenharmony_ci   stbi__rewind(s);
7106cc1dc7a3Sopenharmony_ci   if(!r) {
7107cc1dc7a3Sopenharmony_ci       r = stbi__hdr_test_core(s, "#?RGBE\n");
7108cc1dc7a3Sopenharmony_ci       stbi__rewind(s);
7109cc1dc7a3Sopenharmony_ci   }
7110cc1dc7a3Sopenharmony_ci   return r;
7111cc1dc7a3Sopenharmony_ci}
7112cc1dc7a3Sopenharmony_ci
7113cc1dc7a3Sopenharmony_ci#define STBI__HDR_BUFLEN  1024
7114cc1dc7a3Sopenharmony_cistatic char *stbi__hdr_gettoken(stbi__context *z, char *buffer)
7115cc1dc7a3Sopenharmony_ci{
7116cc1dc7a3Sopenharmony_ci   int len=0;
7117cc1dc7a3Sopenharmony_ci   char c = '\0';
7118cc1dc7a3Sopenharmony_ci
7119cc1dc7a3Sopenharmony_ci   c = (char) stbi__get8(z);
7120cc1dc7a3Sopenharmony_ci
7121cc1dc7a3Sopenharmony_ci   while (!stbi__at_eof(z) && c != '\n') {
7122cc1dc7a3Sopenharmony_ci      buffer[len++] = c;
7123cc1dc7a3Sopenharmony_ci      if (len == STBI__HDR_BUFLEN-1) {
7124cc1dc7a3Sopenharmony_ci         // flush to end of line
7125cc1dc7a3Sopenharmony_ci         while (!stbi__at_eof(z) && stbi__get8(z) != '\n')
7126cc1dc7a3Sopenharmony_ci            ;
7127cc1dc7a3Sopenharmony_ci         break;
7128cc1dc7a3Sopenharmony_ci      }
7129cc1dc7a3Sopenharmony_ci      c = (char) stbi__get8(z);
7130cc1dc7a3Sopenharmony_ci   }
7131cc1dc7a3Sopenharmony_ci
7132cc1dc7a3Sopenharmony_ci   buffer[len] = 0;
7133cc1dc7a3Sopenharmony_ci   return buffer;
7134cc1dc7a3Sopenharmony_ci}
7135cc1dc7a3Sopenharmony_ci
7136cc1dc7a3Sopenharmony_cistatic void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp)
7137cc1dc7a3Sopenharmony_ci{
7138cc1dc7a3Sopenharmony_ci   if ( input[3] != 0 ) {
7139cc1dc7a3Sopenharmony_ci      float f1;
7140cc1dc7a3Sopenharmony_ci      // Exponent
7141cc1dc7a3Sopenharmony_ci      f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8));
7142cc1dc7a3Sopenharmony_ci      if (req_comp <= 2)
7143cc1dc7a3Sopenharmony_ci         output[0] = (input[0] + input[1] + input[2]) * f1 / 3;
7144cc1dc7a3Sopenharmony_ci      else {
7145cc1dc7a3Sopenharmony_ci         output[0] = input[0] * f1;
7146cc1dc7a3Sopenharmony_ci         output[1] = input[1] * f1;
7147cc1dc7a3Sopenharmony_ci         output[2] = input[2] * f1;
7148cc1dc7a3Sopenharmony_ci      }
7149cc1dc7a3Sopenharmony_ci      if (req_comp == 2) output[1] = 1;
7150cc1dc7a3Sopenharmony_ci      if (req_comp == 4) output[3] = 1;
7151cc1dc7a3Sopenharmony_ci   } else {
7152cc1dc7a3Sopenharmony_ci      switch (req_comp) {
7153cc1dc7a3Sopenharmony_ci         case 4: output[3] = 1; /* fallthrough */
7154cc1dc7a3Sopenharmony_ci         case 3: output[0] = output[1] = output[2] = 0;
7155cc1dc7a3Sopenharmony_ci                 break;
7156cc1dc7a3Sopenharmony_ci         case 2: output[1] = 1; /* fallthrough */
7157cc1dc7a3Sopenharmony_ci         case 1: output[0] = 0;
7158cc1dc7a3Sopenharmony_ci                 break;
7159cc1dc7a3Sopenharmony_ci      }
7160cc1dc7a3Sopenharmony_ci   }
7161cc1dc7a3Sopenharmony_ci}
7162cc1dc7a3Sopenharmony_ci
7163cc1dc7a3Sopenharmony_cistatic float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
7164cc1dc7a3Sopenharmony_ci{
7165cc1dc7a3Sopenharmony_ci   char buffer[STBI__HDR_BUFLEN];
7166cc1dc7a3Sopenharmony_ci   char *token;
7167cc1dc7a3Sopenharmony_ci   int valid = 0;
7168cc1dc7a3Sopenharmony_ci   int width, height;
7169cc1dc7a3Sopenharmony_ci   stbi_uc *scanline;
7170cc1dc7a3Sopenharmony_ci   float *hdr_data;
7171cc1dc7a3Sopenharmony_ci   int len;
7172cc1dc7a3Sopenharmony_ci   unsigned char count, value;
7173cc1dc7a3Sopenharmony_ci   int i, j, k, c1,c2, z;
7174cc1dc7a3Sopenharmony_ci   const char *headerToken;
7175cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(ri);
7176cc1dc7a3Sopenharmony_ci
7177cc1dc7a3Sopenharmony_ci   // Check identifier
7178cc1dc7a3Sopenharmony_ci   headerToken = stbi__hdr_gettoken(s,buffer);
7179cc1dc7a3Sopenharmony_ci   if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0)
7180cc1dc7a3Sopenharmony_ci      return stbi__errpf("not HDR", "Corrupt HDR image");
7181cc1dc7a3Sopenharmony_ci
7182cc1dc7a3Sopenharmony_ci   // Parse header
7183cc1dc7a3Sopenharmony_ci   for(;;) {
7184cc1dc7a3Sopenharmony_ci      token = stbi__hdr_gettoken(s,buffer);
7185cc1dc7a3Sopenharmony_ci      if (token[0] == 0) break;
7186cc1dc7a3Sopenharmony_ci      if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;
7187cc1dc7a3Sopenharmony_ci   }
7188cc1dc7a3Sopenharmony_ci
7189cc1dc7a3Sopenharmony_ci   if (!valid)    return stbi__errpf("unsupported format", "Unsupported HDR format");
7190cc1dc7a3Sopenharmony_ci
7191cc1dc7a3Sopenharmony_ci   // Parse width and height
7192cc1dc7a3Sopenharmony_ci   // can't use sscanf() if we're not using stdio!
7193cc1dc7a3Sopenharmony_ci   token = stbi__hdr_gettoken(s,buffer);
7194cc1dc7a3Sopenharmony_ci   if (strncmp(token, "-Y ", 3))  return stbi__errpf("unsupported data layout", "Unsupported HDR format");
7195cc1dc7a3Sopenharmony_ci   token += 3;
7196cc1dc7a3Sopenharmony_ci   height = (int) strtol(token, &token, 10);
7197cc1dc7a3Sopenharmony_ci   while (*token == ' ') ++token;
7198cc1dc7a3Sopenharmony_ci   if (strncmp(token, "+X ", 3))  return stbi__errpf("unsupported data layout", "Unsupported HDR format");
7199cc1dc7a3Sopenharmony_ci   token += 3;
7200cc1dc7a3Sopenharmony_ci   width = (int) strtol(token, NULL, 10);
7201cc1dc7a3Sopenharmony_ci
7202cc1dc7a3Sopenharmony_ci   if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");
7203cc1dc7a3Sopenharmony_ci   if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");
7204cc1dc7a3Sopenharmony_ci
7205cc1dc7a3Sopenharmony_ci   *x = width;
7206cc1dc7a3Sopenharmony_ci   *y = height;
7207cc1dc7a3Sopenharmony_ci
7208cc1dc7a3Sopenharmony_ci   if (comp) *comp = 3;
7209cc1dc7a3Sopenharmony_ci   if (req_comp == 0) req_comp = 3;
7210cc1dc7a3Sopenharmony_ci
7211cc1dc7a3Sopenharmony_ci   if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0))
7212cc1dc7a3Sopenharmony_ci      return stbi__errpf("too large", "HDR image is too large");
7213cc1dc7a3Sopenharmony_ci
7214cc1dc7a3Sopenharmony_ci   // Read data
7215cc1dc7a3Sopenharmony_ci   hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0);
7216cc1dc7a3Sopenharmony_ci   if (!hdr_data)
7217cc1dc7a3Sopenharmony_ci      return stbi__errpf("outofmem", "Out of memory");
7218cc1dc7a3Sopenharmony_ci
7219cc1dc7a3Sopenharmony_ci   // Load image data
7220cc1dc7a3Sopenharmony_ci   // image data is stored as some number of sca
7221cc1dc7a3Sopenharmony_ci   if ( width < 8 || width >= 32768) {
7222cc1dc7a3Sopenharmony_ci      // Read flat data
7223cc1dc7a3Sopenharmony_ci      for (j=0; j < height; ++j) {
7224cc1dc7a3Sopenharmony_ci         for (i=0; i < width; ++i) {
7225cc1dc7a3Sopenharmony_ci            stbi_uc rgbe[4];
7226cc1dc7a3Sopenharmony_ci           main_decode_loop:
7227cc1dc7a3Sopenharmony_ci            stbi__getn(s, rgbe, 4);
7228cc1dc7a3Sopenharmony_ci            stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp);
7229cc1dc7a3Sopenharmony_ci         }
7230cc1dc7a3Sopenharmony_ci      }
7231cc1dc7a3Sopenharmony_ci   } else {
7232cc1dc7a3Sopenharmony_ci      // Read RLE-encoded data
7233cc1dc7a3Sopenharmony_ci      scanline = NULL;
7234cc1dc7a3Sopenharmony_ci
7235cc1dc7a3Sopenharmony_ci      for (j = 0; j < height; ++j) {
7236cc1dc7a3Sopenharmony_ci         c1 = stbi__get8(s);
7237cc1dc7a3Sopenharmony_ci         c2 = stbi__get8(s);
7238cc1dc7a3Sopenharmony_ci         len = stbi__get8(s);
7239cc1dc7a3Sopenharmony_ci         if (c1 != 2 || c2 != 2 || (len & 0x80)) {
7240cc1dc7a3Sopenharmony_ci            // not run-length encoded, so we have to actually use THIS data as a decoded
7241cc1dc7a3Sopenharmony_ci            // pixel (note this can't be a valid pixel--one of RGB must be >= 128)
7242cc1dc7a3Sopenharmony_ci            stbi_uc rgbe[4];
7243cc1dc7a3Sopenharmony_ci            rgbe[0] = (stbi_uc) c1;
7244cc1dc7a3Sopenharmony_ci            rgbe[1] = (stbi_uc) c2;
7245cc1dc7a3Sopenharmony_ci            rgbe[2] = (stbi_uc) len;
7246cc1dc7a3Sopenharmony_ci            rgbe[3] = (stbi_uc) stbi__get8(s);
7247cc1dc7a3Sopenharmony_ci            stbi__hdr_convert(hdr_data, rgbe, req_comp);
7248cc1dc7a3Sopenharmony_ci            i = 1;
7249cc1dc7a3Sopenharmony_ci            j = 0;
7250cc1dc7a3Sopenharmony_ci            STBI_FREE(scanline);
7251cc1dc7a3Sopenharmony_ci            goto main_decode_loop; // yes, this makes no sense
7252cc1dc7a3Sopenharmony_ci         }
7253cc1dc7a3Sopenharmony_ci         len <<= 8;
7254cc1dc7a3Sopenharmony_ci         len |= stbi__get8(s);
7255cc1dc7a3Sopenharmony_ci         if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); }
7256cc1dc7a3Sopenharmony_ci         if (scanline == NULL) {
7257cc1dc7a3Sopenharmony_ci            scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0);
7258cc1dc7a3Sopenharmony_ci            if (!scanline) {
7259cc1dc7a3Sopenharmony_ci               STBI_FREE(hdr_data);
7260cc1dc7a3Sopenharmony_ci               return stbi__errpf("outofmem", "Out of memory");
7261cc1dc7a3Sopenharmony_ci            }
7262cc1dc7a3Sopenharmony_ci         }
7263cc1dc7a3Sopenharmony_ci
7264cc1dc7a3Sopenharmony_ci         for (k = 0; k < 4; ++k) {
7265cc1dc7a3Sopenharmony_ci            int nleft;
7266cc1dc7a3Sopenharmony_ci            i = 0;
7267cc1dc7a3Sopenharmony_ci            while ((nleft = width - i) > 0) {
7268cc1dc7a3Sopenharmony_ci               count = stbi__get8(s);
7269cc1dc7a3Sopenharmony_ci               if (count > 128) {
7270cc1dc7a3Sopenharmony_ci                  // Run
7271cc1dc7a3Sopenharmony_ci                  value = stbi__get8(s);
7272cc1dc7a3Sopenharmony_ci                  count -= 128;
7273cc1dc7a3Sopenharmony_ci                  if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
7274cc1dc7a3Sopenharmony_ci                  for (z = 0; z < count; ++z)
7275cc1dc7a3Sopenharmony_ci                     scanline[i++ * 4 + k] = value;
7276cc1dc7a3Sopenharmony_ci               } else {
7277cc1dc7a3Sopenharmony_ci                  // Dump
7278cc1dc7a3Sopenharmony_ci                  if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
7279cc1dc7a3Sopenharmony_ci                  for (z = 0; z < count; ++z)
7280cc1dc7a3Sopenharmony_ci                     scanline[i++ * 4 + k] = stbi__get8(s);
7281cc1dc7a3Sopenharmony_ci               }
7282cc1dc7a3Sopenharmony_ci            }
7283cc1dc7a3Sopenharmony_ci         }
7284cc1dc7a3Sopenharmony_ci         for (i=0; i < width; ++i)
7285cc1dc7a3Sopenharmony_ci            stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp);
7286cc1dc7a3Sopenharmony_ci      }
7287cc1dc7a3Sopenharmony_ci      if (scanline)
7288cc1dc7a3Sopenharmony_ci         STBI_FREE(scanline);
7289cc1dc7a3Sopenharmony_ci   }
7290cc1dc7a3Sopenharmony_ci
7291cc1dc7a3Sopenharmony_ci   return hdr_data;
7292cc1dc7a3Sopenharmony_ci}
7293cc1dc7a3Sopenharmony_ci
7294cc1dc7a3Sopenharmony_cistatic int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp)
7295cc1dc7a3Sopenharmony_ci{
7296cc1dc7a3Sopenharmony_ci   char buffer[STBI__HDR_BUFLEN];
7297cc1dc7a3Sopenharmony_ci   char *token;
7298cc1dc7a3Sopenharmony_ci   int valid = 0;
7299cc1dc7a3Sopenharmony_ci   int dummy;
7300cc1dc7a3Sopenharmony_ci
7301cc1dc7a3Sopenharmony_ci   if (!x) x = &dummy;
7302cc1dc7a3Sopenharmony_ci   if (!y) y = &dummy;
7303cc1dc7a3Sopenharmony_ci   if (!comp) comp = &dummy;
7304cc1dc7a3Sopenharmony_ci
7305cc1dc7a3Sopenharmony_ci   if (stbi__hdr_test(s) == 0) {
7306cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7307cc1dc7a3Sopenharmony_ci       return 0;
7308cc1dc7a3Sopenharmony_ci   }
7309cc1dc7a3Sopenharmony_ci
7310cc1dc7a3Sopenharmony_ci   for(;;) {
7311cc1dc7a3Sopenharmony_ci      token = stbi__hdr_gettoken(s,buffer);
7312cc1dc7a3Sopenharmony_ci      if (token[0] == 0) break;
7313cc1dc7a3Sopenharmony_ci      if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;
7314cc1dc7a3Sopenharmony_ci   }
7315cc1dc7a3Sopenharmony_ci
7316cc1dc7a3Sopenharmony_ci   if (!valid) {
7317cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7318cc1dc7a3Sopenharmony_ci       return 0;
7319cc1dc7a3Sopenharmony_ci   }
7320cc1dc7a3Sopenharmony_ci   token = stbi__hdr_gettoken(s,buffer);
7321cc1dc7a3Sopenharmony_ci   if (strncmp(token, "-Y ", 3)) {
7322cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7323cc1dc7a3Sopenharmony_ci       return 0;
7324cc1dc7a3Sopenharmony_ci   }
7325cc1dc7a3Sopenharmony_ci   token += 3;
7326cc1dc7a3Sopenharmony_ci   *y = (int) strtol(token, &token, 10);
7327cc1dc7a3Sopenharmony_ci   while (*token == ' ') ++token;
7328cc1dc7a3Sopenharmony_ci   if (strncmp(token, "+X ", 3)) {
7329cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7330cc1dc7a3Sopenharmony_ci       return 0;
7331cc1dc7a3Sopenharmony_ci   }
7332cc1dc7a3Sopenharmony_ci   token += 3;
7333cc1dc7a3Sopenharmony_ci   *x = (int) strtol(token, NULL, 10);
7334cc1dc7a3Sopenharmony_ci   *comp = 3;
7335cc1dc7a3Sopenharmony_ci   return 1;
7336cc1dc7a3Sopenharmony_ci}
7337cc1dc7a3Sopenharmony_ci#endif // STBI_NO_HDR
7338cc1dc7a3Sopenharmony_ci
7339cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_BMP
7340cc1dc7a3Sopenharmony_cistatic int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
7341cc1dc7a3Sopenharmony_ci{
7342cc1dc7a3Sopenharmony_ci   void *p;
7343cc1dc7a3Sopenharmony_ci   stbi__bmp_data info;
7344cc1dc7a3Sopenharmony_ci
7345cc1dc7a3Sopenharmony_ci   info.all_a = 255;
7346cc1dc7a3Sopenharmony_ci   p = stbi__bmp_parse_header(s, &info);
7347cc1dc7a3Sopenharmony_ci   if (p == NULL) {
7348cc1dc7a3Sopenharmony_ci      stbi__rewind( s );
7349cc1dc7a3Sopenharmony_ci      return 0;
7350cc1dc7a3Sopenharmony_ci   }
7351cc1dc7a3Sopenharmony_ci   if (x) *x = s->img_x;
7352cc1dc7a3Sopenharmony_ci   if (y) *y = s->img_y;
7353cc1dc7a3Sopenharmony_ci   if (comp) {
7354cc1dc7a3Sopenharmony_ci      if (info.bpp == 24 && info.ma == 0xff000000)
7355cc1dc7a3Sopenharmony_ci         *comp = 3;
7356cc1dc7a3Sopenharmony_ci      else
7357cc1dc7a3Sopenharmony_ci         *comp = info.ma ? 4 : 3;
7358cc1dc7a3Sopenharmony_ci   }
7359cc1dc7a3Sopenharmony_ci   return 1;
7360cc1dc7a3Sopenharmony_ci}
7361cc1dc7a3Sopenharmony_ci#endif
7362cc1dc7a3Sopenharmony_ci
7363cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_PSD
7364cc1dc7a3Sopenharmony_cistatic int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp)
7365cc1dc7a3Sopenharmony_ci{
7366cc1dc7a3Sopenharmony_ci   int channelCount, dummy, depth;
7367cc1dc7a3Sopenharmony_ci   if (!x) x = &dummy;
7368cc1dc7a3Sopenharmony_ci   if (!y) y = &dummy;
7369cc1dc7a3Sopenharmony_ci   if (!comp) comp = &dummy;
7370cc1dc7a3Sopenharmony_ci   if (stbi__get32be(s) != 0x38425053) {
7371cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7372cc1dc7a3Sopenharmony_ci       return 0;
7373cc1dc7a3Sopenharmony_ci   }
7374cc1dc7a3Sopenharmony_ci   if (stbi__get16be(s) != 1) {
7375cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7376cc1dc7a3Sopenharmony_ci       return 0;
7377cc1dc7a3Sopenharmony_ci   }
7378cc1dc7a3Sopenharmony_ci   stbi__skip(s, 6);
7379cc1dc7a3Sopenharmony_ci   channelCount = stbi__get16be(s);
7380cc1dc7a3Sopenharmony_ci   if (channelCount < 0 || channelCount > 16) {
7381cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7382cc1dc7a3Sopenharmony_ci       return 0;
7383cc1dc7a3Sopenharmony_ci   }
7384cc1dc7a3Sopenharmony_ci   *y = stbi__get32be(s);
7385cc1dc7a3Sopenharmony_ci   *x = stbi__get32be(s);
7386cc1dc7a3Sopenharmony_ci   depth = stbi__get16be(s);
7387cc1dc7a3Sopenharmony_ci   if (depth != 8 && depth != 16) {
7388cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7389cc1dc7a3Sopenharmony_ci       return 0;
7390cc1dc7a3Sopenharmony_ci   }
7391cc1dc7a3Sopenharmony_ci   if (stbi__get16be(s) != 3) {
7392cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7393cc1dc7a3Sopenharmony_ci       return 0;
7394cc1dc7a3Sopenharmony_ci   }
7395cc1dc7a3Sopenharmony_ci   *comp = 4;
7396cc1dc7a3Sopenharmony_ci   return 1;
7397cc1dc7a3Sopenharmony_ci}
7398cc1dc7a3Sopenharmony_ci
7399cc1dc7a3Sopenharmony_cistatic int stbi__psd_is16(stbi__context *s)
7400cc1dc7a3Sopenharmony_ci{
7401cc1dc7a3Sopenharmony_ci   int channelCount, depth;
7402cc1dc7a3Sopenharmony_ci   if (stbi__get32be(s) != 0x38425053) {
7403cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7404cc1dc7a3Sopenharmony_ci       return 0;
7405cc1dc7a3Sopenharmony_ci   }
7406cc1dc7a3Sopenharmony_ci   if (stbi__get16be(s) != 1) {
7407cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7408cc1dc7a3Sopenharmony_ci       return 0;
7409cc1dc7a3Sopenharmony_ci   }
7410cc1dc7a3Sopenharmony_ci   stbi__skip(s, 6);
7411cc1dc7a3Sopenharmony_ci   channelCount = stbi__get16be(s);
7412cc1dc7a3Sopenharmony_ci   if (channelCount < 0 || channelCount > 16) {
7413cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7414cc1dc7a3Sopenharmony_ci       return 0;
7415cc1dc7a3Sopenharmony_ci   }
7416cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(stbi__get32be(s));
7417cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(stbi__get32be(s));
7418cc1dc7a3Sopenharmony_ci   depth = stbi__get16be(s);
7419cc1dc7a3Sopenharmony_ci   if (depth != 16) {
7420cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7421cc1dc7a3Sopenharmony_ci       return 0;
7422cc1dc7a3Sopenharmony_ci   }
7423cc1dc7a3Sopenharmony_ci   return 1;
7424cc1dc7a3Sopenharmony_ci}
7425cc1dc7a3Sopenharmony_ci#endif
7426cc1dc7a3Sopenharmony_ci
7427cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_PIC
7428cc1dc7a3Sopenharmony_cistatic int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp)
7429cc1dc7a3Sopenharmony_ci{
7430cc1dc7a3Sopenharmony_ci   int act_comp=0,num_packets=0,chained,dummy;
7431cc1dc7a3Sopenharmony_ci   stbi__pic_packet packets[10];
7432cc1dc7a3Sopenharmony_ci
7433cc1dc7a3Sopenharmony_ci   if (!x) x = &dummy;
7434cc1dc7a3Sopenharmony_ci   if (!y) y = &dummy;
7435cc1dc7a3Sopenharmony_ci   if (!comp) comp = &dummy;
7436cc1dc7a3Sopenharmony_ci
7437cc1dc7a3Sopenharmony_ci   if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) {
7438cc1dc7a3Sopenharmony_ci      stbi__rewind(s);
7439cc1dc7a3Sopenharmony_ci      return 0;
7440cc1dc7a3Sopenharmony_ci   }
7441cc1dc7a3Sopenharmony_ci
7442cc1dc7a3Sopenharmony_ci   stbi__skip(s, 88);
7443cc1dc7a3Sopenharmony_ci
7444cc1dc7a3Sopenharmony_ci   *x = stbi__get16be(s);
7445cc1dc7a3Sopenharmony_ci   *y = stbi__get16be(s);
7446cc1dc7a3Sopenharmony_ci   if (stbi__at_eof(s)) {
7447cc1dc7a3Sopenharmony_ci      stbi__rewind( s);
7448cc1dc7a3Sopenharmony_ci      return 0;
7449cc1dc7a3Sopenharmony_ci   }
7450cc1dc7a3Sopenharmony_ci   if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) {
7451cc1dc7a3Sopenharmony_ci      stbi__rewind( s );
7452cc1dc7a3Sopenharmony_ci      return 0;
7453cc1dc7a3Sopenharmony_ci   }
7454cc1dc7a3Sopenharmony_ci
7455cc1dc7a3Sopenharmony_ci   stbi__skip(s, 8);
7456cc1dc7a3Sopenharmony_ci
7457cc1dc7a3Sopenharmony_ci   do {
7458cc1dc7a3Sopenharmony_ci      stbi__pic_packet *packet;
7459cc1dc7a3Sopenharmony_ci
7460cc1dc7a3Sopenharmony_ci      if (num_packets==sizeof(packets)/sizeof(packets[0]))
7461cc1dc7a3Sopenharmony_ci         return 0;
7462cc1dc7a3Sopenharmony_ci
7463cc1dc7a3Sopenharmony_ci      packet = &packets[num_packets++];
7464cc1dc7a3Sopenharmony_ci      chained = stbi__get8(s);
7465cc1dc7a3Sopenharmony_ci      packet->size    = stbi__get8(s);
7466cc1dc7a3Sopenharmony_ci      packet->type    = stbi__get8(s);
7467cc1dc7a3Sopenharmony_ci      packet->channel = stbi__get8(s);
7468cc1dc7a3Sopenharmony_ci      act_comp |= packet->channel;
7469cc1dc7a3Sopenharmony_ci
7470cc1dc7a3Sopenharmony_ci      if (stbi__at_eof(s)) {
7471cc1dc7a3Sopenharmony_ci          stbi__rewind( s );
7472cc1dc7a3Sopenharmony_ci          return 0;
7473cc1dc7a3Sopenharmony_ci      }
7474cc1dc7a3Sopenharmony_ci      if (packet->size != 8) {
7475cc1dc7a3Sopenharmony_ci          stbi__rewind( s );
7476cc1dc7a3Sopenharmony_ci          return 0;
7477cc1dc7a3Sopenharmony_ci      }
7478cc1dc7a3Sopenharmony_ci   } while (chained);
7479cc1dc7a3Sopenharmony_ci
7480cc1dc7a3Sopenharmony_ci   *comp = (act_comp & 0x10 ? 4 : 3);
7481cc1dc7a3Sopenharmony_ci
7482cc1dc7a3Sopenharmony_ci   return 1;
7483cc1dc7a3Sopenharmony_ci}
7484cc1dc7a3Sopenharmony_ci#endif
7485cc1dc7a3Sopenharmony_ci
7486cc1dc7a3Sopenharmony_ci// *************************************************************************************************
7487cc1dc7a3Sopenharmony_ci// Portable Gray Map and Portable Pixel Map loader
7488cc1dc7a3Sopenharmony_ci// by Ken Miller
7489cc1dc7a3Sopenharmony_ci//
7490cc1dc7a3Sopenharmony_ci// PGM: http://netpbm.sourceforge.net/doc/pgm.html
7491cc1dc7a3Sopenharmony_ci// PPM: http://netpbm.sourceforge.net/doc/ppm.html
7492cc1dc7a3Sopenharmony_ci//
7493cc1dc7a3Sopenharmony_ci// Known limitations:
7494cc1dc7a3Sopenharmony_ci//    Does not support comments in the header section
7495cc1dc7a3Sopenharmony_ci//    Does not support ASCII image data (formats P2 and P3)
7496cc1dc7a3Sopenharmony_ci
7497cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_PNM
7498cc1dc7a3Sopenharmony_ci
7499cc1dc7a3Sopenharmony_cistatic int      stbi__pnm_test(stbi__context *s)
7500cc1dc7a3Sopenharmony_ci{
7501cc1dc7a3Sopenharmony_ci   char p, t;
7502cc1dc7a3Sopenharmony_ci   p = (char) stbi__get8(s);
7503cc1dc7a3Sopenharmony_ci   t = (char) stbi__get8(s);
7504cc1dc7a3Sopenharmony_ci   if (p != 'P' || (t != '5' && t != '6')) {
7505cc1dc7a3Sopenharmony_ci       stbi__rewind( s );
7506cc1dc7a3Sopenharmony_ci       return 0;
7507cc1dc7a3Sopenharmony_ci   }
7508cc1dc7a3Sopenharmony_ci   return 1;
7509cc1dc7a3Sopenharmony_ci}
7510cc1dc7a3Sopenharmony_ci
7511cc1dc7a3Sopenharmony_cistatic void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
7512cc1dc7a3Sopenharmony_ci{
7513cc1dc7a3Sopenharmony_ci   stbi_uc *out;
7514cc1dc7a3Sopenharmony_ci   STBI_NOTUSED(ri);
7515cc1dc7a3Sopenharmony_ci
7516cc1dc7a3Sopenharmony_ci   ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n);
7517cc1dc7a3Sopenharmony_ci   if (ri->bits_per_channel == 0)
7518cc1dc7a3Sopenharmony_ci      return 0;
7519cc1dc7a3Sopenharmony_ci
7520cc1dc7a3Sopenharmony_ci   if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
7521cc1dc7a3Sopenharmony_ci   if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
7522cc1dc7a3Sopenharmony_ci
7523cc1dc7a3Sopenharmony_ci   *x = s->img_x;
7524cc1dc7a3Sopenharmony_ci   *y = s->img_y;
7525cc1dc7a3Sopenharmony_ci   if (comp) *comp = s->img_n;
7526cc1dc7a3Sopenharmony_ci
7527cc1dc7a3Sopenharmony_ci   if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0))
7528cc1dc7a3Sopenharmony_ci      return stbi__errpuc("too large", "PNM too large");
7529cc1dc7a3Sopenharmony_ci
7530cc1dc7a3Sopenharmony_ci   out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0);
7531cc1dc7a3Sopenharmony_ci   if (!out) return stbi__errpuc("outofmem", "Out of memory");
7532cc1dc7a3Sopenharmony_ci   if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) {
7533cc1dc7a3Sopenharmony_ci      STBI_FREE(out);
7534cc1dc7a3Sopenharmony_ci      return stbi__errpuc("bad PNM", "PNM file truncated");
7535cc1dc7a3Sopenharmony_ci   }
7536cc1dc7a3Sopenharmony_ci
7537cc1dc7a3Sopenharmony_ci   if (req_comp && req_comp != s->img_n) {
7538cc1dc7a3Sopenharmony_ci      if (ri->bits_per_channel == 16) {
7539cc1dc7a3Sopenharmony_ci         out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y);
7540cc1dc7a3Sopenharmony_ci      } else {
7541cc1dc7a3Sopenharmony_ci         out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
7542cc1dc7a3Sopenharmony_ci      }
7543cc1dc7a3Sopenharmony_ci      if (out == NULL) return out; // stbi__convert_format frees input on failure
7544cc1dc7a3Sopenharmony_ci   }
7545cc1dc7a3Sopenharmony_ci   return out;
7546cc1dc7a3Sopenharmony_ci}
7547cc1dc7a3Sopenharmony_ci
7548cc1dc7a3Sopenharmony_cistatic int      stbi__pnm_isspace(char c)
7549cc1dc7a3Sopenharmony_ci{
7550cc1dc7a3Sopenharmony_ci   return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
7551cc1dc7a3Sopenharmony_ci}
7552cc1dc7a3Sopenharmony_ci
7553cc1dc7a3Sopenharmony_cistatic void     stbi__pnm_skip_whitespace(stbi__context *s, char *c)
7554cc1dc7a3Sopenharmony_ci{
7555cc1dc7a3Sopenharmony_ci   for (;;) {
7556cc1dc7a3Sopenharmony_ci      while (!stbi__at_eof(s) && stbi__pnm_isspace(*c))
7557cc1dc7a3Sopenharmony_ci         *c = (char) stbi__get8(s);
7558cc1dc7a3Sopenharmony_ci
7559cc1dc7a3Sopenharmony_ci      if (stbi__at_eof(s) || *c != '#')
7560cc1dc7a3Sopenharmony_ci         break;
7561cc1dc7a3Sopenharmony_ci
7562cc1dc7a3Sopenharmony_ci      while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' )
7563cc1dc7a3Sopenharmony_ci         *c = (char) stbi__get8(s);
7564cc1dc7a3Sopenharmony_ci   }
7565cc1dc7a3Sopenharmony_ci}
7566cc1dc7a3Sopenharmony_ci
7567cc1dc7a3Sopenharmony_cistatic int      stbi__pnm_isdigit(char c)
7568cc1dc7a3Sopenharmony_ci{
7569cc1dc7a3Sopenharmony_ci   return c >= '0' && c <= '9';
7570cc1dc7a3Sopenharmony_ci}
7571cc1dc7a3Sopenharmony_ci
7572cc1dc7a3Sopenharmony_cistatic int      stbi__pnm_getinteger(stbi__context *s, char *c)
7573cc1dc7a3Sopenharmony_ci{
7574cc1dc7a3Sopenharmony_ci   int value = 0;
7575cc1dc7a3Sopenharmony_ci
7576cc1dc7a3Sopenharmony_ci   while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) {
7577cc1dc7a3Sopenharmony_ci      value = value*10 + (*c - '0');
7578cc1dc7a3Sopenharmony_ci      *c = (char) stbi__get8(s);
7579cc1dc7a3Sopenharmony_ci      if((value > 214748364) || (value == 214748364 && *c > '7'))
7580cc1dc7a3Sopenharmony_ci          return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int");
7581cc1dc7a3Sopenharmony_ci   }
7582cc1dc7a3Sopenharmony_ci
7583cc1dc7a3Sopenharmony_ci   return value;
7584cc1dc7a3Sopenharmony_ci}
7585cc1dc7a3Sopenharmony_ci
7586cc1dc7a3Sopenharmony_cistatic int      stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp)
7587cc1dc7a3Sopenharmony_ci{
7588cc1dc7a3Sopenharmony_ci   int maxv, dummy;
7589cc1dc7a3Sopenharmony_ci   char c, p, t;
7590cc1dc7a3Sopenharmony_ci
7591cc1dc7a3Sopenharmony_ci   if (!x) x = &dummy;
7592cc1dc7a3Sopenharmony_ci   if (!y) y = &dummy;
7593cc1dc7a3Sopenharmony_ci   if (!comp) comp = &dummy;
7594cc1dc7a3Sopenharmony_ci
7595cc1dc7a3Sopenharmony_ci   stbi__rewind(s);
7596cc1dc7a3Sopenharmony_ci
7597cc1dc7a3Sopenharmony_ci   // Get identifier
7598cc1dc7a3Sopenharmony_ci   p = (char) stbi__get8(s);
7599cc1dc7a3Sopenharmony_ci   t = (char) stbi__get8(s);
7600cc1dc7a3Sopenharmony_ci   if (p != 'P' || (t != '5' && t != '6')) {
7601cc1dc7a3Sopenharmony_ci       stbi__rewind(s);
7602cc1dc7a3Sopenharmony_ci       return 0;
7603cc1dc7a3Sopenharmony_ci   }
7604cc1dc7a3Sopenharmony_ci
7605cc1dc7a3Sopenharmony_ci   *comp = (t == '6') ? 3 : 1;  // '5' is 1-component .pgm; '6' is 3-component .ppm
7606cc1dc7a3Sopenharmony_ci
7607cc1dc7a3Sopenharmony_ci   c = (char) stbi__get8(s);
7608cc1dc7a3Sopenharmony_ci   stbi__pnm_skip_whitespace(s, &c);
7609cc1dc7a3Sopenharmony_ci
7610cc1dc7a3Sopenharmony_ci   *x = stbi__pnm_getinteger(s, &c); // read width
7611cc1dc7a3Sopenharmony_ci   if(*x == 0)
7612cc1dc7a3Sopenharmony_ci       return stbi__err("invalid width", "PPM image header had zero or overflowing width");
7613cc1dc7a3Sopenharmony_ci   stbi__pnm_skip_whitespace(s, &c);
7614cc1dc7a3Sopenharmony_ci
7615cc1dc7a3Sopenharmony_ci   *y = stbi__pnm_getinteger(s, &c); // read height
7616cc1dc7a3Sopenharmony_ci   if (*y == 0)
7617cc1dc7a3Sopenharmony_ci       return stbi__err("invalid width", "PPM image header had zero or overflowing width");
7618cc1dc7a3Sopenharmony_ci   stbi__pnm_skip_whitespace(s, &c);
7619cc1dc7a3Sopenharmony_ci
7620cc1dc7a3Sopenharmony_ci   maxv = stbi__pnm_getinteger(s, &c);  // read max value
7621cc1dc7a3Sopenharmony_ci   if (maxv > 65535)
7622cc1dc7a3Sopenharmony_ci      return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images");
7623cc1dc7a3Sopenharmony_ci   else if (maxv > 255)
7624cc1dc7a3Sopenharmony_ci      return 16;
7625cc1dc7a3Sopenharmony_ci   else
7626cc1dc7a3Sopenharmony_ci      return 8;
7627cc1dc7a3Sopenharmony_ci}
7628cc1dc7a3Sopenharmony_ci
7629cc1dc7a3Sopenharmony_cistatic int stbi__pnm_is16(stbi__context *s)
7630cc1dc7a3Sopenharmony_ci{
7631cc1dc7a3Sopenharmony_ci   if (stbi__pnm_info(s, NULL, NULL, NULL) == 16)
7632cc1dc7a3Sopenharmony_ci	   return 1;
7633cc1dc7a3Sopenharmony_ci   return 0;
7634cc1dc7a3Sopenharmony_ci}
7635cc1dc7a3Sopenharmony_ci#endif
7636cc1dc7a3Sopenharmony_ci
7637cc1dc7a3Sopenharmony_cistatic int stbi__info_main(stbi__context *s, int *x, int *y, int *comp)
7638cc1dc7a3Sopenharmony_ci{
7639cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_JPEG
7640cc1dc7a3Sopenharmony_ci   if (stbi__jpeg_info(s, x, y, comp)) return 1;
7641cc1dc7a3Sopenharmony_ci   #endif
7642cc1dc7a3Sopenharmony_ci
7643cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_PNG
7644cc1dc7a3Sopenharmony_ci   if (stbi__png_info(s, x, y, comp))  return 1;
7645cc1dc7a3Sopenharmony_ci   #endif
7646cc1dc7a3Sopenharmony_ci
7647cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_GIF
7648cc1dc7a3Sopenharmony_ci   if (stbi__gif_info(s, x, y, comp))  return 1;
7649cc1dc7a3Sopenharmony_ci   #endif
7650cc1dc7a3Sopenharmony_ci
7651cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_BMP
7652cc1dc7a3Sopenharmony_ci   if (stbi__bmp_info(s, x, y, comp))  return 1;
7653cc1dc7a3Sopenharmony_ci   #endif
7654cc1dc7a3Sopenharmony_ci
7655cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_PSD
7656cc1dc7a3Sopenharmony_ci   if (stbi__psd_info(s, x, y, comp))  return 1;
7657cc1dc7a3Sopenharmony_ci   #endif
7658cc1dc7a3Sopenharmony_ci
7659cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_PIC
7660cc1dc7a3Sopenharmony_ci   if (stbi__pic_info(s, x, y, comp))  return 1;
7661cc1dc7a3Sopenharmony_ci   #endif
7662cc1dc7a3Sopenharmony_ci
7663cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_PNM
7664cc1dc7a3Sopenharmony_ci   if (stbi__pnm_info(s, x, y, comp))  return 1;
7665cc1dc7a3Sopenharmony_ci   #endif
7666cc1dc7a3Sopenharmony_ci
7667cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_HDR
7668cc1dc7a3Sopenharmony_ci   if (stbi__hdr_info(s, x, y, comp))  return 1;
7669cc1dc7a3Sopenharmony_ci   #endif
7670cc1dc7a3Sopenharmony_ci
7671cc1dc7a3Sopenharmony_ci   // test tga last because it's a crappy test!
7672cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_TGA
7673cc1dc7a3Sopenharmony_ci   if (stbi__tga_info(s, x, y, comp))
7674cc1dc7a3Sopenharmony_ci       return 1;
7675cc1dc7a3Sopenharmony_ci   #endif
7676cc1dc7a3Sopenharmony_ci   return stbi__err("unknown image type", "Image not of any known type, or corrupt");
7677cc1dc7a3Sopenharmony_ci}
7678cc1dc7a3Sopenharmony_ci
7679cc1dc7a3Sopenharmony_cistatic int stbi__is_16_main(stbi__context *s)
7680cc1dc7a3Sopenharmony_ci{
7681cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_PNG
7682cc1dc7a3Sopenharmony_ci   if (stbi__png_is16(s))  return 1;
7683cc1dc7a3Sopenharmony_ci   #endif
7684cc1dc7a3Sopenharmony_ci
7685cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_PSD
7686cc1dc7a3Sopenharmony_ci   if (stbi__psd_is16(s))  return 1;
7687cc1dc7a3Sopenharmony_ci   #endif
7688cc1dc7a3Sopenharmony_ci
7689cc1dc7a3Sopenharmony_ci   #ifndef STBI_NO_PNM
7690cc1dc7a3Sopenharmony_ci   if (stbi__pnm_is16(s))  return 1;
7691cc1dc7a3Sopenharmony_ci   #endif
7692cc1dc7a3Sopenharmony_ci   return 0;
7693cc1dc7a3Sopenharmony_ci}
7694cc1dc7a3Sopenharmony_ci
7695cc1dc7a3Sopenharmony_ci#ifndef STBI_NO_STDIO
7696cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp)
7697cc1dc7a3Sopenharmony_ci{
7698cc1dc7a3Sopenharmony_ci    FILE *f = stbi__fopen(filename, "rb");
7699cc1dc7a3Sopenharmony_ci    int result;
7700cc1dc7a3Sopenharmony_ci    if (!f) return stbi__err("can't fopen", "Unable to open file");
7701cc1dc7a3Sopenharmony_ci    result = stbi_info_from_file(f, x, y, comp);
7702cc1dc7a3Sopenharmony_ci    fclose(f);
7703cc1dc7a3Sopenharmony_ci    return result;
7704cc1dc7a3Sopenharmony_ci}
7705cc1dc7a3Sopenharmony_ci
7706cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp)
7707cc1dc7a3Sopenharmony_ci{
7708cc1dc7a3Sopenharmony_ci   int r;
7709cc1dc7a3Sopenharmony_ci   stbi__context s;
7710cc1dc7a3Sopenharmony_ci   long pos = ftell(f);
7711cc1dc7a3Sopenharmony_ci   stbi__start_file(&s, f);
7712cc1dc7a3Sopenharmony_ci   r = stbi__info_main(&s,x,y,comp);
7713cc1dc7a3Sopenharmony_ci   fseek(f,pos,SEEK_SET);
7714cc1dc7a3Sopenharmony_ci   return r;
7715cc1dc7a3Sopenharmony_ci}
7716cc1dc7a3Sopenharmony_ci
7717cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_is_16_bit(char const *filename)
7718cc1dc7a3Sopenharmony_ci{
7719cc1dc7a3Sopenharmony_ci    FILE *f = stbi__fopen(filename, "rb");
7720cc1dc7a3Sopenharmony_ci    int result;
7721cc1dc7a3Sopenharmony_ci    if (!f) return stbi__err("can't fopen", "Unable to open file");
7722cc1dc7a3Sopenharmony_ci    result = stbi_is_16_bit_from_file(f);
7723cc1dc7a3Sopenharmony_ci    fclose(f);
7724cc1dc7a3Sopenharmony_ci    return result;
7725cc1dc7a3Sopenharmony_ci}
7726cc1dc7a3Sopenharmony_ci
7727cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_is_16_bit_from_file(FILE *f)
7728cc1dc7a3Sopenharmony_ci{
7729cc1dc7a3Sopenharmony_ci   int r;
7730cc1dc7a3Sopenharmony_ci   stbi__context s;
7731cc1dc7a3Sopenharmony_ci   long pos = ftell(f);
7732cc1dc7a3Sopenharmony_ci   stbi__start_file(&s, f);
7733cc1dc7a3Sopenharmony_ci   r = stbi__is_16_main(&s);
7734cc1dc7a3Sopenharmony_ci   fseek(f,pos,SEEK_SET);
7735cc1dc7a3Sopenharmony_ci   return r;
7736cc1dc7a3Sopenharmony_ci}
7737cc1dc7a3Sopenharmony_ci#endif // !STBI_NO_STDIO
7738cc1dc7a3Sopenharmony_ci
7739cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp)
7740cc1dc7a3Sopenharmony_ci{
7741cc1dc7a3Sopenharmony_ci   stbi__context s;
7742cc1dc7a3Sopenharmony_ci   stbi__start_mem(&s,buffer,len);
7743cc1dc7a3Sopenharmony_ci   return stbi__info_main(&s,x,y,comp);
7744cc1dc7a3Sopenharmony_ci}
7745cc1dc7a3Sopenharmony_ci
7746cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp)
7747cc1dc7a3Sopenharmony_ci{
7748cc1dc7a3Sopenharmony_ci   stbi__context s;
7749cc1dc7a3Sopenharmony_ci   stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);
7750cc1dc7a3Sopenharmony_ci   return stbi__info_main(&s,x,y,comp);
7751cc1dc7a3Sopenharmony_ci}
7752cc1dc7a3Sopenharmony_ci
7753cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len)
7754cc1dc7a3Sopenharmony_ci{
7755cc1dc7a3Sopenharmony_ci   stbi__context s;
7756cc1dc7a3Sopenharmony_ci   stbi__start_mem(&s,buffer,len);
7757cc1dc7a3Sopenharmony_ci   return stbi__is_16_main(&s);
7758cc1dc7a3Sopenharmony_ci}
7759cc1dc7a3Sopenharmony_ci
7760cc1dc7a3Sopenharmony_ciSTBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user)
7761cc1dc7a3Sopenharmony_ci{
7762cc1dc7a3Sopenharmony_ci   stbi__context s;
7763cc1dc7a3Sopenharmony_ci   stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);
7764cc1dc7a3Sopenharmony_ci   return stbi__is_16_main(&s);
7765cc1dc7a3Sopenharmony_ci}
7766cc1dc7a3Sopenharmony_ci
7767cc1dc7a3Sopenharmony_ci#endif // STB_IMAGE_IMPLEMENTATION
7768cc1dc7a3Sopenharmony_ci
7769cc1dc7a3Sopenharmony_ci/*
7770cc1dc7a3Sopenharmony_ci   revision history:
7771cc1dc7a3Sopenharmony_ci      2.20  (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs
7772cc1dc7a3Sopenharmony_ci      2.19  (2018-02-11) fix warning
7773cc1dc7a3Sopenharmony_ci      2.18  (2018-01-30) fix warnings
7774cc1dc7a3Sopenharmony_ci      2.17  (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug
7775cc1dc7a3Sopenharmony_ci                         1-bit BMP
7776cc1dc7a3Sopenharmony_ci                         *_is_16_bit api
7777cc1dc7a3Sopenharmony_ci                         avoid warnings
7778cc1dc7a3Sopenharmony_ci      2.16  (2017-07-23) all functions have 16-bit variants;
7779cc1dc7a3Sopenharmony_ci                         STBI_NO_STDIO works again;
7780cc1dc7a3Sopenharmony_ci                         compilation fixes;
7781cc1dc7a3Sopenharmony_ci                         fix rounding in unpremultiply;
7782cc1dc7a3Sopenharmony_ci                         optimize vertical flip;
7783cc1dc7a3Sopenharmony_ci                         disable raw_len validation;
7784cc1dc7a3Sopenharmony_ci                         documentation fixes
7785cc1dc7a3Sopenharmony_ci      2.15  (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode;
7786cc1dc7a3Sopenharmony_ci                         warning fixes; disable run-time SSE detection on gcc;
7787cc1dc7a3Sopenharmony_ci                         uniform handling of optional "return" values;
7788cc1dc7a3Sopenharmony_ci                         thread-safe initialization of zlib tables
7789cc1dc7a3Sopenharmony_ci      2.14  (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
7790cc1dc7a3Sopenharmony_ci      2.13  (2016-11-29) add 16-bit API, only supported for PNG right now
7791cc1dc7a3Sopenharmony_ci      2.12  (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
7792cc1dc7a3Sopenharmony_ci      2.11  (2016-04-02) allocate large structures on the stack
7793cc1dc7a3Sopenharmony_ci                         remove white matting for transparent PSD
7794cc1dc7a3Sopenharmony_ci                         fix reported channel count for PNG & BMP
7795cc1dc7a3Sopenharmony_ci                         re-enable SSE2 in non-gcc 64-bit
7796cc1dc7a3Sopenharmony_ci                         support RGB-formatted JPEG
7797cc1dc7a3Sopenharmony_ci                         read 16-bit PNGs (only as 8-bit)
7798cc1dc7a3Sopenharmony_ci      2.10  (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED
7799cc1dc7a3Sopenharmony_ci      2.09  (2016-01-16) allow comments in PNM files
7800cc1dc7a3Sopenharmony_ci                         16-bit-per-pixel TGA (not bit-per-component)
7801cc1dc7a3Sopenharmony_ci                         info() for TGA could break due to .hdr handling
7802cc1dc7a3Sopenharmony_ci                         info() for BMP to shares code instead of sloppy parse
7803cc1dc7a3Sopenharmony_ci                         can use STBI_REALLOC_SIZED if allocator doesn't support realloc
7804cc1dc7a3Sopenharmony_ci                         code cleanup
7805cc1dc7a3Sopenharmony_ci      2.08  (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
7806cc1dc7a3Sopenharmony_ci      2.07  (2015-09-13) fix compiler warnings
7807cc1dc7a3Sopenharmony_ci                         partial animated GIF support
7808cc1dc7a3Sopenharmony_ci                         limited 16-bpc PSD support
7809cc1dc7a3Sopenharmony_ci                         #ifdef unused functions
7810cc1dc7a3Sopenharmony_ci                         bug with < 92 byte PIC,PNM,HDR,TGA
7811cc1dc7a3Sopenharmony_ci      2.06  (2015-04-19) fix bug where PSD returns wrong '*comp' value
7812cc1dc7a3Sopenharmony_ci      2.05  (2015-04-19) fix bug in progressive JPEG handling, fix warning
7813cc1dc7a3Sopenharmony_ci      2.04  (2015-04-15) try to re-enable SIMD on MinGW 64-bit
7814cc1dc7a3Sopenharmony_ci      2.03  (2015-04-12) extra corruption checking (mmozeiko)
7815cc1dc7a3Sopenharmony_ci                         stbi_set_flip_vertically_on_load (nguillemot)
7816cc1dc7a3Sopenharmony_ci                         fix NEON support; fix mingw support
7817cc1dc7a3Sopenharmony_ci      2.02  (2015-01-19) fix incorrect assert, fix warning
7818cc1dc7a3Sopenharmony_ci      2.01  (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2
7819cc1dc7a3Sopenharmony_ci      2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG
7820cc1dc7a3Sopenharmony_ci      2.00  (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg)
7821cc1dc7a3Sopenharmony_ci                         progressive JPEG (stb)
7822cc1dc7a3Sopenharmony_ci                         PGM/PPM support (Ken Miller)
7823cc1dc7a3Sopenharmony_ci                         STBI_MALLOC,STBI_REALLOC,STBI_FREE
7824cc1dc7a3Sopenharmony_ci                         GIF bugfix -- seemingly never worked
7825cc1dc7a3Sopenharmony_ci                         STBI_NO_*, STBI_ONLY_*
7826cc1dc7a3Sopenharmony_ci      1.48  (2014-12-14) fix incorrectly-named assert()
7827cc1dc7a3Sopenharmony_ci      1.47  (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb)
7828cc1dc7a3Sopenharmony_ci                         optimize PNG (ryg)
7829cc1dc7a3Sopenharmony_ci                         fix bug in interlaced PNG with user-specified channel count (stb)
7830cc1dc7a3Sopenharmony_ci      1.46  (2014-08-26)
7831cc1dc7a3Sopenharmony_ci              fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG
7832cc1dc7a3Sopenharmony_ci      1.45  (2014-08-16)
7833cc1dc7a3Sopenharmony_ci              fix MSVC-ARM internal compiler error by wrapping malloc
7834cc1dc7a3Sopenharmony_ci      1.44  (2014-08-07)
7835cc1dc7a3Sopenharmony_ci              various warning fixes from Ronny Chevalier
7836cc1dc7a3Sopenharmony_ci      1.43  (2014-07-15)
7837cc1dc7a3Sopenharmony_ci              fix MSVC-only compiler problem in code changed in 1.42
7838cc1dc7a3Sopenharmony_ci      1.42  (2014-07-09)
7839cc1dc7a3Sopenharmony_ci              don't define _CRT_SECURE_NO_WARNINGS (affects user code)
7840cc1dc7a3Sopenharmony_ci              fixes to stbi__cleanup_jpeg path
7841cc1dc7a3Sopenharmony_ci              added STBI_ASSERT to avoid requiring assert.h
7842cc1dc7a3Sopenharmony_ci      1.41  (2014-06-25)
7843cc1dc7a3Sopenharmony_ci              fix search&replace from 1.36 that messed up comments/error messages
7844cc1dc7a3Sopenharmony_ci      1.40  (2014-06-22)
7845cc1dc7a3Sopenharmony_ci              fix gcc struct-initialization warning
7846cc1dc7a3Sopenharmony_ci      1.39  (2014-06-15)
7847cc1dc7a3Sopenharmony_ci              fix to TGA optimization when req_comp != number of components in TGA;
7848cc1dc7a3Sopenharmony_ci              fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite)
7849cc1dc7a3Sopenharmony_ci              add support for BMP version 5 (more ignored fields)
7850cc1dc7a3Sopenharmony_ci      1.38  (2014-06-06)
7851cc1dc7a3Sopenharmony_ci              suppress MSVC warnings on integer casts truncating values
7852cc1dc7a3Sopenharmony_ci              fix accidental rename of 'skip' field of I/O
7853cc1dc7a3Sopenharmony_ci      1.37  (2014-06-04)
7854cc1dc7a3Sopenharmony_ci              remove duplicate typedef
7855cc1dc7a3Sopenharmony_ci      1.36  (2014-06-03)
7856cc1dc7a3Sopenharmony_ci              convert to header file single-file library
7857cc1dc7a3Sopenharmony_ci              if de-iphone isn't set, load iphone images color-swapped instead of returning NULL
7858cc1dc7a3Sopenharmony_ci      1.35  (2014-05-27)
7859cc1dc7a3Sopenharmony_ci              various warnings
7860cc1dc7a3Sopenharmony_ci              fix broken STBI_SIMD path
7861cc1dc7a3Sopenharmony_ci              fix bug where stbi_load_from_file no longer left file pointer in correct place
7862cc1dc7a3Sopenharmony_ci              fix broken non-easy path for 32-bit BMP (possibly never used)
7863cc1dc7a3Sopenharmony_ci              TGA optimization by Arseny Kapoulkine
7864cc1dc7a3Sopenharmony_ci      1.34  (unknown)
7865cc1dc7a3Sopenharmony_ci              use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case
7866cc1dc7a3Sopenharmony_ci      1.33  (2011-07-14)
7867cc1dc7a3Sopenharmony_ci              make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements
7868cc1dc7a3Sopenharmony_ci      1.32  (2011-07-13)
7869cc1dc7a3Sopenharmony_ci              support for "info" function for all supported filetypes (SpartanJ)
7870cc1dc7a3Sopenharmony_ci      1.31  (2011-06-20)
7871cc1dc7a3Sopenharmony_ci              a few more leak fixes, bug in PNG handling (SpartanJ)
7872cc1dc7a3Sopenharmony_ci      1.30  (2011-06-11)
7873cc1dc7a3Sopenharmony_ci              added ability to load files via callbacks to accomidate custom input streams (Ben Wenger)
7874cc1dc7a3Sopenharmony_ci              removed deprecated format-specific test/load functions
7875cc1dc7a3Sopenharmony_ci              removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway
7876cc1dc7a3Sopenharmony_ci              error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha)
7877cc1dc7a3Sopenharmony_ci              fix inefficiency in decoding 32-bit BMP (David Woo)
7878cc1dc7a3Sopenharmony_ci      1.29  (2010-08-16)
7879cc1dc7a3Sopenharmony_ci              various warning fixes from Aurelien Pocheville
7880cc1dc7a3Sopenharmony_ci      1.28  (2010-08-01)
7881cc1dc7a3Sopenharmony_ci              fix bug in GIF palette transparency (SpartanJ)
7882cc1dc7a3Sopenharmony_ci      1.27  (2010-08-01)
7883cc1dc7a3Sopenharmony_ci              cast-to-stbi_uc to fix warnings
7884cc1dc7a3Sopenharmony_ci      1.26  (2010-07-24)
7885cc1dc7a3Sopenharmony_ci              fix bug in file buffering for PNG reported by SpartanJ
7886cc1dc7a3Sopenharmony_ci      1.25  (2010-07-17)
7887cc1dc7a3Sopenharmony_ci              refix trans_data warning (Won Chun)
7888cc1dc7a3Sopenharmony_ci      1.24  (2010-07-12)
7889cc1dc7a3Sopenharmony_ci              perf improvements reading from files on platforms with lock-heavy fgetc()
7890cc1dc7a3Sopenharmony_ci              minor perf improvements for jpeg
7891cc1dc7a3Sopenharmony_ci              deprecated type-specific functions so we'll get feedback if they're needed
7892cc1dc7a3Sopenharmony_ci              attempt to fix trans_data warning (Won Chun)
7893cc1dc7a3Sopenharmony_ci      1.23    fixed bug in iPhone support
7894cc1dc7a3Sopenharmony_ci      1.22  (2010-07-10)
7895cc1dc7a3Sopenharmony_ci              removed image *writing* support
7896cc1dc7a3Sopenharmony_ci              stbi_info support from Jetro Lauha
7897cc1dc7a3Sopenharmony_ci              GIF support from Jean-Marc Lienher
7898cc1dc7a3Sopenharmony_ci              iPhone PNG-extensions from James Brown
7899cc1dc7a3Sopenharmony_ci              warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva)
7900cc1dc7a3Sopenharmony_ci      1.21    fix use of 'stbi_uc' in header (reported by jon blow)
7901cc1dc7a3Sopenharmony_ci      1.20    added support for Softimage PIC, by Tom Seddon
7902cc1dc7a3Sopenharmony_ci      1.19    bug in interlaced PNG corruption check (found by ryg)
7903cc1dc7a3Sopenharmony_ci      1.18  (2008-08-02)
7904cc1dc7a3Sopenharmony_ci              fix a threading bug (local mutable static)
7905cc1dc7a3Sopenharmony_ci      1.17    support interlaced PNG
7906cc1dc7a3Sopenharmony_ci      1.16    major bugfix - stbi__convert_format converted one too many pixels
7907cc1dc7a3Sopenharmony_ci      1.15    initialize some fields for thread safety
7908cc1dc7a3Sopenharmony_ci      1.14    fix threadsafe conversion bug
7909cc1dc7a3Sopenharmony_ci              header-file-only version (#define STBI_HEADER_FILE_ONLY before including)
7910cc1dc7a3Sopenharmony_ci      1.13    threadsafe
7911cc1dc7a3Sopenharmony_ci      1.12    const qualifiers in the API
7912cc1dc7a3Sopenharmony_ci      1.11    Support installable IDCT, colorspace conversion routines
7913cc1dc7a3Sopenharmony_ci      1.10    Fixes for 64-bit (don't use "unsigned long")
7914cc1dc7a3Sopenharmony_ci              optimized upsampling by Fabian "ryg" Giesen
7915cc1dc7a3Sopenharmony_ci      1.09    Fix format-conversion for PSD code (bad global variables!)
7916cc1dc7a3Sopenharmony_ci      1.08    Thatcher Ulrich's PSD code integrated by Nicolas Schulz
7917cc1dc7a3Sopenharmony_ci      1.07    attempt to fix C++ warning/errors again
7918cc1dc7a3Sopenharmony_ci      1.06    attempt to fix C++ warning/errors again
7919cc1dc7a3Sopenharmony_ci      1.05    fix TGA loading to return correct *comp and use good luminance calc
7920cc1dc7a3Sopenharmony_ci      1.04    default float alpha is 1, not 255; use 'void *' for stbi_image_free
7921cc1dc7a3Sopenharmony_ci      1.03    bugfixes to STBI_NO_STDIO, STBI_NO_HDR
7922cc1dc7a3Sopenharmony_ci      1.02    support for (subset of) HDR files, float interface for preferred access to them
7923cc1dc7a3Sopenharmony_ci      1.01    fix bug: possible bug in handling right-side up bmps... not sure
7924cc1dc7a3Sopenharmony_ci              fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all
7925cc1dc7a3Sopenharmony_ci      1.00    interface to zlib that skips zlib header
7926cc1dc7a3Sopenharmony_ci      0.99    correct handling of alpha in palette
7927cc1dc7a3Sopenharmony_ci      0.98    TGA loader by lonesock; dynamically add loaders (untested)
7928cc1dc7a3Sopenharmony_ci      0.97    jpeg errors on too large a file; also catch another malloc failure
7929cc1dc7a3Sopenharmony_ci      0.96    fix detection of invalid v value - particleman@mollyrocket forum
7930cc1dc7a3Sopenharmony_ci      0.95    during header scan, seek to markers in case of padding
7931cc1dc7a3Sopenharmony_ci      0.94    STBI_NO_STDIO to disable stdio usage; rename all #defines the same
7932cc1dc7a3Sopenharmony_ci      0.93    handle jpegtran output; verbose errors
7933cc1dc7a3Sopenharmony_ci      0.92    read 4,8,16,24,32-bit BMP files of several formats
7934cc1dc7a3Sopenharmony_ci      0.91    output 24-bit Windows 3.0 BMP files
7935cc1dc7a3Sopenharmony_ci      0.90    fix a few more warnings; bump version number to approach 1.0
7936cc1dc7a3Sopenharmony_ci      0.61    bugfixes due to Marc LeBlanc, Christopher Lloyd
7937cc1dc7a3Sopenharmony_ci      0.60    fix compiling as c++
7938cc1dc7a3Sopenharmony_ci      0.59    fix warnings: merge Dave Moore's -Wall fixes
7939cc1dc7a3Sopenharmony_ci      0.58    fix bug: zlib uncompressed mode len/nlen was wrong endian
7940cc1dc7a3Sopenharmony_ci      0.57    fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available
7941cc1dc7a3Sopenharmony_ci      0.56    fix bug: zlib uncompressed mode len vs. nlen
7942cc1dc7a3Sopenharmony_ci      0.55    fix bug: restart_interval not initialized to 0
7943cc1dc7a3Sopenharmony_ci      0.54    allow NULL for 'int *comp'
7944cc1dc7a3Sopenharmony_ci      0.53    fix bug in png 3->4; speedup png decoding
7945cc1dc7a3Sopenharmony_ci      0.52    png handles req_comp=3,4 directly; minor cleanup; jpeg comments
7946cc1dc7a3Sopenharmony_ci      0.51    obey req_comp requests, 1-component jpegs return as 1-component,
7947cc1dc7a3Sopenharmony_ci              on 'test' only check type, not whether we support this variant
7948cc1dc7a3Sopenharmony_ci      0.50  (2006-11-19)
7949cc1dc7a3Sopenharmony_ci              first released version
7950cc1dc7a3Sopenharmony_ci*/
7951cc1dc7a3Sopenharmony_ci
7952cc1dc7a3Sopenharmony_ci
7953cc1dc7a3Sopenharmony_ci/*
7954cc1dc7a3Sopenharmony_ci------------------------------------------------------------------------------
7955cc1dc7a3Sopenharmony_ciThis software is available under 2 licenses -- choose whichever you prefer.
7956cc1dc7a3Sopenharmony_ci------------------------------------------------------------------------------
7957cc1dc7a3Sopenharmony_ciALTERNATIVE A - MIT License
7958cc1dc7a3Sopenharmony_ciCopyright (c) 2017 Sean Barrett
7959cc1dc7a3Sopenharmony_ciPermission is hereby granted, free of charge, to any person obtaining a copy of
7960cc1dc7a3Sopenharmony_cithis software and associated documentation files (the "Software"), to deal in
7961cc1dc7a3Sopenharmony_cithe Software without restriction, including without limitation the rights to
7962cc1dc7a3Sopenharmony_ciuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7963cc1dc7a3Sopenharmony_ciof the Software, and to permit persons to whom the Software is furnished to do
7964cc1dc7a3Sopenharmony_ciso, subject to the following conditions:
7965cc1dc7a3Sopenharmony_ciThe above copyright notice and this permission notice shall be included in all
7966cc1dc7a3Sopenharmony_cicopies or substantial portions of the Software.
7967cc1dc7a3Sopenharmony_ciTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
7968cc1dc7a3Sopenharmony_ciIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
7969cc1dc7a3Sopenharmony_ciFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7970cc1dc7a3Sopenharmony_ciAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
7971cc1dc7a3Sopenharmony_ciLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
7972cc1dc7a3Sopenharmony_ciOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
7973cc1dc7a3Sopenharmony_ciSOFTWARE.
7974cc1dc7a3Sopenharmony_ci------------------------------------------------------------------------------
7975cc1dc7a3Sopenharmony_ciALTERNATIVE B - Public Domain (www.unlicense.org)
7976cc1dc7a3Sopenharmony_ciThis is free and unencumbered software released into the public domain.
7977cc1dc7a3Sopenharmony_ciAnyone is free to copy, modify, publish, use, compile, sell, or distribute this
7978cc1dc7a3Sopenharmony_cisoftware, either in source code form or as a compiled binary, for any purpose,
7979cc1dc7a3Sopenharmony_cicommercial or non-commercial, and by any means.
7980cc1dc7a3Sopenharmony_ciIn jurisdictions that recognize copyright laws, the author or authors of this
7981cc1dc7a3Sopenharmony_cisoftware dedicate any and all copyright interest in the software to the public
7982cc1dc7a3Sopenharmony_cidomain. We make this dedication for the benefit of the public at large and to
7983cc1dc7a3Sopenharmony_cithe detriment of our heirs and successors. We intend this dedication to be an
7984cc1dc7a3Sopenharmony_ciovert act of relinquishment in perpetuity of all present and future rights to
7985cc1dc7a3Sopenharmony_cithis software under copyright law.
7986cc1dc7a3Sopenharmony_ciTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
7987cc1dc7a3Sopenharmony_ciIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
7988cc1dc7a3Sopenharmony_ciFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7989cc1dc7a3Sopenharmony_ciAUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
7990cc1dc7a3Sopenharmony_ciACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
7991cc1dc7a3Sopenharmony_ciWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7992cc1dc7a3Sopenharmony_ci------------------------------------------------------------------------------
7993cc1dc7a3Sopenharmony_ci*/
7994