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