xref: /aosp_15_r20/external/armnn/third-party/stb/stb_image_write.h (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright (c) 2017 Sean Barrett
3*89c4ff92SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
4*89c4ff92SAndroid Build Coastguard Worker //
5*89c4ff92SAndroid Build Coastguard Worker 
6*89c4ff92SAndroid Build Coastguard Worker /* stb_image_write - v1.06 - public domain - http://nothings.org/stb/stb_image_write.h
7*89c4ff92SAndroid Build Coastguard Worker    writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
8*89c4ff92SAndroid Build Coastguard Worker                                      no warranty implied; use at your own risk
9*89c4ff92SAndroid Build Coastguard Worker 
10*89c4ff92SAndroid Build Coastguard Worker    Before #including,
11*89c4ff92SAndroid Build Coastguard Worker 
12*89c4ff92SAndroid Build Coastguard Worker        #define STB_IMAGE_WRITE_IMPLEMENTATION
13*89c4ff92SAndroid Build Coastguard Worker 
14*89c4ff92SAndroid Build Coastguard Worker    in the file that you want to have the implementation.
15*89c4ff92SAndroid Build Coastguard Worker 
16*89c4ff92SAndroid Build Coastguard Worker    Will probably not work correctly with strict-aliasing optimizations.
17*89c4ff92SAndroid Build Coastguard Worker 
18*89c4ff92SAndroid Build Coastguard Worker ABOUT:
19*89c4ff92SAndroid Build Coastguard Worker 
20*89c4ff92SAndroid Build Coastguard Worker    This header file is a library for writing images to C stdio. It could be
21*89c4ff92SAndroid Build Coastguard Worker    adapted to write to memory or a general streaming interface; let me know.
22*89c4ff92SAndroid Build Coastguard Worker 
23*89c4ff92SAndroid Build Coastguard Worker    The PNG output is not optimal; it is 20-50% larger than the file
24*89c4ff92SAndroid Build Coastguard Worker    written by a decent optimizing implementation. This library is designed
25*89c4ff92SAndroid Build Coastguard Worker    for source code compactness and simplicity, not optimal image file size
26*89c4ff92SAndroid Build Coastguard Worker    or run-time performance.
27*89c4ff92SAndroid Build Coastguard Worker 
28*89c4ff92SAndroid Build Coastguard Worker BUILDING:
29*89c4ff92SAndroid Build Coastguard Worker 
30*89c4ff92SAndroid Build Coastguard Worker    You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
31*89c4ff92SAndroid Build Coastguard Worker    You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
32*89c4ff92SAndroid Build Coastguard Worker    malloc,realloc,free.
33*89c4ff92SAndroid Build Coastguard Worker    You can define STBIW_MEMMOVE() to replace memmove()
34*89c4ff92SAndroid Build Coastguard Worker 
35*89c4ff92SAndroid Build Coastguard Worker USAGE:
36*89c4ff92SAndroid Build Coastguard Worker 
37*89c4ff92SAndroid Build Coastguard Worker    There are four functions, one for each image file format:
38*89c4ff92SAndroid Build Coastguard Worker 
39*89c4ff92SAndroid Build Coastguard Worker      int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
40*89c4ff92SAndroid Build Coastguard Worker      int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
41*89c4ff92SAndroid Build Coastguard Worker      int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
42*89c4ff92SAndroid Build Coastguard Worker      int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
43*89c4ff92SAndroid Build Coastguard Worker      int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
44*89c4ff92SAndroid Build Coastguard Worker 
45*89c4ff92SAndroid Build Coastguard Worker    There are also four equivalent functions that use an arbitrary write function. You are
46*89c4ff92SAndroid Build Coastguard Worker    expected to open/close your file-equivalent before and after calling these:
47*89c4ff92SAndroid Build Coastguard Worker 
48*89c4ff92SAndroid Build Coastguard Worker      int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data, int stride_in_bytes);
49*89c4ff92SAndroid Build Coastguard Worker      int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
50*89c4ff92SAndroid Build Coastguard Worker      int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
51*89c4ff92SAndroid Build Coastguard Worker      int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
52*89c4ff92SAndroid Build Coastguard Worker      int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
53*89c4ff92SAndroid Build Coastguard Worker 
54*89c4ff92SAndroid Build Coastguard Worker    where the callback is:
55*89c4ff92SAndroid Build Coastguard Worker       void stbi_write_func(void *context, void *data, int size);
56*89c4ff92SAndroid Build Coastguard Worker 
57*89c4ff92SAndroid Build Coastguard Worker    You can define STBI_WRITE_NO_STDIO to disable the file variant of these
58*89c4ff92SAndroid Build Coastguard Worker    functions, so the library will not use stdio.h at all. However, this will
59*89c4ff92SAndroid Build Coastguard Worker    also disable HDR writing, because it requires stdio for formatted output.
60*89c4ff92SAndroid Build Coastguard Worker 
61*89c4ff92SAndroid Build Coastguard Worker    Each function returns 0 on failure and non-0 on success.
62*89c4ff92SAndroid Build Coastguard Worker 
63*89c4ff92SAndroid Build Coastguard Worker    The functions create an image file defined by the parameters. The image
64*89c4ff92SAndroid Build Coastguard Worker    is a rectangle of pixels stored from left-to-right, top-to-bottom.
65*89c4ff92SAndroid Build Coastguard Worker    Each pixel contains 'comp' channels of data stored interleaved with 8-bits
66*89c4ff92SAndroid Build Coastguard Worker    per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is
67*89c4ff92SAndroid Build Coastguard Worker    monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall.
68*89c4ff92SAndroid Build Coastguard Worker    The *data pointer points to the first byte of the top-left-most pixel.
69*89c4ff92SAndroid Build Coastguard Worker    For PNG, "stride_in_bytes" is the distance in bytes from the first byte of
70*89c4ff92SAndroid Build Coastguard Worker    a row of pixels to the first byte of the next row of pixels.
71*89c4ff92SAndroid Build Coastguard Worker 
72*89c4ff92SAndroid Build Coastguard Worker    PNG creates output files with the same number of components as the input.
73*89c4ff92SAndroid Build Coastguard Worker    The BMP format expands Y to RGB in the file format and does not
74*89c4ff92SAndroid Build Coastguard Worker    output alpha.
75*89c4ff92SAndroid Build Coastguard Worker 
76*89c4ff92SAndroid Build Coastguard Worker    PNG supports writing rectangles of data even when the bytes storing rows of
77*89c4ff92SAndroid Build Coastguard Worker    data are not consecutive in memory (e.g. sub-rectangles of a larger image),
78*89c4ff92SAndroid Build Coastguard Worker    by supplying the stride between the beginning of adjacent rows. The other
79*89c4ff92SAndroid Build Coastguard Worker    formats do not. (Thus you cannot write a native-format BMP through the BMP
80*89c4ff92SAndroid Build Coastguard Worker    writer, both because it is in BGR order and because it may have padding
81*89c4ff92SAndroid Build Coastguard Worker    at the end of the line.)
82*89c4ff92SAndroid Build Coastguard Worker 
83*89c4ff92SAndroid Build Coastguard Worker    HDR expects linear float data. Since the format is always 32-bit rgb(e)
84*89c4ff92SAndroid Build Coastguard Worker    data, alpha (if provided) is discarded, and for monochrome data it is
85*89c4ff92SAndroid Build Coastguard Worker    replicated across all three channels.
86*89c4ff92SAndroid Build Coastguard Worker 
87*89c4ff92SAndroid Build Coastguard Worker    TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed
88*89c4ff92SAndroid Build Coastguard Worker    data, set the global variable 'stbi_write_tga_with_rle' to 0.
89*89c4ff92SAndroid Build Coastguard Worker 
90*89c4ff92SAndroid Build Coastguard Worker    JPEG does ignore alpha channels in input data; quality is between 1 and 100.
91*89c4ff92SAndroid Build Coastguard Worker    Higher quality looks better but results in a bigger image.
92*89c4ff92SAndroid Build Coastguard Worker    JPEG baseline (no JPEG progressive).
93*89c4ff92SAndroid Build Coastguard Worker 
94*89c4ff92SAndroid Build Coastguard Worker CREDITS:
95*89c4ff92SAndroid Build Coastguard Worker 
96*89c4ff92SAndroid Build Coastguard Worker    PNG/BMP/TGA
97*89c4ff92SAndroid Build Coastguard Worker       Sean Barrett
98*89c4ff92SAndroid Build Coastguard Worker    HDR
99*89c4ff92SAndroid Build Coastguard Worker       Baldur Karlsson
100*89c4ff92SAndroid Build Coastguard Worker    TGA monochrome:
101*89c4ff92SAndroid Build Coastguard Worker       Jean-Sebastien Guay
102*89c4ff92SAndroid Build Coastguard Worker    misc enhancements:
103*89c4ff92SAndroid Build Coastguard Worker       Tim Kelsey
104*89c4ff92SAndroid Build Coastguard Worker    TGA RLE
105*89c4ff92SAndroid Build Coastguard Worker       Alan Hickman
106*89c4ff92SAndroid Build Coastguard Worker    initial file IO callback implementation
107*89c4ff92SAndroid Build Coastguard Worker       Emmanuel Julien
108*89c4ff92SAndroid Build Coastguard Worker    JPEG
109*89c4ff92SAndroid Build Coastguard Worker       Jon Olick (original jo_jpeg.cpp code)
110*89c4ff92SAndroid Build Coastguard Worker       Daniel Gibson
111*89c4ff92SAndroid Build Coastguard Worker    bugfixes:
112*89c4ff92SAndroid Build Coastguard Worker       github:Chribba
113*89c4ff92SAndroid Build Coastguard Worker       Guillaume Chereau
114*89c4ff92SAndroid Build Coastguard Worker       github:jry2
115*89c4ff92SAndroid Build Coastguard Worker       github:romigrou
116*89c4ff92SAndroid Build Coastguard Worker       Sergio Gonzalez
117*89c4ff92SAndroid Build Coastguard Worker       Jonas Karlsson
118*89c4ff92SAndroid Build Coastguard Worker       Filip Wasil
119*89c4ff92SAndroid Build Coastguard Worker       Thatcher Ulrich
120*89c4ff92SAndroid Build Coastguard Worker       github:poppolopoppo
121*89c4ff92SAndroid Build Coastguard Worker       Patrick Boettcher
122*89c4ff92SAndroid Build Coastguard Worker 
123*89c4ff92SAndroid Build Coastguard Worker LICENSE
124*89c4ff92SAndroid Build Coastguard Worker 
125*89c4ff92SAndroid Build Coastguard Worker   See end of file for license information.
126*89c4ff92SAndroid Build Coastguard Worker 
127*89c4ff92SAndroid Build Coastguard Worker */
128*89c4ff92SAndroid Build Coastguard Worker 
129*89c4ff92SAndroid Build Coastguard Worker #ifndef INCLUDE_STB_IMAGE_WRITE_H
130*89c4ff92SAndroid Build Coastguard Worker #define INCLUDE_STB_IMAGE_WRITE_H
131*89c4ff92SAndroid Build Coastguard Worker 
132*89c4ff92SAndroid Build Coastguard Worker #ifdef __cplusplus
133*89c4ff92SAndroid Build Coastguard Worker extern "C" {
134*89c4ff92SAndroid Build Coastguard Worker #endif
135*89c4ff92SAndroid Build Coastguard Worker 
136*89c4ff92SAndroid Build Coastguard Worker #ifdef STB_IMAGE_WRITE_STATIC
137*89c4ff92SAndroid Build Coastguard Worker #define STBIWDEF static
138*89c4ff92SAndroid Build Coastguard Worker #else
139*89c4ff92SAndroid Build Coastguard Worker #define STBIWDEF extern
140*89c4ff92SAndroid Build Coastguard Worker extern int stbi_write_tga_with_rle;
141*89c4ff92SAndroid Build Coastguard Worker #endif
142*89c4ff92SAndroid Build Coastguard Worker 
143*89c4ff92SAndroid Build Coastguard Worker #ifndef STBI_WRITE_NO_STDIO
144*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void  *data, int stride_in_bytes);
145*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void  *data);
146*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void  *data);
147*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
148*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void  *data, int quality);
149*89c4ff92SAndroid Build Coastguard Worker #endif
150*89c4ff92SAndroid Build Coastguard Worker 
151*89c4ff92SAndroid Build Coastguard Worker typedef void stbi_write_func(void *context, void *data, int size);
152*89c4ff92SAndroid Build Coastguard Worker 
153*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data, int stride_in_bytes);
154*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
155*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
156*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
157*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void  *data, int quality);
158*89c4ff92SAndroid Build Coastguard Worker 
159*89c4ff92SAndroid Build Coastguard Worker #ifdef __cplusplus
160*89c4ff92SAndroid Build Coastguard Worker }
161*89c4ff92SAndroid Build Coastguard Worker #endif
162*89c4ff92SAndroid Build Coastguard Worker 
163*89c4ff92SAndroid Build Coastguard Worker #endif//INCLUDE_STB_IMAGE_WRITE_H
164*89c4ff92SAndroid Build Coastguard Worker 
165*89c4ff92SAndroid Build Coastguard Worker #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
166*89c4ff92SAndroid Build Coastguard Worker 
167*89c4ff92SAndroid Build Coastguard Worker #ifdef _WIN32
168*89c4ff92SAndroid Build Coastguard Worker    #ifndef _CRT_SECURE_NO_WARNINGS
169*89c4ff92SAndroid Build Coastguard Worker    #define _CRT_SECURE_NO_WARNINGS
170*89c4ff92SAndroid Build Coastguard Worker    #endif
171*89c4ff92SAndroid Build Coastguard Worker    #ifndef _CRT_NONSTDC_NO_DEPRECATE
172*89c4ff92SAndroid Build Coastguard Worker    #define _CRT_NONSTDC_NO_DEPRECATE
173*89c4ff92SAndroid Build Coastguard Worker    #endif
174*89c4ff92SAndroid Build Coastguard Worker #endif
175*89c4ff92SAndroid Build Coastguard Worker 
176*89c4ff92SAndroid Build Coastguard Worker #ifndef STBI_WRITE_NO_STDIO
177*89c4ff92SAndroid Build Coastguard Worker #include <stdio.h>
178*89c4ff92SAndroid Build Coastguard Worker #endif // STBI_WRITE_NO_STDIO
179*89c4ff92SAndroid Build Coastguard Worker 
180*89c4ff92SAndroid Build Coastguard Worker #include <stdarg.h>
181*89c4ff92SAndroid Build Coastguard Worker #include <stdlib.h>
182*89c4ff92SAndroid Build Coastguard Worker #include <string.h>
183*89c4ff92SAndroid Build Coastguard Worker #include <math.h>
184*89c4ff92SAndroid Build Coastguard Worker 
185*89c4ff92SAndroid Build Coastguard Worker #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
186*89c4ff92SAndroid Build Coastguard Worker // ok
187*89c4ff92SAndroid Build Coastguard Worker #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
188*89c4ff92SAndroid Build Coastguard Worker // ok
189*89c4ff92SAndroid Build Coastguard Worker #else
190*89c4ff92SAndroid Build Coastguard Worker #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
191*89c4ff92SAndroid Build Coastguard Worker #endif
192*89c4ff92SAndroid Build Coastguard Worker 
193*89c4ff92SAndroid Build Coastguard Worker #ifndef STBIW_MALLOC
194*89c4ff92SAndroid Build Coastguard Worker #define STBIW_MALLOC(sz)        malloc(sz)
195*89c4ff92SAndroid Build Coastguard Worker #define STBIW_REALLOC(p,newsz)  realloc(p,newsz)
196*89c4ff92SAndroid Build Coastguard Worker #define STBIW_FREE(p)           free(p)
197*89c4ff92SAndroid Build Coastguard Worker #endif
198*89c4ff92SAndroid Build Coastguard Worker 
199*89c4ff92SAndroid Build Coastguard Worker #ifndef STBIW_REALLOC_SIZED
200*89c4ff92SAndroid Build Coastguard Worker #define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
201*89c4ff92SAndroid Build Coastguard Worker #endif
202*89c4ff92SAndroid Build Coastguard Worker 
203*89c4ff92SAndroid Build Coastguard Worker 
204*89c4ff92SAndroid Build Coastguard Worker #ifndef STBIW_MEMMOVE
205*89c4ff92SAndroid Build Coastguard Worker #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
206*89c4ff92SAndroid Build Coastguard Worker #endif
207*89c4ff92SAndroid Build Coastguard Worker 
208*89c4ff92SAndroid Build Coastguard Worker 
209*89c4ff92SAndroid Build Coastguard Worker #ifndef STBIW_ASSERT
210*89c4ff92SAndroid Build Coastguard Worker #include <assert.h>
211*89c4ff92SAndroid Build Coastguard Worker #define STBIW_ASSERT(x) assert(x)
212*89c4ff92SAndroid Build Coastguard Worker #endif
213*89c4ff92SAndroid Build Coastguard Worker 
214*89c4ff92SAndroid Build Coastguard Worker #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
215*89c4ff92SAndroid Build Coastguard Worker 
216*89c4ff92SAndroid Build Coastguard Worker typedef struct
217*89c4ff92SAndroid Build Coastguard Worker {
218*89c4ff92SAndroid Build Coastguard Worker    stbi_write_func *func;
219*89c4ff92SAndroid Build Coastguard Worker    void *context;
220*89c4ff92SAndroid Build Coastguard Worker } stbi__write_context;
221*89c4ff92SAndroid Build Coastguard Worker 
222*89c4ff92SAndroid Build Coastguard Worker // initialize a callback-based context
stbi__start_write_callbacks(stbi__write_context * s,stbi_write_func * c,void * context)223*89c4ff92SAndroid Build Coastguard Worker static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context)
224*89c4ff92SAndroid Build Coastguard Worker {
225*89c4ff92SAndroid Build Coastguard Worker    s->func    = c;
226*89c4ff92SAndroid Build Coastguard Worker    s->context = context;
227*89c4ff92SAndroid Build Coastguard Worker }
228*89c4ff92SAndroid Build Coastguard Worker 
229*89c4ff92SAndroid Build Coastguard Worker #ifndef STBI_WRITE_NO_STDIO
230*89c4ff92SAndroid Build Coastguard Worker 
stbi__stdio_write(void * context,void * data,int size)231*89c4ff92SAndroid Build Coastguard Worker static void stbi__stdio_write(void *context, void *data, int size)
232*89c4ff92SAndroid Build Coastguard Worker {
233*89c4ff92SAndroid Build Coastguard Worker    fwrite(data,1,size,(FILE*) context);
234*89c4ff92SAndroid Build Coastguard Worker }
235*89c4ff92SAndroid Build Coastguard Worker 
stbi__start_write_file(stbi__write_context * s,const char * filename)236*89c4ff92SAndroid Build Coastguard Worker static int stbi__start_write_file(stbi__write_context *s, const char *filename)
237*89c4ff92SAndroid Build Coastguard Worker {
238*89c4ff92SAndroid Build Coastguard Worker    FILE *f = fopen(filename, "wb");
239*89c4ff92SAndroid Build Coastguard Worker    stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
240*89c4ff92SAndroid Build Coastguard Worker    return f != NULL;
241*89c4ff92SAndroid Build Coastguard Worker }
242*89c4ff92SAndroid Build Coastguard Worker 
stbi__end_write_file(stbi__write_context * s)243*89c4ff92SAndroid Build Coastguard Worker static void stbi__end_write_file(stbi__write_context *s)
244*89c4ff92SAndroid Build Coastguard Worker {
245*89c4ff92SAndroid Build Coastguard Worker    fclose((FILE *)s->context);
246*89c4ff92SAndroid Build Coastguard Worker }
247*89c4ff92SAndroid Build Coastguard Worker 
248*89c4ff92SAndroid Build Coastguard Worker #endif // !STBI_WRITE_NO_STDIO
249*89c4ff92SAndroid Build Coastguard Worker 
250*89c4ff92SAndroid Build Coastguard Worker typedef unsigned int stbiw_uint32;
251*89c4ff92SAndroid Build Coastguard Worker typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
252*89c4ff92SAndroid Build Coastguard Worker 
253*89c4ff92SAndroid Build Coastguard Worker #ifdef STB_IMAGE_WRITE_STATIC
254*89c4ff92SAndroid Build Coastguard Worker static int stbi_write_tga_with_rle = 1;
255*89c4ff92SAndroid Build Coastguard Worker #else
256*89c4ff92SAndroid Build Coastguard Worker int stbi_write_tga_with_rle = 1;
257*89c4ff92SAndroid Build Coastguard Worker #endif
258*89c4ff92SAndroid Build Coastguard Worker 
stbiw__writefv(stbi__write_context * s,const char * fmt,va_list v)259*89c4ff92SAndroid Build Coastguard Worker static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
260*89c4ff92SAndroid Build Coastguard Worker {
261*89c4ff92SAndroid Build Coastguard Worker    while (*fmt) {
262*89c4ff92SAndroid Build Coastguard Worker       switch (*fmt++) {
263*89c4ff92SAndroid Build Coastguard Worker          case ' ': break;
264*89c4ff92SAndroid Build Coastguard Worker          case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int));
265*89c4ff92SAndroid Build Coastguard Worker                      s->func(s->context,&x,1);
266*89c4ff92SAndroid Build Coastguard Worker                      break; }
267*89c4ff92SAndroid Build Coastguard Worker          case '2': { int x = va_arg(v,int);
268*89c4ff92SAndroid Build Coastguard Worker                      unsigned char b[2];
269*89c4ff92SAndroid Build Coastguard Worker                      b[0] = STBIW_UCHAR(x);
270*89c4ff92SAndroid Build Coastguard Worker                      b[1] = STBIW_UCHAR(x>>8);
271*89c4ff92SAndroid Build Coastguard Worker                      s->func(s->context,b,2);
272*89c4ff92SAndroid Build Coastguard Worker                      break; }
273*89c4ff92SAndroid Build Coastguard Worker          case '4': { stbiw_uint32 x = va_arg(v,int);
274*89c4ff92SAndroid Build Coastguard Worker                      unsigned char b[4];
275*89c4ff92SAndroid Build Coastguard Worker                      b[0]=STBIW_UCHAR(x);
276*89c4ff92SAndroid Build Coastguard Worker                      b[1]=STBIW_UCHAR(x>>8);
277*89c4ff92SAndroid Build Coastguard Worker                      b[2]=STBIW_UCHAR(x>>16);
278*89c4ff92SAndroid Build Coastguard Worker                      b[3]=STBIW_UCHAR(x>>24);
279*89c4ff92SAndroid Build Coastguard Worker                      s->func(s->context,b,4);
280*89c4ff92SAndroid Build Coastguard Worker                      break; }
281*89c4ff92SAndroid Build Coastguard Worker          default:
282*89c4ff92SAndroid Build Coastguard Worker             STBIW_ASSERT(0);
283*89c4ff92SAndroid Build Coastguard Worker             return;
284*89c4ff92SAndroid Build Coastguard Worker       }
285*89c4ff92SAndroid Build Coastguard Worker    }
286*89c4ff92SAndroid Build Coastguard Worker }
287*89c4ff92SAndroid Build Coastguard Worker 
stbiw__writef(stbi__write_context * s,const char * fmt,...)288*89c4ff92SAndroid Build Coastguard Worker static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
289*89c4ff92SAndroid Build Coastguard Worker {
290*89c4ff92SAndroid Build Coastguard Worker    va_list v;
291*89c4ff92SAndroid Build Coastguard Worker    va_start(v, fmt);
292*89c4ff92SAndroid Build Coastguard Worker    stbiw__writefv(s, fmt, v);
293*89c4ff92SAndroid Build Coastguard Worker    va_end(v);
294*89c4ff92SAndroid Build Coastguard Worker }
295*89c4ff92SAndroid Build Coastguard Worker 
stbiw__putc(stbi__write_context * s,unsigned char c)296*89c4ff92SAndroid Build Coastguard Worker static void stbiw__putc(stbi__write_context *s, unsigned char c)
297*89c4ff92SAndroid Build Coastguard Worker {
298*89c4ff92SAndroid Build Coastguard Worker    s->func(s->context, &c, 1);
299*89c4ff92SAndroid Build Coastguard Worker }
300*89c4ff92SAndroid Build Coastguard Worker 
stbiw__write3(stbi__write_context * s,unsigned char a,unsigned char b,unsigned char c)301*89c4ff92SAndroid Build Coastguard Worker static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
302*89c4ff92SAndroid Build Coastguard Worker {
303*89c4ff92SAndroid Build Coastguard Worker    unsigned char arr[3];
304*89c4ff92SAndroid Build Coastguard Worker    arr[0] = a, arr[1] = b, arr[2] = c;
305*89c4ff92SAndroid Build Coastguard Worker    s->func(s->context, arr, 3);
306*89c4ff92SAndroid Build Coastguard Worker }
307*89c4ff92SAndroid Build Coastguard Worker 
stbiw__write_pixel(stbi__write_context * s,int rgb_dir,int comp,int write_alpha,int expand_mono,unsigned char * d)308*89c4ff92SAndroid Build Coastguard Worker static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
309*89c4ff92SAndroid Build Coastguard Worker {
310*89c4ff92SAndroid Build Coastguard Worker    unsigned char bg[3] = { 255, 0, 255}, px[3];
311*89c4ff92SAndroid Build Coastguard Worker    int k;
312*89c4ff92SAndroid Build Coastguard Worker 
313*89c4ff92SAndroid Build Coastguard Worker    if (write_alpha < 0)
314*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, &d[comp - 1], 1);
315*89c4ff92SAndroid Build Coastguard Worker 
316*89c4ff92SAndroid Build Coastguard Worker    switch (comp) {
317*89c4ff92SAndroid Build Coastguard Worker       case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case
318*89c4ff92SAndroid Build Coastguard Worker       case 1:
319*89c4ff92SAndroid Build Coastguard Worker          if (expand_mono)
320*89c4ff92SAndroid Build Coastguard Worker             stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
321*89c4ff92SAndroid Build Coastguard Worker          else
322*89c4ff92SAndroid Build Coastguard Worker             s->func(s->context, d, 1);  // monochrome TGA
323*89c4ff92SAndroid Build Coastguard Worker          break;
324*89c4ff92SAndroid Build Coastguard Worker       case 4:
325*89c4ff92SAndroid Build Coastguard Worker          if (!write_alpha) {
326*89c4ff92SAndroid Build Coastguard Worker             // composite against pink background
327*89c4ff92SAndroid Build Coastguard Worker             for (k = 0; k < 3; ++k)
328*89c4ff92SAndroid Build Coastguard Worker                px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
329*89c4ff92SAndroid Build Coastguard Worker             stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
330*89c4ff92SAndroid Build Coastguard Worker             break;
331*89c4ff92SAndroid Build Coastguard Worker          }
332*89c4ff92SAndroid Build Coastguard Worker          /* FALLTHROUGH */
333*89c4ff92SAndroid Build Coastguard Worker       case 3:
334*89c4ff92SAndroid Build Coastguard Worker          stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
335*89c4ff92SAndroid Build Coastguard Worker          break;
336*89c4ff92SAndroid Build Coastguard Worker    }
337*89c4ff92SAndroid Build Coastguard Worker    if (write_alpha > 0)
338*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, &d[comp - 1], 1);
339*89c4ff92SAndroid Build Coastguard Worker }
340*89c4ff92SAndroid Build Coastguard Worker 
stbiw__write_pixels(stbi__write_context * s,int rgb_dir,int vdir,int x,int y,int comp,void * data,int write_alpha,int scanline_pad,int expand_mono)341*89c4ff92SAndroid Build Coastguard Worker static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
342*89c4ff92SAndroid Build Coastguard Worker {
343*89c4ff92SAndroid Build Coastguard Worker    stbiw_uint32 zero = 0;
344*89c4ff92SAndroid Build Coastguard Worker    int i,j, j_end;
345*89c4ff92SAndroid Build Coastguard Worker 
346*89c4ff92SAndroid Build Coastguard Worker    if (y <= 0)
347*89c4ff92SAndroid Build Coastguard Worker       return;
348*89c4ff92SAndroid Build Coastguard Worker 
349*89c4ff92SAndroid Build Coastguard Worker    if (vdir < 0)
350*89c4ff92SAndroid Build Coastguard Worker       j_end = -1, j = y-1;
351*89c4ff92SAndroid Build Coastguard Worker    else
352*89c4ff92SAndroid Build Coastguard Worker       j_end =  y, j = 0;
353*89c4ff92SAndroid Build Coastguard Worker 
354*89c4ff92SAndroid Build Coastguard Worker    for (; j != j_end; j += vdir) {
355*89c4ff92SAndroid Build Coastguard Worker       for (i=0; i < x; ++i) {
356*89c4ff92SAndroid Build Coastguard Worker          unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
357*89c4ff92SAndroid Build Coastguard Worker          stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
358*89c4ff92SAndroid Build Coastguard Worker       }
359*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, &zero, scanline_pad);
360*89c4ff92SAndroid Build Coastguard Worker    }
361*89c4ff92SAndroid Build Coastguard Worker }
362*89c4ff92SAndroid Build Coastguard Worker 
stbiw__outfile(stbi__write_context * s,int rgb_dir,int vdir,int x,int y,int comp,int expand_mono,void * data,int alpha,int pad,const char * fmt,...)363*89c4ff92SAndroid Build Coastguard Worker static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...)
364*89c4ff92SAndroid Build Coastguard Worker {
365*89c4ff92SAndroid Build Coastguard Worker    if (y < 0 || x < 0) {
366*89c4ff92SAndroid Build Coastguard Worker       return 0;
367*89c4ff92SAndroid Build Coastguard Worker    } else {
368*89c4ff92SAndroid Build Coastguard Worker       va_list v;
369*89c4ff92SAndroid Build Coastguard Worker       va_start(v, fmt);
370*89c4ff92SAndroid Build Coastguard Worker       stbiw__writefv(s, fmt, v);
371*89c4ff92SAndroid Build Coastguard Worker       va_end(v);
372*89c4ff92SAndroid Build Coastguard Worker       stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
373*89c4ff92SAndroid Build Coastguard Worker       return 1;
374*89c4ff92SAndroid Build Coastguard Worker    }
375*89c4ff92SAndroid Build Coastguard Worker }
376*89c4ff92SAndroid Build Coastguard Worker 
stbi_write_bmp_core(stbi__write_context * s,int x,int y,int comp,const void * data)377*89c4ff92SAndroid Build Coastguard Worker static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
378*89c4ff92SAndroid Build Coastguard Worker {
379*89c4ff92SAndroid Build Coastguard Worker    int pad = (-x*3) & 3;
380*89c4ff92SAndroid Build Coastguard Worker    return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
381*89c4ff92SAndroid Build Coastguard Worker            "11 4 22 4" "4 44 22 444444",
382*89c4ff92SAndroid Build Coastguard Worker            'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40,  // file header
383*89c4ff92SAndroid Build Coastguard Worker             40, x,y, 1,24, 0,0,0,0,0,0);             // bitmap header
384*89c4ff92SAndroid Build Coastguard Worker }
385*89c4ff92SAndroid Build Coastguard Worker 
stbi_write_bmp_to_func(stbi_write_func * func,void * context,int x,int y,int comp,const void * data)386*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
387*89c4ff92SAndroid Build Coastguard Worker {
388*89c4ff92SAndroid Build Coastguard Worker    stbi__write_context s;
389*89c4ff92SAndroid Build Coastguard Worker    stbi__start_write_callbacks(&s, func, context);
390*89c4ff92SAndroid Build Coastguard Worker    return stbi_write_bmp_core(&s, x, y, comp, data);
391*89c4ff92SAndroid Build Coastguard Worker }
392*89c4ff92SAndroid Build Coastguard Worker 
393*89c4ff92SAndroid Build Coastguard Worker #ifndef STBI_WRITE_NO_STDIO
stbi_write_bmp(char const * filename,int x,int y,int comp,const void * data)394*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
395*89c4ff92SAndroid Build Coastguard Worker {
396*89c4ff92SAndroid Build Coastguard Worker    stbi__write_context s;
397*89c4ff92SAndroid Build Coastguard Worker    if (stbi__start_write_file(&s,filename)) {
398*89c4ff92SAndroid Build Coastguard Worker       int r = stbi_write_bmp_core(&s, x, y, comp, data);
399*89c4ff92SAndroid Build Coastguard Worker       stbi__end_write_file(&s);
400*89c4ff92SAndroid Build Coastguard Worker       return r;
401*89c4ff92SAndroid Build Coastguard Worker    } else
402*89c4ff92SAndroid Build Coastguard Worker       return 0;
403*89c4ff92SAndroid Build Coastguard Worker }
404*89c4ff92SAndroid Build Coastguard Worker #endif //!STBI_WRITE_NO_STDIO
405*89c4ff92SAndroid Build Coastguard Worker 
stbi_write_tga_core(stbi__write_context * s,int x,int y,int comp,void * data)406*89c4ff92SAndroid Build Coastguard Worker static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data)
407*89c4ff92SAndroid Build Coastguard Worker {
408*89c4ff92SAndroid Build Coastguard Worker    int has_alpha = (comp == 2 || comp == 4);
409*89c4ff92SAndroid Build Coastguard Worker    int colorbytes = has_alpha ? comp-1 : comp;
410*89c4ff92SAndroid Build Coastguard Worker    int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
411*89c4ff92SAndroid Build Coastguard Worker 
412*89c4ff92SAndroid Build Coastguard Worker    if (y < 0 || x < 0)
413*89c4ff92SAndroid Build Coastguard Worker       return 0;
414*89c4ff92SAndroid Build Coastguard Worker 
415*89c4ff92SAndroid Build Coastguard Worker    if (!stbi_write_tga_with_rle) {
416*89c4ff92SAndroid Build Coastguard Worker       return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
417*89c4ff92SAndroid Build Coastguard Worker          "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
418*89c4ff92SAndroid Build Coastguard Worker    } else {
419*89c4ff92SAndroid Build Coastguard Worker       int i,j,k;
420*89c4ff92SAndroid Build Coastguard Worker 
421*89c4ff92SAndroid Build Coastguard Worker       stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8);
422*89c4ff92SAndroid Build Coastguard Worker 
423*89c4ff92SAndroid Build Coastguard Worker       for (j = y - 1; j >= 0; --j) {
424*89c4ff92SAndroid Build Coastguard Worker           unsigned char *row = (unsigned char *) data + j * x * comp;
425*89c4ff92SAndroid Build Coastguard Worker          int len;
426*89c4ff92SAndroid Build Coastguard Worker 
427*89c4ff92SAndroid Build Coastguard Worker          for (i = 0; i < x; i += len) {
428*89c4ff92SAndroid Build Coastguard Worker             unsigned char *begin = row + i * comp;
429*89c4ff92SAndroid Build Coastguard Worker             int diff = 1;
430*89c4ff92SAndroid Build Coastguard Worker             len = 1;
431*89c4ff92SAndroid Build Coastguard Worker 
432*89c4ff92SAndroid Build Coastguard Worker             if (i < x - 1) {
433*89c4ff92SAndroid Build Coastguard Worker                ++len;
434*89c4ff92SAndroid Build Coastguard Worker                diff = memcmp(begin, row + (i + 1) * comp, comp);
435*89c4ff92SAndroid Build Coastguard Worker                if (diff) {
436*89c4ff92SAndroid Build Coastguard Worker                   const unsigned char *prev = begin;
437*89c4ff92SAndroid Build Coastguard Worker                   for (k = i + 2; k < x && len < 128; ++k) {
438*89c4ff92SAndroid Build Coastguard Worker                      if (memcmp(prev, row + k * comp, comp)) {
439*89c4ff92SAndroid Build Coastguard Worker                         prev += comp;
440*89c4ff92SAndroid Build Coastguard Worker                         ++len;
441*89c4ff92SAndroid Build Coastguard Worker                      } else {
442*89c4ff92SAndroid Build Coastguard Worker                         --len;
443*89c4ff92SAndroid Build Coastguard Worker                         break;
444*89c4ff92SAndroid Build Coastguard Worker                      }
445*89c4ff92SAndroid Build Coastguard Worker                   }
446*89c4ff92SAndroid Build Coastguard Worker                } else {
447*89c4ff92SAndroid Build Coastguard Worker                   for (k = i + 2; k < x && len < 128; ++k) {
448*89c4ff92SAndroid Build Coastguard Worker                      if (!memcmp(begin, row + k * comp, comp)) {
449*89c4ff92SAndroid Build Coastguard Worker                         ++len;
450*89c4ff92SAndroid Build Coastguard Worker                      } else {
451*89c4ff92SAndroid Build Coastguard Worker                         break;
452*89c4ff92SAndroid Build Coastguard Worker                      }
453*89c4ff92SAndroid Build Coastguard Worker                   }
454*89c4ff92SAndroid Build Coastguard Worker                }
455*89c4ff92SAndroid Build Coastguard Worker             }
456*89c4ff92SAndroid Build Coastguard Worker 
457*89c4ff92SAndroid Build Coastguard Worker             if (diff) {
458*89c4ff92SAndroid Build Coastguard Worker                unsigned char header = STBIW_UCHAR(len - 1);
459*89c4ff92SAndroid Build Coastguard Worker                s->func(s->context, &header, 1);
460*89c4ff92SAndroid Build Coastguard Worker                for (k = 0; k < len; ++k) {
461*89c4ff92SAndroid Build Coastguard Worker                   stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
462*89c4ff92SAndroid Build Coastguard Worker                }
463*89c4ff92SAndroid Build Coastguard Worker             } else {
464*89c4ff92SAndroid Build Coastguard Worker                unsigned char header = STBIW_UCHAR(len - 129);
465*89c4ff92SAndroid Build Coastguard Worker                s->func(s->context, &header, 1);
466*89c4ff92SAndroid Build Coastguard Worker                stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
467*89c4ff92SAndroid Build Coastguard Worker             }
468*89c4ff92SAndroid Build Coastguard Worker          }
469*89c4ff92SAndroid Build Coastguard Worker       }
470*89c4ff92SAndroid Build Coastguard Worker    }
471*89c4ff92SAndroid Build Coastguard Worker    return 1;
472*89c4ff92SAndroid Build Coastguard Worker }
473*89c4ff92SAndroid Build Coastguard Worker 
stbi_write_tga_to_func(stbi_write_func * func,void * context,int x,int y,int comp,const void * data)474*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
475*89c4ff92SAndroid Build Coastguard Worker {
476*89c4ff92SAndroid Build Coastguard Worker    stbi__write_context s;
477*89c4ff92SAndroid Build Coastguard Worker    stbi__start_write_callbacks(&s, func, context);
478*89c4ff92SAndroid Build Coastguard Worker    return stbi_write_tga_core(&s, x, y, comp, (void *) data);
479*89c4ff92SAndroid Build Coastguard Worker }
480*89c4ff92SAndroid Build Coastguard Worker 
481*89c4ff92SAndroid Build Coastguard Worker #ifndef STBI_WRITE_NO_STDIO
stbi_write_tga(char const * filename,int x,int y,int comp,const void * data)482*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
483*89c4ff92SAndroid Build Coastguard Worker {
484*89c4ff92SAndroid Build Coastguard Worker    stbi__write_context s;
485*89c4ff92SAndroid Build Coastguard Worker    if (stbi__start_write_file(&s,filename)) {
486*89c4ff92SAndroid Build Coastguard Worker       int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
487*89c4ff92SAndroid Build Coastguard Worker       stbi__end_write_file(&s);
488*89c4ff92SAndroid Build Coastguard Worker       return r;
489*89c4ff92SAndroid Build Coastguard Worker    } else
490*89c4ff92SAndroid Build Coastguard Worker       return 0;
491*89c4ff92SAndroid Build Coastguard Worker }
492*89c4ff92SAndroid Build Coastguard Worker #endif
493*89c4ff92SAndroid Build Coastguard Worker 
494*89c4ff92SAndroid Build Coastguard Worker // *************************************************************************************************
495*89c4ff92SAndroid Build Coastguard Worker // Radiance RGBE HDR writer
496*89c4ff92SAndroid Build Coastguard Worker // by Baldur Karlsson
497*89c4ff92SAndroid Build Coastguard Worker 
498*89c4ff92SAndroid Build Coastguard Worker #define stbiw__max(a, b)  ((a) > (b) ? (a) : (b))
499*89c4ff92SAndroid Build Coastguard Worker 
stbiw__linear_to_rgbe(unsigned char * rgbe,float * linear)500*89c4ff92SAndroid Build Coastguard Worker void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
501*89c4ff92SAndroid Build Coastguard Worker {
502*89c4ff92SAndroid Build Coastguard Worker    int exponent;
503*89c4ff92SAndroid Build Coastguard Worker    float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
504*89c4ff92SAndroid Build Coastguard Worker 
505*89c4ff92SAndroid Build Coastguard Worker    if (maxcomp < 1e-32f) {
506*89c4ff92SAndroid Build Coastguard Worker       rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
507*89c4ff92SAndroid Build Coastguard Worker    } else {
508*89c4ff92SAndroid Build Coastguard Worker       float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
509*89c4ff92SAndroid Build Coastguard Worker 
510*89c4ff92SAndroid Build Coastguard Worker       rgbe[0] = (unsigned char)(linear[0] * normalize);
511*89c4ff92SAndroid Build Coastguard Worker       rgbe[1] = (unsigned char)(linear[1] * normalize);
512*89c4ff92SAndroid Build Coastguard Worker       rgbe[2] = (unsigned char)(linear[2] * normalize);
513*89c4ff92SAndroid Build Coastguard Worker       rgbe[3] = (unsigned char)(exponent + 128);
514*89c4ff92SAndroid Build Coastguard Worker    }
515*89c4ff92SAndroid Build Coastguard Worker }
516*89c4ff92SAndroid Build Coastguard Worker 
stbiw__write_run_data(stbi__write_context * s,int length,unsigned char databyte)517*89c4ff92SAndroid Build Coastguard Worker void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
518*89c4ff92SAndroid Build Coastguard Worker {
519*89c4ff92SAndroid Build Coastguard Worker    unsigned char lengthbyte = STBIW_UCHAR(length+128);
520*89c4ff92SAndroid Build Coastguard Worker    STBIW_ASSERT(length+128 <= 255);
521*89c4ff92SAndroid Build Coastguard Worker    s->func(s->context, &lengthbyte, 1);
522*89c4ff92SAndroid Build Coastguard Worker    s->func(s->context, &databyte, 1);
523*89c4ff92SAndroid Build Coastguard Worker }
524*89c4ff92SAndroid Build Coastguard Worker 
stbiw__write_dump_data(stbi__write_context * s,int length,unsigned char * data)525*89c4ff92SAndroid Build Coastguard Worker void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
526*89c4ff92SAndroid Build Coastguard Worker {
527*89c4ff92SAndroid Build Coastguard Worker    unsigned char lengthbyte = STBIW_UCHAR(length);
528*89c4ff92SAndroid Build Coastguard Worker    STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
529*89c4ff92SAndroid Build Coastguard Worker    s->func(s->context, &lengthbyte, 1);
530*89c4ff92SAndroid Build Coastguard Worker    s->func(s->context, data, length);
531*89c4ff92SAndroid Build Coastguard Worker }
532*89c4ff92SAndroid Build Coastguard Worker 
stbiw__write_hdr_scanline(stbi__write_context * s,int width,int ncomp,unsigned char * scratch,float * scanline)533*89c4ff92SAndroid Build Coastguard Worker void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
534*89c4ff92SAndroid Build Coastguard Worker {
535*89c4ff92SAndroid Build Coastguard Worker    unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
536*89c4ff92SAndroid Build Coastguard Worker    unsigned char rgbe[4];
537*89c4ff92SAndroid Build Coastguard Worker    float linear[3];
538*89c4ff92SAndroid Build Coastguard Worker    int x;
539*89c4ff92SAndroid Build Coastguard Worker 
540*89c4ff92SAndroid Build Coastguard Worker    scanlineheader[2] = (width&0xff00)>>8;
541*89c4ff92SAndroid Build Coastguard Worker    scanlineheader[3] = (width&0x00ff);
542*89c4ff92SAndroid Build Coastguard Worker 
543*89c4ff92SAndroid Build Coastguard Worker    /* skip RLE for images too small or large */
544*89c4ff92SAndroid Build Coastguard Worker    if (width < 8 || width >= 32768) {
545*89c4ff92SAndroid Build Coastguard Worker       for (x=0; x < width; x++) {
546*89c4ff92SAndroid Build Coastguard Worker          switch (ncomp) {
547*89c4ff92SAndroid Build Coastguard Worker             case 4: /* fallthrough */
548*89c4ff92SAndroid Build Coastguard Worker             case 3: linear[2] = scanline[x*ncomp + 2];
549*89c4ff92SAndroid Build Coastguard Worker                     linear[1] = scanline[x*ncomp + 1];
550*89c4ff92SAndroid Build Coastguard Worker                     linear[0] = scanline[x*ncomp + 0];
551*89c4ff92SAndroid Build Coastguard Worker                     break;
552*89c4ff92SAndroid Build Coastguard Worker             default:
553*89c4ff92SAndroid Build Coastguard Worker                     linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
554*89c4ff92SAndroid Build Coastguard Worker                     break;
555*89c4ff92SAndroid Build Coastguard Worker          }
556*89c4ff92SAndroid Build Coastguard Worker          stbiw__linear_to_rgbe(rgbe, linear);
557*89c4ff92SAndroid Build Coastguard Worker          s->func(s->context, rgbe, 4);
558*89c4ff92SAndroid Build Coastguard Worker       }
559*89c4ff92SAndroid Build Coastguard Worker    } else {
560*89c4ff92SAndroid Build Coastguard Worker       int c,r;
561*89c4ff92SAndroid Build Coastguard Worker       /* encode into scratch buffer */
562*89c4ff92SAndroid Build Coastguard Worker       for (x=0; x < width; x++) {
563*89c4ff92SAndroid Build Coastguard Worker          switch(ncomp) {
564*89c4ff92SAndroid Build Coastguard Worker             case 4: /* fallthrough */
565*89c4ff92SAndroid Build Coastguard Worker             case 3: linear[2] = scanline[x*ncomp + 2];
566*89c4ff92SAndroid Build Coastguard Worker                     linear[1] = scanline[x*ncomp + 1];
567*89c4ff92SAndroid Build Coastguard Worker                     linear[0] = scanline[x*ncomp + 0];
568*89c4ff92SAndroid Build Coastguard Worker                     break;
569*89c4ff92SAndroid Build Coastguard Worker             default:
570*89c4ff92SAndroid Build Coastguard Worker                     linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
571*89c4ff92SAndroid Build Coastguard Worker                     break;
572*89c4ff92SAndroid Build Coastguard Worker          }
573*89c4ff92SAndroid Build Coastguard Worker          stbiw__linear_to_rgbe(rgbe, linear);
574*89c4ff92SAndroid Build Coastguard Worker          scratch[x + width*0] = rgbe[0];
575*89c4ff92SAndroid Build Coastguard Worker          scratch[x + width*1] = rgbe[1];
576*89c4ff92SAndroid Build Coastguard Worker          scratch[x + width*2] = rgbe[2];
577*89c4ff92SAndroid Build Coastguard Worker          scratch[x + width*3] = rgbe[3];
578*89c4ff92SAndroid Build Coastguard Worker       }
579*89c4ff92SAndroid Build Coastguard Worker 
580*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, scanlineheader, 4);
581*89c4ff92SAndroid Build Coastguard Worker 
582*89c4ff92SAndroid Build Coastguard Worker       /* RLE each component separately */
583*89c4ff92SAndroid Build Coastguard Worker       for (c=0; c < 4; c++) {
584*89c4ff92SAndroid Build Coastguard Worker          unsigned char *comp = &scratch[width*c];
585*89c4ff92SAndroid Build Coastguard Worker 
586*89c4ff92SAndroid Build Coastguard Worker          x = 0;
587*89c4ff92SAndroid Build Coastguard Worker          while (x < width) {
588*89c4ff92SAndroid Build Coastguard Worker             // find first run
589*89c4ff92SAndroid Build Coastguard Worker             r = x;
590*89c4ff92SAndroid Build Coastguard Worker             while (r+2 < width) {
591*89c4ff92SAndroid Build Coastguard Worker                if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
592*89c4ff92SAndroid Build Coastguard Worker                   break;
593*89c4ff92SAndroid Build Coastguard Worker                ++r;
594*89c4ff92SAndroid Build Coastguard Worker             }
595*89c4ff92SAndroid Build Coastguard Worker             if (r+2 >= width)
596*89c4ff92SAndroid Build Coastguard Worker                r = width;
597*89c4ff92SAndroid Build Coastguard Worker             // dump up to first run
598*89c4ff92SAndroid Build Coastguard Worker             while (x < r) {
599*89c4ff92SAndroid Build Coastguard Worker                int len = r-x;
600*89c4ff92SAndroid Build Coastguard Worker                if (len > 128) len = 128;
601*89c4ff92SAndroid Build Coastguard Worker                stbiw__write_dump_data(s, len, &comp[x]);
602*89c4ff92SAndroid Build Coastguard Worker                x += len;
603*89c4ff92SAndroid Build Coastguard Worker             }
604*89c4ff92SAndroid Build Coastguard Worker             // if there's a run, output it
605*89c4ff92SAndroid Build Coastguard Worker             if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd
606*89c4ff92SAndroid Build Coastguard Worker                // find next byte after run
607*89c4ff92SAndroid Build Coastguard Worker                while (r < width && comp[r] == comp[x])
608*89c4ff92SAndroid Build Coastguard Worker                   ++r;
609*89c4ff92SAndroid Build Coastguard Worker                // output run up to r
610*89c4ff92SAndroid Build Coastguard Worker                while (x < r) {
611*89c4ff92SAndroid Build Coastguard Worker                   int len = r-x;
612*89c4ff92SAndroid Build Coastguard Worker                   if (len > 127) len = 127;
613*89c4ff92SAndroid Build Coastguard Worker                   stbiw__write_run_data(s, len, comp[x]);
614*89c4ff92SAndroid Build Coastguard Worker                   x += len;
615*89c4ff92SAndroid Build Coastguard Worker                }
616*89c4ff92SAndroid Build Coastguard Worker             }
617*89c4ff92SAndroid Build Coastguard Worker          }
618*89c4ff92SAndroid Build Coastguard Worker       }
619*89c4ff92SAndroid Build Coastguard Worker    }
620*89c4ff92SAndroid Build Coastguard Worker }
621*89c4ff92SAndroid Build Coastguard Worker 
stbi_write_hdr_core(stbi__write_context * s,int x,int y,int comp,float * data)622*89c4ff92SAndroid Build Coastguard Worker static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data)
623*89c4ff92SAndroid Build Coastguard Worker {
624*89c4ff92SAndroid Build Coastguard Worker    if (y <= 0 || x <= 0 || data == NULL)
625*89c4ff92SAndroid Build Coastguard Worker       return 0;
626*89c4ff92SAndroid Build Coastguard Worker    else {
627*89c4ff92SAndroid Build Coastguard Worker       // Each component is stored separately. Allocate scratch space for full output scanline.
628*89c4ff92SAndroid Build Coastguard Worker       unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
629*89c4ff92SAndroid Build Coastguard Worker       int i, len;
630*89c4ff92SAndroid Build Coastguard Worker       char buffer[128];
631*89c4ff92SAndroid Build Coastguard Worker       char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
632*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, header, sizeof(header)-1);
633*89c4ff92SAndroid Build Coastguard Worker 
634*89c4ff92SAndroid Build Coastguard Worker       len = sprintf(buffer, "EXPOSURE=          1.0000000000000\n\n-Y %d +X %d\n", y, x);
635*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, buffer, len);
636*89c4ff92SAndroid Build Coastguard Worker 
637*89c4ff92SAndroid Build Coastguard Worker       for(i=0; i < y; i++)
638*89c4ff92SAndroid Build Coastguard Worker          stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x);
639*89c4ff92SAndroid Build Coastguard Worker       STBIW_FREE(scratch);
640*89c4ff92SAndroid Build Coastguard Worker       return 1;
641*89c4ff92SAndroid Build Coastguard Worker    }
642*89c4ff92SAndroid Build Coastguard Worker }
643*89c4ff92SAndroid Build Coastguard Worker 
stbi_write_hdr_to_func(stbi_write_func * func,void * context,int x,int y,int comp,const float * data)644*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
645*89c4ff92SAndroid Build Coastguard Worker {
646*89c4ff92SAndroid Build Coastguard Worker    stbi__write_context s;
647*89c4ff92SAndroid Build Coastguard Worker    stbi__start_write_callbacks(&s, func, context);
648*89c4ff92SAndroid Build Coastguard Worker    return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
649*89c4ff92SAndroid Build Coastguard Worker }
650*89c4ff92SAndroid Build Coastguard Worker 
651*89c4ff92SAndroid Build Coastguard Worker #ifndef STBI_WRITE_NO_STDIO
stbi_write_hdr(char const * filename,int x,int y,int comp,const float * data)652*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
653*89c4ff92SAndroid Build Coastguard Worker {
654*89c4ff92SAndroid Build Coastguard Worker    stbi__write_context s;
655*89c4ff92SAndroid Build Coastguard Worker    if (stbi__start_write_file(&s,filename)) {
656*89c4ff92SAndroid Build Coastguard Worker       int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
657*89c4ff92SAndroid Build Coastguard Worker       stbi__end_write_file(&s);
658*89c4ff92SAndroid Build Coastguard Worker       return r;
659*89c4ff92SAndroid Build Coastguard Worker    } else
660*89c4ff92SAndroid Build Coastguard Worker       return 0;
661*89c4ff92SAndroid Build Coastguard Worker }
662*89c4ff92SAndroid Build Coastguard Worker #endif // STBI_WRITE_NO_STDIO
663*89c4ff92SAndroid Build Coastguard Worker 
664*89c4ff92SAndroid Build Coastguard Worker 
665*89c4ff92SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
666*89c4ff92SAndroid Build Coastguard Worker //
667*89c4ff92SAndroid Build Coastguard Worker // PNG writer
668*89c4ff92SAndroid Build Coastguard Worker //
669*89c4ff92SAndroid Build Coastguard Worker 
670*89c4ff92SAndroid Build Coastguard Worker // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
671*89c4ff92SAndroid Build Coastguard Worker #define stbiw__sbraw(a) ((int *) (a) - 2)
672*89c4ff92SAndroid Build Coastguard Worker #define stbiw__sbm(a)   stbiw__sbraw(a)[0]
673*89c4ff92SAndroid Build Coastguard Worker #define stbiw__sbn(a)   stbiw__sbraw(a)[1]
674*89c4ff92SAndroid Build Coastguard Worker 
675*89c4ff92SAndroid Build Coastguard Worker #define stbiw__sbneedgrow(a,n)  ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
676*89c4ff92SAndroid Build Coastguard Worker #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
677*89c4ff92SAndroid Build Coastguard Worker #define stbiw__sbgrow(a,n)  stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
678*89c4ff92SAndroid Build Coastguard Worker 
679*89c4ff92SAndroid Build Coastguard Worker #define stbiw__sbpush(a, v)      (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
680*89c4ff92SAndroid Build Coastguard Worker #define stbiw__sbcount(a)        ((a) ? stbiw__sbn(a) : 0)
681*89c4ff92SAndroid Build Coastguard Worker #define stbiw__sbfree(a)         ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
682*89c4ff92SAndroid Build Coastguard Worker 
stbiw__sbgrowf(void ** arr,int increment,int itemsize)683*89c4ff92SAndroid Build Coastguard Worker static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
684*89c4ff92SAndroid Build Coastguard Worker {
685*89c4ff92SAndroid Build Coastguard Worker    int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
686*89c4ff92SAndroid Build Coastguard Worker    void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
687*89c4ff92SAndroid Build Coastguard Worker    STBIW_ASSERT(p);
688*89c4ff92SAndroid Build Coastguard Worker    if (p) {
689*89c4ff92SAndroid Build Coastguard Worker       if (!*arr) ((int *) p)[1] = 0;
690*89c4ff92SAndroid Build Coastguard Worker       *arr = (void *) ((int *) p + 2);
691*89c4ff92SAndroid Build Coastguard Worker       stbiw__sbm(*arr) = m;
692*89c4ff92SAndroid Build Coastguard Worker    }
693*89c4ff92SAndroid Build Coastguard Worker    return *arr;
694*89c4ff92SAndroid Build Coastguard Worker }
695*89c4ff92SAndroid Build Coastguard Worker 
stbiw__zlib_flushf(unsigned char * data,unsigned int * bitbuffer,int * bitcount)696*89c4ff92SAndroid Build Coastguard Worker static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
697*89c4ff92SAndroid Build Coastguard Worker {
698*89c4ff92SAndroid Build Coastguard Worker    while (*bitcount >= 8) {
699*89c4ff92SAndroid Build Coastguard Worker       stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
700*89c4ff92SAndroid Build Coastguard Worker       *bitbuffer >>= 8;
701*89c4ff92SAndroid Build Coastguard Worker       *bitcount -= 8;
702*89c4ff92SAndroid Build Coastguard Worker    }
703*89c4ff92SAndroid Build Coastguard Worker    return data;
704*89c4ff92SAndroid Build Coastguard Worker }
705*89c4ff92SAndroid Build Coastguard Worker 
stbiw__zlib_bitrev(int code,int codebits)706*89c4ff92SAndroid Build Coastguard Worker static int stbiw__zlib_bitrev(int code, int codebits)
707*89c4ff92SAndroid Build Coastguard Worker {
708*89c4ff92SAndroid Build Coastguard Worker    int res=0;
709*89c4ff92SAndroid Build Coastguard Worker    while (codebits--) {
710*89c4ff92SAndroid Build Coastguard Worker       res = (res << 1) | (code & 1);
711*89c4ff92SAndroid Build Coastguard Worker       code >>= 1;
712*89c4ff92SAndroid Build Coastguard Worker    }
713*89c4ff92SAndroid Build Coastguard Worker    return res;
714*89c4ff92SAndroid Build Coastguard Worker }
715*89c4ff92SAndroid Build Coastguard Worker 
stbiw__zlib_countm(unsigned char * a,unsigned char * b,int limit)716*89c4ff92SAndroid Build Coastguard Worker static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
717*89c4ff92SAndroid Build Coastguard Worker {
718*89c4ff92SAndroid Build Coastguard Worker    int i;
719*89c4ff92SAndroid Build Coastguard Worker    for (i=0; i < limit && i < 258; ++i)
720*89c4ff92SAndroid Build Coastguard Worker       if (a[i] != b[i]) break;
721*89c4ff92SAndroid Build Coastguard Worker    return i;
722*89c4ff92SAndroid Build Coastguard Worker }
723*89c4ff92SAndroid Build Coastguard Worker 
stbiw__zhash(unsigned char * data)724*89c4ff92SAndroid Build Coastguard Worker static unsigned int stbiw__zhash(unsigned char *data)
725*89c4ff92SAndroid Build Coastguard Worker {
726*89c4ff92SAndroid Build Coastguard Worker    stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
727*89c4ff92SAndroid Build Coastguard Worker    hash ^= hash << 3;
728*89c4ff92SAndroid Build Coastguard Worker    hash += hash >> 5;
729*89c4ff92SAndroid Build Coastguard Worker    hash ^= hash << 4;
730*89c4ff92SAndroid Build Coastguard Worker    hash += hash >> 17;
731*89c4ff92SAndroid Build Coastguard Worker    hash ^= hash << 25;
732*89c4ff92SAndroid Build Coastguard Worker    hash += hash >> 6;
733*89c4ff92SAndroid Build Coastguard Worker    return hash;
734*89c4ff92SAndroid Build Coastguard Worker }
735*89c4ff92SAndroid Build Coastguard Worker 
736*89c4ff92SAndroid Build Coastguard Worker #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
737*89c4ff92SAndroid Build Coastguard Worker #define stbiw__zlib_add(code,codebits) \
738*89c4ff92SAndroid Build Coastguard Worker       (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
739*89c4ff92SAndroid Build Coastguard Worker #define stbiw__zlib_huffa(b,c)  stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
740*89c4ff92SAndroid Build Coastguard Worker // default huffman tables
741*89c4ff92SAndroid Build Coastguard Worker #define stbiw__zlib_huff1(n)  stbiw__zlib_huffa(0x30 + (n), 8)
742*89c4ff92SAndroid Build Coastguard Worker #define stbiw__zlib_huff2(n)  stbiw__zlib_huffa(0x190 + (n)-144, 9)
743*89c4ff92SAndroid Build Coastguard Worker #define stbiw__zlib_huff3(n)  stbiw__zlib_huffa(0 + (n)-256,7)
744*89c4ff92SAndroid Build Coastguard Worker #define stbiw__zlib_huff4(n)  stbiw__zlib_huffa(0xc0 + (n)-280,8)
745*89c4ff92SAndroid Build Coastguard Worker #define stbiw__zlib_huff(n)  ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n))
746*89c4ff92SAndroid Build Coastguard Worker #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
747*89c4ff92SAndroid Build Coastguard Worker 
748*89c4ff92SAndroid Build Coastguard Worker #define stbiw__ZHASH   16384
749*89c4ff92SAndroid Build Coastguard Worker 
stbi_zlib_compress(unsigned char * data,int data_len,int * out_len,int quality)750*89c4ff92SAndroid Build Coastguard Worker unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
751*89c4ff92SAndroid Build Coastguard Worker {
752*89c4ff92SAndroid Build Coastguard Worker    static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 };
753*89c4ff92SAndroid Build Coastguard Worker    static unsigned char  lengtheb[]= { 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 };
754*89c4ff92SAndroid Build Coastguard Worker    static unsigned short distc[]   = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 };
755*89c4ff92SAndroid Build Coastguard Worker    static unsigned char  disteb[]  = { 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 };
756*89c4ff92SAndroid Build Coastguard Worker    unsigned int bitbuf=0;
757*89c4ff92SAndroid Build Coastguard Worker    int i,j, bitcount=0;
758*89c4ff92SAndroid Build Coastguard Worker    unsigned char *out = NULL;
759*89c4ff92SAndroid Build Coastguard Worker    unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**));
760*89c4ff92SAndroid Build Coastguard Worker    if (quality < 5) quality = 5;
761*89c4ff92SAndroid Build Coastguard Worker 
762*89c4ff92SAndroid Build Coastguard Worker    stbiw__sbpush(out, 0x78);   // DEFLATE 32K window
763*89c4ff92SAndroid Build Coastguard Worker    stbiw__sbpush(out, 0x5e);   // FLEVEL = 1
764*89c4ff92SAndroid Build Coastguard Worker    stbiw__zlib_add(1,1);  // BFINAL = 1
765*89c4ff92SAndroid Build Coastguard Worker    stbiw__zlib_add(1,2);  // BTYPE = 1 -- fixed huffman
766*89c4ff92SAndroid Build Coastguard Worker 
767*89c4ff92SAndroid Build Coastguard Worker    for (i=0; i < stbiw__ZHASH; ++i)
768*89c4ff92SAndroid Build Coastguard Worker       hash_table[i] = NULL;
769*89c4ff92SAndroid Build Coastguard Worker 
770*89c4ff92SAndroid Build Coastguard Worker    i=0;
771*89c4ff92SAndroid Build Coastguard Worker    while (i < data_len-3) {
772*89c4ff92SAndroid Build Coastguard Worker       // hash next 3 bytes of data to be compressed
773*89c4ff92SAndroid Build Coastguard Worker       int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
774*89c4ff92SAndroid Build Coastguard Worker       unsigned char *bestloc = 0;
775*89c4ff92SAndroid Build Coastguard Worker       unsigned char **hlist = hash_table[h];
776*89c4ff92SAndroid Build Coastguard Worker       int n = stbiw__sbcount(hlist);
777*89c4ff92SAndroid Build Coastguard Worker       for (j=0; j < n; ++j) {
778*89c4ff92SAndroid Build Coastguard Worker          if (hlist[j]-data > i-32768) { // if entry lies within window
779*89c4ff92SAndroid Build Coastguard Worker             int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
780*89c4ff92SAndroid Build Coastguard Worker             if (d >= best) best=d,bestloc=hlist[j];
781*89c4ff92SAndroid Build Coastguard Worker          }
782*89c4ff92SAndroid Build Coastguard Worker       }
783*89c4ff92SAndroid Build Coastguard Worker       // when hash table entry is too long, delete half the entries
784*89c4ff92SAndroid Build Coastguard Worker       if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
785*89c4ff92SAndroid Build Coastguard Worker          STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
786*89c4ff92SAndroid Build Coastguard Worker          stbiw__sbn(hash_table[h]) = quality;
787*89c4ff92SAndroid Build Coastguard Worker       }
788*89c4ff92SAndroid Build Coastguard Worker       stbiw__sbpush(hash_table[h],data+i);
789*89c4ff92SAndroid Build Coastguard Worker 
790*89c4ff92SAndroid Build Coastguard Worker       if (bestloc) {
791*89c4ff92SAndroid Build Coastguard Worker          // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
792*89c4ff92SAndroid Build Coastguard Worker          h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
793*89c4ff92SAndroid Build Coastguard Worker          hlist = hash_table[h];
794*89c4ff92SAndroid Build Coastguard Worker          n = stbiw__sbcount(hlist);
795*89c4ff92SAndroid Build Coastguard Worker          for (j=0; j < n; ++j) {
796*89c4ff92SAndroid Build Coastguard Worker             if (hlist[j]-data > i-32767) {
797*89c4ff92SAndroid Build Coastguard Worker                int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
798*89c4ff92SAndroid Build Coastguard Worker                if (e > best) { // if next match is better, bail on current match
799*89c4ff92SAndroid Build Coastguard Worker                   bestloc = NULL;
800*89c4ff92SAndroid Build Coastguard Worker                   break;
801*89c4ff92SAndroid Build Coastguard Worker                }
802*89c4ff92SAndroid Build Coastguard Worker             }
803*89c4ff92SAndroid Build Coastguard Worker          }
804*89c4ff92SAndroid Build Coastguard Worker       }
805*89c4ff92SAndroid Build Coastguard Worker 
806*89c4ff92SAndroid Build Coastguard Worker       if (bestloc) {
807*89c4ff92SAndroid Build Coastguard Worker          int d = (int) (data+i - bestloc); // distance back
808*89c4ff92SAndroid Build Coastguard Worker          STBIW_ASSERT(d <= 32767 && best <= 258);
809*89c4ff92SAndroid Build Coastguard Worker          for (j=0; best > lengthc[j+1]-1; ++j);
810*89c4ff92SAndroid Build Coastguard Worker          stbiw__zlib_huff(j+257);
811*89c4ff92SAndroid Build Coastguard Worker          if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
812*89c4ff92SAndroid Build Coastguard Worker          for (j=0; d > distc[j+1]-1; ++j);
813*89c4ff92SAndroid Build Coastguard Worker          stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
814*89c4ff92SAndroid Build Coastguard Worker          if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
815*89c4ff92SAndroid Build Coastguard Worker          i += best;
816*89c4ff92SAndroid Build Coastguard Worker       } else {
817*89c4ff92SAndroid Build Coastguard Worker          stbiw__zlib_huffb(data[i]);
818*89c4ff92SAndroid Build Coastguard Worker          ++i;
819*89c4ff92SAndroid Build Coastguard Worker       }
820*89c4ff92SAndroid Build Coastguard Worker    }
821*89c4ff92SAndroid Build Coastguard Worker    // write out final bytes
822*89c4ff92SAndroid Build Coastguard Worker    for (;i < data_len; ++i)
823*89c4ff92SAndroid Build Coastguard Worker       stbiw__zlib_huffb(data[i]);
824*89c4ff92SAndroid Build Coastguard Worker    stbiw__zlib_huff(256); // end of block
825*89c4ff92SAndroid Build Coastguard Worker    // pad with 0 bits to byte boundary
826*89c4ff92SAndroid Build Coastguard Worker    while (bitcount)
827*89c4ff92SAndroid Build Coastguard Worker       stbiw__zlib_add(0,1);
828*89c4ff92SAndroid Build Coastguard Worker 
829*89c4ff92SAndroid Build Coastguard Worker    for (i=0; i < stbiw__ZHASH; ++i)
830*89c4ff92SAndroid Build Coastguard Worker       (void) stbiw__sbfree(hash_table[i]);
831*89c4ff92SAndroid Build Coastguard Worker    STBIW_FREE(hash_table);
832*89c4ff92SAndroid Build Coastguard Worker 
833*89c4ff92SAndroid Build Coastguard Worker    {
834*89c4ff92SAndroid Build Coastguard Worker       // compute adler32 on input
835*89c4ff92SAndroid Build Coastguard Worker       unsigned int s1=1, s2=0;
836*89c4ff92SAndroid Build Coastguard Worker       int blocklen = (int) (data_len % 5552);
837*89c4ff92SAndroid Build Coastguard Worker       j=0;
838*89c4ff92SAndroid Build Coastguard Worker       while (j < data_len) {
839*89c4ff92SAndroid Build Coastguard Worker          for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
840*89c4ff92SAndroid Build Coastguard Worker          s1 %= 65521, s2 %= 65521;
841*89c4ff92SAndroid Build Coastguard Worker          j += blocklen;
842*89c4ff92SAndroid Build Coastguard Worker          blocklen = 5552;
843*89c4ff92SAndroid Build Coastguard Worker       }
844*89c4ff92SAndroid Build Coastguard Worker       stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
845*89c4ff92SAndroid Build Coastguard Worker       stbiw__sbpush(out, STBIW_UCHAR(s2));
846*89c4ff92SAndroid Build Coastguard Worker       stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
847*89c4ff92SAndroid Build Coastguard Worker       stbiw__sbpush(out, STBIW_UCHAR(s1));
848*89c4ff92SAndroid Build Coastguard Worker    }
849*89c4ff92SAndroid Build Coastguard Worker    *out_len = stbiw__sbn(out);
850*89c4ff92SAndroid Build Coastguard Worker    // make returned pointer freeable
851*89c4ff92SAndroid Build Coastguard Worker    STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
852*89c4ff92SAndroid Build Coastguard Worker    return (unsigned char *) stbiw__sbraw(out);
853*89c4ff92SAndroid Build Coastguard Worker }
854*89c4ff92SAndroid Build Coastguard Worker 
stbiw__crc32(unsigned char * buffer,int len)855*89c4ff92SAndroid Build Coastguard Worker static unsigned int stbiw__crc32(unsigned char *buffer, int len)
856*89c4ff92SAndroid Build Coastguard Worker {
857*89c4ff92SAndroid Build Coastguard Worker    static unsigned int crc_table[256] =
858*89c4ff92SAndroid Build Coastguard Worker    {
859*89c4ff92SAndroid Build Coastguard Worker       0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
860*89c4ff92SAndroid Build Coastguard Worker       0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
861*89c4ff92SAndroid Build Coastguard Worker       0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
862*89c4ff92SAndroid Build Coastguard Worker       0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
863*89c4ff92SAndroid Build Coastguard Worker       0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
864*89c4ff92SAndroid Build Coastguard Worker       0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
865*89c4ff92SAndroid Build Coastguard Worker       0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
866*89c4ff92SAndroid Build Coastguard Worker       0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
867*89c4ff92SAndroid Build Coastguard Worker       0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
868*89c4ff92SAndroid Build Coastguard Worker       0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
869*89c4ff92SAndroid Build Coastguard Worker       0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
870*89c4ff92SAndroid Build Coastguard Worker       0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
871*89c4ff92SAndroid Build Coastguard Worker       0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
872*89c4ff92SAndroid Build Coastguard Worker       0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
873*89c4ff92SAndroid Build Coastguard Worker       0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
874*89c4ff92SAndroid Build Coastguard Worker       0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
875*89c4ff92SAndroid Build Coastguard Worker       0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
876*89c4ff92SAndroid Build Coastguard Worker       0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
877*89c4ff92SAndroid Build Coastguard Worker       0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
878*89c4ff92SAndroid Build Coastguard Worker       0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
879*89c4ff92SAndroid Build Coastguard Worker       0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
880*89c4ff92SAndroid Build Coastguard Worker       0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
881*89c4ff92SAndroid Build Coastguard Worker       0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
882*89c4ff92SAndroid Build Coastguard Worker       0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
883*89c4ff92SAndroid Build Coastguard Worker       0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
884*89c4ff92SAndroid Build Coastguard Worker       0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
885*89c4ff92SAndroid Build Coastguard Worker       0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
886*89c4ff92SAndroid Build Coastguard Worker       0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
887*89c4ff92SAndroid Build Coastguard Worker       0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
888*89c4ff92SAndroid Build Coastguard Worker       0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
889*89c4ff92SAndroid Build Coastguard Worker       0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
890*89c4ff92SAndroid Build Coastguard Worker       0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
891*89c4ff92SAndroid Build Coastguard Worker    };
892*89c4ff92SAndroid Build Coastguard Worker 
893*89c4ff92SAndroid Build Coastguard Worker    unsigned int crc = ~0u;
894*89c4ff92SAndroid Build Coastguard Worker    int i;
895*89c4ff92SAndroid Build Coastguard Worker    for (i=0; i < len; ++i)
896*89c4ff92SAndroid Build Coastguard Worker       crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
897*89c4ff92SAndroid Build Coastguard Worker    return ~crc;
898*89c4ff92SAndroid Build Coastguard Worker }
899*89c4ff92SAndroid Build Coastguard Worker 
900*89c4ff92SAndroid Build Coastguard Worker #define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4)
901*89c4ff92SAndroid Build Coastguard Worker #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
902*89c4ff92SAndroid Build Coastguard Worker #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
903*89c4ff92SAndroid Build Coastguard Worker 
stbiw__wpcrc(unsigned char ** data,int len)904*89c4ff92SAndroid Build Coastguard Worker static void stbiw__wpcrc(unsigned char **data, int len)
905*89c4ff92SAndroid Build Coastguard Worker {
906*89c4ff92SAndroid Build Coastguard Worker    unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
907*89c4ff92SAndroid Build Coastguard Worker    stbiw__wp32(*data, crc);
908*89c4ff92SAndroid Build Coastguard Worker }
909*89c4ff92SAndroid Build Coastguard Worker 
stbiw__paeth(int a,int b,int c)910*89c4ff92SAndroid Build Coastguard Worker static unsigned char stbiw__paeth(int a, int b, int c)
911*89c4ff92SAndroid Build Coastguard Worker {
912*89c4ff92SAndroid Build Coastguard Worker    int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
913*89c4ff92SAndroid Build Coastguard Worker    if (pa <= pb && pa <= pc) return STBIW_UCHAR(a);
914*89c4ff92SAndroid Build Coastguard Worker    if (pb <= pc) return STBIW_UCHAR(b);
915*89c4ff92SAndroid Build Coastguard Worker    return STBIW_UCHAR(c);
916*89c4ff92SAndroid Build Coastguard Worker }
917*89c4ff92SAndroid Build Coastguard Worker 
918*89c4ff92SAndroid Build Coastguard Worker // @OPTIMIZE: provide an option that always forces left-predict or paeth predict
stbi_write_png_to_mem(unsigned char * pixels,int stride_bytes,int x,int y,int n,int * out_len)919*89c4ff92SAndroid Build Coastguard Worker unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
920*89c4ff92SAndroid Build Coastguard Worker {
921*89c4ff92SAndroid Build Coastguard Worker    int ctype[5] = { -1, 0, 4, 2, 6 };
922*89c4ff92SAndroid Build Coastguard Worker    unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
923*89c4ff92SAndroid Build Coastguard Worker    unsigned char *out,*o, *filt, *zlib;
924*89c4ff92SAndroid Build Coastguard Worker    signed char *line_buffer;
925*89c4ff92SAndroid Build Coastguard Worker    int i,j,k,p,zlen;
926*89c4ff92SAndroid Build Coastguard Worker 
927*89c4ff92SAndroid Build Coastguard Worker    if (stride_bytes == 0)
928*89c4ff92SAndroid Build Coastguard Worker       stride_bytes = x * n;
929*89c4ff92SAndroid Build Coastguard Worker 
930*89c4ff92SAndroid Build Coastguard Worker    filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
931*89c4ff92SAndroid Build Coastguard Worker    line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
932*89c4ff92SAndroid Build Coastguard Worker    for (j=0; j < y; ++j) {
933*89c4ff92SAndroid Build Coastguard Worker       static int mapping[] = { 0,1,2,3,4 };
934*89c4ff92SAndroid Build Coastguard Worker       static int firstmap[] = { 0,1,0,5,6 };
935*89c4ff92SAndroid Build Coastguard Worker       int *mymap = (j != 0) ? mapping : firstmap;
936*89c4ff92SAndroid Build Coastguard Worker       int best = 0, bestval = 0x7fffffff;
937*89c4ff92SAndroid Build Coastguard Worker       for (p=0; p < 2; ++p) {
938*89c4ff92SAndroid Build Coastguard Worker          for (k= p?best:0; k < 5; ++k) { // @TODO: clarity: rewrite this to go 0..5, and 'continue' the unwanted ones during 2nd pass
939*89c4ff92SAndroid Build Coastguard Worker             int type = mymap[k],est=0;
940*89c4ff92SAndroid Build Coastguard Worker             unsigned char *z = pixels + stride_bytes*j;
941*89c4ff92SAndroid Build Coastguard Worker             for (i=0; i < n; ++i)
942*89c4ff92SAndroid Build Coastguard Worker                switch (type) {
943*89c4ff92SAndroid Build Coastguard Worker                   case 0: line_buffer[i] = z[i]; break;
944*89c4ff92SAndroid Build Coastguard Worker                   case 1: line_buffer[i] = z[i]; break;
945*89c4ff92SAndroid Build Coastguard Worker                   case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
946*89c4ff92SAndroid Build Coastguard Worker                   case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
947*89c4ff92SAndroid Build Coastguard Worker                   case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break;
948*89c4ff92SAndroid Build Coastguard Worker                   case 5: line_buffer[i] = z[i]; break;
949*89c4ff92SAndroid Build Coastguard Worker                   case 6: line_buffer[i] = z[i]; break;
950*89c4ff92SAndroid Build Coastguard Worker                }
951*89c4ff92SAndroid Build Coastguard Worker             for (i=n; i < x*n; ++i) {
952*89c4ff92SAndroid Build Coastguard Worker                switch (type) {
953*89c4ff92SAndroid Build Coastguard Worker                   case 0: line_buffer[i] = z[i]; break;
954*89c4ff92SAndroid Build Coastguard Worker                   case 1: line_buffer[i] = z[i] - z[i-n]; break;
955*89c4ff92SAndroid Build Coastguard Worker                   case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
956*89c4ff92SAndroid Build Coastguard Worker                   case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
957*89c4ff92SAndroid Build Coastguard Worker                   case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
958*89c4ff92SAndroid Build Coastguard Worker                   case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
959*89c4ff92SAndroid Build Coastguard Worker                   case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
960*89c4ff92SAndroid Build Coastguard Worker                }
961*89c4ff92SAndroid Build Coastguard Worker             }
962*89c4ff92SAndroid Build Coastguard Worker             if (p) break;
963*89c4ff92SAndroid Build Coastguard Worker             for (i=0; i < x*n; ++i)
964*89c4ff92SAndroid Build Coastguard Worker                est += abs((signed char) line_buffer[i]);
965*89c4ff92SAndroid Build Coastguard Worker             if (est < bestval) { bestval = est; best = k; }
966*89c4ff92SAndroid Build Coastguard Worker          }
967*89c4ff92SAndroid Build Coastguard Worker       }
968*89c4ff92SAndroid Build Coastguard Worker       // when we get here, best contains the filter type, and line_buffer contains the data
969*89c4ff92SAndroid Build Coastguard Worker       filt[j*(x*n+1)] = (unsigned char) best;
970*89c4ff92SAndroid Build Coastguard Worker       STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
971*89c4ff92SAndroid Build Coastguard Worker    }
972*89c4ff92SAndroid Build Coastguard Worker    STBIW_FREE(line_buffer);
973*89c4ff92SAndroid Build Coastguard Worker    zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
974*89c4ff92SAndroid Build Coastguard Worker    STBIW_FREE(filt);
975*89c4ff92SAndroid Build Coastguard Worker    if (!zlib) return 0;
976*89c4ff92SAndroid Build Coastguard Worker 
977*89c4ff92SAndroid Build Coastguard Worker    // each tag requires 12 bytes of overhead
978*89c4ff92SAndroid Build Coastguard Worker    out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
979*89c4ff92SAndroid Build Coastguard Worker    if (!out) return 0;
980*89c4ff92SAndroid Build Coastguard Worker    *out_len = 8 + 12+13 + 12+zlen + 12;
981*89c4ff92SAndroid Build Coastguard Worker 
982*89c4ff92SAndroid Build Coastguard Worker    o=out;
983*89c4ff92SAndroid Build Coastguard Worker    STBIW_MEMMOVE(o,sig,8); o+= 8;
984*89c4ff92SAndroid Build Coastguard Worker    stbiw__wp32(o, 13); // header length
985*89c4ff92SAndroid Build Coastguard Worker    stbiw__wptag(o, "IHDR");
986*89c4ff92SAndroid Build Coastguard Worker    stbiw__wp32(o, x);
987*89c4ff92SAndroid Build Coastguard Worker    stbiw__wp32(o, y);
988*89c4ff92SAndroid Build Coastguard Worker    *o++ = 8;
989*89c4ff92SAndroid Build Coastguard Worker    *o++ = STBIW_UCHAR(ctype[n]);
990*89c4ff92SAndroid Build Coastguard Worker    *o++ = 0;
991*89c4ff92SAndroid Build Coastguard Worker    *o++ = 0;
992*89c4ff92SAndroid Build Coastguard Worker    *o++ = 0;
993*89c4ff92SAndroid Build Coastguard Worker    stbiw__wpcrc(&o,13);
994*89c4ff92SAndroid Build Coastguard Worker 
995*89c4ff92SAndroid Build Coastguard Worker    stbiw__wp32(o, zlen);
996*89c4ff92SAndroid Build Coastguard Worker    stbiw__wptag(o, "IDAT");
997*89c4ff92SAndroid Build Coastguard Worker    STBIW_MEMMOVE(o, zlib, zlen);
998*89c4ff92SAndroid Build Coastguard Worker    o += zlen;
999*89c4ff92SAndroid Build Coastguard Worker    STBIW_FREE(zlib);
1000*89c4ff92SAndroid Build Coastguard Worker    stbiw__wpcrc(&o, zlen);
1001*89c4ff92SAndroid Build Coastguard Worker 
1002*89c4ff92SAndroid Build Coastguard Worker    stbiw__wp32(o,0);
1003*89c4ff92SAndroid Build Coastguard Worker    stbiw__wptag(o, "IEND");
1004*89c4ff92SAndroid Build Coastguard Worker    stbiw__wpcrc(&o,0);
1005*89c4ff92SAndroid Build Coastguard Worker 
1006*89c4ff92SAndroid Build Coastguard Worker    STBIW_ASSERT(o == out + *out_len);
1007*89c4ff92SAndroid Build Coastguard Worker 
1008*89c4ff92SAndroid Build Coastguard Worker    return out;
1009*89c4ff92SAndroid Build Coastguard Worker }
1010*89c4ff92SAndroid Build Coastguard Worker 
1011*89c4ff92SAndroid Build Coastguard Worker #ifndef STBI_WRITE_NO_STDIO
stbi_write_png(char const * filename,int x,int y,int comp,const void * data,int stride_bytes)1012*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
1013*89c4ff92SAndroid Build Coastguard Worker {
1014*89c4ff92SAndroid Build Coastguard Worker    FILE *f;
1015*89c4ff92SAndroid Build Coastguard Worker    int len;
1016*89c4ff92SAndroid Build Coastguard Worker    unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
1017*89c4ff92SAndroid Build Coastguard Worker    if (png == NULL) return 0;
1018*89c4ff92SAndroid Build Coastguard Worker    f = fopen(filename, "wb");
1019*89c4ff92SAndroid Build Coastguard Worker    if (!f) { STBIW_FREE(png); return 0; }
1020*89c4ff92SAndroid Build Coastguard Worker    fwrite(png, 1, len, f);
1021*89c4ff92SAndroid Build Coastguard Worker    fclose(f);
1022*89c4ff92SAndroid Build Coastguard Worker    STBIW_FREE(png);
1023*89c4ff92SAndroid Build Coastguard Worker    return 1;
1024*89c4ff92SAndroid Build Coastguard Worker }
1025*89c4ff92SAndroid Build Coastguard Worker #endif
1026*89c4ff92SAndroid Build Coastguard Worker 
stbi_write_png_to_func(stbi_write_func * func,void * context,int x,int y,int comp,const void * data,int stride_bytes)1027*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes)
1028*89c4ff92SAndroid Build Coastguard Worker {
1029*89c4ff92SAndroid Build Coastguard Worker    int len;
1030*89c4ff92SAndroid Build Coastguard Worker    unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
1031*89c4ff92SAndroid Build Coastguard Worker    if (png == NULL) return 0;
1032*89c4ff92SAndroid Build Coastguard Worker    func(context, png, len);
1033*89c4ff92SAndroid Build Coastguard Worker    STBIW_FREE(png);
1034*89c4ff92SAndroid Build Coastguard Worker    return 1;
1035*89c4ff92SAndroid Build Coastguard Worker }
1036*89c4ff92SAndroid Build Coastguard Worker 
1037*89c4ff92SAndroid Build Coastguard Worker 
1038*89c4ff92SAndroid Build Coastguard Worker /* ***************************************************************************
1039*89c4ff92SAndroid Build Coastguard Worker  *
1040*89c4ff92SAndroid Build Coastguard Worker  * JPEG writer
1041*89c4ff92SAndroid Build Coastguard Worker  *
1042*89c4ff92SAndroid Build Coastguard Worker  * This is based on Jon Olick's jo_jpeg.cpp:
1043*89c4ff92SAndroid Build Coastguard Worker  * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html
1044*89c4ff92SAndroid Build Coastguard Worker  */
1045*89c4ff92SAndroid Build Coastguard Worker 
1046*89c4ff92SAndroid Build Coastguard Worker static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18,
1047*89c4ff92SAndroid Build Coastguard Worker       24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 };
1048*89c4ff92SAndroid Build Coastguard Worker 
stbiw__jpg_writeBits(stbi__write_context * s,int * bitBufP,int * bitCntP,const unsigned short * bs)1049*89c4ff92SAndroid Build Coastguard Worker static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) {
1050*89c4ff92SAndroid Build Coastguard Worker    int bitBuf = *bitBufP, bitCnt = *bitCntP;
1051*89c4ff92SAndroid Build Coastguard Worker    bitCnt += bs[1];
1052*89c4ff92SAndroid Build Coastguard Worker    bitBuf |= bs[0] << (24 - bitCnt);
1053*89c4ff92SAndroid Build Coastguard Worker    while(bitCnt >= 8) {
1054*89c4ff92SAndroid Build Coastguard Worker       unsigned char c = (bitBuf >> 16) & 255;
1055*89c4ff92SAndroid Build Coastguard Worker       stbiw__putc(s, c);
1056*89c4ff92SAndroid Build Coastguard Worker       if(c == 255) {
1057*89c4ff92SAndroid Build Coastguard Worker          stbiw__putc(s, 0);
1058*89c4ff92SAndroid Build Coastguard Worker       }
1059*89c4ff92SAndroid Build Coastguard Worker       bitBuf <<= 8;
1060*89c4ff92SAndroid Build Coastguard Worker       bitCnt -= 8;
1061*89c4ff92SAndroid Build Coastguard Worker    }
1062*89c4ff92SAndroid Build Coastguard Worker    *bitBufP = bitBuf;
1063*89c4ff92SAndroid Build Coastguard Worker    *bitCntP = bitCnt;
1064*89c4ff92SAndroid Build Coastguard Worker }
1065*89c4ff92SAndroid Build Coastguard Worker 
stbiw__jpg_DCT(float * d0p,float * d1p,float * d2p,float * d3p,float * d4p,float * d5p,float * d6p,float * d7p)1066*89c4ff92SAndroid Build Coastguard Worker static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) {
1067*89c4ff92SAndroid Build Coastguard Worker    float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
1068*89c4ff92SAndroid Build Coastguard Worker    float z1, z2, z3, z4, z5, z11, z13;
1069*89c4ff92SAndroid Build Coastguard Worker 
1070*89c4ff92SAndroid Build Coastguard Worker    float tmp0 = d0 + d7;
1071*89c4ff92SAndroid Build Coastguard Worker    float tmp7 = d0 - d7;
1072*89c4ff92SAndroid Build Coastguard Worker    float tmp1 = d1 + d6;
1073*89c4ff92SAndroid Build Coastguard Worker    float tmp6 = d1 - d6;
1074*89c4ff92SAndroid Build Coastguard Worker    float tmp2 = d2 + d5;
1075*89c4ff92SAndroid Build Coastguard Worker    float tmp5 = d2 - d5;
1076*89c4ff92SAndroid Build Coastguard Worker    float tmp3 = d3 + d4;
1077*89c4ff92SAndroid Build Coastguard Worker    float tmp4 = d3 - d4;
1078*89c4ff92SAndroid Build Coastguard Worker 
1079*89c4ff92SAndroid Build Coastguard Worker    // Even part
1080*89c4ff92SAndroid Build Coastguard Worker    float tmp10 = tmp0 + tmp3;   // phase 2
1081*89c4ff92SAndroid Build Coastguard Worker    float tmp13 = tmp0 - tmp3;
1082*89c4ff92SAndroid Build Coastguard Worker    float tmp11 = tmp1 + tmp2;
1083*89c4ff92SAndroid Build Coastguard Worker    float tmp12 = tmp1 - tmp2;
1084*89c4ff92SAndroid Build Coastguard Worker 
1085*89c4ff92SAndroid Build Coastguard Worker    d0 = tmp10 + tmp11;       // phase 3
1086*89c4ff92SAndroid Build Coastguard Worker    d4 = tmp10 - tmp11;
1087*89c4ff92SAndroid Build Coastguard Worker 
1088*89c4ff92SAndroid Build Coastguard Worker    z1 = (tmp12 + tmp13) * 0.707106781f; // c4
1089*89c4ff92SAndroid Build Coastguard Worker    d2 = tmp13 + z1;       // phase 5
1090*89c4ff92SAndroid Build Coastguard Worker    d6 = tmp13 - z1;
1091*89c4ff92SAndroid Build Coastguard Worker 
1092*89c4ff92SAndroid Build Coastguard Worker    // Odd part
1093*89c4ff92SAndroid Build Coastguard Worker    tmp10 = tmp4 + tmp5;       // phase 2
1094*89c4ff92SAndroid Build Coastguard Worker    tmp11 = tmp5 + tmp6;
1095*89c4ff92SAndroid Build Coastguard Worker    tmp12 = tmp6 + tmp7;
1096*89c4ff92SAndroid Build Coastguard Worker 
1097*89c4ff92SAndroid Build Coastguard Worker    // The rotator is modified from fig 4-8 to avoid extra negations.
1098*89c4ff92SAndroid Build Coastguard Worker    z5 = (tmp10 - tmp12) * 0.382683433f; // c6
1099*89c4ff92SAndroid Build Coastguard Worker    z2 = tmp10 * 0.541196100f + z5; // c2-c6
1100*89c4ff92SAndroid Build Coastguard Worker    z4 = tmp12 * 1.306562965f + z5; // c2+c6
1101*89c4ff92SAndroid Build Coastguard Worker    z3 = tmp11 * 0.707106781f; // c4
1102*89c4ff92SAndroid Build Coastguard Worker 
1103*89c4ff92SAndroid Build Coastguard Worker    z11 = tmp7 + z3;      // phase 5
1104*89c4ff92SAndroid Build Coastguard Worker    z13 = tmp7 - z3;
1105*89c4ff92SAndroid Build Coastguard Worker 
1106*89c4ff92SAndroid Build Coastguard Worker    *d5p = z13 + z2;         // phase 6
1107*89c4ff92SAndroid Build Coastguard Worker    *d3p = z13 - z2;
1108*89c4ff92SAndroid Build Coastguard Worker    *d1p = z11 + z4;
1109*89c4ff92SAndroid Build Coastguard Worker    *d7p = z11 - z4;
1110*89c4ff92SAndroid Build Coastguard Worker 
1111*89c4ff92SAndroid Build Coastguard Worker    *d0p = d0;  *d2p = d2;  *d4p = d4;  *d6p = d6;
1112*89c4ff92SAndroid Build Coastguard Worker }
1113*89c4ff92SAndroid Build Coastguard Worker 
stbiw__jpg_calcBits(int val,unsigned short bits[2])1114*89c4ff92SAndroid Build Coastguard Worker static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) {
1115*89c4ff92SAndroid Build Coastguard Worker    int tmp1 = val < 0 ? -val : val;
1116*89c4ff92SAndroid Build Coastguard Worker    val = val < 0 ? val-1 : val;
1117*89c4ff92SAndroid Build Coastguard Worker    bits[1] = 1;
1118*89c4ff92SAndroid Build Coastguard Worker    while(tmp1 >>= 1) {
1119*89c4ff92SAndroid Build Coastguard Worker       ++bits[1];
1120*89c4ff92SAndroid Build Coastguard Worker    }
1121*89c4ff92SAndroid Build Coastguard Worker    bits[0] = val & ((1<<bits[1])-1);
1122*89c4ff92SAndroid Build Coastguard Worker }
1123*89c4ff92SAndroid Build Coastguard Worker 
stbiw__jpg_processDU(stbi__write_context * s,int * bitBuf,int * bitCnt,float * CDU,float * fdtbl,int DC,const unsigned short HTDC[256][2],const unsigned short HTAC[256][2])1124*89c4ff92SAndroid Build Coastguard Worker static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
1125*89c4ff92SAndroid Build Coastguard Worker    const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
1126*89c4ff92SAndroid Build Coastguard Worker    const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
1127*89c4ff92SAndroid Build Coastguard Worker    int dataOff, i, diff, end0pos;
1128*89c4ff92SAndroid Build Coastguard Worker    int DU[64];
1129*89c4ff92SAndroid Build Coastguard Worker 
1130*89c4ff92SAndroid Build Coastguard Worker    // DCT rows
1131*89c4ff92SAndroid Build Coastguard Worker    for(dataOff=0; dataOff<64; dataOff+=8) {
1132*89c4ff92SAndroid Build Coastguard Worker       stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+1], &CDU[dataOff+2], &CDU[dataOff+3], &CDU[dataOff+4], &CDU[dataOff+5], &CDU[dataOff+6], &CDU[dataOff+7]);
1133*89c4ff92SAndroid Build Coastguard Worker    }
1134*89c4ff92SAndroid Build Coastguard Worker    // DCT columns
1135*89c4ff92SAndroid Build Coastguard Worker    for(dataOff=0; dataOff<8; ++dataOff) {
1136*89c4ff92SAndroid Build Coastguard Worker       stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+8], &CDU[dataOff+16], &CDU[dataOff+24], &CDU[dataOff+32], &CDU[dataOff+40], &CDU[dataOff+48], &CDU[dataOff+56]);
1137*89c4ff92SAndroid Build Coastguard Worker    }
1138*89c4ff92SAndroid Build Coastguard Worker    // Quantize/descale/zigzag the coefficients
1139*89c4ff92SAndroid Build Coastguard Worker    for(i=0; i<64; ++i) {
1140*89c4ff92SAndroid Build Coastguard Worker       float v = CDU[i]*fdtbl[i];
1141*89c4ff92SAndroid Build Coastguard Worker       // DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
1142*89c4ff92SAndroid Build Coastguard Worker       // ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway?
1143*89c4ff92SAndroid Build Coastguard Worker       DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
1144*89c4ff92SAndroid Build Coastguard Worker    }
1145*89c4ff92SAndroid Build Coastguard Worker 
1146*89c4ff92SAndroid Build Coastguard Worker    // Encode DC
1147*89c4ff92SAndroid Build Coastguard Worker    diff = DU[0] - DC;
1148*89c4ff92SAndroid Build Coastguard Worker    if (diff == 0) {
1149*89c4ff92SAndroid Build Coastguard Worker       stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
1150*89c4ff92SAndroid Build Coastguard Worker    } else {
1151*89c4ff92SAndroid Build Coastguard Worker       unsigned short bits[2];
1152*89c4ff92SAndroid Build Coastguard Worker       stbiw__jpg_calcBits(diff, bits);
1153*89c4ff92SAndroid Build Coastguard Worker       stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
1154*89c4ff92SAndroid Build Coastguard Worker       stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1155*89c4ff92SAndroid Build Coastguard Worker    }
1156*89c4ff92SAndroid Build Coastguard Worker    // Encode ACs
1157*89c4ff92SAndroid Build Coastguard Worker    end0pos = 63;
1158*89c4ff92SAndroid Build Coastguard Worker    for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
1159*89c4ff92SAndroid Build Coastguard Worker    }
1160*89c4ff92SAndroid Build Coastguard Worker    // end0pos = first element in reverse order !=0
1161*89c4ff92SAndroid Build Coastguard Worker    if(end0pos == 0) {
1162*89c4ff92SAndroid Build Coastguard Worker       stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1163*89c4ff92SAndroid Build Coastguard Worker       return DU[0];
1164*89c4ff92SAndroid Build Coastguard Worker    }
1165*89c4ff92SAndroid Build Coastguard Worker    for(i = 1; i <= end0pos; ++i) {
1166*89c4ff92SAndroid Build Coastguard Worker       int startpos = i;
1167*89c4ff92SAndroid Build Coastguard Worker       int nrzeroes;
1168*89c4ff92SAndroid Build Coastguard Worker       unsigned short bits[2];
1169*89c4ff92SAndroid Build Coastguard Worker       for (; DU[i]==0 && i<=end0pos; ++i) {
1170*89c4ff92SAndroid Build Coastguard Worker       }
1171*89c4ff92SAndroid Build Coastguard Worker       nrzeroes = i-startpos;
1172*89c4ff92SAndroid Build Coastguard Worker       if ( nrzeroes >= 16 ) {
1173*89c4ff92SAndroid Build Coastguard Worker          int lng = nrzeroes>>4;
1174*89c4ff92SAndroid Build Coastguard Worker          int nrmarker;
1175*89c4ff92SAndroid Build Coastguard Worker          for (nrmarker=1; nrmarker <= lng; ++nrmarker)
1176*89c4ff92SAndroid Build Coastguard Worker             stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
1177*89c4ff92SAndroid Build Coastguard Worker          nrzeroes &= 15;
1178*89c4ff92SAndroid Build Coastguard Worker       }
1179*89c4ff92SAndroid Build Coastguard Worker       stbiw__jpg_calcBits(DU[i], bits);
1180*89c4ff92SAndroid Build Coastguard Worker       stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
1181*89c4ff92SAndroid Build Coastguard Worker       stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1182*89c4ff92SAndroid Build Coastguard Worker    }
1183*89c4ff92SAndroid Build Coastguard Worker    if(end0pos != 63) {
1184*89c4ff92SAndroid Build Coastguard Worker       stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1185*89c4ff92SAndroid Build Coastguard Worker    }
1186*89c4ff92SAndroid Build Coastguard Worker    return DU[0];
1187*89c4ff92SAndroid Build Coastguard Worker }
1188*89c4ff92SAndroid Build Coastguard Worker 
stbi_write_jpg_core(stbi__write_context * s,int width,int height,int comp,const void * data,int quality)1189*89c4ff92SAndroid Build Coastguard Worker static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) {
1190*89c4ff92SAndroid Build Coastguard Worker    // Constants that don't pollute global namespace
1191*89c4ff92SAndroid Build Coastguard Worker    static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0};
1192*89c4ff92SAndroid Build Coastguard Worker    static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1193*89c4ff92SAndroid Build Coastguard Worker    static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d};
1194*89c4ff92SAndroid Build Coastguard Worker    static const unsigned char std_ac_luminance_values[] = {
1195*89c4ff92SAndroid Build Coastguard Worker       0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
1196*89c4ff92SAndroid Build Coastguard Worker       0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
1197*89c4ff92SAndroid Build Coastguard Worker       0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
1198*89c4ff92SAndroid Build Coastguard Worker       0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1199*89c4ff92SAndroid Build Coastguard Worker       0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
1200*89c4ff92SAndroid Build Coastguard Worker       0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
1201*89c4ff92SAndroid Build Coastguard Worker       0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1202*89c4ff92SAndroid Build Coastguard Worker    };
1203*89c4ff92SAndroid Build Coastguard Worker    static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};
1204*89c4ff92SAndroid Build Coastguard Worker    static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1205*89c4ff92SAndroid Build Coastguard Worker    static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77};
1206*89c4ff92SAndroid Build Coastguard Worker    static const unsigned char std_ac_chrominance_values[] = {
1207*89c4ff92SAndroid Build Coastguard Worker       0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
1208*89c4ff92SAndroid Build Coastguard Worker       0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
1209*89c4ff92SAndroid Build Coastguard Worker       0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
1210*89c4ff92SAndroid Build Coastguard Worker       0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
1211*89c4ff92SAndroid Build Coastguard Worker       0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
1212*89c4ff92SAndroid Build Coastguard Worker       0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
1213*89c4ff92SAndroid Build Coastguard Worker       0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1214*89c4ff92SAndroid Build Coastguard Worker    };
1215*89c4ff92SAndroid Build Coastguard Worker    // Huffman tables
1216*89c4ff92SAndroid Build Coastguard Worker    static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}};
1217*89c4ff92SAndroid Build Coastguard Worker    static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}};
1218*89c4ff92SAndroid Build Coastguard Worker    static const unsigned short YAC_HT[256][2] = {
1219*89c4ff92SAndroid Build Coastguard Worker       {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1220*89c4ff92SAndroid Build Coastguard Worker       {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1221*89c4ff92SAndroid Build Coastguard Worker       {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1222*89c4ff92SAndroid Build Coastguard Worker       {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1223*89c4ff92SAndroid Build Coastguard Worker       {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1224*89c4ff92SAndroid Build Coastguard Worker       {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1225*89c4ff92SAndroid Build Coastguard Worker       {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1226*89c4ff92SAndroid Build Coastguard Worker       {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1227*89c4ff92SAndroid Build Coastguard Worker       {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1228*89c4ff92SAndroid Build Coastguard Worker       {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1229*89c4ff92SAndroid Build Coastguard Worker       {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1230*89c4ff92SAndroid Build Coastguard Worker       {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1231*89c4ff92SAndroid Build Coastguard Worker       {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1232*89c4ff92SAndroid Build Coastguard Worker       {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1233*89c4ff92SAndroid Build Coastguard Worker       {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0},
1234*89c4ff92SAndroid Build Coastguard Worker       {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
1235*89c4ff92SAndroid Build Coastguard Worker    };
1236*89c4ff92SAndroid Build Coastguard Worker    static const unsigned short UVAC_HT[256][2] = {
1237*89c4ff92SAndroid Build Coastguard Worker       {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1238*89c4ff92SAndroid Build Coastguard Worker       {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1239*89c4ff92SAndroid Build Coastguard Worker       {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1240*89c4ff92SAndroid Build Coastguard Worker       {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1241*89c4ff92SAndroid Build Coastguard Worker       {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1242*89c4ff92SAndroid Build Coastguard Worker       {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1243*89c4ff92SAndroid Build Coastguard Worker       {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1244*89c4ff92SAndroid Build Coastguard Worker       {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1245*89c4ff92SAndroid Build Coastguard Worker       {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1246*89c4ff92SAndroid Build Coastguard Worker       {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1247*89c4ff92SAndroid Build Coastguard Worker       {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1248*89c4ff92SAndroid Build Coastguard Worker       {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1249*89c4ff92SAndroid Build Coastguard Worker       {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1250*89c4ff92SAndroid Build Coastguard Worker       {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1251*89c4ff92SAndroid Build Coastguard Worker       {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0},
1252*89c4ff92SAndroid Build Coastguard Worker       {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
1253*89c4ff92SAndroid Build Coastguard Worker    };
1254*89c4ff92SAndroid Build Coastguard Worker    static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22,
1255*89c4ff92SAndroid Build Coastguard Worker                              37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99};
1256*89c4ff92SAndroid Build Coastguard Worker    static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99,
1257*89c4ff92SAndroid Build Coastguard Worker                               99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
1258*89c4ff92SAndroid Build Coastguard Worker    static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
1259*89c4ff92SAndroid Build Coastguard Worker                                  1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
1260*89c4ff92SAndroid Build Coastguard Worker 
1261*89c4ff92SAndroid Build Coastguard Worker    int row, col, i, k;
1262*89c4ff92SAndroid Build Coastguard Worker    float fdtbl_Y[64], fdtbl_UV[64];
1263*89c4ff92SAndroid Build Coastguard Worker    unsigned char YTable[64], UVTable[64];
1264*89c4ff92SAndroid Build Coastguard Worker 
1265*89c4ff92SAndroid Build Coastguard Worker    if(!data || !width || !height || comp > 4 || comp < 1) {
1266*89c4ff92SAndroid Build Coastguard Worker       return 0;
1267*89c4ff92SAndroid Build Coastguard Worker    }
1268*89c4ff92SAndroid Build Coastguard Worker 
1269*89c4ff92SAndroid Build Coastguard Worker    quality = quality ? quality : 90;
1270*89c4ff92SAndroid Build Coastguard Worker    quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
1271*89c4ff92SAndroid Build Coastguard Worker    quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
1272*89c4ff92SAndroid Build Coastguard Worker 
1273*89c4ff92SAndroid Build Coastguard Worker    for(i = 0; i < 64; ++i) {
1274*89c4ff92SAndroid Build Coastguard Worker       int uvti, yti = (YQT[i]*quality+50)/100;
1275*89c4ff92SAndroid Build Coastguard Worker       YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
1276*89c4ff92SAndroid Build Coastguard Worker       uvti = (UVQT[i]*quality+50)/100;
1277*89c4ff92SAndroid Build Coastguard Worker       UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
1278*89c4ff92SAndroid Build Coastguard Worker    }
1279*89c4ff92SAndroid Build Coastguard Worker 
1280*89c4ff92SAndroid Build Coastguard Worker    for(row = 0, k = 0; row < 8; ++row) {
1281*89c4ff92SAndroid Build Coastguard Worker       for(col = 0; col < 8; ++col, ++k) {
1282*89c4ff92SAndroid Build Coastguard Worker          fdtbl_Y[k]  = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1283*89c4ff92SAndroid Build Coastguard Worker          fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1284*89c4ff92SAndroid Build Coastguard Worker       }
1285*89c4ff92SAndroid Build Coastguard Worker    }
1286*89c4ff92SAndroid Build Coastguard Worker 
1287*89c4ff92SAndroid Build Coastguard Worker    // Write Headers
1288*89c4ff92SAndroid Build Coastguard Worker    {
1289*89c4ff92SAndroid Build Coastguard Worker       static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 };
1290*89c4ff92SAndroid Build Coastguard Worker       static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
1291*89c4ff92SAndroid Build Coastguard Worker       const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width),
1292*89c4ff92SAndroid Build Coastguard Worker                                       3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
1293*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, (void*)head0, sizeof(head0));
1294*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, (void*)YTable, sizeof(YTable));
1295*89c4ff92SAndroid Build Coastguard Worker       stbiw__putc(s, 1);
1296*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, UVTable, sizeof(UVTable));
1297*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, (void*)head1, sizeof(head1));
1298*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1);
1299*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values));
1300*89c4ff92SAndroid Build Coastguard Worker       stbiw__putc(s, 0x10); // HTYACinfo
1301*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1);
1302*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values));
1303*89c4ff92SAndroid Build Coastguard Worker       stbiw__putc(s, 1); // HTUDCinfo
1304*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1);
1305*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values));
1306*89c4ff92SAndroid Build Coastguard Worker       stbiw__putc(s, 0x11); // HTUACinfo
1307*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1);
1308*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values));
1309*89c4ff92SAndroid Build Coastguard Worker       s->func(s->context, (void*)head2, sizeof(head2));
1310*89c4ff92SAndroid Build Coastguard Worker    }
1311*89c4ff92SAndroid Build Coastguard Worker 
1312*89c4ff92SAndroid Build Coastguard Worker    // Encode 8x8 macroblocks
1313*89c4ff92SAndroid Build Coastguard Worker    {
1314*89c4ff92SAndroid Build Coastguard Worker       static const unsigned short fillBits[] = {0x7F, 7};
1315*89c4ff92SAndroid Build Coastguard Worker       const unsigned char *imageData = (const unsigned char *)data;
1316*89c4ff92SAndroid Build Coastguard Worker       int DCY=0, DCU=0, DCV=0;
1317*89c4ff92SAndroid Build Coastguard Worker       int bitBuf=0, bitCnt=0;
1318*89c4ff92SAndroid Build Coastguard Worker       // comp == 2 is grey+alpha (alpha is ignored)
1319*89c4ff92SAndroid Build Coastguard Worker       int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
1320*89c4ff92SAndroid Build Coastguard Worker       int x, y, pos;
1321*89c4ff92SAndroid Build Coastguard Worker       for(y = 0; y < height; y += 8) {
1322*89c4ff92SAndroid Build Coastguard Worker          for(x = 0; x < width; x += 8) {
1323*89c4ff92SAndroid Build Coastguard Worker             float YDU[64], UDU[64], VDU[64];
1324*89c4ff92SAndroid Build Coastguard Worker             for(row = y, pos = 0; row < y+8; ++row) {
1325*89c4ff92SAndroid Build Coastguard Worker                for(col = x; col < x+8; ++col, ++pos) {
1326*89c4ff92SAndroid Build Coastguard Worker                   int p = row*width*comp + col*comp;
1327*89c4ff92SAndroid Build Coastguard Worker                   float r, g, b;
1328*89c4ff92SAndroid Build Coastguard Worker                   if(row >= height) {
1329*89c4ff92SAndroid Build Coastguard Worker                      p -= width*comp*(row+1 - height);
1330*89c4ff92SAndroid Build Coastguard Worker                   }
1331*89c4ff92SAndroid Build Coastguard Worker                   if(col >= width) {
1332*89c4ff92SAndroid Build Coastguard Worker                      p -= comp*(col+1 - width);
1333*89c4ff92SAndroid Build Coastguard Worker                   }
1334*89c4ff92SAndroid Build Coastguard Worker 
1335*89c4ff92SAndroid Build Coastguard Worker                   r = imageData[p+0];
1336*89c4ff92SAndroid Build Coastguard Worker                   g = imageData[p+ofsG];
1337*89c4ff92SAndroid Build Coastguard Worker                   b = imageData[p+ofsB];
1338*89c4ff92SAndroid Build Coastguard Worker                   YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128;
1339*89c4ff92SAndroid Build Coastguard Worker                   UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b;
1340*89c4ff92SAndroid Build Coastguard Worker                   VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b;
1341*89c4ff92SAndroid Build Coastguard Worker                }
1342*89c4ff92SAndroid Build Coastguard Worker             }
1343*89c4ff92SAndroid Build Coastguard Worker 
1344*89c4ff92SAndroid Build Coastguard Worker             DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1345*89c4ff92SAndroid Build Coastguard Worker             DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1346*89c4ff92SAndroid Build Coastguard Worker             DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1347*89c4ff92SAndroid Build Coastguard Worker          }
1348*89c4ff92SAndroid Build Coastguard Worker       }
1349*89c4ff92SAndroid Build Coastguard Worker 
1350*89c4ff92SAndroid Build Coastguard Worker       // Do the bit alignment of the EOI marker
1351*89c4ff92SAndroid Build Coastguard Worker       stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
1352*89c4ff92SAndroid Build Coastguard Worker    }
1353*89c4ff92SAndroid Build Coastguard Worker 
1354*89c4ff92SAndroid Build Coastguard Worker    // EOI
1355*89c4ff92SAndroid Build Coastguard Worker    stbiw__putc(s, 0xFF);
1356*89c4ff92SAndroid Build Coastguard Worker    stbiw__putc(s, 0xD9);
1357*89c4ff92SAndroid Build Coastguard Worker 
1358*89c4ff92SAndroid Build Coastguard Worker    return 1;
1359*89c4ff92SAndroid Build Coastguard Worker }
1360*89c4ff92SAndroid Build Coastguard Worker 
stbi_write_jpg_to_func(stbi_write_func * func,void * context,int x,int y,int comp,const void * data,int quality)1361*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
1362*89c4ff92SAndroid Build Coastguard Worker {
1363*89c4ff92SAndroid Build Coastguard Worker    stbi__write_context s;
1364*89c4ff92SAndroid Build Coastguard Worker    stbi__start_write_callbacks(&s, func, context);
1365*89c4ff92SAndroid Build Coastguard Worker    return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality);
1366*89c4ff92SAndroid Build Coastguard Worker }
1367*89c4ff92SAndroid Build Coastguard Worker 
1368*89c4ff92SAndroid Build Coastguard Worker 
1369*89c4ff92SAndroid Build Coastguard Worker #ifndef STBI_WRITE_NO_STDIO
stbi_write_jpg(char const * filename,int x,int y,int comp,const void * data,int quality)1370*89c4ff92SAndroid Build Coastguard Worker STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
1371*89c4ff92SAndroid Build Coastguard Worker {
1372*89c4ff92SAndroid Build Coastguard Worker    stbi__write_context s;
1373*89c4ff92SAndroid Build Coastguard Worker    if (stbi__start_write_file(&s,filename)) {
1374*89c4ff92SAndroid Build Coastguard Worker       int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
1375*89c4ff92SAndroid Build Coastguard Worker       stbi__end_write_file(&s);
1376*89c4ff92SAndroid Build Coastguard Worker       return r;
1377*89c4ff92SAndroid Build Coastguard Worker    } else
1378*89c4ff92SAndroid Build Coastguard Worker       return 0;
1379*89c4ff92SAndroid Build Coastguard Worker }
1380*89c4ff92SAndroid Build Coastguard Worker #endif
1381*89c4ff92SAndroid Build Coastguard Worker 
1382*89c4ff92SAndroid Build Coastguard Worker #endif // STB_IMAGE_WRITE_IMPLEMENTATION
1383*89c4ff92SAndroid Build Coastguard Worker 
1384*89c4ff92SAndroid Build Coastguard Worker /* Revision history
1385*89c4ff92SAndroid Build Coastguard Worker       1.06 (2017-07-23)
1386*89c4ff92SAndroid Build Coastguard Worker              writing JPEG (using Jon Olick's code)
1387*89c4ff92SAndroid Build Coastguard Worker       1.05   ???
1388*89c4ff92SAndroid Build Coastguard Worker       1.04 (2017-03-03)
1389*89c4ff92SAndroid Build Coastguard Worker              monochrome BMP expansion
1390*89c4ff92SAndroid Build Coastguard Worker       1.03   ???
1391*89c4ff92SAndroid Build Coastguard Worker       1.02 (2016-04-02)
1392*89c4ff92SAndroid Build Coastguard Worker              avoid allocating large structures on the stack
1393*89c4ff92SAndroid Build Coastguard Worker       1.01 (2016-01-16)
1394*89c4ff92SAndroid Build Coastguard Worker              STBIW_REALLOC_SIZED: support allocators with no realloc support
1395*89c4ff92SAndroid Build Coastguard Worker              avoid race-condition in crc initialization
1396*89c4ff92SAndroid Build Coastguard Worker              minor compile issues
1397*89c4ff92SAndroid Build Coastguard Worker       1.00 (2015-09-14)
1398*89c4ff92SAndroid Build Coastguard Worker              installable file IO function
1399*89c4ff92SAndroid Build Coastguard Worker       0.99 (2015-09-13)
1400*89c4ff92SAndroid Build Coastguard Worker              warning fixes; TGA rle support
1401*89c4ff92SAndroid Build Coastguard Worker       0.98 (2015-04-08)
1402*89c4ff92SAndroid Build Coastguard Worker              added STBIW_MALLOC, STBIW_ASSERT etc
1403*89c4ff92SAndroid Build Coastguard Worker       0.97 (2015-01-18)
1404*89c4ff92SAndroid Build Coastguard Worker              fixed HDR asserts, rewrote HDR rle logic
1405*89c4ff92SAndroid Build Coastguard Worker       0.96 (2015-01-17)
1406*89c4ff92SAndroid Build Coastguard Worker              add HDR output
1407*89c4ff92SAndroid Build Coastguard Worker              fix monochrome BMP
1408*89c4ff92SAndroid Build Coastguard Worker       0.95 (2014-08-17)
1409*89c4ff92SAndroid Build Coastguard Worker 		       add monochrome TGA output
1410*89c4ff92SAndroid Build Coastguard Worker       0.94 (2014-05-31)
1411*89c4ff92SAndroid Build Coastguard Worker              rename private functions to avoid conflicts with stb_image.h
1412*89c4ff92SAndroid Build Coastguard Worker       0.93 (2014-05-27)
1413*89c4ff92SAndroid Build Coastguard Worker              warning fixes
1414*89c4ff92SAndroid Build Coastguard Worker       0.92 (2010-08-01)
1415*89c4ff92SAndroid Build Coastguard Worker              casts to unsigned char to fix warnings
1416*89c4ff92SAndroid Build Coastguard Worker       0.91 (2010-07-17)
1417*89c4ff92SAndroid Build Coastguard Worker              first public release
1418*89c4ff92SAndroid Build Coastguard Worker       0.90   first internal release
1419*89c4ff92SAndroid Build Coastguard Worker */
1420*89c4ff92SAndroid Build Coastguard Worker 
1421*89c4ff92SAndroid Build Coastguard Worker /*
1422*89c4ff92SAndroid Build Coastguard Worker ------------------------------------------------------------------------------
1423*89c4ff92SAndroid Build Coastguard Worker MIT License
1424*89c4ff92SAndroid Build Coastguard Worker Copyright (c) 2017 Sean Barrett
1425*89c4ff92SAndroid Build Coastguard Worker Permission is hereby granted, free of charge, to any person obtaining a copy of
1426*89c4ff92SAndroid Build Coastguard Worker this software and associated documentation files (the "Software"), to deal in
1427*89c4ff92SAndroid Build Coastguard Worker the Software without restriction, including without limitation the rights to
1428*89c4ff92SAndroid Build Coastguard Worker use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1429*89c4ff92SAndroid Build Coastguard Worker of the Software, and to permit persons to whom the Software is furnished to do
1430*89c4ff92SAndroid Build Coastguard Worker so, subject to the following conditions:
1431*89c4ff92SAndroid Build Coastguard Worker The above copyright notice and this permission notice shall be included in all
1432*89c4ff92SAndroid Build Coastguard Worker copies or substantial portions of the Software.
1433*89c4ff92SAndroid Build Coastguard Worker THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1434*89c4ff92SAndroid Build Coastguard Worker IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1435*89c4ff92SAndroid Build Coastguard Worker FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1436*89c4ff92SAndroid Build Coastguard Worker AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1437*89c4ff92SAndroid Build Coastguard Worker LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1438*89c4ff92SAndroid Build Coastguard Worker OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1439*89c4ff92SAndroid Build Coastguard Worker SOFTWARE.
1440*89c4ff92SAndroid Build Coastguard Worker ------------------------------------------------------------------------------
1441*89c4ff92SAndroid Build Coastguard Worker */
1442