yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
fc4c24244
master
1/* stb_image_write - v1.16 - public domain - http://nothings.org/stb 2writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 3no warranty implied; use at your own risk 4 5Before #including, 6 7#define STB_IMAGE_WRITE_IMPLEMENTATION 8 9in the file that you want to have the implementation. 10 11Will probably not work correctly with strict-aliasing optimizations. 12 13ABOUT: 14 15This header file is a library for writing images to C stdio or a callback. 16 17The PNG output is not optimal; it is 20-50% larger than the file 18written by a decent optimizing implementation; though providing a custom 19zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that. 20This library is designed for source code compactness and simplicity, 21not optimal image file size or run-time performance. 22 23BUILDING: 24 25You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. 26You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace 27malloc,realloc,free. 28You can #define STBIW_MEMMOVE() to replace memmove() 29You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function 30for PNG compression (instead of the builtin one), it must have the following signature: 31unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality); 32The returned data will be freed with STBIW_FREE() (free() by default), 33so it must be heap allocated with STBIW_MALLOC() (malloc() by default), 34 35UNICODE: 36 37If compiling for Windows and you wish to use Unicode filenames, compile 38with 39#define STBIW_WINDOWS_UTF8 40and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert 41Windows wchar_t filenames to utf8. 42 43USAGE: 44 45There are five functions, one for each image file format: 46 47int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); 48int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); 49int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); 50int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality); 51int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); 52 53void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically 54 55There are also five equivalent functions that use an arbitrary write function. You are 56expected to open/close your file-equivalent before and after calling these: 57 58int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); 59int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); 60int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); 61int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); 62int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); 63 64where the callback is: 65void stbi_write_func(void *context, void *data, int size); 66 67You can configure it with these global variables: 68int stbi_write_tga_with_rle; // defaults to true; set to 0 to disable RLE 69int stbi_write_png_compression_level; // defaults to 8; set to higher for more compression 70int stbi_write_force_png_filter; // defaults to -1; set to 0..5 to force a filter mode 71 72 73You can define STBI_WRITE_NO_STDIO to disable the file variant of these 74functions, so the library will not use stdio.h at all. However, this will 75also disable HDR writing, because it requires stdio for formatted output. 76 77Each function returns 0 on failure and non-0 on success. 78 79The functions create an image file defined by the parameters. The image 80is a rectangle of pixels stored from left-to-right, top-to-bottom. 81Each pixel contains 'comp' channels of data stored interleaved with 8-bits 82per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is 83monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. 84The *data pointer points to the first byte of the top-left-most pixel. 85For PNG, "stride_in_bytes" is the distance in bytes from the first byte of 86a row of pixels to the first byte of the next row of pixels. 87 88PNG creates output files with the same number of components as the input. 89The BMP format expands Y to RGB in the file format and does not 90output alpha. 91 92PNG supports writing rectangles of data even when the bytes storing rows of 93data are not consecutive in memory (e.g. sub-rectangles of a larger image), 94by supplying the stride between the beginning of adjacent rows. The other 95formats do not. (Thus you cannot write a native-format BMP through the BMP 96writer, both because it is in BGR order and because it may have padding 97at the end of the line.) 98 99PNG allows you to set the deflate compression level by setting the global 100variable 'stbi_write_png_compression_level' (it defaults to 8). 101 102HDR expects linear float data. Since the format is always 32-bit rgb(e) 103data, alpha (if provided) is discarded, and for monochrome data it is 104replicated across all three channels. 105 106TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed 107data, set the global variable 'stbi_write_tga_with_rle' to 0. 108 109JPEG does ignore alpha channels in input data; quality is between 1 and 100. 110Higher quality looks better but results in a bigger image. 111JPEG baseline (no JPEG progressive). 112 113CREDITS: 114 115 116Sean Barrett - PNG/BMP/TGA 117Baldur Karlsson - HDR 118Jean-Sebastien Guay - TGA monochrome 119Tim Kelsey - misc enhancements 120Alan Hickman - TGA RLE 121Emmanuel Julien - initial file IO callback implementation 122Jon Olick - original jo_jpeg.cpp code 123Daniel Gibson - integrate JPEG, allow external zlib 124Aarni Koskela - allow choosing PNG filter 125 126bugfixes: 127github:Chribba 128Guillaume Chereau 129github:jry2 130github:romigrou 131Sergio Gonzalez 132Jonas Karlsson 133Filip Wasil 134Thatcher Ulrich 135github:poppolopoppo 136Patrick Boettcher 137github:xeekworx 138Cap Petschulat 139Simon Rodriguez 140Ivan Tikhonov 141github:ignotion 142Adam Schackart 143Andrew Kensler 144 145LICENSE 146 147See end of file for license information. 148 149*/ 150 151#ifndef INCLUDE_STB_IMAGE_WRITE_H 152#define INCLUDE_STB_IMAGE_WRITE_H 153 154#include <stdlib.h> 155 156// if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline' 157#ifndef STBIWDEF 158#ifdef STB_IMAGE_WRITE_STATIC 159#define STBIWDEF static 160#else 161#ifdef __cplusplus 162#define STBIWDEF extern "C" 163#else 164#define STBIWDEF extern 165#endif 166#endif 167#endif 168 169#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations 170STBIWDEF int stbi_write_tga_with_rle ; 171STBIWDEF int stbi_write_png_compression_level ; 172STBIWDEF int stbi_write_force_png_filter ; 173#endif 174 175#ifndef STBI_WRITE_NO_STDIO 176STBIWDEF int stbi_write_png (char const * filename ,int w ,int h ,int comp ,const void * data ,int stride_in_bytes ); 177STBIWDEF int stbi_write_bmp (char const * filename ,int w ,int h ,int comp ,const void * data ); 178STBIWDEF int stbi_write_tga (char const * filename ,int w ,int h ,int comp ,const void * data ); 179STBIWDEF int stbi_write_hdr (char const * filename ,int w ,int h ,int comp ,const float * data ); 180STBIWDEF int stbi_write_jpg (char const * filename ,int x ,int y ,int comp ,const void * data ,int quality ); 181 182#ifdef STBIW_WINDOWS_UTF8 183STBIWDEF int stbiw_convert_wchar_to_utf8 (char * buffer ,size_t bufferlen ,const wchar_t * input ); 184#endif 185#endif 186 187typedef void stbi_write_func (void * context ,void * data ,int size ); 188 189STBIWDEF 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 ); 190STBIWDEF int stbi_write_bmp_to_func (stbi_write_func * func ,void * context ,int w ,int h ,int comp ,const void * data ); 191STBIWDEF int stbi_write_tga_to_func (stbi_write_func * func ,void * context ,int w ,int h ,int comp ,const void * data ); 192STBIWDEF int stbi_write_hdr_to_func (stbi_write_func * func ,void * context ,int w ,int h ,int comp ,const float * data ); 193STBIWDEF int stbi_write_jpg_to_func (stbi_write_func * func ,void * context ,int x ,int y ,int comp ,const void * data ,int quality ); 194 195STBIWDEF void stbi_flip_vertically_on_write (int flip_boolean ); 196 197#endif //INCLUDE_STB_IMAGE_WRITE_H 198 199#ifdef STB_IMAGE_WRITE_IMPLEMENTATION 200 201#ifdef _WIN32 202#ifndef _CRT_SECURE_NO_WARNINGS 203#define _CRT_SECURE_NO_WARNINGS 204#endif 205#ifndef _CRT_NONSTDC_NO_DEPRECATE 206#define _CRT_NONSTDC_NO_DEPRECATE 207#endif 208#endif 209 210#ifndef STBI_WRITE_NO_STDIO 211#include <stdio.h> 212#endif // STBI_WRITE_NO_STDIO 213 214#include <stdarg.h> 215#include <stdlib.h> 216#include <string.h> 217#include <math.h> 218 219#if defined(STBIW_MALLOC )&& defined(STBIW_FREE )&& (defined(STBIW_REALLOC )|| defined(STBIW_REALLOC_SIZED )) 220// ok 221#elif !defined(STBIW_MALLOC )&& !defined(STBIW_FREE )&& !defined(STBIW_REALLOC )&& !defined(STBIW_REALLOC_SIZED ) 222// ok 223#else 224#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." 225#endif 226 227#ifndef STBIW_MALLOC 228#define STBIW_MALLOC (sz ) malloc(sz) 229#define STBIW_REALLOC (p ,newsz ) realloc(p,newsz) 230#define STBIW_FREE (p ) free(p) 231#endif 232 233#ifndef STBIW_REALLOC_SIZED 234#define STBIW_REALLOC_SIZED (p ,oldsz ,newsz ) STBIW_REALLOC(p,newsz) 235#endif 236 237 238#ifndef STBIW_MEMMOVE 239#define STBIW_MEMMOVE (a ,b ,sz ) memmove(a,b,sz) 240#endif 241 242 243#ifndef STBIW_ASSERT 244#include <assert.h> 245#define STBIW_ASSERT (x ) assert(x) 246#endif 247 248#define STBIW_UCHAR (x ) (unsigned char) ((x) & 0xff) 249 250#ifdef STB_IMAGE_WRITE_STATIC 251static int stbi_write_png_compression_level = 8 ; 252static int stbi_write_tga_with_rle = 1 ; 253static int stbi_write_force_png_filter = -1 ; 254#else 255int stbi_write_png_compression_level = 8 ; 256int stbi_write_tga_with_rle = 1 ; 257int stbi_write_force_png_filter = -1 ; 258#endif 259 260static int stbi__flip_vertically_on_write = 0 ; 261 262STBIWDEF void stbi_flip_vertically_on_write (int flag ) 263{ 264stbi__flip_vertically_on_write = flag ; 265} 266 267typedef struct 268{ 269stbi_write_func * func ; 270void * context ; 271unsigned char buffer [64 ]; 272int buf_used ; 273}stbi__write_context ; 274 275// initialize a callback-based context 276static void stbi__start_write_callbacks (stbi__write_context * s ,stbi_write_func * c ,void * context ) 277{ 278s -> func = c ; 279s -> context = context ; 280} 281 282#ifndef STBI_WRITE_NO_STDIO 283 284static void stbi__stdio_write (void * context ,void * data ,int size ) 285{ 286fwrite (data ,1 ,size ,(FILE * )context ); 287} 288 289#if defined(_WIN32 )&& defined(STBIW_WINDOWS_UTF8 ) 290#ifdef __cplusplus 291#define STBIW_EXTERN extern "C" 292#else 293#define STBIW_EXTERN extern 294#endif 295STBIW_EXTERN __declspec(dllimport )int __stdcallMultiByteToWideChar (unsigned int cp ,unsigned long flags ,const char * str ,int cbmb ,wchar_t * widestr ,int cchwide ); 296STBIW_EXTERN __declspec(dllimport )int __stdcallWideCharToMultiByte (unsigned int cp ,unsigned long flags ,const wchar_t * widestr ,int cchwide ,char * str ,int cbmb ,const char * defchar ,int * used_default ); 297 298STBIWDEF int stbiw_convert_wchar_to_utf8 (char * buffer ,size_t bufferlen ,const wchar_t * input ) 299{ 300return WideCharToMultiByte (65001 /* UTF8 */ ,0 ,input ,-1 ,buffer , (int )bufferlen ,NULL ,NULL ); 301} 302#endif 303 304static FILE * stbiw__fopen (char const * filename ,char const * mode ) 305{ 306FILE * f ; 307#if defined(_WIN32 )&& defined(STBIW_WINDOWS_UTF8 ) 308wchar_t wMode [64 ]; 309wchar_t wFilename [1024 ]; 310if (0 == MultiByteToWideChar (65001 /* UTF8 */ ,0 ,filename ,-1 ,wFilename ,sizeof (wFilename )/sizeof (* wFilename ))) 311return 0 ; 312 313if (0 == MultiByteToWideChar (65001 /* UTF8 */ ,0 ,mode ,-1 ,wMode ,sizeof (wMode )/sizeof (* wMode ))) 314return 0 ; 315 316#if defined(_MSC_VER )&& _MSC_VER >=1400 317if (0 != _wfopen_s (& f ,wFilename ,wMode )) 318f = 0 ; 319#else 320f = _wfopen (wFilename ,wMode ); 321#endif 322 323#elif defined(_MSC_VER )&& _MSC_VER >=1400 324if (0 != fopen_s (& f ,filename ,mode )) 325f = 0 ; 326#else 327f = fopen (filename ,mode ); 328#endif 329return f ; 330} 331 332static int stbi__start_write_file (stbi__write_context * s ,const char * filename ) 333{ 334FILE * f = stbiw__fopen (filename ,"wb" ); 335stbi__start_write_callbacks (s ,stbi__stdio_write , (void * )f ); 336return f != NULL ; 337} 338 339static void stbi__end_write_file (stbi__write_context * s ) 340{ 341fclose ((FILE * )s -> context ); 342} 343 344#endif // !STBI_WRITE_NO_STDIO 345 346typedef unsigned int stbiw_uint32 ; 347typedef int stb_image_write_test [sizeof (stbiw_uint32 )== 4 ?1 :-1 ]; 348 349static void stbiw__writefv (stbi__write_context * s ,const char * fmt ,va_list v ) 350{ 351while (* fmt ) { 352switch (* fmt ++ ) { 353case ' ' :break ; 354case '1' : {unsigned char x = STBIW_UCHAR (va_arg (v ,int )); 355s -> func (s -> context ,& x ,1 ); 356break ; } 357case '2' : {int x = va_arg (v ,int ); 358unsigned char b [2 ]; 359b [0 ]= STBIW_UCHAR (x ); 360b [1 ]= STBIW_UCHAR (x >>8 ); 361s -> func (s -> context ,b ,2 ); 362break ; } 363case '4' : {stbiw_uint32 x = va_arg (v ,int ); 364unsigned char b [4 ]; 365b [0 ]= STBIW_UCHAR (x ); 366b [1 ]= STBIW_UCHAR (x >>8 ); 367b [2 ]= STBIW_UCHAR (x >>16 ); 368b [3 ]= STBIW_UCHAR (x >>24 ); 369s -> func (s -> context ,b ,4 ); 370break ; } 371default : 372STBIW_ASSERT (0 ); 373return ; 374 } 375 } 376} 377 378static void stbiw__writef (stbi__write_context * s ,const char * fmt , ...) 379{ 380va_list v ; 381va_start (v ,fmt ); 382stbiw__writefv (s ,fmt ,v ); 383va_end (v ); 384} 385 386static void stbiw__write_flush (stbi__write_context * s ) 387{ 388if (s -> buf_used ) { 389s -> func (s -> context ,& s -> buffer ,s -> buf_used ); 390s -> buf_used = 0 ; 391 } 392} 393 394static void stbiw__putc (stbi__write_context * s ,unsigned char c ) 395{ 396s -> func (s -> context ,& c ,1 ); 397} 398 399static void stbiw__write1 (stbi__write_context * s ,unsigned char a ) 400{ 401if ((size_t )s -> buf_used + 1 > sizeof (s -> buffer )) 402stbiw__write_flush (s ); 403s -> buffer [s -> buf_used ++ ]= a ; 404} 405 406static void stbiw__write3 (stbi__write_context * s ,unsigned char a ,unsigned char b ,unsigned char c ) 407{ 408int n ; 409if ((size_t )s -> buf_used + 3 > sizeof (s -> buffer )) 410stbiw__write_flush (s ); 411n = s -> buf_used ; 412s -> buf_used = n + 3 ; 413s -> buffer [n + 0 ]= a ; 414s -> buffer [n + 1 ]= b ; 415s -> buffer [n + 2 ]= c ; 416} 417 418static void stbiw__write_pixel (stbi__write_context * s ,int rgb_dir ,int comp ,int write_alpha ,int expand_mono ,unsigned char * d ) 419{ 420unsigned char bg [3 ]= {255 ,0 ,255 },px [3 ]; 421int k ; 422 423if (write_alpha < 0 ) 424stbiw__write1 (s ,d [comp - 1 ]); 425 426switch (comp ) { 427case 2 :// 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case 428case 1 : 429if (expand_mono ) 430stbiw__write3 (s ,d [0 ],d [0 ],d [0 ]);// monochrome bmp 431else 432stbiw__write1 (s ,d [0 ]);// monochrome TGA 433break ; 434case 4 : 435if (!write_alpha ) { 436// composite against pink background 437for (k = 0 ;k < 3 ;++ k ) 438px [k ]= bg [k ]+ ((d [k ]- bg [k ])* d [3 ]) /255 ; 439stbiw__write3 (s ,px [1 - rgb_dir ],px [1 ],px [1 + rgb_dir ]); 440break ; 441 } 442/* FALLTHROUGH */ 443case 3 : 444stbiw__write3 (s ,d [1 - rgb_dir ],d [1 ],d [1 + rgb_dir ]); 445break ; 446 } 447if (write_alpha > 0 ) 448stbiw__write1 (s ,d [comp - 1 ]); 449} 450 451static 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 ) 452{ 453stbiw_uint32 zero = 0 ; 454int i ,j ,j_end ; 455 456if (y <=0 ) 457return ; 458 459if (stbi__flip_vertically_on_write ) 460vdir *=-1 ; 461 462if (vdir < 0 ) { 463j_end = -1 ;j = y - 1 ; 464 }else { 465j_end = y ;j = 0 ; 466 } 467 468for (;j != j_end ;j += vdir ) { 469for (i = 0 ;i < x ;++ i ) { 470unsigned char * d = (unsigned char * )data + (j * x + i )* comp ; 471stbiw__write_pixel (s ,rgb_dir ,comp ,write_alpha ,expand_mono ,d ); 472 } 473stbiw__write_flush (s ); 474s -> func (s -> context ,& zero ,scanline_pad ); 475 } 476} 477 478static 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 , ...) 479{ 480if (y < 0 || x < 0 ) { 481return 0 ; 482 }else { 483va_list v ; 484va_start (v ,fmt ); 485stbiw__writefv (s ,fmt ,v ); 486va_end (v ); 487stbiw__write_pixels (s ,rgb_dir ,vdir ,x ,y ,comp ,data ,alpha ,pad ,expand_mono ); 488return 1 ; 489 } 490} 491 492static int stbi_write_bmp_core (stbi__write_context * s ,int x ,int y ,int comp ,const void * data ) 493{ 494if (comp != 4 ) { 495// write RGB bitmap 496int pad = (- x * 3 )& 3 ; 497return stbiw__outfile (s ,-1 ,-1 ,x ,y ,comp ,1 ,(void * )data ,0 ,pad , 498"11 4 22 4" "4 44 22 444444" , 499'B' ,'M' ,14 + 40 + (x * 3 + pad )* y ,0 ,0 ,14 + 40 ,// file header 50040 ,x ,y ,1 ,24 ,0 ,0 ,0 ,0 ,0 ,0 );// bitmap header 501 }else { 502// RGBA bitmaps need a v4 header 503// use BI_BITFIELDS mode with 32bpp and alpha mask 504// (straight BI_RGB with alpha mask doesn't work in most readers) 505return stbiw__outfile (s ,-1 ,-1 ,x ,y ,comp ,1 ,(void * )data ,1 ,0 , 506"11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444" , 507'B' ,'M' ,14 + 108 + x * y * 4 ,0 ,0 ,14 + 108 ,// file header 508108 ,x ,y ,1 ,32 ,3 ,0 ,0 ,0 ,0 ,0 ,0xff0000 ,0xff00 ,0xff ,0xff000000u ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 );// bitmap V4 header 509 } 510} 511 512STBIWDEF int stbi_write_bmp_to_func (stbi_write_func * func ,void * context ,int x ,int y ,int comp ,const void * data ) 513{ 514stbi__write_context s = {0 }; 515stbi__start_write_callbacks (& s ,func ,context ); 516return stbi_write_bmp_core (& s ,x ,y ,comp ,data ); 517} 518 519#ifndef STBI_WRITE_NO_STDIO 520STBIWDEF int stbi_write_bmp (char const * filename ,int x ,int y ,int comp ,const void * data ) 521{ 522stbi__write_context s = {0 }; 523if (stbi__start_write_file (& s ,filename )) { 524int r = stbi_write_bmp_core (& s ,x ,y ,comp ,data ); 525stbi__end_write_file (& s ); 526return r ; 527 }else 528return 0 ; 529} 530#endif //!STBI_WRITE_NO_STDIO 531 532static int stbi_write_tga_core (stbi__write_context * s ,int x ,int y ,int comp ,void * data ) 533{ 534int has_alpha = (comp == 2 || comp == 4 ); 535int colorbytes = has_alpha ?comp - 1 :comp ; 536int format = colorbytes < 2 ?3 :2 ;// 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 537 538if (y < 0 || x < 0 ) 539return 0 ; 540 541if (!stbi_write_tga_with_rle ) { 542return stbiw__outfile (s ,-1 ,-1 ,x ,y ,comp ,0 , (void * )data ,has_alpha ,0 , 543"111 221 2222 11" ,0 ,0 ,format ,0 ,0 ,0 ,0 ,0 ,x ,y , (colorbytes + has_alpha )* 8 ,has_alpha * 8 ); 544 }else { 545int i ,j ,k ; 546int jend ,jdir ; 547 548stbiw__writef (s ,"111 221 2222 11" ,0 ,0 ,format + 8 ,0 ,0 ,0 ,0 ,0 ,x ,y , (colorbytes + has_alpha )* 8 ,has_alpha * 8 ); 549 550if (stbi__flip_vertically_on_write ) { 551j = 0 ; 552jend = y ; 553jdir = 1 ; 554 }else { 555j = y - 1 ; 556jend = -1 ; 557jdir = -1 ; 558 } 559for (;j != jend ;j += jdir ) { 560unsigned char * row = (unsigned char * )data + j * x * comp ; 561int len ; 562 563for (i = 0 ;i < x ;i += len ) { 564unsigned char * begin = row + i * comp ; 565int diff = 1 ; 566len = 1 ; 567 568if (i < x - 1 ) { 569++ len ; 570diff = memcmp (begin ,row + (i + 1 )* comp ,comp ); 571if (diff ) { 572const unsigned char * prev = begin ; 573for (k = i + 2 ;k < x && len < 128 ;++ k ) { 574if (memcmp (prev ,row + k * comp ,comp )) { 575prev += comp ; 576++ len ; 577 }else { 578-- len ; 579break ; 580 } 581 } 582 }else { 583for (k = i + 2 ;k < x && len < 128 ;++ k ) { 584if (!memcmp (begin ,row + k * comp ,comp )) { 585++ len ; 586 }else { 587break ; 588 } 589 } 590 } 591 } 592 593if (diff ) { 594unsigned char header = STBIW_UCHAR (len - 1 ); 595stbiw__write1 (s ,header ); 596for (k = 0 ;k < len ;++ k ) { 597stbiw__write_pixel (s ,-1 ,comp ,has_alpha ,0 ,begin + k * comp ); 598 } 599 }else { 600unsigned char header = STBIW_UCHAR (len - 129 ); 601stbiw__write1 (s ,header ); 602stbiw__write_pixel (s ,-1 ,comp ,has_alpha ,0 ,begin ); 603 } 604 } 605 } 606stbiw__write_flush (s ); 607 } 608return 1 ; 609} 610 611STBIWDEF int stbi_write_tga_to_func (stbi_write_func * func ,void * context ,int x ,int y ,int comp ,const void * data ) 612{ 613stbi__write_context s = {0 }; 614stbi__start_write_callbacks (& s ,func ,context ); 615return stbi_write_tga_core (& s ,x ,y ,comp , (void * )data ); 616} 617 618#ifndef STBI_WRITE_NO_STDIO 619STBIWDEF int stbi_write_tga (char const * filename ,int x ,int y ,int comp ,const void * data ) 620{ 621stbi__write_context s = {0 }; 622if (stbi__start_write_file (& s ,filename )) { 623int r = stbi_write_tga_core (& s ,x ,y ,comp , (void * )data ); 624stbi__end_write_file (& s ); 625return r ; 626 }else 627return 0 ; 628} 629#endif 630 631// ************************************************************************************************* 632// Radiance RGBE HDR writer 633// by Baldur Karlsson 634 635#define stbiw__max (a ,b ) ((a) > (b) ? (a) : (b)) 636 637#ifndef STBI_WRITE_NO_STDIO 638 639static void stbiw__linear_to_rgbe (unsigned char * rgbe ,float * linear ) 640{ 641int exponent ; 642float maxcomp = stbiw__max (linear [0 ],stbiw__max (linear [1 ],linear [2 ])); 643 644if (maxcomp < 1e-32f ) { 645rgbe [0 ]= rgbe [1 ]= rgbe [2 ]= rgbe [3 ]= 0 ; 646 }else { 647float normalize = (float )frexp (maxcomp ,& exponent )* 256.0f /maxcomp ; 648 649rgbe [0 ]= (unsigned char )(linear [0 ]* normalize ); 650rgbe [1 ]= (unsigned char )(linear [1 ]* normalize ); 651rgbe [2 ]= (unsigned char )(linear [2 ]* normalize ); 652rgbe [3 ]= (unsigned char )(exponent + 128 ); 653 } 654} 655 656static void stbiw__write_run_data (stbi__write_context * s ,int length ,unsigned char databyte ) 657{ 658unsigned char lengthbyte = STBIW_UCHAR (length + 128 ); 659STBIW_ASSERT (length + 128 <=255 ); 660s -> func (s -> context ,& lengthbyte ,1 ); 661s -> func (s -> context ,& databyte ,1 ); 662} 663 664static void stbiw__write_dump_data (stbi__write_context * s ,int length ,unsigned char * data ) 665{ 666unsigned char lengthbyte = STBIW_UCHAR (length ); 667STBIW_ASSERT (length <=128 );// inconsistent with spec but consistent with official code 668s -> func (s -> context ,& lengthbyte ,1 ); 669s -> func (s -> context ,data ,length ); 670} 671 672static void stbiw__write_hdr_scanline (stbi__write_context * s ,int width ,int ncomp ,unsigned char * scratch ,float * scanline ) 673{ 674unsigned char scanlineheader [4 ]= {2 ,2 ,0 ,0 }; 675unsigned char rgbe [4 ]; 676float linear [3 ]; 677int x ; 678 679scanlineheader [2 ]= (width & 0xff00 )>>8 ; 680scanlineheader [3 ]= (width & 0x00ff ); 681 682/* skip RLE for images too small or large */ 683if (width < 8 || width >=32768 ) { 684for (x = 0 ;x < width ;x ++ ) { 685switch (ncomp ) { 686case 4 :/* fallthrough */ 687case 3 :linear [2 ]= scanline [x * ncomp + 2 ]; 688linear [1 ]= scanline [x * ncomp + 1 ]; 689linear [0 ]= scanline [x * ncomp + 0 ]; 690break ; 691default : 692linear [0 ]= linear [1 ]= linear [2 ]= scanline [x * ncomp + 0 ]; 693break ; 694 } 695stbiw__linear_to_rgbe (rgbe ,linear ); 696s -> func (s -> context ,rgbe ,4 ); 697 } 698 }else { 699int c ,r ; 700/* encode into scratch buffer */ 701for (x = 0 ;x < width ;x ++ ) { 702switch (ncomp ) { 703case 4 :/* fallthrough */ 704case 3 :linear [2 ]= scanline [x * ncomp + 2 ]; 705linear [1 ]= scanline [x * ncomp + 1 ]; 706linear [0 ]= scanline [x * ncomp + 0 ]; 707break ; 708default : 709linear [0 ]= linear [1 ]= linear [2 ]= scanline [x * ncomp + 0 ]; 710break ; 711 } 712stbiw__linear_to_rgbe (rgbe ,linear ); 713scratch [x + width * 0 ]= rgbe [0 ]; 714scratch [x + width * 1 ]= rgbe [1 ]; 715scratch [x + width * 2 ]= rgbe [2 ]; 716scratch [x + width * 3 ]= rgbe [3 ]; 717 } 718 719s -> func (s -> context ,scanlineheader ,4 ); 720 721/* RLE each component separately */ 722for (c = 0 ;c < 4 ;c ++ ) { 723unsigned char * comp = & scratch [width * c ]; 724 725x = 0 ; 726while (x < width ) { 727// find first run 728r = x ; 729while (r + 2 < width ) { 730if (comp [r ]== comp [r + 1 ]&& comp [r ]== comp [r + 2 ]) 731break ; 732++ r ; 733 } 734if (r + 2 >=width ) 735r = width ; 736// dump up to first run 737while (x < r ) { 738int len = r - x ; 739if (len > 128 )len = 128 ; 740stbiw__write_dump_data (s ,len ,& comp [x ]); 741x += len ; 742 } 743// if there's a run, output it 744if (r + 2 < width ) {// same test as what we break out of in search loop, so only true if we break'd 745// find next byte after run 746while (r < width && comp [r ]== comp [x ]) 747++ r ; 748// output run up to r 749while (x < r ) { 750int len = r - x ; 751if (len > 127 )len = 127 ; 752stbiw__write_run_data (s ,len ,comp [x ]); 753x += len ; 754 } 755 } 756 } 757 } 758 } 759} 760 761static int stbi_write_hdr_core (stbi__write_context * s ,int x ,int y ,int comp ,float * data ) 762{ 763if (y <=0 || x <=0 || data == NULL ) 764return 0 ; 765else { 766// Each component is stored separately. Allocate scratch space for full output scanline. 767unsigned char * scratch = (unsigned char * )STBIW_MALLOC (x * 4 ); 768int i ,len ; 769char buffer [128 ]; 770char header []= "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n" ; 771s -> func (s -> context ,header ,sizeof (header )- 1 ); 772 773#ifdef __STDC_LIB_EXT1__ 774len = sprintf_s (buffer ,sizeof (buffer ),"EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" ,y ,x ); 775#else 776len = snprintf (buffer ,sizeof (buffer ),"EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" ,y ,x ); 777#endif 778s -> func (s -> context ,buffer ,len ); 779 780for (i = 0 ;i < y ;i ++ ) 781stbiw__write_hdr_scanline (s ,x ,comp ,scratch ,data + comp * x * (stbi__flip_vertically_on_write ?y - 1 - i :i )); 782STBIW_FREE (scratch ); 783return 1 ; 784 } 785} 786 787STBIWDEF int stbi_write_hdr_to_func (stbi_write_func * func ,void * context ,int x ,int y ,int comp ,const float * data ) 788{ 789stbi__write_context s = {0 }; 790stbi__start_write_callbacks (& s ,func ,context ); 791return stbi_write_hdr_core (& s ,x ,y ,comp , (float * )data ); 792} 793 794STBIWDEF int stbi_write_hdr (char const * filename ,int x ,int y ,int comp ,const float * data ) 795{ 796stbi__write_context s = {0 }; 797if (stbi__start_write_file (& s ,filename )) { 798int r = stbi_write_hdr_core (& s ,x ,y ,comp , (float * )data ); 799stbi__end_write_file (& s ); 800return r ; 801 }else 802return 0 ; 803} 804#endif // STBI_WRITE_NO_STDIO 805 806 807////////////////////////////////////////////////////////////////////////////// 808// 809// PNG writer 810// 811 812#ifndef STBIW_ZLIB_COMPRESS 813// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() 814#define stbiw__sbraw (a ) ((int *) (void *) (a) - 2) 815#define stbiw__sbm (a ) stbiw__sbraw(a)[0] 816#define stbiw__sbn (a ) stbiw__sbraw(a)[1] 817 818#define stbiw__sbneedgrow (a ,n ) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) 819#define stbiw__sbmaybegrow (a ,n ) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) 820#define stbiw__sbgrow (a ,n ) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) 821 822#define stbiw__sbpush (a ,v ) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) 823#define stbiw__sbcount (a ) ((a) ? stbiw__sbn(a) : 0) 824#define stbiw__sbfree (a ) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) 825 826static void * stbiw__sbgrowf (void ** arr ,int increment ,int itemsize ) 827{ 828int m = * arr ?2 * stbiw__sbm (* arr )+ increment :increment + 1 ; 829void * p = STBIW_REALLOC_SIZED (* arr ?stbiw__sbraw (* arr ) :0 ,* arr ? (stbiw__sbm (* arr )* itemsize + sizeof (int )* 2 ) :0 ,itemsize * m + sizeof (int )* 2 ); 830STBIW_ASSERT (p ); 831if (p ) { 832if (!* arr ) ((int * )p )[1 ]= 0 ; 833* arr = (void * ) ((int * )p + 2 ); 834stbiw__sbm (* arr )= m ; 835 } 836return * arr ; 837} 838 839static unsigned char * stbiw__zlib_flushf (unsigned char * data ,unsigned int * bitbuffer ,int * bitcount ) 840{ 841while (* bitcount >=8 ) { 842stbiw__sbpush (data ,STBIW_UCHAR (* bitbuffer )); 843* bitbuffer >>=8 ; 844* bitcount -= 8 ; 845 } 846return data ; 847} 848 849static int stbiw__zlib_bitrev (int code ,int codebits ) 850{ 851int res = 0 ; 852while (codebits -- ) { 853res = (res <<1 ) | (code & 1 ); 854code >>=1 ; 855 } 856return res ; 857} 858 859static unsigned int stbiw__zlib_countm (unsigned char * a ,unsigned char * b ,int limit ) 860{ 861int i ; 862for (i = 0 ;i < limit && i < 258 ;++ i ) 863if (a [i ]!= b [i ])break ; 864return i ; 865} 866 867static unsigned int stbiw__zhash (unsigned char * data ) 868{ 869stbiw_uint32 hash = data [0 ]+ (data [1 ] <<8 )+ (data [2 ] <<16 ); 870hash ^=hash <<3 ; 871hash += hash >>5 ; 872hash ^=hash <<4 ; 873hash += hash >>17 ; 874hash ^=hash <<25 ; 875hash += hash >>6 ; 876return hash ; 877} 878 879#define stbiw__zlib_flush () (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) 880#define stbiw__zlib_add (code ,codebits ) \ 881 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) 882#define stbiw__zlib_huffa (b ,c ) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) 883// default huffman tables 884#define stbiw__zlib_huff1 (n ) stbiw__zlib_huffa(0x30 + (n), 8) 885#define stbiw__zlib_huff2 (n ) stbiw__zlib_huffa(0x190 + (n)-144, 9) 886#define stbiw__zlib_huff3 (n ) stbiw__zlib_huffa(0 + (n)-256,7) 887#define stbiw__zlib_huff4 (n ) stbiw__zlib_huffa(0xc0 + (n)-280,8) 888#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)) 889#define stbiw__zlib_huffb (n ) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) 890 891#define stbiw__ZHASH 16384 892 893#endif // STBIW_ZLIB_COMPRESS 894 895STBIWDEF unsigned char * stbi_zlib_compress (unsigned char * data ,int data_len ,int * out_len ,int quality ) 896{ 897#ifdef STBIW_ZLIB_COMPRESS 898// user provided a zlib compress implementation, use that 899return STBIW_ZLIB_COMPRESS (data ,data_len ,out_len ,quality ); 900#else // use builtin 901static 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 }; 902static 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 }; 903static 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 }; 904static 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 }; 905unsigned int bitbuf = 0 ; 906int i ,j ,bitcount = 0 ; 907unsigned char * out = NULL ; 908unsigned char *** hash_table = (unsigned char *** )STBIW_MALLOC (stbiw__ZHASH * sizeof (unsigned char ** )); 909if (hash_table == NULL ) 910return NULL ; 911if (quality < 5 )quality = 5 ; 912 913stbiw__sbpush (out ,0x78 );// DEFLATE 32K window 914stbiw__sbpush (out ,0x5e );// FLEVEL = 1 915stbiw__zlib_add (1 ,1 );// BFINAL = 1 916stbiw__zlib_add (1 ,2 );// BTYPE = 1 -- fixed huffman 917 918for (i = 0 ;i < stbiw__ZHASH ;++ i ) 919hash_table [i ]= NULL ; 920 921i = 0 ; 922while (i < data_len - 3 ) { 923// hash next 3 bytes of data to be compressed 924int h = stbiw__zhash (data + i )& (stbiw__ZHASH - 1 ),best = 3 ; 925unsigned char * bestloc = 0 ; 926unsigned char ** hlist = hash_table [h ]; 927int n = stbiw__sbcount (hlist ); 928for (j = 0 ;j < n ;++ j ) { 929if (hlist [j ]- data > i - 32768 ) {// if entry lies within window 930int d = stbiw__zlib_countm (hlist [j ],data + i ,data_len - i ); 931if (d >=best ) {best = d ;bestloc = hlist [j ]; } 932 } 933 } 934// when hash table entry is too long, delete half the entries 935if (hash_table [h ]&& stbiw__sbn (hash_table [h ])== 2 * quality ) { 936STBIW_MEMMOVE (hash_table [h ],hash_table [h ]+ quality ,sizeof (hash_table [h ][0 ])* quality ); 937stbiw__sbn (hash_table [h ])= quality ; 938 } 939stbiw__sbpush (hash_table [h ],data + i ); 940 941if (bestloc ) { 942// "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal 943h = stbiw__zhash (data + i + 1 )& (stbiw__ZHASH - 1 ); 944hlist = hash_table [h ]; 945n = stbiw__sbcount (hlist ); 946for (j = 0 ;j < n ;++ j ) { 947if (hlist [j ]- data > i - 32767 ) { 948int e = stbiw__zlib_countm (hlist [j ],data + i + 1 ,data_len - i - 1 ); 949if (e > best ) {// if next match is better, bail on current match 950bestloc = NULL ; 951break ; 952 } 953 } 954 } 955 } 956 957if (bestloc ) { 958int d = (int ) (data + i - bestloc );// distance back 959STBIW_ASSERT (d <=32767 && best <=258 ); 960for (j = 0 ;best > lengthc [j + 1 ]- 1 ;++ j ); 961stbiw__zlib_huff (j + 257 ); 962if (lengtheb [j ])stbiw__zlib_add (best - lengthc [j ],lengtheb [j ]); 963for (j = 0 ;d > distc [j + 1 ]- 1 ;++ j ); 964stbiw__zlib_add (stbiw__zlib_bitrev (j ,5 ),5 ); 965if (disteb [j ])stbiw__zlib_add (d - distc [j ],disteb [j ]); 966i += best ; 967 }else { 968stbiw__zlib_huffb (data [i ]); 969++ i ; 970 } 971 } 972// write out final bytes 973for (;i < data_len ;++ i ) 974stbiw__zlib_huffb (data [i ]); 975stbiw__zlib_huff (256 );// end of block 976// pad with 0 bits to byte boundary 977while (bitcount ) 978stbiw__zlib_add (0 ,1 ); 979 980for (i = 0 ;i < stbiw__ZHASH ;++ i ) 981 (void )stbiw__sbfree (hash_table [i ]); 982STBIW_FREE (hash_table ); 983 984// store uncompressed instead if compression was worse 985if (stbiw__sbn (out )> data_len + 2 + ((data_len + 32766 )/32767 )* 5 ) { 986stbiw__sbn (out )= 2 ;// truncate to DEFLATE 32K window and FLEVEL = 1 987for (j = 0 ;j < data_len ;) { 988int blocklen = data_len - j ; 989if (blocklen > 32767 )blocklen = 32767 ; 990stbiw__sbpush (out ,data_len - j == blocklen );// BFINAL = ?, BTYPE = 0 -- no compression 991stbiw__sbpush (out ,STBIW_UCHAR (blocklen ));// LEN 992stbiw__sbpush (out ,STBIW_UCHAR (blocklen >>8 )); 993stbiw__sbpush (out ,STBIW_UCHAR (~blocklen ));// NLEN 994stbiw__sbpush (out ,STBIW_UCHAR (~blocklen >>8 )); 995memcpy (out + stbiw__sbn (out ),data + j ,blocklen ); 996stbiw__sbn (out )+= blocklen ; 997j += blocklen ; 998 } 999 } 1000 1001 { 1002// compute adler32 on input 1003unsigned int s1 = 1 ,s2 = 0 ; 1004int blocklen = (int ) (data_len %5552 ); 1005j = 0 ; 1006while (j < data_len ) { 1007for (i = 0 ;i < blocklen ;++ i ) {s1 += data [j + i ];s2 += s1 ; } 1008s1 %=65521 ;s2 %=65521 ; 1009j += blocklen ; 1010blocklen = 5552 ; 1011 } 1012stbiw__sbpush (out ,STBIW_UCHAR (s2 >>8 )); 1013stbiw__sbpush (out ,STBIW_UCHAR (s2 )); 1014stbiw__sbpush (out ,STBIW_UCHAR (s1 >>8 )); 1015stbiw__sbpush (out ,STBIW_UCHAR (s1 )); 1016 } 1017* out_len = stbiw__sbn (out ); 1018// make returned pointer freeable 1019STBIW_MEMMOVE (stbiw__sbraw (out ),out ,* out_len ); 1020return (unsigned char * )stbiw__sbraw (out ); 1021#endif // STBIW_ZLIB_COMPRESS 1022} 1023 1024static unsigned int stbiw__crc32 (unsigned char * buffer ,int len ) 1025{ 1026#ifdef STBIW_CRC32 1027return STBIW_CRC32 (buffer ,len ); 1028#else 1029static unsigned int crc_table [256 ]= 1030 { 10310x00000000 ,0x77073096 ,0xEE0E612C ,0x990951BA ,0x076DC419 ,0x706AF48F ,0xE963A535 ,0x9E6495A3 , 10320x0eDB8832 ,0x79DCB8A4 ,0xE0D5E91E ,0x97D2D988 ,0x09B64C2B ,0x7EB17CBD ,0xE7B82D07 ,0x90BF1D91 , 10330x1DB71064 ,0x6AB020F2 ,0xF3B97148 ,0x84BE41DE ,0x1ADAD47D ,0x6DDDE4EB ,0xF4D4B551 ,0x83D385C7 , 10340x136C9856 ,0x646BA8C0 ,0xFD62F97A ,0x8A65C9EC ,0x14015C4F ,0x63066CD9 ,0xFA0F3D63 ,0x8D080DF5 , 10350x3B6E20C8 ,0x4C69105E ,0xD56041E4 ,0xA2677172 ,0x3C03E4D1 ,0x4B04D447 ,0xD20D85FD ,0xA50AB56B , 10360x35B5A8FA ,0x42B2986C ,0xDBBBC9D6 ,0xACBCF940 ,0x32D86CE3 ,0x45DF5C75 ,0xDCD60DCF ,0xABD13D59 , 10370x26D930AC ,0x51DE003A ,0xC8D75180 ,0xBFD06116 ,0x21B4F4B5 ,0x56B3C423 ,0xCFBA9599 ,0xB8BDA50F , 10380x2802B89E ,0x5F058808 ,0xC60CD9B2 ,0xB10BE924 ,0x2F6F7C87 ,0x58684C11 ,0xC1611DAB ,0xB6662D3D , 10390x76DC4190 ,0x01DB7106 ,0x98D220BC ,0xEFD5102A ,0x71B18589 ,0x06B6B51F ,0x9FBFE4A5 ,0xE8B8D433 , 10400x7807C9A2 ,0x0F00F934 ,0x9609A88E ,0xE10E9818 ,0x7F6A0DBB ,0x086D3D2D ,0x91646C97 ,0xE6635C01 , 10410x6B6B51F4 ,0x1C6C6162 ,0x856530D8 ,0xF262004E ,0x6C0695ED ,0x1B01A57B ,0x8208F4C1 ,0xF50FC457 , 10420x65B0D9C6 ,0x12B7E950 ,0x8BBEB8EA ,0xFCB9887C ,0x62DD1DDF ,0x15DA2D49 ,0x8CD37CF3 ,0xFBD44C65 , 10430x4DB26158 ,0x3AB551CE ,0xA3BC0074 ,0xD4BB30E2 ,0x4ADFA541 ,0x3DD895D7 ,0xA4D1C46D ,0xD3D6F4FB , 10440x4369E96A ,0x346ED9FC ,0xAD678846 ,0xDA60B8D0 ,0x44042D73 ,0x33031DE5 ,0xAA0A4C5F ,0xDD0D7CC9 , 10450x5005713C ,0x270241AA ,0xBE0B1010 ,0xC90C2086 ,0x5768B525 ,0x206F85B3 ,0xB966D409 ,0xCE61E49F , 10460x5EDEF90E ,0x29D9C998 ,0xB0D09822 ,0xC7D7A8B4 ,0x59B33D17 ,0x2EB40D81 ,0xB7BD5C3B ,0xC0BA6CAD , 10470xEDB88320 ,0x9ABFB3B6 ,0x03B6E20C ,0x74B1D29A ,0xEAD54739 ,0x9DD277AF ,0x04DB2615 ,0x73DC1683 , 10480xE3630B12 ,0x94643B84 ,0x0D6D6A3E ,0x7A6A5AA8 ,0xE40ECF0B ,0x9309FF9D ,0x0A00AE27 ,0x7D079EB1 , 10490xF00F9344 ,0x8708A3D2 ,0x1E01F268 ,0x6906C2FE ,0xF762575D ,0x806567CB ,0x196C3671 ,0x6E6B06E7 , 10500xFED41B76 ,0x89D32BE0 ,0x10DA7A5A ,0x67DD4ACC ,0xF9B9DF6F ,0x8EBEEFF9 ,0x17B7BE43 ,0x60B08ED5 , 10510xD6D6A3E8 ,0xA1D1937E ,0x38D8C2C4 ,0x4FDFF252 ,0xD1BB67F1 ,0xA6BC5767 ,0x3FB506DD ,0x48B2364B , 10520xD80D2BDA ,0xAF0A1B4C ,0x36034AF6 ,0x41047A60 ,0xDF60EFC3 ,0xA867DF55 ,0x316E8EEF ,0x4669BE79 , 10530xCB61B38C ,0xBC66831A ,0x256FD2A0 ,0x5268E236 ,0xCC0C7795 ,0xBB0B4703 ,0x220216B9 ,0x5505262F , 10540xC5BA3BBE ,0xB2BD0B28 ,0x2BB45A92 ,0x5CB36A04 ,0xC2D7FFA7 ,0xB5D0CF31 ,0x2CD99E8B ,0x5BDEAE1D , 10550x9B64C2B0 ,0xEC63F226 ,0x756AA39C ,0x026D930A ,0x9C0906A9 ,0xEB0E363F ,0x72076785 ,0x05005713 , 10560x95BF4A82 ,0xE2B87A14 ,0x7BB12BAE ,0x0CB61B38 ,0x92D28E9B ,0xE5D5BE0D ,0x7CDCEFB7 ,0x0BDBDF21 , 10570x86D3D2D4 ,0xF1D4E242 ,0x68DDB3F8 ,0x1FDA836E ,0x81BE16CD ,0xF6B9265B ,0x6FB077E1 ,0x18B74777 , 10580x88085AE6 ,0xFF0F6A70 ,0x66063BCA ,0x11010B5C ,0x8F659EFF ,0xF862AE69 ,0x616BFFD3 ,0x166CCF45 , 10590xA00AE278 ,0xD70DD2EE ,0x4E048354 ,0x3903B3C2 ,0xA7672661 ,0xD06016F7 ,0x4969474D ,0x3E6E77DB , 10600xAED16A4A ,0xD9D65ADC ,0x40DF0B66 ,0x37D83BF0 ,0xA9BCAE53 ,0xDEBB9EC5 ,0x47B2CF7F ,0x30B5FFE9 , 10610xBDBDF21C ,0xCABAC28A ,0x53B39330 ,0x24B4A3A6 ,0xBAD03605 ,0xCDD70693 ,0x54DE5729 ,0x23D967BF , 10620xB3667A2E ,0xC4614AB8 ,0x5D681B02 ,0x2A6F2B94 ,0xB40BBE37 ,0xC30C8EA1 ,0x5A05DF1B ,0x2D02EF8D 1063 }; 1064 1065unsigned int crc = ~0u ; 1066int i ; 1067for (i = 0 ;i < len ;++ i ) 1068crc = (crc >>8 ) ^crc_table [buffer [i ] ^ (crc & 0xff )]; 1069return ~crc ; 1070#endif 1071} 1072 1073#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) 1074#define stbiw__wp32 (data ,v ) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); 1075#define stbiw__wptag (data ,s ) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) 1076 1077static void stbiw__wpcrc (unsigned char ** data ,int len ) 1078{ 1079unsigned int crc = stbiw__crc32 (* data - len - 4 ,len + 4 ); 1080stbiw__wp32 (* data ,crc ); 1081} 1082 1083static unsigned char stbiw__paeth (int a ,int b ,int c ) 1084{ 1085int p = a + b - c ,pa = abs (p - a ),pb = abs (p - b ),pc = abs (p - c ); 1086if (pa <=pb && pa <=pc )return STBIW_UCHAR (a ); 1087if (pb <=pc )return STBIW_UCHAR (b ); 1088return STBIW_UCHAR (c ); 1089} 1090 1091// @OPTIMIZE: provide an option that always forces left-predict or paeth predict 1092static void stbiw__encode_png_line (unsigned char * pixels ,int stride_bytes ,int width ,int height ,int y ,int n ,int filter_type ,signed char * line_buffer ) 1093{ 1094static int mapping []= {0 ,1 ,2 ,3 ,4 }; 1095static int firstmap []= {0 ,1 ,0 ,5 ,6 }; 1096int * mymap = (y != 0 ) ?mapping :firstmap ; 1097int i ; 1098int type = mymap [filter_type ]; 1099unsigned char * z = pixels + stride_bytes * (stbi__flip_vertically_on_write ?height - 1 - y :y ); 1100int signed_stride = stbi__flip_vertically_on_write ?- stride_bytes :stride_bytes ; 1101 1102if (type == 0 ) { 1103memcpy (line_buffer ,z ,width * n ); 1104return ; 1105 } 1106 1107// first loop isn't optimized since it's just one pixel 1108for (i = 0 ;i < n ;++ i ) { 1109switch (type ) { 1110case 1 :line_buffer [i ]= z [i ];break ; 1111case 2 :line_buffer [i ]= z [i ]- z [i - signed_stride ];break ; 1112case 3 :line_buffer [i ]= z [i ]- (z [i - signed_stride ]>>1 );break ; 1113case 4 :line_buffer [i ]= (signed char ) (z [i ]- stbiw__paeth (0 ,z [i - signed_stride ],0 ));break ; 1114case 5 :line_buffer [i ]= z [i ];break ; 1115case 6 :line_buffer [i ]= z [i ];break ; 1116 } 1117 } 1118switch (type ) { 1119case 1 :for (i = n ;i < width * n ;++ i )line_buffer [i ]= z [i ]- z [i - n ];break ; 1120case 2 :for (i = n ;i < width * n ;++ i )line_buffer [i ]= z [i ]- z [i - signed_stride ];break ; 1121case 3 :for (i = n ;i < width * n ;++ i )line_buffer [i ]= z [i ]- ((z [i - n ]+ z [i - signed_stride ])>>1 );break ; 1122case 4 :for (i = n ;i < width * n ;++ i )line_buffer [i ]= z [i ]- stbiw__paeth (z [i - n ],z [i - signed_stride ],z [i - signed_stride - n ]);break ; 1123case 5 :for (i = n ;i < width * n ;++ i )line_buffer [i ]= z [i ]- (z [i - n ]>>1 );break ; 1124case 6 :for (i = n ;i < width * n ;++ i )line_buffer [i ]= z [i ]- stbiw__paeth (z [i - n ],0 ,0 );break ; 1125 } 1126} 1127 1128STBIWDEF unsigned char * stbi_write_png_to_mem (const unsigned char * pixels ,int stride_bytes ,int x ,int y ,int n ,int * out_len ) 1129{ 1130int force_filter = stbi_write_force_png_filter ; 1131int ctype [5 ]= {-1 ,0 ,4 ,2 ,6 }; 1132unsigned char sig [8 ]= {137 ,80 ,78 ,71 ,13 ,10 ,26 ,10 }; 1133unsigned char * out ,* o ,* filt ,* zlib ; 1134signed char * line_buffer ; 1135int j ,zlen ; 1136 1137if (stride_bytes == 0 ) 1138stride_bytes = x * n ; 1139 1140if (force_filter >=5 ) { 1141force_filter = -1 ; 1142 } 1143 1144filt = (unsigned char * )STBIW_MALLOC ((x * n + 1 )* y );if (!filt )return 0 ; 1145line_buffer = (signed char * )STBIW_MALLOC (x * n );if (!line_buffer ) {STBIW_FREE (filt );return 0 ; } 1146for (j = 0 ;j < y ;++ j ) { 1147int filter_type ; 1148if (force_filter > -1 ) { 1149filter_type = force_filter ; 1150stbiw__encode_png_line ((unsigned char * )(pixels ),stride_bytes ,x ,y ,j ,n ,force_filter ,line_buffer ); 1151 }else {// Estimate the best filter by running through all of them: 1152int best_filter = 0 ,best_filter_val = 0x7fffffff ,est ,i ; 1153for (filter_type = 0 ;filter_type < 5 ;filter_type ++ ) { 1154stbiw__encode_png_line ((unsigned char * )(pixels ),stride_bytes ,x ,y ,j ,n ,filter_type ,line_buffer ); 1155 1156// Estimate the entropy of the line using this filter; the less, the better. 1157est = 0 ; 1158for (i = 0 ;i < x * n ;++ i ) { 1159est += abs ((signed char )line_buffer [i ]); 1160 } 1161if (est < best_filter_val ) { 1162best_filter_val = est ; 1163best_filter = filter_type ; 1164 } 1165 } 1166if (filter_type != best_filter ) {// If the last iteration already got us the best filter, don't redo it 1167stbiw__encode_png_line ((unsigned char * )(pixels ),stride_bytes ,x ,y ,j ,n ,best_filter ,line_buffer ); 1168filter_type = best_filter ; 1169 } 1170 } 1171// when we get here, filter_type contains the filter type, and line_buffer contains the data 1172filt [j * (x * n + 1 )]= (unsigned char )filter_type ; 1173STBIW_MEMMOVE (filt + j * (x * n + 1 )+ 1 ,line_buffer ,x * n ); 1174 } 1175STBIW_FREE (line_buffer ); 1176zlib = stbi_zlib_compress (filt ,y * (x * n + 1 ),& zlen ,stbi_write_png_compression_level ); 1177STBIW_FREE (filt ); 1178if (!zlib )return 0 ; 1179 1180// each tag requires 12 bytes of overhead 1181out = (unsigned char * )STBIW_MALLOC (8 + 12 + 13 + 12 + zlen + 12 ); 1182if (!out )return 0 ; 1183* out_len = 8 + 12 + 13 + 12 + zlen + 12 ; 1184 1185o = out ; 1186STBIW_MEMMOVE (o ,sig ,8 );o += 8 ; 1187stbiw__wp32 (o ,13 );// header length 1188stbiw__wptag (o ,"IHDR" ); 1189stbiw__wp32 (o ,x ); 1190stbiw__wp32 (o ,y ); 1191* o ++ = 8 ; 1192* o ++ = STBIW_UCHAR (ctype [n ]); 1193* o ++ = 0 ; 1194* o ++ = 0 ; 1195* o ++ = 0 ; 1196stbiw__wpcrc (& o ,13 ); 1197 1198stbiw__wp32 (o ,zlen ); 1199stbiw__wptag (o ,"IDAT" ); 1200STBIW_MEMMOVE (o ,zlib ,zlen ); 1201o += zlen ; 1202STBIW_FREE (zlib ); 1203stbiw__wpcrc (& o ,zlen ); 1204 1205stbiw__wp32 (o ,0 ); 1206stbiw__wptag (o ,"IEND" ); 1207stbiw__wpcrc (& o ,0 ); 1208 1209STBIW_ASSERT (o == out + * out_len ); 1210 1211return out ; 1212} 1213 1214#ifndef STBI_WRITE_NO_STDIO 1215STBIWDEF int stbi_write_png (char const * filename ,int x ,int y ,int comp ,const void * data ,int stride_bytes ) 1216{ 1217FILE * f ; 1218int len ; 1219unsigned char * png = stbi_write_png_to_mem ((const unsigned char * )data ,stride_bytes ,x ,y ,comp ,& len ); 1220if (png == NULL )return 0 ; 1221 1222f = stbiw__fopen (filename ,"wb" ); 1223if (!f ) {STBIW_FREE (png );return 0 ; } 1224fwrite (png ,1 ,len ,f ); 1225fclose (f ); 1226STBIW_FREE (png ); 1227return 1 ; 1228} 1229#endif 1230 1231STBIWDEF int stbi_write_png_to_func (stbi_write_func * func ,void * context ,int x ,int y ,int comp ,const void * data ,int stride_bytes ) 1232{ 1233int len ; 1234unsigned char * png = stbi_write_png_to_mem ((const unsigned char * )data ,stride_bytes ,x ,y ,comp ,& len ); 1235if (png == NULL )return 0 ; 1236func (context ,png ,len ); 1237STBIW_FREE (png ); 1238return 1 ; 1239} 1240 1241 1242/* *************************************************************************** 1243* 1244* JPEG writer 1245* 1246* This is based on Jon Olick's jo_jpeg.cpp: 1247* public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html 1248*/ 1249 1250static 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 , 125124 ,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 }; 1252 1253static void stbiw__jpg_writeBits (stbi__write_context * s ,int * bitBufP ,int * bitCntP ,const unsigned short * bs ) { 1254int bitBuf = * bitBufP ,bitCnt = * bitCntP ; 1255bitCnt += bs [1 ]; 1256bitBuf |=bs [0 ] << (24 - bitCnt ); 1257while (bitCnt >=8 ) { 1258unsigned char c = (bitBuf >>16 )& 255 ; 1259stbiw__putc (s ,c ); 1260if (c == 255 ) { 1261stbiw__putc (s ,0 ); 1262 } 1263bitBuf <<=8 ; 1264bitCnt -= 8 ; 1265 } 1266* bitBufP = bitBuf ; 1267* bitCntP = bitCnt ; 1268} 1269 1270static void stbiw__jpg_DCT (float * d0p ,float * d1p ,float * d2p ,float * d3p ,float * d4p ,float * d5p ,float * d6p ,float * d7p ) { 1271float d0 = * d0p ,d1 = * d1p ,d2 = * d2p ,d3 = * d3p ,d4 = * d4p ,d5 = * d5p ,d6 = * d6p ,d7 = * d7p ; 1272float z1 ,z2 ,z3 ,z4 ,z5 ,z11 ,z13 ; 1273 1274float tmp0 = d0 + d7 ; 1275float tmp7 = d0 - d7 ; 1276float tmp1 = d1 + d6 ; 1277float tmp6 = d1 - d6 ; 1278float tmp2 = d2 + d5 ; 1279float tmp5 = d2 - d5 ; 1280float tmp3 = d3 + d4 ; 1281float tmp4 = d3 - d4 ; 1282 1283// Even part 1284float tmp10 = tmp0 + tmp3 ;// phase 2 1285float tmp13 = tmp0 - tmp3 ; 1286float tmp11 = tmp1 + tmp2 ; 1287float tmp12 = tmp1 - tmp2 ; 1288 1289d0 = tmp10 + tmp11 ;// phase 3 1290d4 = tmp10 - tmp11 ; 1291 1292z1 = (tmp12 + tmp13 )* 0.707106781f ;// c4 1293d2 = tmp13 + z1 ;// phase 5 1294d6 = tmp13 - z1 ; 1295 1296// Odd part 1297tmp10 = tmp4 + tmp5 ;// phase 2 1298tmp11 = tmp5 + tmp6 ; 1299tmp12 = tmp6 + tmp7 ; 1300 1301// The rotator is modified from fig 4-8 to avoid extra negations. 1302z5 = (tmp10 - tmp12 )* 0.382683433f ;// c6 1303z2 = tmp10 * 0.541196100f + z5 ;// c2-c6 1304z4 = tmp12 * 1.306562965f + z5 ;// c2+c6 1305z3 = tmp11 * 0.707106781f ;// c4 1306 1307z11 = tmp7 + z3 ;// phase 5 1308z13 = tmp7 - z3 ; 1309 1310* d5p = z13 + z2 ;// phase 6 1311* d3p = z13 - z2 ; 1312* d1p = z11 + z4 ; 1313* d7p = z11 - z4 ; 1314 1315* d0p = d0 ;* d2p = d2 ;* d4p = d4 ;* d6p = d6 ; 1316} 1317 1318static void stbiw__jpg_calcBits (int val ,unsigned short bits [2 ]) { 1319int tmp1 = val < 0 ?- val :val ; 1320val = val < 0 ?val - 1 :val ; 1321bits [1 ]= 1 ; 1322while (tmp1 >>=1 ) { 1323++ bits [1 ]; 1324 } 1325bits [0 ]= val & ((1 <<bits [1 ])- 1 ); 1326} 1327 1328static int stbiw__jpg_processDU (stbi__write_context * s ,int * bitBuf ,int * bitCnt ,float * CDU ,int du_stride ,float * fdtbl ,int DC ,const unsigned short HTDC [256 ][2 ],const unsigned short HTAC [256 ][2 ]) { 1329const unsigned short EOB [2 ]= {HTAC [0x00 ][0 ],HTAC [0x00 ][1 ] }; 1330const unsigned short M16zeroes [2 ]= {HTAC [0xF0 ][0 ],HTAC [0xF0 ][1 ] }; 1331int dataOff ,i ,j ,n ,diff ,end0pos ,x ,y ; 1332int DU [64 ]; 1333 1334// DCT rows 1335for (dataOff = 0 ,n = du_stride * 8 ;dataOff < n ;dataOff += du_stride ) { 1336stbiw__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 ]); 1337 } 1338// DCT columns 1339for (dataOff = 0 ;dataOff < 8 ;++ dataOff ) { 1340stbiw__jpg_DCT (& CDU [dataOff ],& CDU [dataOff + du_stride ],& CDU [dataOff + du_stride * 2 ],& CDU [dataOff + du_stride * 3 ],& CDU [dataOff + du_stride * 4 ], 1341& CDU [dataOff + du_stride * 5 ],& CDU [dataOff + du_stride * 6 ],& CDU [dataOff + du_stride * 7 ]); 1342 } 1343// Quantize/descale/zigzag the coefficients 1344for (y = 0 ,j = 0 ;y < 8 ;++ y ) { 1345for (x = 0 ;x < 8 ;++ x ,++ j ) { 1346float v ; 1347i = y * du_stride + x ; 1348v = CDU [i ]* fdtbl [j ]; 1349// DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f)); 1350// ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway? 1351DU [stbiw__jpg_ZigZag [j ]]= (int )(v < 0 ?v - 0.5f :v + 0.5f ); 1352 } 1353 } 1354 1355// Encode DC 1356diff = DU [0 ]- DC ; 1357if (diff == 0 ) { 1358stbiw__jpg_writeBits (s ,bitBuf ,bitCnt ,HTDC [0 ]); 1359 }else { 1360unsigned short bits [2 ]; 1361stbiw__jpg_calcBits (diff ,bits ); 1362stbiw__jpg_writeBits (s ,bitBuf ,bitCnt ,HTDC [bits [1 ]]); 1363stbiw__jpg_writeBits (s ,bitBuf ,bitCnt ,bits ); 1364 } 1365// Encode ACs 1366end0pos = 63 ; 1367for (; (end0pos > 0 )&& (DU [end0pos ]== 0 );-- end0pos ) { 1368 } 1369// end0pos = first element in reverse order !=0 1370if (end0pos == 0 ) { 1371stbiw__jpg_writeBits (s ,bitBuf ,bitCnt ,EOB ); 1372return DU [0 ]; 1373 } 1374for (i = 1 ;i <=end0pos ;++ i ) { 1375int startpos = i ; 1376int nrzeroes ; 1377unsigned short bits [2 ]; 1378for (;DU [i ]== 0 && i <=end0pos ;++ i ) { 1379 } 1380nrzeroes = i - startpos ; 1381if (nrzeroes >=16 ) { 1382int lng = nrzeroes >>4 ; 1383int nrmarker ; 1384for (nrmarker = 1 ;nrmarker <=lng ;++ nrmarker ) 1385stbiw__jpg_writeBits (s ,bitBuf ,bitCnt ,M16zeroes ); 1386nrzeroes &=15 ; 1387 } 1388stbiw__jpg_calcBits (DU [i ],bits ); 1389stbiw__jpg_writeBits (s ,bitBuf ,bitCnt ,HTAC [(nrzeroes <<4 )+ bits [1 ]]); 1390stbiw__jpg_writeBits (s ,bitBuf ,bitCnt ,bits ); 1391 } 1392if (end0pos != 63 ) { 1393stbiw__jpg_writeBits (s ,bitBuf ,bitCnt ,EOB ); 1394 } 1395return DU [0 ]; 1396} 1397 1398static int stbi_write_jpg_core (stbi__write_context * s ,int width ,int height ,int comp ,const void * data ,int quality ) { 1399// Constants that don't pollute global namespace 1400static const unsigned char std_dc_luminance_nrcodes []= {0 ,0 ,1 ,5 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 }; 1401static const unsigned char std_dc_luminance_values []= {0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 }; 1402static const unsigned char std_ac_luminance_nrcodes []= {0 ,0 ,2 ,1 ,3 ,3 ,2 ,4 ,3 ,5 ,5 ,4 ,4 ,0 ,0 ,1 ,0x7d }; 1403static const unsigned char std_ac_luminance_values []= { 14040x01 ,0x02 ,0x03 ,0x00 ,0x04 ,0x11 ,0x05 ,0x12 ,0x21 ,0x31 ,0x41 ,0x06 ,0x13 ,0x51 ,0x61 ,0x07 ,0x22 ,0x71 ,0x14 ,0x32 ,0x81 ,0x91 ,0xa1 ,0x08 , 14050x23 ,0x42 ,0xb1 ,0xc1 ,0x15 ,0x52 ,0xd1 ,0xf0 ,0x24 ,0x33 ,0x62 ,0x72 ,0x82 ,0x09 ,0x0a ,0x16 ,0x17 ,0x18 ,0x19 ,0x1a ,0x25 ,0x26 ,0x27 ,0x28 , 14060x29 ,0x2a ,0x34 ,0x35 ,0x36 ,0x37 ,0x38 ,0x39 ,0x3a ,0x43 ,0x44 ,0x45 ,0x46 ,0x47 ,0x48 ,0x49 ,0x4a ,0x53 ,0x54 ,0x55 ,0x56 ,0x57 ,0x58 ,0x59 , 14070x5a ,0x63 ,0x64 ,0x65 ,0x66 ,0x67 ,0x68 ,0x69 ,0x6a ,0x73 ,0x74 ,0x75 ,0x76 ,0x77 ,0x78 ,0x79 ,0x7a ,0x83 ,0x84 ,0x85 ,0x86 ,0x87 ,0x88 ,0x89 , 14080x8a ,0x92 ,0x93 ,0x94 ,0x95 ,0x96 ,0x97 ,0x98 ,0x99 ,0x9a ,0xa2 ,0xa3 ,0xa4 ,0xa5 ,0xa6 ,0xa7 ,0xa8 ,0xa9 ,0xaa ,0xb2 ,0xb3 ,0xb4 ,0xb5 ,0xb6 , 14090xb7 ,0xb8 ,0xb9 ,0xba ,0xc2 ,0xc3 ,0xc4 ,0xc5 ,0xc6 ,0xc7 ,0xc8 ,0xc9 ,0xca ,0xd2 ,0xd3 ,0xd4 ,0xd5 ,0xd6 ,0xd7 ,0xd8 ,0xd9 ,0xda ,0xe1 ,0xe2 , 14100xe3 ,0xe4 ,0xe5 ,0xe6 ,0xe7 ,0xe8 ,0xe9 ,0xea ,0xf1 ,0xf2 ,0xf3 ,0xf4 ,0xf5 ,0xf6 ,0xf7 ,0xf8 ,0xf9 ,0xfa 1411 }; 1412static const unsigned char std_dc_chrominance_nrcodes []= {0 ,0 ,3 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 }; 1413static const unsigned char std_dc_chrominance_values []= {0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 }; 1414static const unsigned char std_ac_chrominance_nrcodes []= {0 ,0 ,2 ,1 ,2 ,4 ,4 ,3 ,4 ,7 ,5 ,4 ,4 ,0 ,1 ,2 ,0x77 }; 1415static const unsigned char std_ac_chrominance_values []= { 14160x00 ,0x01 ,0x02 ,0x03 ,0x11 ,0x04 ,0x05 ,0x21 ,0x31 ,0x06 ,0x12 ,0x41 ,0x51 ,0x07 ,0x61 ,0x71 ,0x13 ,0x22 ,0x32 ,0x81 ,0x08 ,0x14 ,0x42 ,0x91 , 14170xa1 ,0xb1 ,0xc1 ,0x09 ,0x23 ,0x33 ,0x52 ,0xf0 ,0x15 ,0x62 ,0x72 ,0xd1 ,0x0a ,0x16 ,0x24 ,0x34 ,0xe1 ,0x25 ,0xf1 ,0x17 ,0x18 ,0x19 ,0x1a ,0x26 , 14180x27 ,0x28 ,0x29 ,0x2a ,0x35 ,0x36 ,0x37 ,0x38 ,0x39 ,0x3a ,0x43 ,0x44 ,0x45 ,0x46 ,0x47 ,0x48 ,0x49 ,0x4a ,0x53 ,0x54 ,0x55 ,0x56 ,0x57 ,0x58 , 14190x59 ,0x5a ,0x63 ,0x64 ,0x65 ,0x66 ,0x67 ,0x68 ,0x69 ,0x6a ,0x73 ,0x74 ,0x75 ,0x76 ,0x77 ,0x78 ,0x79 ,0x7a ,0x82 ,0x83 ,0x84 ,0x85 ,0x86 ,0x87 , 14200x88 ,0x89 ,0x8a ,0x92 ,0x93 ,0x94 ,0x95 ,0x96 ,0x97 ,0x98 ,0x99 ,0x9a ,0xa2 ,0xa3 ,0xa4 ,0xa5 ,0xa6 ,0xa7 ,0xa8 ,0xa9 ,0xaa ,0xb2 ,0xb3 ,0xb4 , 14210xb5 ,0xb6 ,0xb7 ,0xb8 ,0xb9 ,0xba ,0xc2 ,0xc3 ,0xc4 ,0xc5 ,0xc6 ,0xc7 ,0xc8 ,0xc9 ,0xca ,0xd2 ,0xd3 ,0xd4 ,0xd5 ,0xd6 ,0xd7 ,0xd8 ,0xd9 ,0xda , 14220xe2 ,0xe3 ,0xe4 ,0xe5 ,0xe6 ,0xe7 ,0xe8 ,0xe9 ,0xea ,0xf2 ,0xf3 ,0xf4 ,0xf5 ,0xf6 ,0xf7 ,0xf8 ,0xf9 ,0xfa 1423 }; 1424// Huffman tables 1425static 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 }}; 1426static 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 }}; 1427static const unsigned short YAC_HT [256 ][2 ]= { 1428 {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 }, 1429 {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 }, 1430 {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 }, 1431 {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 }, 1432 {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 }, 1433 {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 }, 1434 {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 }, 1435 {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 }, 1436 {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 }, 1437 {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 }, 1438 {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 }, 1439 {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 }, 1440 {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 }, 1441 {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 }, 1442 {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 }, 1443 {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 } 1444 }; 1445static const unsigned short UVAC_HT [256 ][2 ]= { 1446 {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 }, 1447 {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 }, 1448 {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 }, 1449 {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 }, 1450 {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 }, 1451 {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 }, 1452 {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 }, 1453 {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 }, 1454 {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 }, 1455 {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 }, 1456 {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 }, 1457 {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 }, 1458 {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 }, 1459 {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 }, 1460 {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 }, 1461 {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 } 1462 }; 1463static 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 , 146437 ,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 }; 1465static 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 , 146699 ,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 }; 1467static const float aasf []= {1.0f * 2.828427125f ,1.387039845f * 2.828427125f ,1.306562965f * 2.828427125f ,1.175875602f * 2.828427125f , 14681.0f * 2.828427125f ,0.785694958f * 2.828427125f ,0.541196100f * 2.828427125f ,0.275899379f * 2.828427125f }; 1469 1470int row ,col ,i ,k ,subsample ; 1471float fdtbl_Y [64 ],fdtbl_UV [64 ]; 1472unsigned char YTable [64 ],UVTable [64 ]; 1473 1474if (!data || !width || !height || comp > 4 || comp < 1 ) { 1475return 0 ; 1476 } 1477 1478quality = quality ?quality :90 ; 1479subsample = quality <=90 ?1 :0 ; 1480quality = quality < 1 ?1 :quality > 100 ?100 :quality ; 1481quality = quality < 50 ?5000 /quality :200 - quality * 2 ; 1482 1483for (i = 0 ;i < 64 ;++ i ) { 1484int uvti ,yti = (YQT [i ]* quality + 50 )/100 ; 1485YTable [stbiw__jpg_ZigZag [i ]]= (unsigned char ) (yti < 1 ?1 :yti > 255 ?255 :yti ); 1486uvti = (UVQT [i ]* quality + 50 )/100 ; 1487UVTable [stbiw__jpg_ZigZag [i ]]= (unsigned char ) (uvti < 1 ?1 :uvti > 255 ?255 :uvti ); 1488 } 1489 1490for (row = 0 ,k = 0 ;row < 8 ;++ row ) { 1491for (col = 0 ;col < 8 ;++ col ,++ k ) { 1492fdtbl_Y [k ]= 1 / (YTable [stbiw__jpg_ZigZag [k ]]* aasf [row ]* aasf [col ]); 1493fdtbl_UV [k ]= 1 / (UVTable [stbiw__jpg_ZigZag [k ]]* aasf [row ]* aasf [col ]); 1494 } 1495 } 1496 1497// Write Headers 1498 { 1499static 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 }; 1500static const unsigned char head2 []= {0xFF ,0xDA ,0 ,0xC ,3 ,1 ,0 ,2 ,0x11 ,3 ,0x11 ,0 ,0x3F ,0 }; 1501const unsigned char head1 []= {0xFF ,0xC0 ,0 ,0x11 ,8 ,(unsigned char )(height >>8 ),STBIW_UCHAR (height ),(unsigned char )(width >>8 ),STBIW_UCHAR (width ), 15023 ,1 ,(unsigned char )(subsample ?0x22 :0x11 ),0 ,2 ,0x11 ,1 ,3 ,0x11 ,1 ,0xFF ,0xC4 ,0x01 ,0xA2 ,0 }; 1503s -> func (s -> context , (void * )head0 ,sizeof (head0 )); 1504s -> func (s -> context , (void * )YTable ,sizeof (YTable )); 1505stbiw__putc (s ,1 ); 1506s -> func (s -> context ,UVTable ,sizeof (UVTable )); 1507s -> func (s -> context , (void * )head1 ,sizeof (head1 )); 1508s -> func (s -> context , (void * )(std_dc_luminance_nrcodes + 1 ),sizeof (std_dc_luminance_nrcodes )- 1 ); 1509s -> func (s -> context , (void * )std_dc_luminance_values ,sizeof (std_dc_luminance_values )); 1510stbiw__putc (s ,0x10 );// HTYACinfo 1511s -> func (s -> context , (void * )(std_ac_luminance_nrcodes + 1 ),sizeof (std_ac_luminance_nrcodes )- 1 ); 1512s -> func (s -> context , (void * )std_ac_luminance_values ,sizeof (std_ac_luminance_values )); 1513stbiw__putc (s ,1 );// HTUDCinfo 1514s -> func (s -> context , (void * )(std_dc_chrominance_nrcodes + 1 ),sizeof (std_dc_chrominance_nrcodes )- 1 ); 1515s -> func (s -> context , (void * )std_dc_chrominance_values ,sizeof (std_dc_chrominance_values )); 1516stbiw__putc (s ,0x11 );// HTUACinfo 1517s -> func (s -> context , (void * )(std_ac_chrominance_nrcodes + 1 ),sizeof (std_ac_chrominance_nrcodes )- 1 ); 1518s -> func (s -> context , (void * )std_ac_chrominance_values ,sizeof (std_ac_chrominance_values )); 1519s -> func (s -> context , (void * )head2 ,sizeof (head2 )); 1520 } 1521 1522// Encode 8x8 macroblocks 1523 { 1524static const unsigned short fillBits []= {0x7F ,7 }; 1525int DCY = 0 ,DCU = 0 ,DCV = 0 ; 1526int bitBuf = 0 ,bitCnt = 0 ; 1527// comp == 2 is grey+alpha (alpha is ignored) 1528int ofsG = comp > 2 ?1 :0 ,ofsB = comp > 2 ?2 :0 ; 1529const unsigned char * dataR = (const unsigned char * )data ; 1530const unsigned char * dataG = dataR + ofsG ; 1531const unsigned char * dataB = dataR + ofsB ; 1532int x ,y ,pos ; 1533if (subsample ) { 1534for (y = 0 ;y < height ;y += 16 ) { 1535for (x = 0 ;x < width ;x += 16 ) { 1536float Y [256 ],U [256 ],V [256 ]; 1537for (row = y ,pos = 0 ;row < y + 16 ;++ row ) { 1538// row >= height => use last input row 1539int clamped_row = (row < height ) ?row :height - 1 ; 1540int base_p = (stbi__flip_vertically_on_write ? (height - 1 - clamped_row ) :clamped_row )* width * comp ; 1541for (col = x ;col < x + 16 ;++ col ,++ pos ) { 1542// if col >= width => use pixel from last input column 1543int p = base_p + ((col < width ) ?col : (width - 1 ))* comp ; 1544float r = dataR [p ],g = dataG [p ],b = dataB [p ]; 1545Y [pos ]= +0.29900f * r + 0.58700f * g + 0.11400f * b - 128 ; 1546U [pos ]= -0.16874f * r - 0.33126f * g + 0.50000f * b ; 1547V [pos ]= +0.50000f * r - 0.41869f * g - 0.08131f * b ; 1548 } 1549 } 1550DCY = stbiw__jpg_processDU (s ,& bitBuf ,& bitCnt ,Y + 0 ,16 ,fdtbl_Y ,DCY ,YDC_HT ,YAC_HT ); 1551DCY = stbiw__jpg_processDU (s ,& bitBuf ,& bitCnt ,Y + 8 ,16 ,fdtbl_Y ,DCY ,YDC_HT ,YAC_HT ); 1552DCY = stbiw__jpg_processDU (s ,& bitBuf ,& bitCnt ,Y + 128 ,16 ,fdtbl_Y ,DCY ,YDC_HT ,YAC_HT ); 1553DCY = stbiw__jpg_processDU (s ,& bitBuf ,& bitCnt ,Y + 136 ,16 ,fdtbl_Y ,DCY ,YDC_HT ,YAC_HT ); 1554 1555// subsample U,V 1556 { 1557float subU [64 ],subV [64 ]; 1558int yy ,xx ; 1559for (yy = 0 ,pos = 0 ;yy < 8 ;++ yy ) { 1560for (xx = 0 ;xx < 8 ;++ xx ,++ pos ) { 1561int j = yy * 32 + xx * 2 ; 1562subU [pos ]= (U [j + 0 ]+ U [j + 1 ]+ U [j + 16 ]+ U [j + 17 ])* 0.25f ; 1563subV [pos ]= (V [j + 0 ]+ V [j + 1 ]+ V [j + 16 ]+ V [j + 17 ])* 0.25f ; 1564 } 1565 } 1566DCU = stbiw__jpg_processDU (s ,& bitBuf ,& bitCnt ,subU ,8 ,fdtbl_UV ,DCU ,UVDC_HT ,UVAC_HT ); 1567DCV = stbiw__jpg_processDU (s ,& bitBuf ,& bitCnt ,subV ,8 ,fdtbl_UV ,DCV ,UVDC_HT ,UVAC_HT ); 1568 } 1569 } 1570 } 1571 }else { 1572for (y = 0 ;y < height ;y += 8 ) { 1573for (x = 0 ;x < width ;x += 8 ) { 1574float Y [64 ],U [64 ],V [64 ]; 1575for (row = y ,pos = 0 ;row < y + 8 ;++ row ) { 1576// row >= height => use last input row 1577int clamped_row = (row < height ) ?row :height - 1 ; 1578int base_p = (stbi__flip_vertically_on_write ? (height - 1 - clamped_row ) :clamped_row )* width * comp ; 1579for (col = x ;col < x + 8 ;++ col ,++ pos ) { 1580// if col >= width => use pixel from last input column 1581int p = base_p + ((col < width ) ?col : (width - 1 ))* comp ; 1582float r = dataR [p ],g = dataG [p ],b = dataB [p ]; 1583Y [pos ]= +0.29900f * r + 0.58700f * g + 0.11400f * b - 128 ; 1584U [pos ]= -0.16874f * r - 0.33126f * g + 0.50000f * b ; 1585V [pos ]= +0.50000f * r - 0.41869f * g - 0.08131f * b ; 1586 } 1587 } 1588 1589DCY = stbiw__jpg_processDU (s ,& bitBuf ,& bitCnt ,Y ,8 ,fdtbl_Y ,DCY ,YDC_HT ,YAC_HT ); 1590DCU = stbiw__jpg_processDU (s ,& bitBuf ,& bitCnt ,U ,8 ,fdtbl_UV ,DCU ,UVDC_HT ,UVAC_HT ); 1591DCV = stbiw__jpg_processDU (s ,& bitBuf ,& bitCnt ,V ,8 ,fdtbl_UV ,DCV ,UVDC_HT ,UVAC_HT ); 1592 } 1593 } 1594 } 1595 1596// Do the bit alignment of the EOI marker 1597stbiw__jpg_writeBits (s ,& bitBuf ,& bitCnt ,fillBits ); 1598 } 1599 1600// EOI 1601stbiw__putc (s ,0xFF ); 1602stbiw__putc (s ,0xD9 ); 1603 1604return 1 ; 1605} 1606 1607STBIWDEF int stbi_write_jpg_to_func (stbi_write_func * func ,void * context ,int x ,int y ,int comp ,const void * data ,int quality ) 1608{ 1609stbi__write_context s = {0 }; 1610stbi__start_write_callbacks (& s ,func ,context ); 1611return stbi_write_jpg_core (& s ,x ,y ,comp , (void * )data ,quality ); 1612} 1613 1614 1615#ifndef STBI_WRITE_NO_STDIO 1616STBIWDEF int stbi_write_jpg (char const * filename ,int x ,int y ,int comp ,const void * data ,int quality ) 1617{ 1618stbi__write_context s = {0 }; 1619if (stbi__start_write_file (& s ,filename )) { 1620int r = stbi_write_jpg_core (& s ,x ,y ,comp ,data ,quality ); 1621stbi__end_write_file (& s ); 1622return r ; 1623 }else 1624return 0 ; 1625} 1626#endif 1627 1628#endif // STB_IMAGE_WRITE_IMPLEMENTATION 1629 1630/* Revision history 16311.16 (2021-07-11) 1632make Deflate code emit uncompressed blocks when it would otherwise expand 1633support writing BMPs with alpha channel 16341.15 (2020-07-13) unknown 16351.14 (2020-02-02) updated JPEG writer to downsample chroma channels 16361.13 16371.12 16381.11 (2019-08-11) 1639 16401.10 (2019-02-07) 1641support utf8 filenames in Windows; fix warnings and platform ifdefs 16421.09 (2018-02-11) 1643fix typo in zlib quality API, improve STB_I_W_STATIC in C++ 16441.08 (2018-01-29) 1645add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter 16461.07 (2017-07-24) 1647doc fix 16481.06 (2017-07-23) 1649writing JPEG (using Jon Olick's code) 16501.05 ??? 16511.04 (2017-03-03) 1652monochrome BMP expansion 16531.03 ??? 16541.02 (2016-04-02) 1655avoid allocating large structures on the stack 16561.01 (2016-01-16) 1657STBIW_REALLOC_SIZED: support allocators with no realloc support 1658avoid race-condition in crc initialization 1659minor compile issues 16601.00 (2015-09-14) 1661installable file IO function 16620.99 (2015-09-13) 1663warning fixes; TGA rle support 16640.98 (2015-04-08) 1665added STBIW_MALLOC, STBIW_ASSERT etc 16660.97 (2015-01-18) 1667fixed HDR asserts, rewrote HDR rle logic 16680.96 (2015-01-17) 1669add HDR output 1670fix monochrome BMP 16710.95 (2014-08-17) 1672add monochrome TGA output 16730.94 (2014-05-31) 1674rename private functions to avoid conflicts with stb_image.h 16750.93 (2014-05-27) 1676warning fixes 16770.92 (2010-08-01) 1678casts to unsigned char to fix warnings 16790.91 (2010-07-17) 1680first public release 16810.90 first internal release 1682*/ 1683 1684/* 1685------------------------------------------------------------------------------ 1686This software is available under 2 licenses -- choose whichever you prefer. 1687------------------------------------------------------------------------------ 1688ALTERNATIVE A - MIT License 1689Copyright (c) 2017 Sean Barrett 1690Permission is hereby granted, free of charge, to any person obtaining a copy of 1691this software and associated documentation files (the "Software"), to deal in 1692the Software without restriction, including without limitation the rights to 1693use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 1694of the Software, and to permit persons to whom the Software is furnished to do 1695so, subject to the following conditions: 1696The above copyright notice and this permission notice shall be included in all 1697copies or substantial portions of the Software. 1698THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1699IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1700FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1701AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1702LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1703OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1704SOFTWARE. 1705------------------------------------------------------------------------------ 1706ALTERNATIVE B - Public Domain (www.unlicense.org) 1707This is free and unencumbered software released into the public domain. 1708Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 1709software, either in source code form or as a compiled binary, for any purpose, 1710commercial or non-commercial, and by any means. 1711In jurisdictions that recognize copyright laws, the author or authors of this 1712software dedicate any and all copyright interest in the software to the public 1713domain. We make this dedication for the benefit of the public at large and to 1714the detriment of our heirs and successors. We intend this dedication to be an 1715overt act of relinquishment in perpetuity of all present and future rights to 1716this software under copyright law. 1717THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1718IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1719FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1720AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 1721ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 1722WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 1723------------------------------------------------------------------------------ 1724*/