Updated external libraries

This commit is contained in:
Ray
2018-02-09 00:00:47 +01:00
parent 2ace360230
commit f72b315cb6
6 changed files with 726 additions and 305 deletions

View File

@@ -1,5 +1,5 @@
// Audio playback and capture library. Public domain. See "unlicense" statement at the end of this file. // Audio playback and capture library. Public domain. See "unlicense" statement at the end of this file.
// mini_al - v0.x - xxxx-xx-xx // mini_al - v0.6b - 2018-02-03
// //
// David Reid - davidreidsoftware@gmail.com // David Reid - davidreidsoftware@gmail.com
@@ -1774,7 +1774,10 @@ typedef HWND (WINAPI * MAL_PFN_GetDesktopWindow)();
#define mal_buffer_frame_capacity(buffer, channels, format) (sizeof(buffer) / mal_get_sample_size_in_bytes(format) / (channels)) #define mal_buffer_frame_capacity(buffer, channels, format) (sizeof(buffer) / mal_get_sample_size_in_bytes(format) / (channels))
// Some of these string utility functions are unused on some platforms. // Some of these string utility functions are unused on some platforms.
#if defined(__GNUC__) #if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4505)
#elif defined(__GNUC__)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-function"
#endif #endif
@@ -1972,7 +1975,9 @@ static int mal_strcmp(const char* str1, const char* str2)
return ((unsigned char*)str1)[0] - ((unsigned char*)str2)[0]; return ((unsigned char*)str1)[0] - ((unsigned char*)str2)[0];
} }
#if defined(__GNUC__) #if defined(_MSC_VER)
#pragma warning(pop)
#elif defined(__GNUC__)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
@@ -8843,6 +8848,8 @@ mal_result mal_device_init__sdl(mal_context* pContext, mal_device_type type, mal
mal_assert(pConfig != NULL); mal_assert(pConfig != NULL);
mal_assert(pDevice != NULL); mal_assert(pDevice != NULL);
(void)pContext;
// SDL wants the buffer size to be a power of 2. The SDL_AudioSpec property for this is only a Uint16, so we need // SDL wants the buffer size to be a power of 2. The SDL_AudioSpec property for this is only a Uint16, so we need
// to explicitly clamp this because it will be easy to overflow. // to explicitly clamp this because it will be easy to overflow.
mal_uint32 bufferSize = pConfig->bufferSizeInFrames; mal_uint32 bufferSize = pConfig->bufferSizeInFrames;
@@ -10760,7 +10767,7 @@ static void mal_dsp_mix_channels__inc(float* pFramesOut, mal_uint32 channelsOut,
(void)channelMapOut; (void)channelMapOut;
(void)channelMapIn; (void)channelMapIn;
if (mode == mal_channel_mix_mode_basic) {\ if (mode == mal_channel_mix_mode_basic) {
// Basic mode is where we just zero out extra channels. // Basic mode is where we just zero out extra channels.
for (mal_uint32 iFrame = 0; iFrame < frameCount; ++iFrame) { for (mal_uint32 iFrame = 0; iFrame < frameCount; ++iFrame) {
switch (channelsIn) { switch (channelsIn) {
@@ -10785,23 +10792,23 @@ static void mal_dsp_mix_channels__inc(float* pFramesOut, mal_uint32 channelsOut,
// Zero out extra channels. // Zero out extra channels.
switch (channelsOut - channelsIn) { switch (channelsOut - channelsIn) {
case 17: pFramesOut[iFrame*channelsOut+16] = 0; case 17: pFramesOut[iFrame*channelsOut+16 + channelsIn] = 0;
case 16: pFramesOut[iFrame*channelsOut+15] = 0; case 16: pFramesOut[iFrame*channelsOut+15 + channelsIn] = 0;
case 15: pFramesOut[iFrame*channelsOut+14] = 0; case 15: pFramesOut[iFrame*channelsOut+14 + channelsIn] = 0;
case 14: pFramesOut[iFrame*channelsOut+13] = 0; case 14: pFramesOut[iFrame*channelsOut+13 + channelsIn] = 0;
case 13: pFramesOut[iFrame*channelsOut+12] = 0; case 13: pFramesOut[iFrame*channelsOut+12 + channelsIn] = 0;
case 12: pFramesOut[iFrame*channelsOut+11] = 0; case 12: pFramesOut[iFrame*channelsOut+11 + channelsIn] = 0;
case 11: pFramesOut[iFrame*channelsOut+10] = 0; case 11: pFramesOut[iFrame*channelsOut+10 + channelsIn] = 0;
case 10: pFramesOut[iFrame*channelsOut+ 9] = 0; case 10: pFramesOut[iFrame*channelsOut+ 9 + channelsIn] = 0;
case 9: pFramesOut[iFrame*channelsOut+ 8] = 0; case 9: pFramesOut[iFrame*channelsOut+ 8 + channelsIn] = 0;
case 8: pFramesOut[iFrame*channelsOut+ 7] = 0; case 8: pFramesOut[iFrame*channelsOut+ 7 + channelsIn] = 0;
case 7: pFramesOut[iFrame*channelsOut+ 6] = 0; case 7: pFramesOut[iFrame*channelsOut+ 6 + channelsIn] = 0;
case 6: pFramesOut[iFrame*channelsOut+ 5] = 0; case 6: pFramesOut[iFrame*channelsOut+ 5 + channelsIn] = 0;
case 5: pFramesOut[iFrame*channelsOut+ 4] = 0; case 5: pFramesOut[iFrame*channelsOut+ 4 + channelsIn] = 0;
case 4: pFramesOut[iFrame*channelsOut+ 3] = 0; case 4: pFramesOut[iFrame*channelsOut+ 3 + channelsIn] = 0;
case 3: pFramesOut[iFrame*channelsOut+ 2] = 0; case 3: pFramesOut[iFrame*channelsOut+ 2 + channelsIn] = 0;
case 2: pFramesOut[iFrame*channelsOut+ 1] = 0; case 2: pFramesOut[iFrame*channelsOut+ 1 + channelsIn] = 0;
case 1: pFramesOut[iFrame*channelsOut+ 0] = 0; case 1: pFramesOut[iFrame*channelsOut+ 0 + channelsIn] = 0;
} }
} }
} else { } else {
@@ -10832,10 +10839,10 @@ static void mal_dsp_mix_channels__inc(float* pFramesOut, mal_uint32 channelsOut,
} }
} else if (channelsIn == 2) { } else if (channelsIn == 2) {
// TODO: Implement an optimized stereo conversion. // TODO: Implement an optimized stereo conversion.
mal_dsp_mix_channels__dec(pFramesOut, channelsOut, channelMapOut, pFramesIn, channelsIn, channelMapIn, frameCount, mal_channel_mix_mode_basic); mal_dsp_mix_channels__inc(pFramesOut, channelsOut, channelMapOut, pFramesIn, channelsIn, channelMapIn, frameCount, mal_channel_mix_mode_basic);
} else { } else {
// Fall back to basic mixing mode. // Fall back to basic mixing mode.
mal_dsp_mix_channels__dec(pFramesOut, channelsOut, channelMapOut, pFramesIn, channelsIn, channelMapIn, frameCount, mal_channel_mix_mode_basic); mal_dsp_mix_channels__inc(pFramesOut, channelsOut, channelMapOut, pFramesIn, channelsIn, channelMapIn, frameCount, mal_channel_mix_mode_basic);
} }
} }
} }
@@ -11494,7 +11501,11 @@ void mal_pcm_f32_to_s32(int* pOut, const float* pIn, unsigned int count)
// REVISION HISTORY // REVISION HISTORY
// ================ // ================
// //
// v0.x - xxxx-xx-xx // v0.6b - 2018-02-03
// - Fix some warnings when compiling with Visual C++.
//
// v0.6a - 2018-01-26
// - Fix errors with channel mixing when increasing the channel count.
// - Improvements to the build system for the OpenAL backend. // - Improvements to the build system for the OpenAL backend.
// - Documentation fixes. // - Documentation fixes.
// //

View File

@@ -1,4 +1,4 @@
/* stb_image - v2.16 - public domain image loader - http://nothings.org/stb_image.h /* stb_image - v2.18 - public domain image loader - http://nothings.org/stb
no warranty implied; use at your own risk no warranty implied; use at your own risk
Do this: Do this:
@@ -48,6 +48,8 @@ LICENSE
RECENT REVISION HISTORY: RECENT REVISION HISTORY:
2.18 (2018-01-30) fix warnings
2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings
2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes
2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC
2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
@@ -74,11 +76,11 @@ RECENT REVISION HISTORY:
Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip)
Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD)
github:urraka (animated gif) Junggon Kim (PNM comments) github:urraka (animated gif) Junggon Kim (PNM comments)
Daniel Gibson (16-bit TGA) Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA)
socks-the-fox (16-bit PNG) socks-the-fox (16-bit PNG)
Jeremy Sawicki (handle all ImageNet JPGs) Jeremy Sawicki (handle all ImageNet JPGs)
Optimizations & bugfixes Optimizations & bugfixes Mikhail Morozov (1-bit BMP)
Fabian "ryg" Giesen Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query)
Arseny Kapoulkine Arseny Kapoulkine
John-Mark Allen John-Mark Allen
@@ -87,16 +89,17 @@ RECENT REVISION HISTORY:
Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan
Dave Moore Roy Eltham Hayaki Saito Nathan Reed Dave Moore Roy Eltham Hayaki Saito Nathan Reed
Won Chun Luke Graham Johan Duparc Nick Verigakis Won Chun Luke Graham Johan Duparc Nick Verigakis
the Horde3D community Thomas Ruf Ronny Chevalier Baldur Karlsson the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh
Janez Zemva John Bartholomew Michal Cichon github:rlyeh Janez Zemva John Bartholomew Michal Cichon github:romigrou
Jonathan Blow Ken Hamada Tero Hanninen github:romigrou Jonathan Blow Ken Hamada Tero Hanninen github:svdijk
Laurent Gomila Cort Stratton Sergio Gonzalez github:svdijk Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar
Aruelien Pocheville Thibault Reuille Cass Everitt github:snagar Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex
Ryamond Barbiero Paul Du Bois Engin Manap github:Zelex Ryamond Barbiero Paul Du Bois Engin Manap github:grim210
Michaelangel007@github Philipp Wiesemann Dale Weiler github:grim210 Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw
Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:sammyhw Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus
Blazej Dariusz Roszkowski Gregory Mullen github:phprus Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo
Christian Floisand Kevin Schmidt github:poppolopoppo Christian Floisand Kevin Schmidt github:darealshinji
Blazej Dariusz Roszkowski github:Michaelangel007
*/ */
#ifndef STBI_INCLUDE_STB_IMAGE_H #ifndef STBI_INCLUDE_STB_IMAGE_H
@@ -105,10 +108,8 @@ RECENT REVISION HISTORY:
// DOCUMENTATION // DOCUMENTATION
// //
// Limitations: // Limitations:
// - no 16-bit-per-channel PNG
// - no 12-bit-per-channel JPEG // - no 12-bit-per-channel JPEG
// - no JPEGs with arithmetic coding // - no JPEGs with arithmetic coding
// - no 1-bit BMP
// - GIF always returns *comp=4 // - GIF always returns *comp=4
// //
// Basic usage (see HDR discussion below for HDR usage): // Basic usage (see HDR discussion below for HDR usage):
@@ -353,6 +354,10 @@ typedef struct
STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels);
STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels);
#ifndef STBI_NO_GIF
STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
#endif
#ifndef STBI_NO_STDIO #ifndef STBI_NO_STDIO
STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
@@ -416,11 +421,14 @@ STBIDEF void stbi_image_free (void *retval_from_stbi_load);
// get image dimensions & components without fully decoding // get image dimensions & components without fully decoding
STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);
STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len);
STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user);
#ifndef STBI_NO_STDIO #ifndef STBI_NO_STDIO
STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp);
STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp);
STBIDEF int stbi_is_16_bit (char const *filename);
STBIDEF int stbi_is_16_bit_from_file(FILE *f);
#endif #endif
@@ -504,7 +512,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#include <limits.h> #include <limits.h>
#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) #if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
#include <math.h> // ldexp #include <math.h> // ldexp, pow
#endif #endif
#ifndef STBI_NO_STDIO #ifndef STBI_NO_STDIO
@@ -784,6 +792,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp);
static int stbi__png_test(stbi__context *s); static int stbi__png_test(stbi__context *s);
static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp);
static int stbi__png_is16(stbi__context *s);
#endif #endif
#ifndef STBI_NO_BMP #ifndef STBI_NO_BMP
@@ -802,6 +811,7 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp);
static int stbi__psd_test(stbi__context *s); static int stbi__psd_test(stbi__context *s);
static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc);
static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp);
static int stbi__psd_is16(stbi__context *s);
#endif #endif
#ifndef STBI_NO_HDR #ifndef STBI_NO_HDR
@@ -819,6 +829,7 @@ static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp);
#ifndef STBI_NO_GIF #ifndef STBI_NO_GIF
static int stbi__gif_test(stbi__context *s); static int stbi__gif_test(stbi__context *s);
static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp);
#endif #endif
@@ -893,11 +904,13 @@ static int stbi__mad3sizes_valid(int a, int b, int c, int add)
} }
// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow // returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow
#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
{ {
return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add);
} }
#endif
// mallocs with size overflow checking // mallocs with size overflow checking
static void *stbi__malloc_mad2(int a, int b, int add) static void *stbi__malloc_mad2(int a, int b, int add)
@@ -912,11 +925,13 @@ static void *stbi__malloc_mad3(int a, int b, int c, int add)
return stbi__malloc(a*b*c + add); return stbi__malloc(a*b*c + add);
} }
#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
{ {
if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL;
return stbi__malloc(a*b*c*d + add); return stbi__malloc(a*b*c*d + add);
} }
#endif
// stbi__err - error // stbi__err - error
// stbi__errpf - error returning pointer to float // stbi__errpf - error returning pointer to float
@@ -1054,6 +1069,18 @@ static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel)
} }
} }
static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel)
{
int slice;
int slice_size = w * h * bytes_per_pixel;
stbi_uc *bytes = (stbi_uc *)image;
for (slice = 0; slice < z; ++slice) {
stbi__vertical_flip(bytes, w, h, bytes_per_pixel);
bytes += slice_size;
}
}
static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{ {
stbi__result_info ri; stbi__result_info ri;
@@ -1103,7 +1130,7 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x,
return (stbi__uint16 *) result; return (stbi__uint16 *) result;
} }
#ifndef STBI_NO_HDR #if !defined(STBI_NO_HDR) || !defined(STBI_NO_LINEAR)
static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp)
{ {
if (stbi__vertically_flip_on_load && result != NULL) { if (stbi__vertically_flip_on_load && result != NULL) {
@@ -1205,6 +1232,22 @@ STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *u
return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
} }
#ifndef STBI_NO_GIF
STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
{
unsigned char *result;
stbi__context s;
stbi__start_mem(&s,buffer,len);
result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp);
if (stbi__vertically_flip_on_load) {
stbi__vertical_flip_slices( result, *x, *y, *z, *comp );
}
return result;
}
#endif
#ifndef STBI_NO_LINEAR #ifndef STBI_NO_LINEAR
static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{ {
@@ -1291,9 +1334,13 @@ STBIDEF int stbi_is_hdr (char const *filename)
STBIDEF int stbi_is_hdr_from_file(FILE *f) STBIDEF int stbi_is_hdr_from_file(FILE *f)
{ {
#ifndef STBI_NO_HDR #ifndef STBI_NO_HDR
long pos = ftell(f);
int res;
stbi__context s; stbi__context s;
stbi__start_file(&s,f); stbi__start_file(&s,f);
return stbi__hdr_test(&s); res = stbi__hdr_test(&s);
fseek(f, pos, SEEK_SET);
return res;
#else #else
STBI_NOTUSED(f); STBI_NOTUSED(f);
return 0; return 0;
@@ -1705,7 +1752,8 @@ typedef struct
static int stbi__build_huffman(stbi__huffman *h, int *count) static int stbi__build_huffman(stbi__huffman *h, int *count)
{ {
int i,j,k=0,code; int i,j,k=0;
unsigned int code;
// build size list for each symbol (from JPEG spec) // build size list for each symbol (from JPEG spec)
for (i=0; i < 16; ++i) for (i=0; i < 16; ++i)
for (j=0; j < count[i]; ++j) for (j=0; j < count[i]; ++j)
@@ -1721,7 +1769,7 @@ static int stbi__build_huffman(stbi__huffman *h, int *count)
if (h->size[k] == j) { if (h->size[k] == j) {
while (h->size[k] == j) while (h->size[k] == j)
h->code[k++] = (stbi__uint16) (code++); h->code[k++] = (stbi__uint16) (code++);
if (code-1 >= (1 << j)) return stbi__err("bad code lengths","Corrupt JPEG"); if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG");
} }
// compute largest code + 1 for this size, preshifted as needed later // compute largest code + 1 for this size, preshifted as needed later
h->maxcode[j] = code << (16-j); h->maxcode[j] = code << (16-j);
@@ -1765,7 +1813,7 @@ static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h)
if (k < m) k += (~0U << magbits) + 1; if (k < m) k += (~0U << magbits) + 1;
// if the result is small enough, we can fit it in fast_ac table // if the result is small enough, we can fit it in fast_ac table
if (k >= -128 && k <= 127) if (k >= -128 && k <= 127)
fast_ac[i] = (stbi__int16) ((k << 8) + (run << 4) + (len + magbits)); fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits));
} }
} }
} }
@@ -1774,7 +1822,7 @@ static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h)
static void stbi__grow_buffer_unsafe(stbi__jpeg *j) static void stbi__grow_buffer_unsafe(stbi__jpeg *j)
{ {
do { do {
int b = j->nomore ? 0 : stbi__get8(j->s); unsigned int b = j->nomore ? 0 : stbi__get8(j->s);
if (b == 0xff) { if (b == 0xff) {
int c = stbi__get8(j->s); int c = stbi__get8(j->s);
while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes
@@ -1790,7 +1838,7 @@ static void stbi__grow_buffer_unsafe(stbi__jpeg *j)
} }
// (1 << n) - 1 // (1 << n) - 1
static stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535};
// decode a jpeg huffman value from the bitstream // decode a jpeg huffman value from the bitstream
stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h)
@@ -1843,7 +1891,7 @@ stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h)
} }
// bias[n] = (-1<<n) + 1 // bias[n] = (-1<<n) + 1
static int const stbi__jbias[16] = {0,-1,-3,-7,-15,-31,-63,-127,-255,-511,-1023,-2047,-4095,-8191,-16383,-32767}; static const int stbi__jbias[16] = {0,-1,-3,-7,-15,-31,-63,-127,-255,-511,-1023,-2047,-4095,-8191,-16383,-32767};
// combined JPEG 'receive' and JPEG 'extend', since baseline // combined JPEG 'receive' and JPEG 'extend', since baseline
// always extends everything it receives. // always extends everything it receives.
@@ -1886,7 +1934,7 @@ stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j)
// given a value that's at position X in the zigzag stream, // given a value that's at position X in the zigzag stream,
// where does it appear in the 8x8 matrix coded as row-major? // where does it appear in the 8x8 matrix coded as row-major?
static stbi_uc stbi__jpeg_dezigzag[64+15] = static const stbi_uc stbi__jpeg_dezigzag[64+15] =
{ {
0, 1, 8, 16, 9, 2, 3, 10, 0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5, 17, 24, 32, 25, 18, 11, 4, 5,
@@ -2112,7 +2160,7 @@ stbi_inline static stbi_uc stbi__clamp(int x)
} }
#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) #define stbi__f2f(x) ((int) (((x) * 4096 + 0.5)))
#define stbi__fsh(x) ((x) << 12) #define stbi__fsh(x) ((x) * 4096)
// derived from jidctint -- DCT_ISLOW // derived from jidctint -- DCT_ISLOW
#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ #define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \
@@ -2167,7 +2215,7 @@ static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64])
// (1|2|3|4|5|6|7)==0 0 seconds // (1|2|3|4|5|6|7)==0 0 seconds
// all separate -0.047 seconds // all separate -0.047 seconds
// 1 && 2|3 && 4|5 && 6|7: -0.047 seconds // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds
int dcterm = d[0] << 2; int dcterm = d[0]*4;
v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm;
} else { } else {
STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56])
@@ -2968,7 +3016,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
z->rgb = 0; z->rgb = 0;
for (i=0; i < s->img_n; ++i) { for (i=0; i < s->img_n; ++i) {
static unsigned char rgb[3] = { 'R', 'G', 'B' }; static const unsigned char rgb[3] = { 'R', 'G', 'B' };
z->img_comp[i].id = stbi__get8(s); z->img_comp[i].id = stbi__get8(s);
if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) if (s->img_n == 3 && z->img_comp[i].id == rgb[i])
++z->rgb; ++z->rgb;
@@ -3093,8 +3141,8 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j)
} else if (stbi__DNL(m)) { } else if (stbi__DNL(m)) {
int Ld = stbi__get16be(j->s); int Ld = stbi__get16be(j->s);
stbi__uint32 NL = stbi__get16be(j->s); stbi__uint32 NL = stbi__get16be(j->s);
if (Ld != 4) stbi__err("bad DNL len", "Corrupt JPEG"); if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG");
if (NL != j->s->img_y) stbi__err("bad DNL height", "Corrupt JPEG"); if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG");
} else { } else {
if (!stbi__process_marker(j, m)) return 0; if (!stbi__process_marker(j, m)) return 0;
} }
@@ -3912,18 +3960,18 @@ static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room
return 1; return 1;
} }
static int stbi__zlength_base[31] = { static const int stbi__zlength_base[31] = {
3,4,5,6,7,8,9,10,11,13, 3,4,5,6,7,8,9,10,11,13,
15,17,19,23,27,31,35,43,51,59, 15,17,19,23,27,31,35,43,51,59,
67,83,99,115,131,163,195,227,258,0,0 }; 67,83,99,115,131,163,195,227,258,0,0 };
static int stbi__zlength_extra[31]= static const int stbi__zlength_extra[31]=
{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 };
static int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, static const int stbi__zdist_base[32] = { 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,0,0}; 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
static int stbi__zdist_extra[32] = static const int stbi__zdist_extra[32] =
{ 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}; { 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};
static int stbi__parse_huffman_block(stbi__zbuf *a) static int stbi__parse_huffman_block(stbi__zbuf *a)
@@ -3970,7 +4018,7 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
static int stbi__compute_huffman_codes(stbi__zbuf *a) static int stbi__compute_huffman_codes(stbi__zbuf *a)
{ {
static stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
stbi__zhuffman z_codelength; stbi__zhuffman z_codelength;
stbi_uc lencodes[286+32+137];//padding for maximum single op stbi_uc lencodes[286+32+137];//padding for maximum single op
stbi_uc codelength_sizes[19]; stbi_uc codelength_sizes[19];
@@ -4229,7 +4277,7 @@ static stbi__pngchunk stbi__get_chunk_header(stbi__context *s)
static int stbi__check_png_header(stbi__context *s) static int stbi__check_png_header(stbi__context *s)
{ {
static stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 };
int i; int i;
for (i=0; i < 8; ++i) for (i=0; i < 8; ++i)
if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG");
@@ -4275,7 +4323,7 @@ static int stbi__paeth(int a, int b, int c)
return c; return c;
} }
static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 };
// create the png data from post-deflated data // create the png data from post-deflated data
static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
@@ -4295,8 +4343,10 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
if (!a->out) return stbi__err("outofmem", "Out of memory"); if (!a->out) return stbi__err("outofmem", "Out of memory");
if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG");
img_width_bytes = (((img_n * x * depth) + 7) >> 3); img_width_bytes = (((img_n * x * depth) + 7) >> 3);
img_len = (img_width_bytes + 1) * y; img_len = (img_width_bytes + 1) * y;
// we used to check for exact match between raw_len and img_len on non-interlaced PNGs, // we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
// but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros),
// so just check for raw_len < img_len always. // so just check for raw_len < img_len always.
@@ -4675,7 +4725,7 @@ static void stbi__de_iphone(stbi__png *z)
} }
} }
#define STBI__PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) #define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d))
static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
{ {
@@ -4912,6 +4962,19 @@ static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp)
p.s = s; p.s = s;
return stbi__png_info_raw(&p, x, y, comp); return stbi__png_info_raw(&p, x, y, comp);
} }
static int stbi__png_is16(stbi__context *s)
{
stbi__png p;
p.s = s;
if (!stbi__png_info_raw(&p, NULL, NULL, NULL))
return 0;
if (p.depth != 16) {
stbi__rewind(p.s);
return 0;
}
return 1;
}
#endif #endif
// Microsoft/Windows BMP image // Microsoft/Windows BMP image
@@ -4963,21 +5026,27 @@ static int stbi__bitcount(unsigned int a)
return a & 0xff; return a & 0xff;
} }
// extract an arbitrarily-aligned N-bit value (N=bits)
// from v, and then make it 8-bits long and fractionally
// extend it to full full range.
static int stbi__shiftsigned(int v, int shift, int bits) static int stbi__shiftsigned(int v, int shift, int bits)
{ {
int result; static unsigned int mul_table[9] = {
int z=0; 0,
0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/,
if (shift < 0) v <<= -shift; 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/,
else v >>= shift; };
result = v; static unsigned int shift_table[9] = {
0, 0,0,1,0,2,4,6,0,
z = bits; };
while (z < 8) { if (shift < 0)
result += v >> z; v <<= -shift;
z += bits; else
} v >>= shift;
return result; STBI_ASSERT(v >= 0 && v < 256);
v >>= (8-bits);
STBI_ASSERT(bits >= 0 && bits <= 8);
return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits];
} }
typedef struct typedef struct
@@ -5007,7 +5076,6 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
} }
if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP");
info->bpp = stbi__get16le(s); info->bpp = stbi__get16le(s);
if (info->bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit");
if (hsz != 12) { if (hsz != 12) {
int compress = stbi__get32le(s); int compress = stbi__get32le(s);
if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");
@@ -5125,10 +5193,27 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
pal[i][3] = 255; pal[i][3] = 255;
} }
stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
if (info.bpp == 4) width = (s->img_x + 1) >> 1; if (info.bpp == 1) width = (s->img_x + 7) >> 3;
else if (info.bpp == 4) width = (s->img_x + 1) >> 1;
else if (info.bpp == 8) width = s->img_x; else if (info.bpp == 8) width = s->img_x;
else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); }
pad = (-width)&3; pad = (-width)&3;
if (info.bpp == 1) {
for (j=0; j < (int) s->img_y; ++j) {
int bit_offset = 7, v = stbi__get8(s);
for (i=0; i < (int) s->img_x; ++i) {
int color = (v>>bit_offset)&0x1;
out[z++] = pal[color][0];
out[z++] = pal[color][1];
out[z++] = pal[color][2];
if((--bit_offset) < 0) {
bit_offset = 7;
v = stbi__get8(s);
}
}
stbi__skip(s, pad);
}
} else {
for (j=0; j < (int) s->img_y; ++j) { for (j=0; j < (int) s->img_y; ++j) {
for (i=0; i < (int) s->img_x; i += 2) { for (i=0; i < (int) s->img_x; i += 2) {
int v=stbi__get8(s),v2=0; int v=stbi__get8(s),v2=0;
@@ -5149,6 +5234,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
} }
stbi__skip(s, pad); stbi__skip(s, pad);
} }
}
} else { } else {
int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
int z = 0; int z = 0;
@@ -5188,7 +5274,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
int bpp = info.bpp; int bpp = info.bpp;
for (i=0; i < (int) s->img_x; ++i) { for (i=0; i < (int) s->img_x; ++i) {
stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s));
int a; unsigned int a;
out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount));
out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount));
out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount));
@@ -5240,10 +5326,10 @@ static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16)
switch(bits_per_pixel) { switch(bits_per_pixel) {
case 8: return STBI_grey; case 8: return STBI_grey;
case 16: if(is_grey) return STBI_grey_alpha; case 16: if(is_grey) return STBI_grey_alpha;
// else: fall-through // fallthrough
case 15: if(is_rgb16) *is_rgb16 = 1; case 15: if(is_rgb16) *is_rgb16 = 1;
return STBI_rgb; return STBI_rgb;
case 24: // fall-through case 24: // fallthrough
case 32: return bits_per_pixel/8; case 32: return bits_per_pixel/8;
default: return 0; default: return 0;
} }
@@ -6038,11 +6124,13 @@ typedef struct
typedef struct typedef struct
{ {
int w,h; int w,h;
stbi_uc *out, *old_out; // output buffer (always 4 components) stbi_uc *out; // output buffer (always 4 components)
int flags, bgindex, ratio, transparent, eflags, delay; stbi_uc *background; // The current "background" as far as a gif is concerned
stbi_uc *history;
int flags, bgindex, ratio, transparent, eflags;
stbi_uc pal[256][4]; stbi_uc pal[256][4];
stbi_uc lpal[256][4]; stbi_uc lpal[256][4];
stbi__gif_lzw codes[4096]; stbi__gif_lzw codes[8192];
stbi_uc *color_table; stbi_uc *color_table;
int parse, step; int parse, step;
int lflags; int lflags;
@@ -6050,6 +6138,7 @@ typedef struct
int max_x, max_y; int max_x, max_y;
int cur_x, cur_y; int cur_x, cur_y;
int line_size; int line_size;
int delay;
} stbi__gif; } stbi__gif;
static int stbi__gif_test_raw(stbi__context *s) static int stbi__gif_test_raw(stbi__context *s)
@@ -6125,6 +6214,7 @@ static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code)
{ {
stbi_uc *p, *c; stbi_uc *p, *c;
int idx;
// recurse to decode the prefixes, since the linked-list is backwards, // recurse to decode the prefixes, since the linked-list is backwards,
// and working backwards through an interleaved image would be nasty // and working backwards through an interleaved image would be nasty
@@ -6133,10 +6223,12 @@ static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code)
if (g->cur_y >= g->max_y) return; if (g->cur_y >= g->max_y) return;
p = &g->out[g->cur_x + g->cur_y]; idx = g->cur_x + g->cur_y;
c = &g->color_table[g->codes[code].suffix * 4]; p = &g->out[idx];
g->history[idx / 4] = 1;
if (c[3] >= 128) { c = &g->color_table[g->codes[code].suffix * 4];
if (c[3] > 128) { // don't render transparent pixels;
p[0] = c[2]; p[0] = c[2];
p[1] = c[1]; p[1] = c[1];
p[2] = c[0]; p[2] = c[0];
@@ -6210,11 +6302,16 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g)
stbi__skip(s,len); stbi__skip(s,len);
return g->out; return g->out;
} else if (code <= avail) { } else if (code <= avail) {
if (first) return stbi__errpuc("no clear code", "Corrupt GIF"); if (first) {
return stbi__errpuc("no clear code", "Corrupt GIF");
}
if (oldcode >= 0) { if (oldcode >= 0) {
p = &g->codes[avail++]; p = &g->codes[avail++];
if (avail > 4096) return stbi__errpuc("too many codes", "Corrupt GIF"); if (avail > 8192) {
return stbi__errpuc("too many codes", "Corrupt GIF");
}
p->prefix = (stbi__int16) oldcode; p->prefix = (stbi__int16) oldcode;
p->first = g->codes[oldcode].first; p->first = g->codes[oldcode].first;
p->suffix = (code == avail) ? p->first : g->codes[code].first; p->suffix = (code == avail) ? p->first : g->codes[code].first;
@@ -6236,62 +6333,72 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g)
} }
} }
static void stbi__fill_gif_background(stbi__gif *g, int x0, int y0, int x1, int y1)
{
int x, y;
stbi_uc *c = g->pal[g->bgindex];
for (y = y0; y < y1; y += 4 * g->w) {
for (x = x0; x < x1; x += 4) {
stbi_uc *p = &g->out[y + x];
p[0] = c[2];
p[1] = c[1];
p[2] = c[0];
p[3] = 0;
}
}
}
// this function is designed to support animated gifs, although stb_image doesn't support it // this function is designed to support animated gifs, although stb_image doesn't support it
static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp) // two back is the image from two frames ago, used for a very specific disposal format
static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back)
{ {
int i; int dispose;
stbi_uc *prev_out = 0; int first_frame;
int pi;
int pcount;
if (g->out == 0 && !stbi__gif_header(s, g, comp,0)) // on first frame, any non-written pixels get the background colour (non-transparent)
return 0; // stbi__g_failure_reason set by stbi__gif_header first_frame = 0;
if (g->out == 0) {
if (!stbi__mad3sizes_valid(g->w, g->h, 4, 0)) if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header
return stbi__errpuc("too large", "GIF too large"); g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h);
g->background = (stbi_uc *) stbi__malloc(4 * g->w * g->h);
prev_out = g->out; g->history = (stbi_uc *) stbi__malloc(g->w * g->h);
g->out = (stbi_uc *) stbi__malloc_mad3(4, g->w, g->h, 0);
if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory");
switch ((g->eflags & 0x1C) >> 2) { // image is treated as "tranparent" at the start - ie, nothing overwrites the current background;
case 0: // unspecified (also always used on 1st frame) // background colour is only used for pixels that are not rendered first frame, after that "background"
stbi__fill_gif_background(g, 0, 0, 4 * g->w, 4 * g->w * g->h); // color refers to teh color that was there the previous frame.
break; memset( g->out, 0x00, 4 * g->w * g->h );
case 1: // do not dispose memset( g->background, 0x00, 4 * g->w * g->h ); // state of the background (starts transparent)
if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame
g->old_out = prev_out; first_frame = 1;
break; } else {
case 2: // dispose to background // second frame - how do we dispoase of the previous one?
if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); dispose = (g->eflags & 0x1C) >> 2;
stbi__fill_gif_background(g, g->start_x, g->start_y, g->max_x, g->max_y); pcount = g->w * g->h;
break;
case 3: // dispose to previous if ((dispose == 3) && (two_back == 0)) {
if (g->old_out) { dispose = 2; // if I don't have an image to revert back to, default to the old background
for (i = g->start_y; i < g->max_y; i += 4 * g->w)
memcpy(&g->out[i + g->start_x], &g->old_out[i + g->start_x], g->max_x - g->start_x);
}
break;
} }
if (dispose == 3) { // use previous graphic
for (pi = 0; pi < pcount; ++pi) {
if (g->history[pi]) {
memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 );
}
}
} else if (dispose == 2) {
// restore what was changed last frame to background before that frame;
for (pi = 0; pi < pcount; ++pi) {
if (g->history[pi]) {
memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 );
}
}
} else {
// This is a non-disposal case eithe way, so just
// leave the pixels as is, and they will become the new background
// 1: do not dispose
// 0: not specified.
}
// background is what out is after the undoing of the previou frame;
memcpy( g->background, g->out, 4 * g->w * g->h );
}
// clear my history;
memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame
for (;;) { for (;;) {
switch (stbi__get8(s)) { int tag = stbi__get8(s);
switch (tag) {
case 0x2C: /* Image Descriptor */ case 0x2C: /* Image Descriptor */
{ {
int prev_trans = -1;
stbi__int32 x, y, w, h; stbi__int32 x, y, w, h;
stbi_uc *o; stbi_uc *o;
@@ -6324,10 +6431,6 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1);
g->color_table = (stbi_uc *) g->lpal; g->color_table = (stbi_uc *) g->lpal;
} else if (g->flags & 0x80) { } else if (g->flags & 0x80) {
if (g->transparent >= 0 && (g->eflags & 0x01)) {
prev_trans = g->pal[g->transparent][3];
g->pal[g->transparent][3] = 0;
}
g->color_table = (stbi_uc *) g->pal; g->color_table = (stbi_uc *) g->pal;
} else } else
return stbi__errpuc("missing color table", "Corrupt GIF"); return stbi__errpuc("missing color table", "Corrupt GIF");
@@ -6335,8 +6438,17 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
o = stbi__process_gif_raster(s, g); o = stbi__process_gif_raster(s, g);
if (o == NULL) return NULL; if (o == NULL) return NULL;
if (prev_trans != -1) // if this was the first frame,
g->pal[g->transparent][3] = (stbi_uc) prev_trans; pcount = g->w * g->h;
if (first_frame && (g->bgindex > 0)) {
// if first frame, any pixel not drawn to gets the background color
for (pi = 0; pi < pcount; ++pi) {
if (g->history[pi] == 0) {
g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be;
memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 );
}
}
}
return o; return o;
} }
@@ -6344,19 +6456,35 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
case 0x21: // Comment Extension. case 0x21: // Comment Extension.
{ {
int len; int len;
if (stbi__get8(s) == 0xF9) { // Graphic Control Extension. int ext = stbi__get8(s);
if (ext == 0xF9) { // Graphic Control Extension.
len = stbi__get8(s); len = stbi__get8(s);
if (len == 4) { if (len == 4) {
g->eflags = stbi__get8(s); g->eflags = stbi__get8(s);
g->delay = stbi__get16le(s); g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths.
// unset old transparent
if (g->transparent >= 0) {
g->pal[g->transparent][3] = 255;
}
if (g->eflags & 0x01) {
g->transparent = stbi__get8(s); g->transparent = stbi__get8(s);
if (g->transparent >= 0) {
g->pal[g->transparent][3] = 0;
}
} else {
// don't need transparent
stbi__skip(s, 1);
g->transparent = -1;
}
} else { } else {
stbi__skip(s, len); stbi__skip(s, len);
break; break;
} }
} }
while ((len = stbi__get8(s)) != 0) while ((len = stbi__get8(s)) != 0) {
stbi__skip(s, len); stbi__skip(s, len);
}
break; break;
} }
@@ -6367,28 +6495,92 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
return stbi__errpuc("unknown code", "Corrupt GIF"); return stbi__errpuc("unknown code", "Corrupt GIF");
} }
} }
}
STBI_NOTUSED(req_comp); static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
{
if (stbi__gif_test(s)) {
int layers = 0;
stbi_uc *u = 0;
stbi_uc *out = 0;
stbi_uc *two_back = 0;
stbi__gif g;
int stride;
memset(&g, 0, sizeof(g));
if (delays) {
*delays = 0;
}
do {
u = stbi__gif_load_next(s, &g, comp, req_comp, two_back);
if (u == (stbi_uc *) s) u = 0; // end of animated gif marker
if (u) {
*x = g.w;
*y = g.h;
++layers;
stride = g.w * g.h * 4;
if (out) {
out = (stbi_uc*) STBI_REALLOC( out, layers * stride );
if (delays) {
*delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers );
}
} else {
out = (stbi_uc*)stbi__malloc( layers * stride );
if (delays) {
*delays = (int*) stbi__malloc( layers * sizeof(int) );
}
}
memcpy( out + ((layers - 1) * stride), u, stride );
if (layers >= 2) {
two_back = out - 2 * stride;
}
if (delays) {
(*delays)[layers - 1U] = g.delay;
}
}
} while (u != 0);
// free temp buffer;
STBI_FREE(g.out);
STBI_FREE(g.history);
STBI_FREE(g.background);
// do the final conversion after loading everything;
if (req_comp && req_comp != 4)
out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h);
*z = layers;
return out;
} else {
return stbi__errpuc("not GIF", "Image was not as a gif type.");
}
} }
static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
{ {
stbi_uc *u = 0; stbi_uc *u = 0;
stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); stbi__gif g;
memset(g, 0, sizeof(*g)); memset(&g, 0, sizeof(g));
STBI_NOTUSED(ri);
u = stbi__gif_load_next(s, g, comp, req_comp); u = stbi__gif_load_next(s, &g, comp, req_comp, 0);
if (u == (stbi_uc *) s) u = 0; // end of animated gif marker if (u == (stbi_uc *) s) u = 0; // end of animated gif marker
if (u) { if (u) {
*x = g->w; *x = g.w;
*y = g->h; *y = g.h;
// moved conversion to after successful load so that the same
// can be done for multiple frames.
if (req_comp && req_comp != 4) if (req_comp && req_comp != 4)
u = stbi__convert_format(u, 4, req_comp, g->w, g->h); u = stbi__convert_format(u, 4, req_comp, g.w, g.h);
} }
else if (g->out)
STBI_FREE(g->out); // free buffers needed for multiple frame loading;
STBI_FREE(g); STBI_FREE(g.history);
STBI_FREE(g.background);
return u; return u;
} }
@@ -6667,7 +6859,7 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
#ifndef STBI_NO_PSD #ifndef STBI_NO_PSD
static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp)
{ {
int channelCount, dummy; int channelCount, dummy, depth;
if (!x) x = &dummy; if (!x) x = &dummy;
if (!y) y = &dummy; if (!y) y = &dummy;
if (!comp) comp = &dummy; if (!comp) comp = &dummy;
@@ -6687,7 +6879,8 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp)
} }
*y = stbi__get32be(s); *y = stbi__get32be(s);
*x = stbi__get32be(s); *x = stbi__get32be(s);
if (stbi__get16be(s) != 8) { depth = stbi__get16be(s);
if (depth != 8 && depth != 16) {
stbi__rewind( s ); stbi__rewind( s );
return 0; return 0;
} }
@@ -6698,6 +6891,33 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp)
*comp = 4; *comp = 4;
return 1; return 1;
} }
static int stbi__psd_is16(stbi__context *s)
{
int channelCount, dummy, depth;
if (stbi__get32be(s) != 0x38425053) {
stbi__rewind( s );
return 0;
}
if (stbi__get16be(s) != 1) {
stbi__rewind( s );
return 0;
}
stbi__skip(s, 6);
channelCount = stbi__get16be(s);
if (channelCount < 0 || channelCount > 16) {
stbi__rewind( s );
return 0;
}
dummy = stbi__get32be(s);
dummy = stbi__get32be(s);
depth = stbi__get16be(s);
if (depth != 16) {
stbi__rewind( s );
return 0;
}
return 1;
}
#endif #endif
#ifndef STBI_NO_PIC #ifndef STBI_NO_PIC
@@ -6928,6 +7148,19 @@ static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp)
return stbi__err("unknown image type", "Image not of any known type, or corrupt"); return stbi__err("unknown image type", "Image not of any known type, or corrupt");
} }
static int stbi__is_16_main(stbi__context *s)
{
#ifndef STBI_NO_PNG
if (stbi__png_is16(s)) return 1;
#endif
#ifndef STBI_NO_PSD
if (stbi__psd_is16(s)) return 1;
#endif
return 0;
}
#ifndef STBI_NO_STDIO #ifndef STBI_NO_STDIO
STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp)
{ {
@@ -6949,6 +7182,27 @@ STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp)
fseek(f,pos,SEEK_SET); fseek(f,pos,SEEK_SET);
return r; return r;
} }
STBIDEF int stbi_is_16_bit(char const *filename)
{
FILE *f = stbi__fopen(filename, "rb");
int result;
if (!f) return stbi__err("can't fopen", "Unable to open file");
result = stbi_is_16_bit_from_file(f);
fclose(f);
return result;
}
STBIDEF int stbi_is_16_bit_from_file(FILE *f)
{
int r;
stbi__context s;
long pos = ftell(f);
stbi__start_file(&s, f);
r = stbi__is_16_main(&s);
fseek(f,pos,SEEK_SET);
return r;
}
#endif // !STBI_NO_STDIO #endif // !STBI_NO_STDIO
STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp)
@@ -6965,10 +7219,28 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
return stbi__info_main(&s,x,y,comp); return stbi__info_main(&s,x,y,comp);
} }
STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len)
{
stbi__context s;
stbi__start_mem(&s,buffer,len);
return stbi__is_16_main(&s);
}
STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user)
{
stbi__context s;
stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);
return stbi__is_16_main(&s);
}
#endif // STB_IMAGE_IMPLEMENTATION #endif // STB_IMAGE_IMPLEMENTATION
/* /*
revision history: revision history:
2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug
1-bit BMP
*_is_16_bit api
avoid warnings
2.16 (2017-07-23) all functions have 16-bit variants; 2.16 (2017-07-23) all functions have 16-bit variants;
STBI_NO_STDIO works again; STBI_NO_STDIO works again;
compilation fixes; compilation fixes;

View File

@@ -1,4 +1,4 @@
/* stb_image_write - v1.07 - public domain - http://nothings.org/stb/stb_image_write.h /* stb_image_write - v1.08 - public domain - http://nothings.org/stb/stb_image_write.h
writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
no warranty implied; use at your own risk no warranty implied; use at your own risk
@@ -10,34 +10,47 @@
Will probably not work correctly with strict-aliasing optimizations. Will probably not work correctly with strict-aliasing optimizations.
If using a modern Microsoft Compiler, non-safe versions of CRT calls may cause
compilation warnings or even errors. To avoid this, also before #including,
#define STBI_MSC_SECURE_CRT
ABOUT: ABOUT:
This header file is a library for writing images to C stdio. It could be This header file is a library for writing images to C stdio. It could be
adapted to write to memory or a general streaming interface; let me know. adapted to write to memory or a general streaming interface; let me know.
The PNG output is not optimal; it is 20-50% larger than the file The PNG output is not optimal; it is 20-50% larger than the file
written by a decent optimizing implementation. This library is designed written by a decent optimizing implementation; though providing a custom
for source code compactness and simplicity, not optimal image file size zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that.
or run-time performance. This library is designed for source code compactness and simplicity,
not optimal image file size or run-time performance.
BUILDING: BUILDING:
You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
malloc,realloc,free. malloc,realloc,free.
You can define STBIW_MEMMOVE() to replace memmove() You can #define STBIW_MEMMOVE() to replace memmove()
You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function
for PNG compression (instead of the builtin one), it must have the following signature:
unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality);
The returned data will be freed with STBIW_FREE() (free() by default),
so it must be heap allocated with STBIW_MALLOC() (malloc() by default),
USAGE: USAGE:
There are four functions, one for each image file format: There are five functions, one for each image file format:
int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
int stbi_write_jpg(char const *filename, int w, int h, int comp, const float *data); int stbi_write_jpg(char const *filename, int w, int h, int comp, const float *data, int quality);
There are also four equivalent functions that use an arbitrary write function. You are void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically
There are also five equivalent functions that use an arbitrary write function. You are
expected to open/close your file-equivalent before and after calling these: expected to open/close your file-equivalent before and after calling these:
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); 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,6 +62,12 @@ USAGE:
where the callback is: where the callback is:
void stbi_write_func(void *context, void *data, int size); void stbi_write_func(void *context, void *data, int size);
You can configure it with these global variables:
int stbi_write_tga_with_rle; // defaults to true; set to 0 to disable RLE
int stbi_write_png_compression_level; // defaults to 8; set to higher for more compression
int stbi_write_force_png_filter; // defaults to -1; set to 0..5 to force a filter mode
You can define STBI_WRITE_NO_STDIO to disable the file variant of these You can define STBI_WRITE_NO_STDIO to disable the file variant of these
functions, so the library will not use stdio.h at all. However, this will functions, so the library will not use stdio.h at all. However, this will
also disable HDR writing, because it requires stdio for formatted output. also disable HDR writing, because it requires stdio for formatted output.
@@ -75,6 +94,9 @@ USAGE:
writer, both because it is in BGR order and because it may have padding writer, both because it is in BGR order and because it may have padding
at the end of the line.) at the end of the line.)
PNG allows you to set the deflate compression level by setting the global
variable 'stbi_write_png_level' (it defaults to 8).
HDR expects linear float data. Since the format is always 32-bit rgb(e) HDR expects linear float data. Since the format is always 32-bit rgb(e)
data, alpha (if provided) is discarded, and for monochrome data it is data, alpha (if provided) is discarded, and for monochrome data it is
replicated across all three channels. replicated across all three channels.
@@ -88,21 +110,17 @@ USAGE:
CREDITS: CREDITS:
PNG/BMP/TGA
Sean Barrett Sean Barrett - PNG/BMP/TGA
HDR Baldur Karlsson - HDR
Baldur Karlsson Jean-Sebastien Guay - TGA monochrome
TGA monochrome: Tim Kelsey - misc enhancements
Jean-Sebastien Guay Alan Hickman - TGA RLE
misc enhancements: Emmanuel Julien - initial file IO callback implementation
Tim Kelsey Jon Olick - original jo_jpeg.cpp code
TGA RLE Daniel Gibson - integrate JPEG, allow external zlib
Alan Hickman Aarni Koskela - allow choosing PNG filter
initial file IO callback implementation
Emmanuel Julien
JPEG
Jon Olick (original jo_jpeg.cpp code)
Daniel Gibson
bugfixes: bugfixes:
github:Chribba github:Chribba
Guillaume Chereau Guillaume Chereau
@@ -114,6 +132,7 @@ CREDITS:
Thatcher Ulrich Thatcher Ulrich
github:poppolopoppo github:poppolopoppo
Patrick Boettcher Patrick Boettcher
github:xeekworx
LICENSE LICENSE
@@ -132,9 +151,12 @@ extern "C" {
#define STBIWDEF static #define STBIWDEF static
#else #else
#define STBIWDEF extern #define STBIWDEF extern
extern int stbi_write_tga_with_rle;
#endif #endif
STBIWDEF int stbi_write_tga_with_rle;
STBIWDEF int stbi_write_png_comperssion_level;
STBIWDEF int stbi_write_force_png_filter;
#ifndef STBI_WRITE_NO_STDIO #ifndef STBI_WRITE_NO_STDIO
STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
@@ -151,6 +173,8 @@ STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w,
STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@@ -208,6 +232,23 @@ STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x,
#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
#ifdef STB_IMAGE_WRITE_STATIC
static stbi__flip_vertically_on_write=0;
static int stbi_write_png_compression level = 8;
static int stbi_write_tga_with_rle = 1;
static int stbi_write_force_png_filter = -1;
#else
int stbi_write_png_compression_level = 8;
int stbi__flip_vertically_on_write=0;
int stbi_write_tga_with_rle = 1;
int stbi_write_force_png_filter = -1;
#endif
STBIWDEF void stbi_flip_vertically_on_write(int flag)
{
stbi__flip_vertically_on_write = flag;
}
typedef struct typedef struct
{ {
stbi_write_func *func; stbi_write_func *func;
@@ -230,7 +271,13 @@ static void stbi__stdio_write(void *context, void *data, int size)
static int stbi__start_write_file(stbi__write_context *s, const char *filename) static int stbi__start_write_file(stbi__write_context *s, const char *filename)
{ {
FILE *f = fopen(filename, "wb"); FILE *f;
#ifdef STBI_MSC_SECURE_CRT
if (fopen_s(&f, filename, "wb"))
f = NULL;
#else
f = fopen(filename, "wb");
#endif
stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
return f != NULL; return f != NULL;
} }
@@ -245,12 +292,6 @@ static void stbi__end_write_file(stbi__write_context *s)
typedef unsigned int stbiw_uint32; typedef unsigned int stbiw_uint32;
typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
#ifdef STB_IMAGE_WRITE_STATIC
static int stbi_write_tga_with_rle = 1;
#else
int stbi_write_tga_with_rle = 1;
#endif
static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
{ {
while (*fmt) { while (*fmt) {
@@ -341,6 +382,9 @@ static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, i
if (y <= 0) if (y <= 0)
return; return;
if (stbi__flip_vertically_on_write)
vdir *= -1;
if (vdir < 0) if (vdir < 0)
j_end = -1, j = y-1; j_end = -1, j = y-1;
else else
@@ -412,10 +456,20 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v
"111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
} else { } else {
int i,j,k; int i,j,k;
int jend, jdir;
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); 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);
for (j = y - 1; j >= 0; --j) { if (stbi__flip_vertically_on_write) {
j = 0;
jend = y;
jdir = 1;
} else {
j = y-1;
jend = -1;
jdir = -1;
}
for (; j != jend; j += jdir) {
unsigned char *row = (unsigned char *) data + j * x * comp; unsigned char *row = (unsigned char *) data + j * x * comp;
int len; int len;
@@ -626,11 +680,15 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f
char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
s->func(s->context, header, sizeof(header)-1); s->func(s->context, header, sizeof(header)-1);
#ifdef STBI_MSC_SECURE_CRT
len = sprintf_s(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
#else
len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
#endif
s->func(s->context, buffer, len); s->func(s->context, buffer, len);
for(i=0; i < y; i++) for(i=0; i < y; i++)
stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)*x);
STBIW_FREE(scratch); STBIW_FREE(scratch);
return 1; return 1;
} }
@@ -662,6 +720,7 @@ STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const
// PNG writer // PNG writer
// //
#ifndef STBIW_ZLIB_COMPRESS
// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
#define stbiw__sbraw(a) ((int *) (a) - 2) #define stbiw__sbraw(a) ((int *) (a) - 2)
#define stbiw__sbm(a) stbiw__sbraw(a)[0] #define stbiw__sbm(a) stbiw__sbraw(a)[0]
@@ -742,8 +801,14 @@ static unsigned int stbiw__zhash(unsigned char *data)
#define stbiw__ZHASH 16384 #define stbiw__ZHASH 16384
#endif // STBIW_ZLIB_COMPRESS
unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
{ {
#ifdef STBIW_ZLIB_COMPRESS
// user provided a zlib compress implementation, use that
return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
#else // use builtin
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 }; 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 };
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 }; 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 };
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 }; 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 };
@@ -752,6 +817,8 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
int i,j, bitcount=0; int i,j, bitcount=0;
unsigned char *out = NULL; unsigned char *out = NULL;
unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**));
if (hash_table == NULL)
return NULL;
if (quality < 5) quality = 5; if (quality < 5) quality = 5;
stbiw__sbpush(out, 0x78); // DEFLATE 32K window stbiw__sbpush(out, 0x78); // DEFLATE 32K window
@@ -845,6 +912,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
// make returned pointer freeable // make returned pointer freeable
STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
return (unsigned char *) stbiw__sbraw(out); return (unsigned char *) stbiw__sbraw(out);
#endif // STBIW_ZLIB_COMPRESS
} }
static unsigned int stbiw__crc32(unsigned char *buffer, int len) static unsigned int stbiw__crc32(unsigned char *buffer, int len)
@@ -911,29 +979,15 @@ static unsigned char stbiw__paeth(int a, int b, int c)
} }
// @OPTIMIZE: provide an option that always forces left-predict or paeth predict // @OPTIMIZE: provide an option that always forces left-predict or paeth predict
unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) static 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)
{ {
int ctype[5] = { -1, 0, 4, 2, 6 };
unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
unsigned char *out,*o, *filt, *zlib;
signed char *line_buffer;
int i,j,k,p,zlen;
if (stride_bytes == 0)
stride_bytes = x * n;
filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
for (j=0; j < y; ++j) {
static int mapping[] = { 0,1,2,3,4 }; static int mapping[] = { 0,1,2,3,4 };
static int firstmap[] = { 0,1,0,5,6 }; static int firstmap[] = { 0,1,0,5,6 };
int *mymap = (j != 0) ? mapping : firstmap; int *mymap = (y != 0) ? mapping : firstmap;
int best = 0, bestval = 0x7fffffff; int i;
for (p=0; p < 2; ++p) { int type = mymap[filter_type];
for (k= p?best:0; k < 5; ++k) { // @TODO: clarity: rewrite this to go 0..5, and 'continue' the unwanted ones during 2nd pass unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y);
int type = mymap[k],est=0; for (i = 0; i < n; ++i) {
unsigned char *z = pixels + stride_bytes*j;
for (i=0; i < n; ++i)
switch (type) { switch (type) {
case 0: line_buffer[i] = z[i]; break; case 0: line_buffer[i] = z[i]; break;
case 1: line_buffer[i] = z[i]; break; case 1: line_buffer[i] = z[i]; break;
@@ -943,7 +997,8 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
case 5: line_buffer[i] = z[i]; break; case 5: line_buffer[i] = z[i]; break;
case 6: line_buffer[i] = z[i]; break; case 6: line_buffer[i] = z[i]; break;
} }
for (i=n; i < x*n; ++i) { }
for (i=n; i < width*n; ++i) {
switch (type) { switch (type) {
case 0: line_buffer[i] = z[i]; break; case 0: line_buffer[i] = z[i]; break;
case 1: line_buffer[i] = z[i] - z[i-n]; break; case 1: line_buffer[i] = z[i] - z[i-n]; break;
@@ -954,18 +1009,57 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
} }
} }
if (p) break; }
for (i=0; i < x*n; ++i)
unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
{
int force_filter = stbi_write_force_png_filter;
int ctype[5] = { -1, 0, 4, 2, 6 };
unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
unsigned char *out,*o, *filt, *zlib;
signed char *line_buffer;
int j,zlen;
if (stride_bytes == 0)
stride_bytes = x * n;
if (force_filter >= 5) {
force_filter = -1;
}
filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
for (j=0; j < y; ++j) {
int filter_type;
if (force_filter > -1) {
filter_type = force_filter;
stbiw__encode_png_line(pixels, stride_bytes, x, y, j, n, force_filter, line_buffer);
} else { // Estimate the best filter by running through all of them:
int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
for (filter_type = 0; filter_type < 5; filter_type++) {
stbiw__encode_png_line(pixels, stride_bytes, x, y, j, n, filter_type, line_buffer);
// Estimate the entropy of the line using this filter; the less, the better.
est = 0;
for (i = 0; i < x*n; ++i) {
est += abs((signed char) line_buffer[i]); est += abs((signed char) line_buffer[i]);
if (est < bestval) { bestval = est; best = k; } }
if (est < best_filter_val) {
best_filter_val = est;
best_filter = filter_type;
} }
} }
// when we get here, best contains the filter type, and line_buffer contains the data if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it
filt[j*(x*n+1)] = (unsigned char) best; stbiw__encode_png_line(pixels, stride_bytes, x, y, j, n, best_filter, line_buffer);
filter_type = best_filter;
}
}
// when we get here, filter_type contains the filter type, and line_buffer contains the data
filt[j*(x*n+1)] = (unsigned char) filter_type;
STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
} }
STBIW_FREE(line_buffer); STBIW_FREE(line_buffer);
zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level);
STBIW_FREE(filt); STBIW_FREE(filt);
if (!zlib) return 0; if (!zlib) return 0;
@@ -1010,7 +1104,12 @@ STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const
int len; int len;
unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
if (png == NULL) return 0; if (png == NULL) return 0;
#ifdef STBI_MSC_SECURE_CRT
if (fopen_s(&f, filename, "wb"))
f = NULL;
#else
f = fopen(filename, "wb"); f = fopen(filename, "wb");
#endif
if (!f) { STBIW_FREE(png); return 0; } if (!f) { STBIW_FREE(png); return 0; }
fwrite(png, 1, len, f); fwrite(png, 1, len, f);
fclose(f); fclose(f);
@@ -1318,7 +1417,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
float YDU[64], UDU[64], VDU[64]; float YDU[64], UDU[64], VDU[64];
for(row = y, pos = 0; row < y+8; ++row) { for(row = y, pos = 0; row < y+8; ++row) {
for(col = x; col < x+8; ++col, ++pos) { for(col = x; col < x+8; ++col, ++pos) {
int p = row*width*comp + col*comp; int p = (stbi__flip_vertically_on_write ? height-1-row : row)*width*comp + col*comp;
float r, g, b; float r, g, b;
if(row >= height) { if(row >= height) {
p -= width*comp*(row+1 - height); p -= width*comp*(row+1 - height);
@@ -1377,6 +1476,8 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const
#endif // STB_IMAGE_WRITE_IMPLEMENTATION #endif // STB_IMAGE_WRITE_IMPLEMENTATION
/* Revision history /* Revision history
1.08 (2018-01-29)
add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter
1.07 (2017-07-24) 1.07 (2017-07-24)
doc fix doc fix
1.06 (2017-07-23) 1.06 (2017-07-23)

View File

@@ -1,4 +1,4 @@
// stb_truetype.h - v1.17 - public domain // stb_truetype.h - v1.18 - public domain
// authored from 2009-2016 by Sean Barrett / RAD Game Tools // authored from 2009-2016 by Sean Barrett / RAD Game Tools
// //
// This library processes TrueType files: // This library processes TrueType files:
@@ -30,33 +30,24 @@
// Imanol Celaya // Imanol Celaya
// //
// Bug/warning reports/fixes: // Bug/warning reports/fixes:
// "Zer" on mollyrocket // "Zer" on mollyrocket Fabian "ryg" Giesen
// Cass Everitt // Cass Everitt Martins Mozeiko
// stoiko (Haemimont Games) // stoiko (Haemimont Games) Cap Petschulat
// Brian Hook // Brian Hook Omar Cornut
// Walter van Niftrik // Walter van Niftrik github:aloucks
// David Gow // David Gow Peter LaValle
// David Given // David Given Sergey Popov
// Ivan-Assen Ivanov // Ivan-Assen Ivanov Giumo X. Clanjor
// Anthony Pesch // Anthony Pesch Higor Euripedes
// Johan Duparc // Johan Duparc Thomas Fields
// Hou Qiming // Hou Qiming Derek Vinyard
// Fabian "ryg" Giesen // Rob Loach Cort Stratton
// Martins Mozeiko // Kenney Phillis Jr. github:oyvindjam
// Cap Petschulat // Brian Costabile github:vassvik
// Omar Cornut
// github:aloucks
// Peter LaValle
// Sergey Popov
// Giumo X. Clanjor
// Higor Euripedes
// Thomas Fields
// Derek Vinyard
// Cort Stratton
// github:oyvindjam
// //
// VERSION HISTORY // VERSION HISTORY
// //
// 1.18 (2018-01-29) add missing function
// 1.17 (2017-07-23) make more arguments const; doc fix // 1.17 (2017-07-23) make more arguments const; doc fix
// 1.16 (2017-07-12) SDF support // 1.16 (2017-07-12) SDF support
// 1.15 (2017-03-03) make more arguments const // 1.15 (2017-03-03) make more arguments const
@@ -171,7 +162,7 @@
// measurement for describing font size, defined as 72 points per inch. // measurement for describing font size, defined as 72 points per inch.
// stb_truetype provides a point API for compatibility. However, true // stb_truetype provides a point API for compatibility. However, true
// "per inch" conventions don't make much sense on computer displays // "per inch" conventions don't make much sense on computer displays
// since they different monitors have different number of pixels per // since different monitors have different number of pixels per
// inch. For example, Windows traditionally uses a convention that // inch. For example, Windows traditionally uses a convention that
// there are 96 pixels per inch, thus making 'inch' measurements have // there are 96 pixels per inch, thus making 'inch' measurements have
// nothing to do with inches, and thus effectively defining a point to // nothing to do with inches, and thus effectively defining a point to
@@ -181,6 +172,39 @@
// for non-commercial fonts, thus making fonts scaled in points // for non-commercial fonts, thus making fonts scaled in points
// according to the TrueType spec incoherently sized in practice. // according to the TrueType spec incoherently sized in practice.
// //
// DETAILED USAGE:
//
// Scale:
// Select how high you want the font to be, in points or pixels.
// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute
// a scale factor SF that will be used by all other functions.
//
// Baseline:
// You need to select a y-coordinate that is the baseline of where
// your text will appear. Call GetFontBoundingBox to get the baseline-relative
// bounding box for all characters. SF*-y0 will be the distance in pixels
// that the worst-case character could extend above the baseline, so if
// you want the top edge of characters to appear at the top of the
// screen where y=0, then you would set the baseline to SF*-y0.
//
// Current point:
// Set the current point where the first character will appear. The
// first character could extend left of the current point; this is font
// dependent. You can either choose a current point that is the leftmost
// point and hope, or add some padding, or check the bounding box or
// left-side-bearing of the first character to be displayed and set
// the current point based on that.
//
// Displaying a character:
// Compute the bounding box of the character. It will contain signed values
// relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1,
// then the character should be displayed in the rectangle from
// <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1).
//
// Advancing for the next character:
// Call GlyphHMetrics, and compute 'current_point += SF * advance'.
//
//
// ADVANCED USAGE // ADVANCED USAGE
// //
// Quality: // Quality:
@@ -427,11 +451,6 @@ int main(int arg, char **argv)
#define STBTT_fabs(x) fabs(x) #define STBTT_fabs(x) fabs(x)
#endif #endif
#ifndef STBTT_fabs
#include <math.h>
#define STBTT_fabs(x) fabs(x)
#endif
// #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
#ifndef STBTT_malloc #ifndef STBTT_malloc
#include <stdlib.h> #include <stdlib.h>
@@ -2172,7 +2191,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
// push immediate // push immediate
if (b0 == 255) { if (b0 == 255) {
f = (float)stbtt__buf_get32(&b) / 0x10000; f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
} else { } else {
stbtt__buf_skip(&b, -1); stbtt__buf_skip(&b, -1);
f = (float)(stbtt_int16)stbtt__cff_int(&b); f = (float)(stbtt_int16)stbtt__cff_int(&b);
@@ -2210,12 +2229,10 @@ static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, in
{ {
stbtt__csctx c = STBTT__CSCTX_INIT(1); stbtt__csctx c = STBTT__CSCTX_INIT(1);
int r = stbtt__run_charstring(info, glyph_index, &c); int r = stbtt__run_charstring(info, glyph_index, &c);
if (x0) { if (x0) *x0 = r ? c.min_x : 0;
*x0 = r ? c.min_x : 0; if (y0) *y0 = r ? c.min_y : 0;
*y0 = r ? c.min_y : 0; if (x1) *x1 = r ? c.max_x : 0;
*x1 = r ? c.max_x : 0; if (y1) *y1 = r ? c.max_y : 0;
*y1 = r ? c.max_y : 0;
}
return r ? c.num_vertices : 0; return r ? c.num_vertices : 0;
} }
@@ -2395,7 +2412,7 @@ static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
hh->num_remaining_in_head_chunk = count; hh->num_remaining_in_head_chunk = count;
} }
--hh->num_remaining_in_head_chunk; --hh->num_remaining_in_head_chunk;
return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk; return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
} }
} }
@@ -3230,7 +3247,8 @@ error:
STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
{ {
float scale = scale_x > scale_y ? scale_y : scale_x; float scale = scale_x > scale_y ? scale_y : scale_x;
int winding_count, *winding_lengths; int winding_count = 0;
int *winding_lengths = NULL;
stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
if (windings) { if (windings) {
stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
@@ -3318,6 +3336,11 @@ STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *
return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
} }
STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
{
stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
}
STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
{ {
stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));

View File

@@ -1658,6 +1658,8 @@ static int residue_decode(vorb *f, Codebook *book, float *target, int offset, in
return TRUE; return TRUE;
} }
// n is 1/2 of the blocksize --
// specification: "Correct per-vector decode length is [n]/2"
static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode) static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode)
{ {
int i,j,pass; int i,j,pass;
@@ -1665,7 +1667,10 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
int rtype = f->residue_types[rn]; int rtype = f->residue_types[rn];
int c = r->classbook; int c = r->classbook;
int classwords = f->codebooks[c].dimensions; int classwords = f->codebooks[c].dimensions;
int n_read = r->end - r->begin; unsigned int actual_size = rtype == 2 ? n*2 : n;
unsigned int limit_r_begin = (r->begin < actual_size ? r->begin : actual_size);
unsigned int limit_r_end = (r->end < actual_size ? r->end : actual_size);
int n_read = limit_r_end - limit_r_begin;
int part_read = n_read / r->part_size; int part_read = n_read / r->part_size;
int temp_alloc_point = temp_alloc_save(f); int temp_alloc_point = temp_alloc_save(f);
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
@@ -3007,7 +3012,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
if (f->last_seg_which == f->end_seg_with_known_loc) { if (f->last_seg_which == f->end_seg_with_known_loc) {
// if we have a valid current loc, and this is final: // if we have a valid current loc, and this is final:
if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) { if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) {
uint32 current_end = f->known_loc_for_packet - (n-right_end); uint32 current_end = f->known_loc_for_packet;
// then let's infer the size of the (probably) short final frame // then let's infer the size of the (probably) short final frame
if (current_end < f->current_loc + (right_end-left_start)) { if (current_end < f->current_loc + (right_end-left_start)) {
if (current_end < f->current_loc) { if (current_end < f->current_loc) {
@@ -3016,7 +3021,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
} else { } else {
*len = current_end - f->current_loc; *len = current_end - f->current_loc;
} }
*len += left_start; *len += left_start; // this doesn't seem right, but has no ill effect on my test files
if (*len > right_end) *len = right_end; // this should never happen if (*len > right_end) *len = right_end; // this should never happen
f->current_loc += *len; f->current_loc += *len;
return TRUE; return TRUE;
@@ -3693,7 +3698,10 @@ static int start_decoder(vorb *f)
int i,max_part_read=0; int i,max_part_read=0;
for (i=0; i < f->residue_count; ++i) { for (i=0; i < f->residue_count; ++i) {
Residue *r = f->residue_config + i; Residue *r = f->residue_config + i;
int n_read = r->end - r->begin; unsigned int actual_size = f->blocksize_1 / 2;
unsigned int limit_r_begin = r->begin < actual_size ? r->begin : actual_size;
unsigned int limit_r_end = r->end < actual_size ? r->end : actual_size;
int n_read = limit_r_end - limit_r_begin;
int part_read = n_read / r->part_size; int part_read = n_read / r->part_size;
if (part_read > max_part_read) if (part_read > max_part_read)
max_part_read = part_read; max_part_read = part_read;
@@ -3704,6 +3712,8 @@ static int start_decoder(vorb *f)
classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *)); classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *));
#endif #endif
// maximum reasonable partition size is f->blocksize_1
f->temp_memory_required = classify_mem; f->temp_memory_required = classify_mem;
if (imdct_mem > f->temp_memory_required) if (imdct_mem > f->temp_memory_required)
f->temp_memory_required = imdct_mem; f->temp_memory_required = imdct_mem;
@@ -4967,6 +4977,8 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in
#endif // STB_VORBIS_NO_PULLDATA_API #endif // STB_VORBIS_NO_PULLDATA_API
/* Version history /* Version history
1.12 - 2017/11/21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
1.11 - 2017/07/23 - fix MinGW compilation
1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory
1.09 - 2016/04/04 - back out 'avoid discarding last frame' fix from previous version 1.09 - 2016/04/04 - back out 'avoid discarding last frame' fix from previous version
1.08 - 2016/04/02 - fixed multiple warnings; fix setup memory leaks; 1.08 - 2016/04/02 - fixed multiple warnings; fix setup memory leaks;

View File

@@ -1,11 +1,11 @@
// Ogg Vorbis audio decoder - v1.11 - public domain // Ogg Vorbis audio decoder - v1.13b - public domain
// http://nothings.org/stb_vorbis/ // http://nothings.org/stb_vorbis/
// //
// Original version written by Sean Barrett in 2007. // Original version written by Sean Barrett in 2007.
// //
// Originally sponsored by RAD Game Tools. Seeking sponsored // Originally sponsored by RAD Game Tools. Seeking implementation
// by Phillip Bennefall, Marc Andersen, Aaron Baker, Elias Software, // sponsored by Phillip Bennefall, Marc Andersen, Aaron Baker,
// Aras Pranckevicius, and Sean Barrett. // Elias Software, Aras Pranckevicius, and Sean Barrett.
// //
// LICENSE // LICENSE
// //
@@ -32,6 +32,8 @@
// manxorist@github saga musix github:infatum // manxorist@github saga musix github:infatum
// //
// Partial history: // Partial history:
// 1.13 - 2018/01/29 - fix truncation of last frame (hopefully)
// 1.12 - 2017/11/21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
// 1.11 - 2017/07/23 - fix MinGW compilation // 1.11 - 2017/07/23 - fix MinGW compilation
// 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory // 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory
// 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version // 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version