Merge branch 'master' into working

This commit is contained in:
Sean Barrett 2024-07-15 08:28:08 -07:00
commit 6e9f34d542
50 changed files with 17356 additions and 2248 deletions

24
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,24 @@
---
name: Bug report
about: if you're having trouble using a library, try the support forum instead
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.

4
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,4 @@
contact_links:
- name: support forum
url: https://github.com/nothings/stb/discussions/categories/q-a
about: having trouble using an stb library? don't create an issue, post in the forum

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: 4 enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

23
.github/workflows/ci-fuzz.yml vendored Normal file
View File

@ -0,0 +1,23 @@
name: CIFuzz
on: [pull_request]
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'stb'
dry-run: false
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'stb'
fuzz-seconds: 900
dry-run: false
- name: Upload Crash
uses: actions/upload-artifact@v1
if: failure()
with:
name: artifacts
path: ./out/artifacts

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.o
*.obj
*.exe

View File

@ -1,4 +1,7 @@
language: C
arch:
- AMD64
- ppc64le
install: true
script:
- cd tests

View File

@ -5,50 +5,62 @@ stb
single-file public domain (or MIT licensed) libraries for C/C++
# This project discusses security-relevant bugs in public in Github Issues and Pull Requests, and it may take significant time for security fixes to be implemented or merged. If this poses an unreasonable risk to your project, do not use stb libraries.
Noteworthy:
* image loader: [stb_image.h](stb_image.h)
* image writer: [stb_image_write.h](stb_image_write.h)
* image resizer: [stb_image_resize.h](stb_image_resize.h)
* image resizer: [stb_image_resize2.h](stb_image_resize2.h)
* font text rasterizer: [stb_truetype.h](stb_truetype.h)
* typesafe containers: [stb_ds.h](stb_ds.h)
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, stb_image_resize
by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts.
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, original stb_image_resize
by Jorge L. "VinoBS" Rodriguez, and stb_image_resize2 and stb_sprintf by Jeff Roberts.
<a name="stb_libs"></a>
library | lastest version | category | LoC | description
--------------------- | ---- | -------- | --- | --------------------------------
**[stb_vorbis.c](stb_vorbis.c)** | 1.20 | audio | 5563 | decode ogg vorbis files from file/memory to float/16-bit signed output
**[stb_image.h](stb_image.h)** | 2.26 | graphics | 7762 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC, PNM
**[stb_truetype.h](stb_truetype.h)** | 1.24 | graphics | 5011 | parse, decode, and rasterize characters from truetype fonts
**[stb_image_write.h](stb_image_write.h)** | 1.15 | graphics | 1690 | image writing to disk: PNG, TGA, BMP, JPG, HDR
**[stb_image_resize.h](stb_image_resize.h)** | 0.96 | graphics | 2631 | resize images larger/smaller with good quality
**[stb_rect_pack.h](stb_rect_pack.h)** | 1.00 | graphics | 628 | simple 2D rectangle packer with decent quality
**[stb_ds.h](stb_ds.h)** | 0.66 | utility | 1893 | typesafe dynamic array and hash tables for C, will compile in C++
**[stb_sprintf.h](stb_sprintf.h)** | 1.09 | utility | 1879 | fast sprintf, snprintf for C/C++
**[stb_textedit.h](stb_textedit.h)** | 1.13 | user&nbsp;interface | 1404 | guts of a text editor for games etc implementing them from scratch
**[stb_vorbis.c](stb_vorbis.c)** | 1.22 | audio | 5584 | decode ogg vorbis files from file/memory to float/16-bit signed output
**[stb_hexwave.h](stb_hexwave.h)** | 0.5 | audio | 680 | audio waveform synthesizer
**[stb_image.h](stb_image.h)** | 2.29 | graphics | 7985 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
**[stb_truetype.h](stb_truetype.h)** | 1.26 | graphics | 5077 | parse, decode, and rasterize characters from truetype fonts
**[stb_image_write.h](stb_image_write.h)** | 1.16 | graphics | 1724 | image writing to disk: PNG, TGA, BMP
**[stb_image_resize2.h](stb_image_resize2.h)** | 2.07 | graphics | 10366 | resize images larger/smaller with good quality
**[stb_rect_pack.h](stb_rect_pack.h)** | 1.01 | graphics | 623 | simple 2D rectangle packer with decent quality
**[stb_perlin.h](stb_perlin.h)** | 0.5 | graphics | 428 | perlin's revised simplex noise w/ different seeds
**[stb_ds.h](stb_ds.h)** | 0.67 | utility | 1895 | typesafe dynamic array and hash tables for C, will compile in C++
**[stb_sprintf.h](stb_sprintf.h)** | 1.10 | utility | 1906 | fast sprintf, snprintf for C/C++
**[stb_textedit.h](stb_textedit.h)** | 1.14 | user&nbsp;interface | 1429 | guts of a text editor for games etc implementing them from scratch
**[stb_voxel_render.h](stb_voxel_render.h)** | 0.89 | 3D&nbsp;graphics | 3807 | Minecraft-esque voxel rendering "engine" with many more features
**[stb_dxt.h](stb_dxt.h)** | 1.10 | 3D&nbsp;graphics | 753 | Fabian "ryg" Giesen's real-time DXT compressor
**[stb_perlin.h](stb_perlin.h)** | 0.5 | 3D&nbsp;graphics | 428 | revised Perlin noise (3D input, 1D output)
**[stb_dxt.h](stb_dxt.h)** | 1.12 | 3D&nbsp;graphics | 719 | Fabian "ryg" Giesen's real-time DXT compressor
**[stb_easy_font.h](stb_easy_font.h)** | 1.1 | 3D&nbsp;graphics | 305 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
**[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.41 | game&nbsp;dev | 4161 | embeddable tilemap editor
**[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.42 | game&nbsp;dev | 4187 | embeddable tilemap editor
**[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.7 | game&nbsp;dev | 1221 | herringbone Wang tile map generator
**[stb_c_lexer.h](stb_c_lexer.h)** | 0.11 | parsing | 966 | simplify writing parsers for C-like languages
**[stb_divide.h](stb_divide.h)** | 0.93 | math | 430 | more useful 32-bit modulus e.g. "euclidean divide"
**[stb_c_lexer.h](stb_c_lexer.h)** | 0.12 | parsing | 940 | simplify writing parsers for C-like languages
**[stb_divide.h](stb_divide.h)** | 0.94 | math | 433 | more useful 32-bit modulus e.g. "euclidean divide"
**[stb_connected_comp...](stb_connected_components.h)** | 0.96 | misc | 1049 | incrementally compute reachability on grids
**[stb.h](stb.h)** | 2.37 | misc | 14454 | helper functions for C, mostly redundant in C++; basically author's personal stuff
**[stb_leakcheck.h](stb_leakcheck.h)** | 0.6 | misc | 194 | quick-and-dirty malloc/free leak-checking
**[stb_include.h](stb_include.h)** | 0.02 | misc | 295 | implement recursive #include support, particularly for GLSL
Total libraries: 21
Total lines of C code: 56530
Total lines of C code: 50847
FAQ
---
#### What's the license?
These libraries are in the public domain. You can do anything you
want with them. You have no legal obligation
to do anything else, although I appreciate attribution.
They are also licensed under the MIT open source license, if you have lawyers
who are unhappy with public domain. Every source file includes an explicit
dual-license for you to choose from.
#### How do I use these libraries?
The idea behind single-header file libraries is that they're easy to distribute and deploy
@ -67,16 +79,6 @@ include stb_image.h regularly, but instead does
The right macro to define is pointed out right at the top of each of these libraries.
#### What's the license?
These libraries are in the public domain. You can do anything you
want with them. You have no legal obligation
to do anything else, although I appreciate attribution.
They are also licensed under the MIT open source license, if you have lawyers
who are unhappy with public domain. Every source file includes an explicit
dual-license for you to choose from.
#### <a name="other_libs"></a> Are there other single-file public-domain/open source libraries with minimal dependencies out there?
[Yes.](https://github.com/nothings/single_file_libs)

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* stb_image_resize - v0.96 - public domain image resizing
/* stb_image_resize - v0.97 - public domain image resizing
by Jorge L Rodriguez (@VinoBS) - 2014
http://github.com/nothings/stb
@ -1064,7 +1064,11 @@ static void stbir__calculate_coefficients_upsample(stbir_filter filter, float sc
total_filter += coefficient_group[i];
}
STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0);
// NOTE(fg): Not actually true in general, nor is there any reason to expect it should be.
// It would be true in exact math but is at best approximately true in floating-point math,
// and it would not make sense to try and put actual bounds on this here because it depends
// on the image aspect ratio which can get pretty extreme.
//STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0);
STBIR_ASSERT(total_filter > 0.9);
STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off.
@ -1089,7 +1093,7 @@ static void stbir__calculate_coefficients_downsample(stbir_filter filter, float
{
int i;
STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical.
STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical.
contributor->n0 = out_first_pixel;
contributor->n1 = out_last_pixel;
@ -1103,7 +1107,11 @@ static void stbir__calculate_coefficients_downsample(stbir_filter filter, float
coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio;
}
STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0);
// NOTE(fg): Not actually true in general, nor is there any reason to expect it should be.
// It would be true in exact math but is at best approximately true in floating-point math,
// and it would not make sense to try and put actual bounds on this here because it depends
// on the image aspect ratio which can get pretty extreme.
//STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0);
for (i = out_last_pixel - out_first_pixel; i >= 0; i--)
{
@ -1552,7 +1560,6 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float
{
int out_pixel_index = k * 1;
float coefficient = horizontal_coefficients[coefficient_group + k - n0];
STBIR_ASSERT(coefficient != 0);
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
}
}
@ -1573,7 +1580,6 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float
{
int out_pixel_index = k * 2;
float coefficient = horizontal_coefficients[coefficient_group + k - n0];
STBIR_ASSERT(coefficient != 0);
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
}
@ -1595,7 +1601,6 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float
{
int out_pixel_index = k * 3;
float coefficient = horizontal_coefficients[coefficient_group + k - n0];
STBIR_ASSERT(coefficient != 0);
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
@ -1618,7 +1623,6 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float
{
int out_pixel_index = k * 4;
float coefficient = horizontal_coefficients[coefficient_group + k - n0];
STBIR_ASSERT(coefficient != 0);
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
@ -1643,7 +1647,6 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float
int c;
int out_pixel_index = k * channels;
float coefficient = horizontal_coefficients[coefficient_group + k - n0];
STBIR_ASSERT(coefficient != 0);
for (c = 0; c < channels; c++)
output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
}

View File

@ -1,4 +1,4 @@
// stb_c_lexer.h - v0.11 - public domain Sean Barrett 2013
// stb_c_lexer.h - v0.12 - public domain Sean Barrett 2013
// lexer for making little C-like languages with recursive-descent parsers
//
// This file provides both the interface and the implementation.
@ -10,6 +10,7 @@
// suffixes on integer constants are not handled (you can override this).
//
// History:
// 0.12 fix compilation bug for NUL support; better support separate inclusion
// 0.11 fix clang static analysis warning
// 0.10 fix warnings
// 0.09 hex floats, no-stdlib fixes
@ -43,12 +44,19 @@
//
// See end of file for license information.
#ifdef STB_C_LEXER_IMPLEMENTATION
#ifndef STB_C_LEXER_DEFINITIONS
// to change the default parsing rules, copy the following lines
// into your C/C++ file *before* including this, and then replace
// the Y's with N's for the ones you don't want.
// the Y's with N's for the ones you don't want. This needs to be
// set to the same values for every place in your program where
// stb_c_lexer.h is included.
// --BEGIN--
#if defined(Y) || defined(N)
#error "Can only use stb_c_lexer in contexts where the preprocessor symbols 'Y' and 'N' are not defined"
#endif
#define STB_C_LEX_C_DECIMAL_INTS Y // "0|[1-9][0-9]*" CLEX_intlit
#define STB_C_LEX_C_HEX_INTS Y // "0x[0-9a-fA-F]+" CLEX_intlit
#define STB_C_LEX_C_OCTAL_INTS Y // "[0-7]+" CLEX_intlit
@ -96,7 +104,7 @@
#define STB_C_LEXER_DEFINITIONS // This line prevents the header file from replacing your definitions
// --END--
#endif
#endif
#ifndef INCLUDE_STB_C_LEXER_H
@ -166,15 +174,45 @@ extern void stb_c_lexer_get_location(const stb_lexer *lexer, const char *where,
}
#endif
enum
{
CLEX_eof = 256,
CLEX_parse_error,
CLEX_intlit ,
CLEX_floatlit ,
CLEX_id ,
CLEX_dqstring ,
CLEX_sqstring ,
CLEX_charlit ,
CLEX_eq ,
CLEX_noteq ,
CLEX_lesseq ,
CLEX_greatereq ,
CLEX_andand ,
CLEX_oror ,
CLEX_shl ,
CLEX_shr ,
CLEX_plusplus ,
CLEX_minusminus ,
CLEX_pluseq ,
CLEX_minuseq ,
CLEX_muleq ,
CLEX_diveq ,
CLEX_modeq ,
CLEX_andeq ,
CLEX_oreq ,
CLEX_xoreq ,
CLEX_arrow ,
CLEX_eqarrow ,
CLEX_shleq, CLEX_shreq,
CLEX_first_unused_token
};
#endif // INCLUDE_STB_C_LEXER_H
#ifdef STB_C_LEXER_IMPLEMENTATION
#if defined(Y) || defined(N)
#error "Can only use stb_c_lexer in contexts where the preprocessor symbols 'Y' and 'N' are not defined"
#endif
// Hacky definitions so we can easily #if on them
#define Y(x) 1
#define N(x) 0
@ -195,14 +233,6 @@ typedef long stb__clex_int;
#define STB__clex_parse_suffixes
#endif
#if STB_C_LEX_C_DECIMAL_INTS(x) || STB_C_LEX_C_HEX_INTS(x) || STB_C_LEX_DEFINE_ALL_TOKEN_NAMES(x)
#define STB__clex_define_int
#endif
#if (STB_C_LEX_C_ARITHEQ(x) && STB_C_LEX_C_SHIFTS(x)) || STB_C_LEX_DEFINE_ALL_TOKEN_NAMES(x)
#define STB__clex_define_shifts
#endif
#if STB_C_LEX_C99_HEX_FLOATS(x)
#define STB__clex_hex_floats
#endif
@ -232,66 +262,10 @@ typedef long stb__clex_int;
#include <stdlib.h>
#endif
// Now pick a definition of Y/N that's conducive to
// defining the enum of token names.
#if STB_C_LEX_DEFINE_ALL_TOKEN_NAMES(x) || defined(STB_C_LEXER_SELF_TEST)
#undef N
#define N(a) Y(a)
#else
#undef N
#define N(a)
#endif
#undef Y
#define Y(a) a,
enum
{
CLEX_eof = 256,
CLEX_parse_error,
#ifdef STB__clex_define_int
CLEX_intlit,
#endif
STB_C_LEX_C_DECIMAL_FLOATS( CLEX_floatlit )
STB_C_LEX_C_IDENTIFIERS( CLEX_id )
STB_C_LEX_C_DQ_STRINGS( CLEX_dqstring )
STB_C_LEX_C_SQ_STRINGS( CLEX_sqstring )
STB_C_LEX_C_CHARS( CLEX_charlit )
STB_C_LEX_C_COMPARISONS( CLEX_eq )
STB_C_LEX_C_COMPARISONS( CLEX_noteq )
STB_C_LEX_C_COMPARISONS( CLEX_lesseq )
STB_C_LEX_C_COMPARISONS( CLEX_greatereq )
STB_C_LEX_C_LOGICAL( CLEX_andand )
STB_C_LEX_C_LOGICAL( CLEX_oror )
STB_C_LEX_C_SHIFTS( CLEX_shl )
STB_C_LEX_C_SHIFTS( CLEX_shr )
STB_C_LEX_C_INCREMENTS( CLEX_plusplus )
STB_C_LEX_C_INCREMENTS( CLEX_minusminus )
STB_C_LEX_C_ARITHEQ( CLEX_pluseq )
STB_C_LEX_C_ARITHEQ( CLEX_minuseq )
STB_C_LEX_C_ARITHEQ( CLEX_muleq )
STB_C_LEX_C_ARITHEQ( CLEX_diveq )
STB_C_LEX_C_ARITHEQ( CLEX_modeq )
STB_C_LEX_C_BITWISEEQ( CLEX_andeq )
STB_C_LEX_C_BITWISEEQ( CLEX_oreq )
STB_C_LEX_C_BITWISEEQ( CLEX_xoreq )
STB_C_LEX_C_ARROW( CLEX_arrow )
STB_C_LEX_EQUAL_ARROW( CLEX_eqarrow )
#ifdef STB__clex_define_shifts
CLEX_shleq, CLEX_shreq,
#endif
CLEX_first_unused_token
#undef Y
#define Y(a) a
};
// Now for the rest of the file we'll use the basic definition where
// where Y expands to its contents and N expands to nothing
#undef Y
#define Y(a) a
#undef N
#define N(a)
@ -609,7 +583,7 @@ int stb_c_lexer_get_token(stb_lexer *lexer)
// check for EOF
STB_C_LEX_0_IS_EOF(
if (*p == 0)
return stb__clex_eof(tok);
return stb__clex_eof(lexer);
)
single_char:

View File

@ -1,8 +1,9 @@
// stb_divide.h - v0.93 - public domain - Sean Barrett, Feb 2010
// stb_divide.h - v0.94 - public domain - Sean Barrett, Feb 2010
// Three kinds of divide/modulus of signed integers.
//
// HISTORY
//
// v0.94 Fix integer overflow issues
// v0.93 2020-02-02 Write useful exit() value from main()
// v0.92 2019-02-25 Fix warning
// v0.91 2010-02-27 Fix euclidean division by INT_MIN for non-truncating C
@ -166,15 +167,15 @@ int stb_div_floor(int v1, int v2)
return v1/v2;
#else
if (v1 >= 0 && v2 < 0) {
if ((-v1)+v2+1 < 0) // check if increasing v1's magnitude overflows
return -stb__div(-v1+v2+1,v2); // nope, so just compute it
if (v2 + 1 >= INT_MIN + v1) // check if increasing v1's magnitude overflows
return -stb__div((v2+1)-v1,v2); // nope, so just compute it
else
return -stb__div(-v1,v2) + ((-v1)%v2 ? -1 : 0);
}
if (v1 < 0 && v2 >= 0) {
if (v1 != INT_MIN) {
if (v1-v2+1 < 0) // check if increasing v1's magnitude overflows
return -stb__div(v1-v2+1,-v2); // nope, so just compute it
if (v1 + 1 >= INT_MIN + v2) // check if increasing v1's magnitude overflows
return -stb__div((v1+1)-v2,-v2); // nope, so just compute it
else
return -stb__div(-v1,v2) + (stb__mod(v1,-v2) ? -1 : 0);
} else // it must be possible to compute -(v1+v2) without overflowing
@ -209,8 +210,10 @@ int stb_div_eucl(int v1, int v2)
else // if v1 is INT_MIN, we have to move away from overflow place
if (v2 >= 0)
q = -stb__div(-(v1+v2),v2)-1, r = -stb__mod(-(v1+v2),v2);
else
else if (v2 != INT_MIN)
q = stb__div(-(v1-v2),-v2)+1, r = -stb__mod(-(v1-v2),-v2);
else // for INT_MIN / INT_MIN, we need to be extra-careful to avoid overflow
q = 1, r = 0;
#endif
if (r >= 0)
return q;
@ -228,13 +231,13 @@ int stb_mod_trunc(int v1, int v2)
if (r >= 0)
return r;
else
return r + (v2 > 0 ? v2 : -v2);
return r - (v2 < 0 ? v2 : -v2);
} else { // modulus result should always be negative
int r = stb__mod(v1,v2);
if (r <= 0)
return r;
else
return r - (v2 > 0 ? v2 : -v2);
return r + (v2 < 0 ? v2 : -v2);
}
#endif
}
@ -267,7 +270,7 @@ int stb_mod_eucl(int v1, int v2)
if (r >= 0)
return r;
else
return r + (v2 > 0 ? v2 : -v2); // abs()
return r - (v2 < 0 ? v2 : -v2); // negative abs() [to avoid overflow]
}
#ifdef STB_DIVIDE_TEST

View File

@ -1,4 +1,4 @@
/* stb_ds.h - v0.66 - public domain data structures - Sean Barrett 2019
/* stb_ds.h - v0.67 - public domain data structures - Sean Barrett 2019
This is a single-header-file library that provides easy-to-use
dynamic arrays and hash tables for C (also works in C++).
@ -104,7 +104,7 @@ DOCUMENTATION
moving the rest of the array over. Returns b.
arrinsn:
void arrins(T* a, int p, int n);
void arrinsn(T* a, int p, int n);
Inserts n uninitialized items into array a starting at a[p],
moving the rest of the array over.
@ -123,7 +123,7 @@ DOCUMENTATION
Deletes the element at a[p], moving the rest of the array over.
arrdeln:
void arrdel(T* a, int p, int n);
void arrdeln(T* a, int p, int n);
Deletes n elements starting at a[p], moving the rest of the array over.
arrdelswap:
@ -381,6 +381,7 @@ CREDITS
github:srdjanstipic
Macoy Madson
Andreas Vennstrom
Tobias Mansfield-Williams
*/
#ifdef STBDS_UNIT_TESTS
@ -534,24 +535,25 @@ extern void * stbds_shmode_func(size_t elemsize, int mode);
#define stbds_temp(t) stbds_header(t)->temp
#define stbds_temp_key(t) (*(char **) stbds_header(t)->hash_table)
#define stbds_arrsetcap(a,n) (stbds_arrgrow(a,0,n))
#define stbds_arrsetlen(a,n) ((stbds_arrcap(a) < (size_t) (n) ? stbds_arrsetcap((a),(size_t)(n)),0 : 0), (a) ? stbds_header(a)->length = (size_t) (n) : 0)
#define stbds_arrcap(a) ((a) ? stbds_header(a)->capacity : 0)
#define stbds_arrlen(a) ((a) ? (ptrdiff_t) stbds_header(a)->length : 0)
#define stbds_arrlenu(a) ((a) ? stbds_header(a)->length : 0)
#define stbds_arrput(a,v) (stbds_arrmaybegrow(a,1), (a)[stbds_header(a)->length++] = (v))
#define stbds_arrpush stbds_arrput // synonym
#define stbds_arrpop(a) (stbds_header(a)->length--, (a)[stbds_header(a)->length])
#define stbds_arraddn(a,n) ((void)(stbds_arraddnoff(a, n))) // deprecated, use one of the following instead:
#define stbds_arraddnptr(a,n) (stbds_arrmaybegrow(a,n), stbds_header(a)->length += (n), &(a)[stbds_header(a)->length-(n)])
#define stbds_arraddnoff(a,n) (stbds_arrmaybegrow(a,n), stbds_header(a)->length += (n), stbds_header(a)->length-(n))
#define stbds_arrlast(a) ((a)[stbds_header(a)->length-1])
#define stbds_arrfree(a) ((void) ((a) ? stbds_arrfreef(a) : (void)0), (a)=NULL)
#define stbds_arrdel(a,i) stbds_arrdeln(a,i,1)
#define stbds_arrdeln(a,i,n) (memmove(&(a)[i], &(a)[(i)+(n)], sizeof *(a) * (stbds_header(a)->length-(n)-(i))), stbds_header(a)->length -= (n))
#define stbds_arrdelswap(a,i) ((a)[i] = stbds_arrlast(a), stbds_header(a)->length -= 1)
#define stbds_arrinsn(a,i,n) ((a)?stbds_temp(a)=(i):0,stbds_arraddn((a),(n)), memmove(&(a)[stbds_temp(a)+(n)], &(a)[stbds_temp(a)], sizeof *(a) * (stbds_header(a)->length-(n)-stbds_temp(a))))
#define stbds_arrins(a,i,v) (stbds_arrinsn((a),(i),1), (a)[i]=(v))
#define stbds_arrsetcap(a,n) (stbds_arrgrow(a,0,n))
#define stbds_arrsetlen(a,n) ((stbds_arrcap(a) < (size_t) (n) ? stbds_arrsetcap((a),(size_t)(n)),0 : 0), (a) ? stbds_header(a)->length = (size_t) (n) : 0)
#define stbds_arrcap(a) ((a) ? stbds_header(a)->capacity : 0)
#define stbds_arrlen(a) ((a) ? (ptrdiff_t) stbds_header(a)->length : 0)
#define stbds_arrlenu(a) ((a) ? stbds_header(a)->length : 0)
#define stbds_arrput(a,v) (stbds_arrmaybegrow(a,1), (a)[stbds_header(a)->length++] = (v))
#define stbds_arrpush stbds_arrput // synonym
#define stbds_arrpop(a) (stbds_header(a)->length--, (a)[stbds_header(a)->length])
#define stbds_arraddn(a,n) ((void)(stbds_arraddnindex(a, n))) // deprecated, use one of the following instead:
#define stbds_arraddnptr(a,n) (stbds_arrmaybegrow(a,n), (n) ? (stbds_header(a)->length += (n), &(a)[stbds_header(a)->length-(n)]) : (a))
#define stbds_arraddnindex(a,n)(stbds_arrmaybegrow(a,n), (n) ? (stbds_header(a)->length += (n), stbds_header(a)->length-(n)) : stbds_arrlen(a))
#define stbds_arraddnoff stbds_arraddnindex
#define stbds_arrlast(a) ((a)[stbds_header(a)->length-1])
#define stbds_arrfree(a) ((void) ((a) ? STBDS_FREE(NULL,stbds_header(a)) : (void)0), (a)=NULL)
#define stbds_arrdel(a,i) stbds_arrdeln(a,i,1)
#define stbds_arrdeln(a,i,n) (memmove(&(a)[i], &(a)[(i)+(n)], sizeof *(a) * (stbds_header(a)->length-(n)-(i))), stbds_header(a)->length -= (n))
#define stbds_arrdelswap(a,i) ((a)[i] = stbds_arrlast(a), stbds_header(a)->length -= 1)
#define stbds_arrinsn(a,i,n) (stbds_arraddn((a),(n)), memmove(&(a)[(i)+(n)], &(a)[i], sizeof *(a) * (stbds_header(a)->length-(n)-(i))))
#define stbds_arrins(a,i,v) (stbds_arrinsn((a),(i),1), (a)[i]=(v))
#define stbds_arrmaybegrow(a,n) ((!(a) || stbds_header(a)->length + (n) > stbds_header(a)->capacity) \
? (stbds_arrgrow(a,n,0),0) : 0)

133
stb_dxt.h
View File

@ -1,4 +1,4 @@
// stb_dxt.h - v1.11 - DXT1/DXT5 compressor - public domain
// stb_dxt.h - v1.12 - DXT1/DXT5 compressor - public domain
// original by fabian "ryg" giesen - ported to C by stb
// use '#define STB_DXT_IMPLEMENTATION' before including to create the implementation
//
@ -10,6 +10,7 @@
// You can turn on dithering and "high quality" using mode.
//
// version history:
// v1.12 - (ryg) fix bug in single-color table generator
// v1.11 - (ryg) avoid racy global init, better single-color tables, remove dither
// v1.10 - (i.c) various small quality improvements
// v1.09 - (stb) update documentation re: surprising alpha channel requirement
@ -92,72 +93,72 @@ STBDDEF void stb_compress_bc5_block(unsigned char *dest, const unsigned char *sr
#endif
static const unsigned char stb__OMatch5[256][2] = {
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 1 },
{ 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 2, 2 }, { 2, 2 }, { 2, 2 },
{ 2, 2 }, { 2, 2 }, { 2, 2 }, { 2, 2 }, { 2, 2 }, { 3, 3 }, { 3, 3 }, { 3, 3 },
{ 3, 3 }, { 3, 3 }, { 3, 3 }, { 3, 3 }, { 3, 3 }, { 4, 4 }, { 4, 4 }, { 4, 4 },
{ 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 5, 5 }, { 5, 5 },
{ 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 }, { 6, 6 }, { 6, 6 },
{ 6, 6 }, { 6, 6 }, { 6, 6 }, { 6, 6 }, { 6, 6 }, { 6, 6 }, { 7, 7 }, { 7, 7 },
{ 7, 7 }, { 7, 7 }, { 7, 7 }, { 7, 7 }, { 7, 7 }, { 7, 7 }, { 8, 8 }, { 8, 8 },
{ 8, 8 }, { 8, 8 }, { 8, 8 }, { 8, 8 }, { 8, 8 }, { 8, 8 }, { 8, 8 }, { 9, 9 },
{ 9, 9 }, { 9, 9 }, { 9, 9 }, { 9, 9 }, { 9, 9 }, { 9, 9 }, { 9, 9 }, { 10, 10 },
{ 10, 10 }, { 10, 10 }, { 10, 10 }, { 10, 10 }, { 10, 10 }, { 10, 10 }, { 10, 10 }, { 11, 11 },
{ 11, 11 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 12, 12 },
{ 12, 12 }, { 12, 12 }, { 12, 12 }, { 12, 12 }, { 12, 12 }, { 12, 12 }, { 12, 12 }, { 12, 12 },
{ 13, 13 }, { 13, 13 }, { 13, 13 }, { 13, 13 }, { 13, 13 }, { 13, 13 }, { 13, 13 }, { 13, 13 },
{ 14, 14 }, { 14, 14 }, { 14, 14 }, { 14, 14 }, { 14, 14 }, { 14, 14 }, { 14, 14 }, { 14, 14 },
{ 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 15 },
{ 16, 16 }, { 16, 16 }, { 16, 16 }, { 16, 16 }, { 16, 16 }, { 16, 16 }, { 16, 16 }, { 16, 16 },
{ 16, 16 }, { 17, 17 }, { 17, 17 }, { 17, 17 }, { 17, 17 }, { 17, 17 }, { 17, 17 }, { 17, 17 },
{ 17, 17 }, { 18, 18 }, { 18, 18 }, { 18, 18 }, { 18, 18 }, { 18, 18 }, { 18, 18 }, { 18, 18 },
{ 18, 18 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, { 19, 19 },
{ 19, 19 }, { 20, 20 }, { 20, 20 }, { 20, 20 }, { 20, 20 }, { 20, 20 }, { 20, 20 }, { 20, 20 },
{ 20, 20 }, { 20, 20 }, { 21, 21 }, { 21, 21 }, { 21, 21 }, { 21, 21 }, { 21, 21 }, { 21, 21 },
{ 21, 21 }, { 21, 21 }, { 22, 22 }, { 22, 22 }, { 22, 22 }, { 22, 22 }, { 22, 22 }, { 22, 22 },
{ 22, 22 }, { 22, 22 }, { 23, 23 }, { 23, 23 }, { 23, 23 }, { 23, 23 }, { 23, 23 }, { 23, 23 },
{ 23, 23 }, { 23, 23 }, { 24, 24 }, { 24, 24 }, { 24, 24 }, { 24, 24 }, { 24, 24 }, { 24, 24 },
{ 24, 24 }, { 24, 24 }, { 24, 24 }, { 25, 25 }, { 25, 25 }, { 25, 25 }, { 25, 25 }, { 25, 25 },
{ 25, 25 }, { 25, 25 }, { 25, 25 }, { 26, 26 }, { 26, 26 }, { 26, 26 }, { 26, 26 }, { 26, 26 },
{ 26, 26 }, { 26, 26 }, { 26, 26 }, { 27, 27 }, { 27, 27 }, { 27, 27 }, { 27, 27 }, { 27, 27 },
{ 27, 27 }, { 27, 27 }, { 27, 27 }, { 28, 28 }, { 28, 28 }, { 28, 28 }, { 28, 28 }, { 28, 28 },
{ 28, 28 }, { 28, 28 }, { 28, 28 }, { 28, 28 }, { 29, 29 }, { 29, 29 }, { 29, 29 }, { 29, 29 },
{ 29, 29 }, { 29, 29 }, { 29, 29 }, { 29, 29 }, { 30, 30 }, { 30, 30 }, { 30, 30 }, { 30, 30 },
{ 30, 30 }, { 30, 30 }, { 30, 30 }, { 30, 30 }, { 31, 31 }, { 31, 31 }, { 31, 31 }, { 31, 31 },
{ 0, 0 }, { 0, 0 }, { 0, 1 }, { 0, 1 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 1 },
{ 1, 1 }, { 1, 1 }, { 1, 2 }, { 0, 4 }, { 2, 1 }, { 2, 1 }, { 2, 1 }, { 2, 2 },
{ 2, 2 }, { 2, 2 }, { 2, 3 }, { 1, 5 }, { 3, 2 }, { 3, 2 }, { 4, 0 }, { 3, 3 },
{ 3, 3 }, { 3, 3 }, { 3, 4 }, { 3, 4 }, { 3, 4 }, { 3, 5 }, { 4, 3 }, { 4, 3 },
{ 5, 2 }, { 4, 4 }, { 4, 4 }, { 4, 5 }, { 4, 5 }, { 5, 4 }, { 5, 4 }, { 5, 4 },
{ 6, 3 }, { 5, 5 }, { 5, 5 }, { 5, 6 }, { 4, 8 }, { 6, 5 }, { 6, 5 }, { 6, 5 },
{ 6, 6 }, { 6, 6 }, { 6, 6 }, { 6, 7 }, { 5, 9 }, { 7, 6 }, { 7, 6 }, { 8, 4 },
{ 7, 7 }, { 7, 7 }, { 7, 7 }, { 7, 8 }, { 7, 8 }, { 7, 8 }, { 7, 9 }, { 8, 7 },
{ 8, 7 }, { 9, 6 }, { 8, 8 }, { 8, 8 }, { 8, 9 }, { 8, 9 }, { 9, 8 }, { 9, 8 },
{ 9, 8 }, { 10, 7 }, { 9, 9 }, { 9, 9 }, { 9, 10 }, { 8, 12 }, { 10, 9 }, { 10, 9 },
{ 10, 9 }, { 10, 10 }, { 10, 10 }, { 10, 10 }, { 10, 11 }, { 9, 13 }, { 11, 10 }, { 11, 10 },
{ 12, 8 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 11, 12 }, { 11, 12 }, { 11, 12 }, { 11, 13 },
{ 12, 11 }, { 12, 11 }, { 13, 10 }, { 12, 12 }, { 12, 12 }, { 12, 13 }, { 12, 13 }, { 13, 12 },
{ 13, 12 }, { 13, 12 }, { 14, 11 }, { 13, 13 }, { 13, 13 }, { 13, 14 }, { 12, 16 }, { 14, 13 },
{ 14, 13 }, { 14, 13 }, { 14, 14 }, { 14, 14 }, { 14, 14 }, { 14, 15 }, { 13, 17 }, { 15, 14 },
{ 15, 14 }, { 16, 12 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 16 }, { 15, 16 }, { 15, 16 },
{ 15, 17 }, { 16, 15 }, { 16, 15 }, { 17, 14 }, { 16, 16 }, { 16, 16 }, { 16, 17 }, { 16, 17 },
{ 17, 16 }, { 17, 16 }, { 17, 16 }, { 18, 15 }, { 17, 17 }, { 17, 17 }, { 17, 18 }, { 16, 20 },
{ 18, 17 }, { 18, 17 }, { 18, 17 }, { 18, 18 }, { 18, 18 }, { 18, 18 }, { 18, 19 }, { 17, 21 },
{ 19, 18 }, { 19, 18 }, { 20, 16 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, { 19, 20 }, { 19, 20 },
{ 19, 20 }, { 19, 21 }, { 20, 19 }, { 20, 19 }, { 21, 18 }, { 20, 20 }, { 20, 20 }, { 20, 21 },
{ 20, 21 }, { 21, 20 }, { 21, 20 }, { 21, 20 }, { 22, 19 }, { 21, 21 }, { 21, 21 }, { 21, 22 },
{ 20, 24 }, { 22, 21 }, { 22, 21 }, { 22, 21 }, { 22, 22 }, { 22, 22 }, { 22, 22 }, { 22, 23 },
{ 21, 25 }, { 23, 22 }, { 23, 22 }, { 24, 20 }, { 23, 23 }, { 23, 23 }, { 23, 23 }, { 23, 24 },
{ 23, 24 }, { 23, 24 }, { 23, 25 }, { 24, 23 }, { 24, 23 }, { 25, 22 }, { 24, 24 }, { 24, 24 },
{ 24, 25 }, { 24, 25 }, { 25, 24 }, { 25, 24 }, { 25, 24 }, { 26, 23 }, { 25, 25 }, { 25, 25 },
{ 25, 26 }, { 24, 28 }, { 26, 25 }, { 26, 25 }, { 26, 25 }, { 26, 26 }, { 26, 26 }, { 26, 26 },
{ 26, 27 }, { 25, 29 }, { 27, 26 }, { 27, 26 }, { 28, 24 }, { 27, 27 }, { 27, 27 }, { 27, 27 },
{ 27, 28 }, { 27, 28 }, { 27, 28 }, { 27, 29 }, { 28, 27 }, { 28, 27 }, { 29, 26 }, { 28, 28 },
{ 28, 28 }, { 28, 29 }, { 28, 29 }, { 29, 28 }, { 29, 28 }, { 29, 28 }, { 30, 27 }, { 29, 29 },
{ 29, 29 }, { 29, 30 }, { 29, 30 }, { 30, 29 }, { 30, 29 }, { 30, 29 }, { 30, 30 }, { 30, 30 },
{ 30, 30 }, { 30, 31 }, { 30, 31 }, { 31, 30 }, { 31, 30 }, { 31, 30 }, { 31, 31 }, { 31, 31 },
};
static const unsigned char stb__OMatch6[256][2] = {
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 2, 2 },
{ 2, 2 }, { 2, 2 }, { 2, 2 }, { 3, 3 }, { 3, 3 }, { 3, 3 }, { 3, 3 }, { 4, 4 },
{ 4, 4 }, { 4, 4 }, { 4, 4 }, { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 }, { 6, 6 },
{ 6, 6 }, { 6, 6 }, { 6, 6 }, { 7, 7 }, { 7, 7 }, { 7, 7 }, { 7, 7 }, { 8, 8 },
{ 8, 8 }, { 8, 8 }, { 8, 8 }, { 9, 9 }, { 9, 9 }, { 9, 9 }, { 9, 9 }, { 10, 10 },
{ 10, 10 }, { 10, 10 }, { 10, 10 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 12, 12 },
{ 12, 12 }, { 12, 12 }, { 12, 12 }, { 13, 13 }, { 13, 13 }, { 13, 13 }, { 13, 13 }, { 14, 14 },
{ 14, 14 }, { 14, 14 }, { 14, 14 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 16, 16 },
{ 16, 16 }, { 16, 16 }, { 16, 16 }, { 16, 16 }, { 17, 17 }, { 17, 17 }, { 17, 17 }, { 17, 17 },
{ 18, 18 }, { 18, 18 }, { 18, 18 }, { 18, 18 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, { 19, 19 },
{ 20, 20 }, { 20, 20 }, { 20, 20 }, { 20, 20 }, { 21, 21 }, { 21, 21 }, { 21, 21 }, { 21, 21 },
{ 22, 22 }, { 22, 22 }, { 22, 22 }, { 22, 22 }, { 23, 23 }, { 23, 23 }, { 23, 23 }, { 23, 23 },
{ 24, 24 }, { 24, 24 }, { 24, 24 }, { 24, 24 }, { 25, 25 }, { 25, 25 }, { 25, 25 }, { 25, 25 },
{ 26, 26 }, { 26, 26 }, { 26, 26 }, { 26, 26 }, { 27, 27 }, { 27, 27 }, { 27, 27 }, { 27, 27 },
{ 28, 28 }, { 28, 28 }, { 28, 28 }, { 28, 28 }, { 29, 29 }, { 29, 29 }, { 29, 29 }, { 29, 29 },
{ 30, 30 }, { 30, 30 }, { 30, 30 }, { 30, 30 }, { 31, 31 }, { 31, 31 }, { 31, 31 }, { 31, 31 },
{ 32, 32 }, { 32, 32 }, { 32, 32 }, { 32, 32 }, { 32, 32 }, { 33, 33 }, { 33, 33 }, { 33, 33 },
{ 33, 33 }, { 34, 34 }, { 34, 34 }, { 34, 34 }, { 34, 34 }, { 35, 35 }, { 35, 35 }, { 35, 35 },
{ 35, 35 }, { 36, 36 }, { 36, 36 }, { 36, 36 }, { 36, 36 }, { 37, 37 }, { 37, 37 }, { 37, 37 },
{ 37, 37 }, { 38, 38 }, { 38, 38 }, { 38, 38 }, { 38, 38 }, { 39, 39 }, { 39, 39 }, { 39, 39 },
{ 39, 39 }, { 40, 40 }, { 40, 40 }, { 40, 40 }, { 40, 40 }, { 41, 41 }, { 41, 41 }, { 41, 41 },
{ 41, 41 }, { 42, 42 }, { 42, 42 }, { 42, 42 }, { 42, 42 }, { 43, 43 }, { 43, 43 }, { 43, 43 },
{ 43, 43 }, { 44, 44 }, { 44, 44 }, { 44, 44 }, { 44, 44 }, { 45, 45 }, { 45, 45 }, { 45, 45 },
{ 45, 45 }, { 46, 46 }, { 46, 46 }, { 46, 46 }, { 46, 46 }, { 47, 47 }, { 47, 47 }, { 47, 47 },
{ 47, 47 }, { 48, 48 }, { 48, 48 }, { 48, 48 }, { 48, 48 }, { 48, 48 }, { 49, 49 }, { 49, 49 },
{ 49, 49 }, { 49, 49 }, { 50, 50 }, { 50, 50 }, { 50, 50 }, { 50, 50 }, { 51, 51 }, { 51, 51 },
{ 51, 51 }, { 51, 51 }, { 52, 52 }, { 52, 52 }, { 52, 52 }, { 52, 52 }, { 53, 53 }, { 53, 53 },
{ 53, 53 }, { 53, 53 }, { 54, 54 }, { 54, 54 }, { 54, 54 }, { 54, 54 }, { 55, 55 }, { 55, 55 },
{ 55, 55 }, { 55, 55 }, { 56, 56 }, { 56, 56 }, { 56, 56 }, { 56, 56 }, { 57, 57 }, { 57, 57 },
{ 57, 57 }, { 57, 57 }, { 58, 58 }, { 58, 58 }, { 58, 58 }, { 58, 58 }, { 59, 59 }, { 59, 59 },
{ 59, 59 }, { 59, 59 }, { 60, 60 }, { 60, 60 }, { 60, 60 }, { 60, 60 }, { 61, 61 }, { 61, 61 },
{ 61, 61 }, { 61, 61 }, { 62, 62 }, { 62, 62 }, { 62, 62 }, { 62, 62 }, { 63, 63 }, { 63, 63 },
{ 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1 }, { 1, 1 }, { 1, 2 }, { 2, 1 }, { 2, 2 },
{ 2, 2 }, { 2, 3 }, { 3, 2 }, { 3, 3 }, { 3, 3 }, { 3, 4 }, { 4, 3 }, { 4, 4 },
{ 4, 4 }, { 4, 5 }, { 5, 4 }, { 5, 5 }, { 5, 5 }, { 5, 6 }, { 6, 5 }, { 6, 6 },
{ 6, 6 }, { 6, 7 }, { 7, 6 }, { 7, 7 }, { 7, 7 }, { 7, 8 }, { 8, 7 }, { 8, 8 },
{ 8, 8 }, { 8, 9 }, { 9, 8 }, { 9, 9 }, { 9, 9 }, { 9, 10 }, { 10, 9 }, { 10, 10 },
{ 10, 10 }, { 10, 11 }, { 11, 10 }, { 8, 16 }, { 11, 11 }, { 11, 12 }, { 12, 11 }, { 9, 17 },
{ 12, 12 }, { 12, 13 }, { 13, 12 }, { 11, 16 }, { 13, 13 }, { 13, 14 }, { 14, 13 }, { 12, 17 },
{ 14, 14 }, { 14, 15 }, { 15, 14 }, { 14, 16 }, { 15, 15 }, { 15, 16 }, { 16, 14 }, { 16, 15 },
{ 17, 14 }, { 16, 16 }, { 16, 17 }, { 17, 16 }, { 18, 15 }, { 17, 17 }, { 17, 18 }, { 18, 17 },
{ 20, 14 }, { 18, 18 }, { 18, 19 }, { 19, 18 }, { 21, 15 }, { 19, 19 }, { 19, 20 }, { 20, 19 },
{ 20, 20 }, { 20, 20 }, { 20, 21 }, { 21, 20 }, { 21, 21 }, { 21, 21 }, { 21, 22 }, { 22, 21 },
{ 22, 22 }, { 22, 22 }, { 22, 23 }, { 23, 22 }, { 23, 23 }, { 23, 23 }, { 23, 24 }, { 24, 23 },
{ 24, 24 }, { 24, 24 }, { 24, 25 }, { 25, 24 }, { 25, 25 }, { 25, 25 }, { 25, 26 }, { 26, 25 },
{ 26, 26 }, { 26, 26 }, { 26, 27 }, { 27, 26 }, { 24, 32 }, { 27, 27 }, { 27, 28 }, { 28, 27 },
{ 25, 33 }, { 28, 28 }, { 28, 29 }, { 29, 28 }, { 27, 32 }, { 29, 29 }, { 29, 30 }, { 30, 29 },
{ 28, 33 }, { 30, 30 }, { 30, 31 }, { 31, 30 }, { 30, 32 }, { 31, 31 }, { 31, 32 }, { 32, 30 },
{ 32, 31 }, { 33, 30 }, { 32, 32 }, { 32, 33 }, { 33, 32 }, { 34, 31 }, { 33, 33 }, { 33, 34 },
{ 34, 33 }, { 36, 30 }, { 34, 34 }, { 34, 35 }, { 35, 34 }, { 37, 31 }, { 35, 35 }, { 35, 36 },
{ 36, 35 }, { 36, 36 }, { 36, 36 }, { 36, 37 }, { 37, 36 }, { 37, 37 }, { 37, 37 }, { 37, 38 },
{ 38, 37 }, { 38, 38 }, { 38, 38 }, { 38, 39 }, { 39, 38 }, { 39, 39 }, { 39, 39 }, { 39, 40 },
{ 40, 39 }, { 40, 40 }, { 40, 40 }, { 40, 41 }, { 41, 40 }, { 41, 41 }, { 41, 41 }, { 41, 42 },
{ 42, 41 }, { 42, 42 }, { 42, 42 }, { 42, 43 }, { 43, 42 }, { 40, 48 }, { 43, 43 }, { 43, 44 },
{ 44, 43 }, { 41, 49 }, { 44, 44 }, { 44, 45 }, { 45, 44 }, { 43, 48 }, { 45, 45 }, { 45, 46 },
{ 46, 45 }, { 44, 49 }, { 46, 46 }, { 46, 47 }, { 47, 46 }, { 46, 48 }, { 47, 47 }, { 47, 48 },
{ 48, 46 }, { 48, 47 }, { 49, 46 }, { 48, 48 }, { 48, 49 }, { 49, 48 }, { 50, 47 }, { 49, 49 },
{ 49, 50 }, { 50, 49 }, { 52, 46 }, { 50, 50 }, { 50, 51 }, { 51, 50 }, { 53, 47 }, { 51, 51 },
{ 51, 52 }, { 52, 51 }, { 52, 52 }, { 52, 52 }, { 52, 53 }, { 53, 52 }, { 53, 53 }, { 53, 53 },
{ 53, 54 }, { 54, 53 }, { 54, 54 }, { 54, 54 }, { 54, 55 }, { 55, 54 }, { 55, 55 }, { 55, 55 },
{ 55, 56 }, { 56, 55 }, { 56, 56 }, { 56, 56 }, { 56, 57 }, { 57, 56 }, { 57, 57 }, { 57, 57 },
{ 57, 58 }, { 58, 57 }, { 58, 58 }, { 58, 58 }, { 58, 59 }, { 59, 58 }, { 59, 59 }, { 59, 59 },
{ 59, 60 }, { 60, 59 }, { 60, 60 }, { 60, 60 }, { 60, 61 }, { 61, 60 }, { 61, 61 }, { 61, 61 },
{ 61, 62 }, { 62, 61 }, { 62, 62 }, { 62, 62 }, { 62, 63 }, { 63, 62 }, { 63, 63 }, { 63, 63 },
};
static int stb__Mul8Bit(int a, int b)
@ -649,7 +650,7 @@ int main()
for (mx=0;mx<size;mx++) {
int mine = (mn * dequant) >> 4;
int maxe = (mx * dequant) >> 4;
int err = abs(stb__Lerp13(maxe, mine) - j);
int err = abs(stb__Lerp13(maxe, mine) - j) * 100;
// DX10 spec says that interpolation must be within 3% of "correct" result,
// add this as error term. Normally we'd expect a random distribution of

File diff suppressed because it is too large Load Diff

10366
stb_image_resize2.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,224 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _MSC_VER
#define stop() __debugbreak()
#include <windows.h>
#define int64 __int64
#pragma warning(disable:4127)
#define get_milliseconds GetTickCount
#else
#define stop() __builtin_trap()
#define int64 long long
typedef unsigned int U32;
typedef unsigned long long U64;
#include <time.h>
static int get_milliseconds()
{
struct timespec ts;
clock_gettime( CLOCK_MONOTONIC, &ts );
return (U32) ( ( ((U64)(U32)ts.tv_sec) * 1000LL ) + (U64)(((U32)ts.tv_nsec+500000)/1000000) );
}
#endif
#if defined(TIME_SIMD)
// default for most platforms
#elif defined(TIME_SCALAR)
#define STBIR_NO_SIMD
#else
#error You must define TIME_SIMD or TIME_SCALAR when compiling this file.
#endif
#define STBIR_PROFILE
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#define STBIR__V_FIRST_INFO_BUFFER v_info
#include "stb_image_resize2.h" // new one!
#if defined(TIME_SIMD) && !defined(STBIR_SIMD)
#error Timing SIMD, but scalar was ON!
#endif
#if defined(TIME_SCALAR) && defined(STBIR_SIMD)
#error Timing scalar, but SIMD was ON!
#endif
#define HEADER 32
static int file_write( const char *filename, void * buffer, size_t size )
{
FILE * f = fopen( filename, "wb" );
if ( f == 0 ) return 0;
if ( fwrite( buffer, 1, size, f) != size ) return 0;
fclose(f);
return 1;
}
int64 nresize( void * o, int ox, int oy, int op, void * i, int ix, int iy, int ip, int buf, int type, int edg, int flt )
{
STBIR_RESIZE resize;
int t;
int64 b;
stbir_resize_init( &resize, i, ix, iy, ip, o, ox, oy, op, buf, type );
stbir_set_edgemodes( &resize, edg, edg );
stbir_set_filters( &resize, flt, flt );
stbir_build_samplers_with_splits( &resize, 1 );
b = 0x7fffffffffffffffULL;
for( t = 0 ; t < 16 ; t++ )
{
STBIR_PROFILE_INFO profile;
int64 v;
if(!stbir_resize_extended( &resize ) )
stop();
stbir_resize_extended_profile_info( &profile, &resize );
v = profile.clocks[1]+profile.clocks[2];
if ( v < b )
{
b = v;
t = 0;
}
}
stbir_free_samplers( &resize );
return b;
}
#define INSIZES 5
#define TYPESCOUNT 5
#define NUM 64
static const int sizes[INSIZES]={63,126,252,520,772};
static const int types[TYPESCOUNT]={STBIR_1CHANNEL,STBIR_2CHANNEL,STBIR_RGB,STBIR_4CHANNEL,STBIR_RGBA};
static const int effective[TYPESCOUNT]={1,2,3,4,7};
int main( int argc, char ** argv )
{
unsigned char * input;
unsigned char * output;
int dimensionx, dimensiony;
int scalex, scaley;
int totalms;
int timing_count;
int ir;
int * file;
int * ts;
int64 totalcycles;
if ( argc != 6 )
{
printf("command: dotimings x_samps y_samps x_scale y_scale outfilename\n");
exit(1);
}
input = malloc( 4*1200*1200 );
memset( input, 0x80, 4*1200*1200 );
output = malloc( 4*10000*10000ULL );
dimensionx = atoi( argv[1] );
dimensiony = atoi( argv[2] );
scalex = atoi( argv[3] );
scaley = atoi( argv[4] );
timing_count = dimensionx * dimensiony * INSIZES * TYPESCOUNT;
file = malloc( sizeof(int) * ( 2 * timing_count + HEADER ) );
ts = file + HEADER;
totalms = get_milliseconds();
totalcycles = STBIR_PROFILE_FUNC();
for( ir = 0 ; ir < INSIZES ; ir++ )
{
int ix, iy, ty;
ix = iy = sizes[ir];
for( ty = 0 ; ty < TYPESCOUNT ; ty++ )
{
int h, hh;
h = 1;
for( hh = 0 ; hh < dimensiony; hh++ )
{
int ww, w = 1;
for( ww = 0 ; ww < dimensionx; ww++ )
{
int64 VF, HF;
int good;
v_info.control_v_first = 2; // vertical first
VF = nresize( output, w, h, (w*4*1)&~3, input, ix, iy, ix*4*1, types[ty], STBIR_TYPE_UINT8, STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL );
v_info.control_v_first = 1; // horizonal first
HF = nresize( output, w, h, (w*4*1)&~3, input, ix, iy, ix*4*1, types[ty], STBIR_TYPE_UINT8, STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL );
good = ( ((HF<=VF) && (!v_info.v_first)) || ((VF<=HF) && (v_info.v_first)));
// printf("\r%d,%d, %d,%d, %d, %I64d,%I64d, // Good: %c(%c-%d) CompEst: %.1f %.1f\n", ix, iy, w, h, ty, VF, HF, good?'y':'n', v_info.v_first?'v':'h', v_info.v_resize_classification, v_info.v_cost,v_info.h_cost );
ts[0] = (int)VF;
ts[1] = (int)HF;
ts += 2;
w += scalex;
}
printf(".");
h += scaley;
}
}
}
totalms = get_milliseconds() - totalms;
totalcycles = STBIR_PROFILE_FUNC() - totalcycles;
printf("\n");
file[0] = 'VFT1';
#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(__SSE2__) || defined( _M_IX86_FP ) || defined(__i386) || defined( __i386__ ) || defined( _M_IX86 ) || defined( _X86_ )
file[1] = 1; // x64
#elif defined( _M_AMD64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__) || defined(__ARM_NEON) || defined(__arm__) || defined( _M_ARM )
file[1] = 2; // arm
#else
file[1] = 99; // who knows???
#endif
#ifdef STBIR_SIMD8
file[2] = 2; // simd-8
#elif defined( STBIR_SIMD )
file[2] = 1; // simd-4
#else
file[2] = 0; // nosimd
#endif
file[3] = dimensionx; // dimx
file[4] = dimensiony; // dimy
file[5] = TYPESCOUNT; // channel types
file[ 6] = types[0]; file[7] = types[1]; file[8] = types[2]; file[9] = types[3]; file[10] = types[4]; // buffer_type
file[11] = effective[0]; file[12] = effective[1]; file[13] = effective[2]; file[14] = effective[3]; file[15] = effective[4]; // effective channels
file[16] = INSIZES; // resizes
file[17] = sizes[0]; file[18] = sizes[0]; // input sizes (w x h)
file[19] = sizes[1]; file[20] = sizes[1];
file[21] = sizes[2]; file[22] = sizes[2];
file[23] = sizes[3]; file[24] = sizes[3];
file[25] = sizes[4]; file[26] = sizes[4];
file[27] = scalex; file[28] = scaley; // scale the dimx and dimy amount ( for(i=0;i<dimx) outputx = 1 + i*scalex; )
file[29] = totalms;
((int64*)(file+30))[0] = totalcycles;
if ( !file_write( argv[5], file, sizeof(int) * ( 2 * timing_count + HEADER ) ) )
printf( "Error writing file: %s\n", argv[5] );
else
printf( "Successfully wrote timing file: %s\n", argv[5] );
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
#include <stdio.h>
#include <stdlib.h>
#ifdef _MSC_VER
#define stop() __debugbreak()
#else
#define stop() __builtin_trap()
#endif
//#define HEAVYTM
#include "tm.h"
#define STBIR_SATURATE_INT
#define STB_IMAGE_RESIZE_STATIC
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "old_image_resize.h"
static int types[4] = { STBIR_TYPE_UINT8, STBIR_TYPE_UINT8, STBIR_TYPE_UINT16, STBIR_TYPE_FLOAT };
static int edges[4] = { STBIR_EDGE_CLAMP, STBIR_EDGE_REFLECT, STBIR_EDGE_ZERO, STBIR_EDGE_WRAP };
static int flts[5] = { STBIR_FILTER_BOX, STBIR_FILTER_TRIANGLE, STBIR_FILTER_CUBICBSPLINE, STBIR_FILTER_CATMULLROM, STBIR_FILTER_MITCHELL };
static int channels[20] = { 1, 2, 3, 4, 4,4, 2,2, 4,4, 2,2, 4,4, 2,2, 4,4, 2,2 };
static int alphapos[20] = { -1, -1, -1, -1, 3,0, 1,0, 3,0, 1,0, 3,0, 1,0, 3,0, 1,0 };
void oresize( void * o, int ox, int oy, int op, void * i, int ix, int iy, int ip, int buf, int type, int edg, int flt )
{
int t = types[type];
int ic = channels[buf];
int alpha = alphapos[buf];
int e = edges[edg];
int f = flts[flt];
int space = ( type == 1 ) ? STBIR_COLORSPACE_SRGB : 0;
int flags = ( buf >= 16 ) ? STBIR_FLAG_ALPHA_PREMULTIPLIED : ( ( buf >= 12 ) ? STBIR_FLAG_ALPHA_OUT_PREMULTIPLIED : ( ( buf >= 8 ) ? (STBIR_FLAG_ALPHA_PREMULTIPLIED|STBIR_FLAG_ALPHA_OUT_PREMULTIPLIED) : 0 ) );
stbir_uint64 start;
ENTER( "Resize (old)" );
start = tmGetAccumulationStart( tm_mask );
if(!stbir_resize( i, ix, iy, ip, o, ox, oy, op, t, ic, alpha, flags, e, e, f, f, space, 0 ) )
stop();
#ifdef STBIR_PROFILE
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.setup, "Setup (old)" );
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.filters, "Filters (old)" );
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.looping, "Looping (old)" );
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.vertical, "Vertical (old)" );
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.horizontal, "Horizontal (old)" );
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.decode, "Scanline input (old)" );
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.encode, "Scanline output (old)" );
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.alpha, "Alpha weighting (old)" );
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.unalpha, "Alpha unweighting (old)" );
#endif
LEAVE();
}

View File

@ -0,0 +1,992 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#define HEAVYTM
#include "tm.h"
#ifdef RADUSETM3
tm_api * g_tm_api;
//#define PROFILE_MODE
#endif
#include <math.h>
#ifdef _MSC_VER
#define stop() __debugbreak()
#include <windows.h>
#define int64 __int64
#define uint64 unsigned __int64
#else
#define stop() __builtin_trap()
#define int64 long long
#define uint64 unsigned long long
#endif
#ifdef _MSC_VER
#pragma warning(disable:4127)
#endif
//#define NOCOMP
//#define PROFILE_NEW_ONLY
//#define PROFILE_MODE
#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(__SSE2__) || defined(STBIR_SSE) || defined( _M_IX86_FP ) || defined(__i386) || defined( __i386__ ) || defined( _M_IX86 ) || defined( _X86_ )
#ifdef _MSC_VER
uint64 __rdtsc();
#define __cycles() __rdtsc()
#else // non msvc
static inline uint64 __cycles()
{
unsigned int lo, hi;
asm volatile ("rdtsc" : "=a" (lo), "=d" (hi) );
return ( ( (uint64) hi ) << 32 ) | ( (uint64) lo );
}
#endif // msvc
#elif defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__)
#ifdef _MSC_VER
#define __cycles() _ReadStatusReg(ARM64_CNTVCT)
#else
static inline uint64 __cycles()
{
uint64 tsc;
asm volatile("mrs %0, cntvct_el0" : "=r" (tsc));
return tsc;
}
#endif
#else // x64, arm
#error Unknown platform for timing.
#endif //x64 and
#ifdef PROFILE_MODE
#define STBIR_ASSERT(cond)
#endif
#ifdef _DEBUG
#undef STBIR_ASSERT
#define STBIR_ASSERT(cond) { if (!(cond)) stop(); }
#endif
#define SHRINKBYW 2
#define ZOOMBYW 2
#define SHRINKBYH 2
#define ZOOMBYH 2
int mem_count = 0;
#ifdef TEST_WITH_VALLOC
#define STBIR__SEPARATE_ALLOCATIONS
#if TEST_WITH_LIMIT_AT_FRONT
void * wmalloc(SIZE_T size)
{
static unsigned int pagesize=0;
void* p;
SIZE_T s;
// get the page size, if we haven't yet
if (pagesize==0)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
pagesize=si.dwPageSize;
}
// we need room for the size, 8 bytes to hide the original pointer and a
// validation dword, and enough data to completely fill one page
s=(size+(pagesize-1))&~(pagesize-1);
// allocate the size plus a page (for the guard)
p=VirtualAlloc(0,(SIZE_T)s,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
return p;
}
void wfree(void * ptr)
{
if (ptr)
{
if ( ((ptrdiff_t)ptr) & 4095 ) stop();
if ( VirtualFree(ptr,0,MEM_RELEASE) == 0 ) stop();
}
}
#else
void * wmalloc(SIZE_T size)
{
static unsigned int pagesize=0;
void* p;
SIZE_T s;
// get the page size, if we haven't yet
if (pagesize==0)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
pagesize=si.dwPageSize;
}
// we need room for the size, 8 bytes to hide the original pointer and a
// validation dword, and enough data to completely fill one page
s=(size+16+(pagesize-1))&~(pagesize-1);
// allocate the size plus a page (for the guard)
p=VirtualAlloc(0,(SIZE_T)(s+pagesize+pagesize),MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
if (p)
{
DWORD oldprot;
void* orig=p;
// protect the first page
VirtualProtect(((char*)p),pagesize,PAGE_NOACCESS,&oldprot);
// protect the final page
VirtualProtect(((char*)p)+s+pagesize,pagesize,PAGE_NOACCESS,&oldprot);
// now move the returned pointer so that it bumps right up against the
// the next (protected) page (this may result in unaligned return
// addresses - pre-align the sizes if you always want aligned ptrs)
//#define ERROR_ON_FRONT
#ifdef ERROR_ON_FRONT
p=((char*)p)+pagesize+16;
#else
p=((char*)p)+(s-size)+pagesize;
#endif
// hide the validation value and the original pointer (which we'll
// need used for freeing) right behind the returned pointer
((unsigned int*)p)[-1]=0x98765432;
((void**)p)[-2]=orig;
++mem_count;
//printf("aloc: %p bytes: %d\n",p,(int)size);
return(p);
}
return 0;
}
void wfree(void * ptr)
{
if (ptr)
{
int err=0;
// is this one of our allocations?
if (((((unsigned int*)ptr)[-1])!=0x98765432) || ((((void**)ptr)[-2])==0))
{
err=1;
}
if (err)
{
__debugbreak();
}
else
{
// back up to find the original pointer
void* p=((void**)ptr)[-2];
// clear the validation value and the original pointer
((unsigned int*)ptr)[-1]=0;
((void**)ptr)[-2]=0;
//printf("free: %p\n",ptr);
--mem_count;
// now free the pages
if (p)
VirtualFree(p,0,MEM_RELEASE);
}
}
}
#endif
#define STBIR_MALLOC(size,user_data) ((void)(user_data), wmalloc(size))
#define STBIR_FREE(ptr,user_data) ((void)(user_data), wfree(ptr))
#endif
#define STBIR_PROFILE
//#define STBIR_NO_SIMD
//#define STBIR_AVX
//#define STBIR_AVX2
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize2.h" // new one!
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
int tsizes[5] = { 1, 1, 2, 4, 2 };
int ttypes[5] = { STBIR_TYPE_UINT8, STBIR_TYPE_UINT8_SRGB, STBIR_TYPE_UINT16, STBIR_TYPE_FLOAT, STBIR_TYPE_HALF_FLOAT };
int cedges[4] = { STBIR_EDGE_CLAMP, STBIR_EDGE_REFLECT, STBIR_EDGE_ZERO, STBIR_EDGE_WRAP };
int flts[5] = { STBIR_FILTER_BOX, STBIR_FILTER_TRIANGLE, STBIR_FILTER_CUBICBSPLINE, STBIR_FILTER_CATMULLROM, STBIR_FILTER_MITCHELL };
int buffers[20] = { STBIR_1CHANNEL, STBIR_2CHANNEL, STBIR_RGB, STBIR_4CHANNEL,
STBIR_BGRA, STBIR_ARGB, STBIR_RA, STBIR_AR,
STBIR_RGBA_PM, STBIR_ARGB_PM, STBIR_RA_PM, STBIR_AR_PM,
STBIR_RGBA, STBIR_ARGB, STBIR_RA, STBIR_AR,
STBIR_RGBA_PM, STBIR_ARGB_PM, STBIR_RA_PM, STBIR_AR_PM,
};
int obuffers[20] = { STBIR_1CHANNEL, STBIR_2CHANNEL, STBIR_RGB, STBIR_4CHANNEL,
STBIR_BGRA, STBIR_ARGB, STBIR_RA, STBIR_AR,
STBIR_RGBA_PM, STBIR_ARGB_PM, STBIR_RA_PM, STBIR_AR_PM,
STBIR_RGBA_PM, STBIR_ARGB_PM, STBIR_RA_PM, STBIR_AR_PM,
STBIR_RGBA, STBIR_ARGB, STBIR_RA, STBIR_AR,
};
int bchannels[20] = { 1, 2, 3, 4, 4,4, 2,2, 4,4, 2,2, 4,4, 2,2, 4,4, 2,2 };
int alphapos[20] = { -1, -1, -1, -1, 3,0, 1,0, 3,0, 1,0, 3,0, 1,0,3,0, 1,0 };
char const * buffstrs[20] = { "1ch", "2ch", "3ch", "4ch", "RGBA", "ARGB", "RA", "AR", "RGBA_both_pre", "ARGB_both_pre", "RA_both_pre", "AR_both_pre", "RGBA_out_pre", "ARGB_out_pre", "RA_out_pre", "AR_out_pre", "RGBA_in_pre", "ARGB_in_pre", "RA_in_pre", "AR_in_pre" };
char const * typestrs[5] = { "Bytes", "BytesSRGB", "Shorts", "Floats", "Half Floats"};
char const * edgestrs[4] = { "Clamp", "Reflect", "Zero", "Wrap" };
char const * fltstrs[5] = { "Box", "Triangle", "Cubic", "Catmullrom", "Mitchell" };
#ifdef STBIR_PROFILE
static void do_acc_zones( STBIR_PROFILE_INFO * profile )
{
stbir_uint32 j;
stbir_uint64 start = tmGetAccumulationStart( tm_mask ); start=start;
for( j = 0 ; j < profile->count ; j++ )
{
if ( profile->clocks[j] )
tmEmitAccumulationZone( 0, 0, (tm_uint64*)&start, 0, profile->clocks[j], profile->descriptions[j] );
}
}
#else
#define do_acc_zones(...)
#endif
int64 vert;
//#define WINTHREADTEST
#ifdef WINTHREADTEST
static STBIR_RESIZE * thread_resize;
static LONG which;
static int threads_started = 0;
static HANDLE threads[32];
static HANDLE starts,stops;
static DWORD resize_shim( LPVOID p )
{
for(;;)
{
LONG wh;
WaitForSingleObject( starts, INFINITE );
wh = InterlockedAdd( &which, 1 ) - 1;
ENTER( "Split %d", wh );
stbir_resize_split( thread_resize, wh, 1 );
#ifdef STBIR_PROFILE
{ STBIR_PROFILE_INFO profile; stbir_resize_split_profile_info( &profile, thread_resize, wh, 1 ); do_acc_zones( &profile ); vert = profile.clocks[1]; }
#endif
LEAVE();
ReleaseSemaphore( stops, 1, 0 );
}
}
#endif
void nresize( void * o, int ox, int oy, int op, void * i, int ix, int iy, int ip, int buf, int type, int edg, int flt )
{
STBIR_RESIZE resize;
stbir_resize_init( &resize, i, ix, iy, ip, o, ox, oy, op, buffers[buf], ttypes[type] );
stbir_set_pixel_layouts( &resize, buffers[buf], obuffers[buf] );
stbir_set_edgemodes( &resize, cedges[edg], cedges[edg] );
stbir_set_filters( &resize, flts[flt], /*STBIR_FILTER_POINT_SAMPLE */ flts[flt] );
//stbir_set_input_subrect( &resize, 0.55f,0.333f,0.75f,0.50f);
//stbir_set_output_pixel_subrect( &resize, 00, 00, ox/2,oy/2);
//stbir_set_pixel_subrect(&resize, 1430,1361,30,30);
ENTER( "Resize" );
#ifndef WINTHREADTEST
ENTER( "Filters" );
stbir_build_samplers_with_splits( &resize, 1 );
#ifdef STBIR_PROFILE
{ STBIR_PROFILE_INFO profile; stbir_resize_build_profile_info( &profile, &resize ); do_acc_zones( &profile ); }
#endif
LEAVE();
ENTER( "Resize" );
if(!stbir_resize_extended( &resize ) )
stop();
#ifdef STBIR_PROFILE
{ STBIR_PROFILE_INFO profile; stbir_resize_extended_profile_info( &profile, &resize ); do_acc_zones( &profile ); vert = profile.clocks[1]; }
#endif
LEAVE();
#else
{
int c, cnt;
ENTER( "Filters" );
cnt = stbir_build_samplers_with_splits( &resize, 4 );
#ifdef STBIR_PROFILE
{ STBIR_PROFILE_INFO profile; stbir_resize_build_profile_info( &profile, &resize ); do_acc_zones( &profile ); }
#endif
LEAVE();
ENTER( "Thread start" );
if ( threads_started == 0 )
{
starts = CreateSemaphore( 0, 0, 32, 0 );
stops = CreateSemaphore( 0, 0, 32, 0 );
}
for( c = threads_started ; c < cnt ; c++ )
threads[ c ] = CreateThread( 0, 2048*1024, resize_shim, 0, 0, 0 );
threads_started = cnt;
thread_resize = &resize;
which = 0;
LEAVE();
// starts the threads
ReleaseSemaphore( starts, cnt, 0 );
ENTER( "Wait" );
for( c = 0 ; c < cnt; c++ )
WaitForSingleObject( stops, INFINITE );
LEAVE();
}
#endif
ENTER( "Free" );
stbir_free_samplers( &resize );
LEAVE();
LEAVE();
}
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
extern void oresize( void * o, int ox, int oy, int op, void * i, int ix, int iy, int ip, int buf, int type, int edg, int flt );
#define TYPESTART 0
#define TYPEEND 4
#define LAYOUTSTART 0
#define LAYOUTEND 19
#define SIZEWSTART 0
#define SIZEWEND 2
#define SIZEHSTART 0
#define SIZEHEND 2
#define EDGESTART 0
#define EDGEEND 3
#define FILTERSTART 0
#define FILTEREND 4
#define HEIGHTSTART 0
#define HEIGHTEND 2
#define WIDTHSTART 0
#define WIDTHEND 2
static void * convert8to16( unsigned char * i, int w, int h, int c )
{
unsigned short * ret;
int p;
ret = malloc( w*h*c*sizeof(short) );
for(p = 0 ; p < (w*h*c) ; p++ )
{
ret[p]=(short)((((int)i[p])<<8)+i[p]);
}
return ret;
}
static void * convert8tof( unsigned char * i, int w, int h, int c )
{
float * ret;
int p;
ret = malloc( w*h*c*sizeof(float) );
for(p = 0 ; p < (w*h*c) ; p++ )
{
ret[p]=((float)i[p])*(1.0f/255.0f);
}
return ret;
}
static void * convert8tohf( unsigned char * i, int w, int h, int c )
{
stbir__FP16 * ret;
int p;
ret = malloc( w*h*c*sizeof(stbir__FP16) );
for(p = 0 ; p < (w*h*c) ; p++ )
{
ret[p]=stbir__float_to_half(((float)i[p])*(1.0f/255.0f));
}
return ret;
}
static void * convert8tohff( unsigned char * i, int w, int h, int c )
{
float * ret;
int p;
ret = malloc( w*h*c*sizeof(float) );
for(p = 0 ; p < (w*h*c) ; p++ )
{
ret[p]=stbir__half_to_float(stbir__float_to_half(((float)i[p])*(1.0f/255.0f)));
}
return ret;
}
static int isprime( int v )
{
int i;
if ( v <= 3 )
return ( v > 1 );
if ( ( v & 1 ) == 0 )
return 0;
if ( ( v % 3 ) == 0 )
return 0;
i = 5;
while ( (i*i) <= v )
{
if ( ( v % i ) == 0 )
return 0;
if ( ( v % ( i + 2 ) ) == 0 )
return 0;
i += 6;
}
return 1;
}
static int getprime( int v )
{
int i;
i = 0;
for(;;)
{
if ( i >= v )
return v; // can't find any, just return orig
if (isprime(v - i))
return v - i;
if (isprime(v + i))
return v + i;
++i;
}
}
int main( int argc, char ** argv )
{
int ix, iy, ic;
unsigned char * input[6];
char * ir1;
char * ir2;
int szhs[3];
int szws[3];
int aw, ah, ac;
unsigned char * correctalpha;
int layouts, types, heights, widths, edges, filters;
if ( argc != 2 )
{
printf("command: stbirtest [imagefile]\n");
exit(1);
}
SetupTM( "127.0.0.1" );
correctalpha = stbi_load( "correctalpha.png", &aw, &ah, &ac, 0 );
input[0] = stbi_load( argv[1], &ix, &iy, &ic, 0 );
input[1] = input[0];
input[2] = convert8to16( input[0], ix, iy, ic );
input[3] = convert8tof( input[0], ix, iy, ic );
input[4] = convert8tohf( input[0], ix, iy, ic );
input[5] = convert8tohff( input[0], ix, iy, ic );
printf("Input %dx%d (%d channels)\n",ix,iy,ic);
ir1 = malloc( 4 * 4 * 3000 * 3000ULL );
ir2 = malloc( 4 * 4 * 3000 * 3000ULL );
szhs[0] = getprime( iy/SHRINKBYH );
szhs[1] = iy;
szhs[2] = getprime( iy*ZOOMBYH );
szws[0] = getprime( ix/SHRINKBYW );
szws[1] = ix;
szws[2] = getprime( ix*ZOOMBYW );
#if 1
for( types = TYPESTART ; types <= TYPEEND ; types++ )
#else
for( types = 1 ; types <= 1 ; types++ )
#endif
{
ENTER( "Test type: %s",typestrs[types]);
#if 1
for( layouts = LAYOUTSTART ; layouts <= LAYOUTEND ; layouts++ )
#else
for( layouts = 16; layouts <= 16 ; layouts++ )
#endif
{
ENTER( "Test layout: %s",buffstrs[layouts]);
#if 0
for( heights = HEIGHTSTART ; heights <= HEIGHTEND ; heights++ )
{
int w, h = szhs[heights];
#else
for( heights = 0 ; heights <= 11 ; heights++ )
{
static int szhsz[12]={32, 200, 350, 400, 450, 509, 532, 624, 700, 824, 1023, 2053 };
int w, h = szhsz[heights];
#endif
ENTER( "Test height: %d %s %d",iy,(h<iy)?"Down":((h>iy)?"Up":"Same"),h);
#if 0
for( widths = WIDTHSTART ; widths <= WIDTHEND ; widths++ )
{
w = szws[widths];
#else
for( widths = 0 ; widths <= 12 ; widths++ )
{
static int szwsz[13]={2, 32, 200, 350, 400, 450, 509, 532, 624, 700, 824, 1023, 2053 };
w = szwsz[widths];
#endif
ENTER( "Test width: %d %s %d",ix, (w<ix)?"Down":((w>ix)?"Up":"Same"), w);
#if 0
for( edges = EDGESTART ; edges <= EDGEEND ; edges++ )
#else
for( edges = 0 ; edges <= 0 ; edges++ )
#endif
{
ENTER( "Test edge: %s",edgestrs[edges]);
#if 0
for( filters = FILTERSTART ; filters <= FILTEREND ; filters++ )
#else
for( filters = 3 ; filters <= 3 ; filters++ )
#endif
{
int op, opw, np,npw, c, a;
#ifdef COMPARE_SAME
int oldtypes = types;
#else
int oldtypes = (types==4)?3:types;
#endif
ENTER( "Test filter: %s",fltstrs[filters]);
{
c = bchannels[layouts];
a = alphapos[layouts];
op = w*tsizes[oldtypes]*c + 60;
opw = w*tsizes[oldtypes]*c;
np = w*tsizes[types]*c + 60;
npw = w*tsizes[types]*c;
printf( "%s:layout: %s w: %d h: %d edge: %s filt: %s\n", typestrs[types],buffstrs[layouts], w, h, edgestrs[edges], fltstrs[filters] );
// clear pixel area to different, right edge to zero
#ifndef NOCLEAR
ENTER( "Test clear padding" );
{
int d;
for( d = 0 ; d < h ; d++ )
{
int oofs = d * op;
int nofs = d * np;
memset( ir1 + oofs, 192, opw );
memset( ir1 + oofs+opw, 79, op-opw );
memset( ir2 + nofs, 255, npw );
memset( ir2 + nofs+npw, 79, np-npw );
}
}
LEAVE();
#endif
#ifdef COMPARE_SAME
#define TIMINGS 1
#else
#define TIMINGS 1
#endif
ENTER( "Test both" );
{
#ifndef PROFILE_NEW_ONLY
{
int ttt, max = 0x7fffffff;
ENTER( "Test old" );
for( ttt = 0 ; ttt < TIMINGS ; ttt++ )
{
int64 m = __cycles();
oresize( ir1, w, h, op,
#ifdef COMPARE_SAME
input[types],
#else
input[(types==4)?5:types],
#endif
ix, iy, ix*ic*tsizes[oldtypes], layouts, oldtypes, edges, filters );
m = __cycles() - m;
if ( ( (int)m ) < max )
max = (int) m;
}
LEAVE();
printf("old: %d\n", max );
}
#endif
{
int ttt, max = 0x7fffffff, maxv = 0x7fffffff;
ENTER( "Test new" );
for( ttt = 0 ; ttt < TIMINGS ; ttt++ )
{
int64 m = __cycles();
nresize( ir2, w, h, np, input[types], ix, iy, ix*ic*tsizes[types], layouts, types, edges, filters );
m = __cycles() - m;
if ( ( (int)m ) < max )
max = (int) m;
if ( ( (int)vert ) < maxv )
maxv = (int) vert;
}
LEAVE(); // test new
printf("new: %d (v: %d)\n", max, maxv );
}
}
LEAVE(); // test both
if ( mem_count!= 0 )
stop();
#ifndef NOCOMP
ENTER( "Test compare" );
{
int x,y,ch;
int nums = 0;
for( y = 0 ; y < h ; y++ )
{
for( x = 0 ; x < w ; x++ )
{
switch(types)
{
case 0:
case 1: //SRGB
{
unsigned char * p1 = (unsigned char *)&ir1[y*op+x*c];
unsigned char * p2 = (unsigned char *)&ir2[y*np+x*c];
for( ch = 0 ; ch < c ; ch++ )
{
float pp1,pp2,d;
float av = (a==-1)?1.0f:((float)p1[a]/255.0f);
pp1 = p1[ch];
pp2 = p2[ch];
// compare in premult space
#ifndef COMPARE_SAME
if ( ( ( layouts >=4 ) && ( layouts <= 7 ) ) || ( ( layouts >=16 ) && ( layouts <= 19 ) ) )
{
pp1 *= av;
pp2 *= av;
}
#endif
d = pp1 - pp2;
if ( d < 0 ) d = -d;
#ifdef COMPARE_SAME
if ( d > 0 )
#else
if ( d > 1 )
#endif
{
printf("Error at %d x %d (chan %d) (d: %g a: %g) [%d %d %d %d] [%d %d %d %d]\n",x,y,ch, d,av, p1[0],p1[1],p1[2],p1[3], p2[0],p2[1],p2[2],p2[3]);
++nums;
if ( nums > 16 ) goto ex;
//if (d) exit(1);
//goto ex;
}
}
}
break;
case 2:
{
unsigned short * p1 = (unsigned short *)&ir1[y*op+x*c*sizeof(short)];
unsigned short * p2 = (unsigned short *)&ir2[y*np+x*c*sizeof(short)];
for( ch = 0 ; ch < c ; ch++ )
{
float thres,pp1,pp2,d;
float av = (a==-1)?1.0f:((float)p1[a]/65535.0f);
pp1 = p1[ch];
pp2 = p2[ch];
// compare in premult space
#ifndef COMPARE_SAME
if ( ( ( layouts >=4 ) && ( layouts <= 7 ) ) || ( ( layouts >= 16 ) && ( layouts <= 19 ) ) )
{
pp1 *= av;
pp2 *= av;
}
#endif
d = pp1 - pp2;
if ( d < 0 ) d = -d;
thres=((float)p1[ch]*0.007f)+2.0f;
if (thres<4) thres = 4;
#ifdef COMPARE_SAME
if ( d > 0 )
#else
if ( d > thres)
#endif
{
printf("Error at %d x %d (chan %d) %d %d [df: %g th: %g al: %g] (%d %d %d %d) (%d %d %d %d)\n",x,y,ch, p1[ch],p2[ch],d,thres,av,p1[0],p1[1],p1[2],p1[3],p2[0],p2[1],p2[2],p2[3]);
++nums;
if ( nums > 16 ) goto ex;
//if (d) exit(1);
//goto ex;
}
}
}
break;
case 3:
{
float * p1 = (float *)&ir1[y*op+x*c*sizeof(float)];
float * p2 = (float *)&ir2[y*np+x*c*sizeof(float)];
for( ch = 0 ; ch < c ; ch++ )
{
float pp1 = p1[ch], pp2 = p2[ch];
float av = (a==-1)?1.0f:p1[a];
float thres, d;
// clamp
if (pp1<=0.0f) pp1 = 0;
if (pp2<=0.0f) pp2 = 0;
if (av<=0.0f) av = 0;
if (pp1>1.0f) pp1 = 1.0f;
if (pp2>1.0f) pp2 = 1.0f;
if (av>1.0f) av = 1.0f;
// compare in premult space
#ifndef COMPARE_SAME
if ( ( ( layouts >=4 ) && ( layouts <= 7 ) ) || ( ( layouts >= 16 ) && ( layouts <= 19 ) ) )
{
pp1 *= av;
pp2 *= av;
}
#endif
d = pp1 - pp2;
if ( d < 0 ) d = -d;
thres=(p1[ch]*0.002f)+0.0002f;
if ( thres < 0 ) thres = -thres;
#ifdef COMPARE_SAME
if ( d != 0.0f )
#else
if ( d > thres )
#endif
{
printf("Error at %d x %d (chan %d) %g %g [df: %g th: %g al: %g] (%g %g %g %g) (%g %g %g %g)\n",x,y,ch, p1[ch],p2[ch],d,thres,av,p1[0],p1[1],p1[2],p1[3],p2[0],p2[1],p2[2],p2[3]);
++nums;
if ( nums > 16 ) goto ex;
//if (d) exit(1);
//goto ex;
}
}
}
break;
case 4:
{
#ifdef COMPARE_SAME
stbir__FP16 * p1 = (stbir__FP16 *)&ir1[y*op+x*c*sizeof(stbir__FP16)];
#else
float * p1 = (float *)&ir1[y*op+x*c*sizeof(float)];
#endif
stbir__FP16 * p2 = (stbir__FP16 *)&ir2[y*np+x*c*sizeof(stbir__FP16)];
for( ch = 0 ; ch < c ; ch++ )
{
#ifdef COMPARE_SAME
float pp1 = stbir__half_to_float(p1[ch]);
float av = (a==-1)?1.0f:stbir__half_to_float(p1[a]);
#else
float pp1 = stbir__half_to_float(stbir__float_to_half(p1[ch]));
float av = (a==-1)?1.0f:stbir__half_to_float(stbir__float_to_half(p1[a]));
#endif
float pp2 = stbir__half_to_float(p2[ch]);
float d, thres;
// clamp
if (pp1<=0.0f) pp1 = 0;
if (pp2<=0.0f) pp2 = 0;
if (av<=0.0f) av = 0;
if (pp1>1.0f) pp1 = 1.0f;
if (pp2>1.0f) pp2 = 1.0f;
if (av>1.0f) av = 1.0f;
thres=(pp1*0.002f)+0.0002f;
// compare in premult space
#ifndef COMPARE_SAME
if ( ( ( layouts >=4 ) && ( layouts <= 7 ) ) || ( ( layouts >= 16 ) && ( layouts <= 19 ) ) )
{
pp1 *= av;
pp2 *= av;
}
#endif
d = pp1 - pp2;
if ( d < 0 ) d = -d;
#ifdef COMPARE_SAME
if ( d != 0.0f )
#else
if ( d > thres )
#endif
{
printf("Error at %d x %d (chan %d) %g %g [df: %g th: %g al: %g] (%g %g %g %g) (%g %g %g %g)\n",x,y,ch,
#ifdef COMPARE_SAME
stbir__half_to_float(p1[ch]),
#else
p1[ch],
#endif
stbir__half_to_float(p2[ch]),
d,thres,av,
#ifdef COMPARE_SAME
stbir__half_to_float(p1[0]),stbir__half_to_float(p1[1]),stbir__half_to_float(p1[2]),stbir__half_to_float(p1[3]),
#else
p1[0],p1[1],p1[2],p1[3],
#endif
stbir__half_to_float(p2[0]),stbir__half_to_float(p2[1]),stbir__half_to_float(p2[2]),stbir__half_to_float(p2[3]) );
++nums;
if ( nums > 16 ) goto ex;
//if (d) exit(1);
//goto ex;
}
}
}
break;
}
}
for( x = (w*c)*tsizes[oldtypes]; x < op; x++ )
{
if ( ir1[y*op+x] != 79 )
{
printf("Margin error at %d x %d %d (should be 79) OLD!\n",x,y,(unsigned char)ir1[y*op+x]);
goto ex;
}
}
for( x = (w*c)*tsizes[types]; x < np; x++ )
{
if ( ir2[y*np+x] != 79 )
{
printf("Margin error at %d x %d %d (should be 79) NEW\n",x,y,(unsigned char)ir2[y*np+x]);
goto ex;
}
}
}
ex:
ENTER( "OUTPUT IMAGES" );
printf(" tot pix: %d, errs: %d\n", w*h*c,nums );
if (nums)
{
stbi_write_png("old.png", w, h, c, ir1, op);
stbi_write_png("new.png", w, h, c, ir2, np);
exit(1);
}
LEAVE(); // output images
}
LEAVE(); //test compare
#endif
}
LEAVE(); // test filter
}
LEAVE(); // test edge
}
LEAVE(); // test width
}
LEAVE(); // test height
}
LEAVE(); // test type
}
LEAVE(); // test layout
}
CloseTM();
return 0;
}

View File

@ -0,0 +1,999 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define stop() __debugbreak()
#include <windows.h>
#define int64 __int64
#pragma warning(disable:4127)
#define STBIR__WEIGHT_TABLES
#define STBIR_PROFILE
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize2.h"
static int * file_read( char const * filename )
{
size_t s;
int * m;
FILE * f = fopen( filename, "rb" );
if ( f == 0 ) return 0;
fseek( f, 0, SEEK_END);
s = ftell( f );
fseek( f, 0, SEEK_SET);
m = malloc( s + 4 );
m[0] = (int)s;
fread( m+1, 1, s, f);
fclose(f);
return( m );
}
typedef struct fileinfo
{
int * timings;
int timing_count;
int dimensionx, dimensiony;
int numtypes;
int * types;
int * effective;
int cpu;
int simd;
int numinputrects;
int * inputrects;
int outputscalex, outputscaley;
int milliseconds;
int64 cycles;
double scale_time;
int bitmapx, bitmapy;
char const * filename;
} fileinfo;
int numfileinfo;
fileinfo fi[256];
unsigned char * bitmap;
int bitmapw, bitmaph, bitmapp;
static int use_timing_file( char const * filename, int index )
{
int * base = file_read( filename );
int * file = base;
if ( base == 0 ) return 0;
++file; // skip file image size;
if ( *file++ != 'VFT1' ) return 0;
fi[index].cpu = *file++;
fi[index].simd = *file++;
fi[index].dimensionx = *file++;
fi[index].dimensiony = *file++;
fi[index].numtypes = *file++;
fi[index].types = file; file += fi[index].numtypes;
fi[index].effective = file; file += fi[index].numtypes;
fi[index].numinputrects = *file++;
fi[index].inputrects = file; file += fi[index].numinputrects * 2;
fi[index].outputscalex = *file++;
fi[index].outputscaley = *file++;
fi[index].milliseconds = *file++;
fi[index].cycles = ((int64*)file)[0]; file += 2;
fi[index].filename = filename;
fi[index].timings = file;
fi[index].timing_count = (int) ( ( base[0] - ( ((char*)file - (char*)base - sizeof(int) ) ) ) / (sizeof(int)*2) );
fi[index].scale_time = (double)fi[index].milliseconds / (double)fi[index].cycles;
return 1;
}
static int vert_first( float weights_table[STBIR_RESIZE_CLASSIFICATIONS][4], int ox, int oy, int ix, int iy, int filter, STBIR__V_FIRST_INFO * v_info )
{
float h_scale=(float)ox/(float)(ix);
float v_scale=(float)oy/(float)(iy);
stbir__support_callback * support = stbir__builtin_supports[filter];
int vertical_filter_width = stbir__get_filter_pixel_width(support,v_scale,0);
int vertical_gather = ( v_scale >= ( 1.0f - stbir__small_float ) ) || ( vertical_filter_width <= STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT );
return stbir__should_do_vertical_first( weights_table, stbir__get_filter_pixel_width(support,h_scale,0), h_scale, ox, vertical_filter_width, v_scale, oy, vertical_gather, v_info );
}
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
static void alloc_bitmap()
{
int findex;
int x = 0, y = 0;
int w = 0, h = 0;
for( findex = 0 ; findex < numfileinfo ; findex++ )
{
int nx, ny;
int thisw, thish;
thisw = ( fi[findex].dimensionx * fi[findex].numtypes ) + ( fi[findex].numtypes - 1 );
thish = ( fi[findex].dimensiony * fi[findex].numinputrects ) + ( fi[findex].numinputrects - 1 );
for(;;)
{
nx = x + ((x)?4:0) + thisw;
ny = y + ((y)?4:0) + thish;
if ( ( nx <= 3600 ) || ( x == 0 ) )
{
fi[findex].bitmapx = x + ((x)?4:0);
fi[findex].bitmapy = y + ((y)?4:0);
x = nx;
if ( x > w ) w = x;
if ( ny > h ) h = ny;
break;
}
else
{
x = 0;
y = h;
}
}
}
w = (w+3) & ~3;
bitmapw = w;
bitmaph = h;
bitmapp = w * 3; // RGB
bitmap = malloc( bitmapp * bitmaph );
memset( bitmap, 0, bitmapp * bitmaph );
}
static void build_bitmap( float weights[STBIR_RESIZE_CLASSIFICATIONS][4], int do_channel_count_index, int findex )
{
static int colors[STBIR_RESIZE_CLASSIFICATIONS];
STBIR__V_FIRST_INFO v_info = {0};
int * ts;
int ir;
unsigned char * bitm = bitmap + ( fi[findex].bitmapx*3 ) + ( fi[findex].bitmapy*bitmapp) ;
for( ir = 0; ir < STBIR_RESIZE_CLASSIFICATIONS ; ir++ ) colors[ ir ] = 127*ir/STBIR_RESIZE_CLASSIFICATIONS+128;
ts = fi[findex].timings;
for( ir = 0 ; ir < fi[findex].numinputrects ; ir++ )
{
int ix, iy, chanind;
ix = fi[findex].inputrects[ir*2];
iy = fi[findex].inputrects[ir*2+1];
for( chanind = 0 ; chanind < fi[findex].numtypes ; chanind++ )
{
int ofs, h, hh;
// just do the type that we're on
if ( chanind != do_channel_count_index )
{
ts += 2 * fi[findex].dimensionx * fi[findex].dimensiony;
continue;
}
// bitmap offset
ofs=chanind*(fi[findex].dimensionx+1)*3+ir*(fi[findex].dimensiony+1)*bitmapp;
h = 1;
for( hh = 0 ; hh < fi[findex].dimensiony; hh++ )
{
int ww, w = 1;
for( ww = 0 ; ww < fi[findex].dimensionx; ww++ )
{
int good, v_first, VF, HF;
VF = ts[0];
HF = ts[1];
v_first = vert_first( weights, w, h, ix, iy, STBIR_FILTER_MITCHELL, &v_info );
good = ( ((HF<=VF) && (!v_first)) || ((VF<=HF) && (v_first)));
if ( good )
{
bitm[ofs+2] = 0;
bitm[ofs+1] = (unsigned char)colors[v_info.v_resize_classification];
}
else
{
double r;
if ( HF < VF )
r = (double)(VF-HF)/(double)HF;
else
r = (double)(HF-VF)/(double)VF;
if ( r > 0.4f) r = 0.4;
r *= 1.0f/0.4f;
bitm[ofs+2] = (char)(255.0f*r);
bitm[ofs+1] = (char)(((float)colors[v_info.v_resize_classification])*(1.0f-r));
}
bitm[ofs] = 0;
ofs += 3;
ts += 2;
w += fi[findex].outputscalex;
}
ofs += bitmapp - fi[findex].dimensionx*3;
h += fi[findex].outputscaley;
}
}
}
}
static void build_comp_bitmap( float weights[STBIR_RESIZE_CLASSIFICATIONS][4], int do_channel_count_index )
{
int * ts0;
int * ts1;
int ir;
unsigned char * bitm = bitmap + ( fi[0].bitmapx*3 ) + ( fi[0].bitmapy*bitmapp) ;
ts0 = fi[0].timings;
ts1 = fi[1].timings;
for( ir = 0 ; ir < fi[0].numinputrects ; ir++ )
{
int ix, iy, chanind;
ix = fi[0].inputrects[ir*2];
iy = fi[0].inputrects[ir*2+1];
for( chanind = 0 ; chanind < fi[0].numtypes ; chanind++ )
{
int ofs, h, hh;
// just do the type that we're on
if ( chanind != do_channel_count_index )
{
ts0 += 2 * fi[0].dimensionx * fi[0].dimensiony;
ts1 += 2 * fi[0].dimensionx * fi[0].dimensiony;
continue;
}
// bitmap offset
ofs=chanind*(fi[0].dimensionx+1)*3+ir*(fi[0].dimensiony+1)*bitmapp;
h = 1;
for( hh = 0 ; hh < fi[0].dimensiony; hh++ )
{
int ww, w = 1;
for( ww = 0 ; ww < fi[0].dimensionx; ww++ )
{
int v_first, time0, time1;
v_first = vert_first( weights, w, h, ix, iy, STBIR_FILTER_MITCHELL, 0 );
time0 = ( v_first ) ? ts0[0] : ts0[1];
time1 = ( v_first ) ? ts1[0] : ts1[1];
if ( time0 < time1 )
{
double r = (double)(time1-time0)/(double)time0;
if ( r > 0.4f) r = 0.4;
r *= 1.0f/0.4f;
bitm[ofs+2] = 0;
bitm[ofs+1] = (char)(255.0f*r);
bitm[ofs] = (char)(64.0f*(1.0f-r));
}
else
{
double r = (double)(time0-time1)/(double)time1;
if ( r > 0.4f) r = 0.4;
r *= 1.0f/0.4f;
bitm[ofs+2] = (char)(255.0f*r);
bitm[ofs+1] = 0;
bitm[ofs] = (char)(64.0f*(1.0f-r));
}
ofs += 3;
ts0 += 2;
ts1 += 2;
w += fi[0].outputscalex;
}
ofs += bitmapp - fi[0].dimensionx*3;
h += fi[0].outputscaley;
}
}
}
}
static void write_bitmap()
{
stbi_write_png( "results.png", bitmapp / 3, bitmaph, 3|STB_IMAGE_BGR, bitmap, bitmapp );
}
static void calc_errors( float weights_table[STBIR_RESIZE_CLASSIFICATIONS][4], int * curtot, double * curerr, int do_channel_count_index )
{
int th, findex;
STBIR__V_FIRST_INFO v_info = {0};
for(th=0;th<STBIR_RESIZE_CLASSIFICATIONS;th++)
{
curerr[th]=0;
curtot[th]=0;
}
for( findex = 0 ; findex < numfileinfo ; findex++ )
{
int * ts;
int ir;
ts = fi[findex].timings;
for( ir = 0 ; ir < fi[findex].numinputrects ; ir++ )
{
int ix, iy, chanind;
ix = fi[findex].inputrects[ir*2];
iy = fi[findex].inputrects[ir*2+1];
for( chanind = 0 ; chanind < fi[findex].numtypes ; chanind++ )
{
int h, hh;
// just do the type that we're on
if ( chanind != do_channel_count_index )
{
ts += 2 * fi[findex].dimensionx * fi[findex].dimensiony;
continue;
}
h = 1;
for( hh = 0 ; hh < fi[findex].dimensiony; hh++ )
{
int ww, w = 1;
for( ww = 0 ; ww < fi[findex].dimensionx; ww++ )
{
int good, v_first, VF, HF;
VF = ts[0];
HF = ts[1];
v_first = vert_first( weights_table, w, h, ix, iy, STBIR_FILTER_MITCHELL, &v_info );
good = ( ((HF<=VF) && (!v_first)) || ((VF<=HF) && (v_first)));
if ( !good )
{
double diff;
if ( VF < HF )
diff = ((double)HF-(double)VF) * fi[findex].scale_time;
else
diff = ((double)VF-(double)HF) * fi[findex].scale_time;
curtot[v_info.v_resize_classification] += 1;
curerr[v_info.v_resize_classification] += diff;
}
ts += 2;
w += fi[findex].outputscalex;
}
h += fi[findex].outputscaley;
}
}
}
}
}
#define TRIESPERWEIGHT 32
#define MAXRANGE ((TRIESPERWEIGHT+1) * (TRIESPERWEIGHT+1) * (TRIESPERWEIGHT+1) * (TRIESPERWEIGHT+1) - 1)
static void expand_to_floats( float * weights, int range )
{
weights[0] = (float)( range % (TRIESPERWEIGHT+1) ) / (float)TRIESPERWEIGHT;
weights[1] = (float)( range/(TRIESPERWEIGHT+1) % (TRIESPERWEIGHT+1) ) / (float)TRIESPERWEIGHT;
weights[2] = (float)( range/(TRIESPERWEIGHT+1)/(TRIESPERWEIGHT+1) % (TRIESPERWEIGHT+1) ) / (float)TRIESPERWEIGHT;
weights[3] = (float)( range/(TRIESPERWEIGHT+1)/(TRIESPERWEIGHT+1)/(TRIESPERWEIGHT+1) % (TRIESPERWEIGHT+1) ) / (float)TRIESPERWEIGHT;
}
static char const * expand_to_string( int range )
{
static char str[128];
int w0,w1,w2,w3;
w0 = range % (TRIESPERWEIGHT+1);
w1 = range/(TRIESPERWEIGHT+1) % (TRIESPERWEIGHT+1);
w2 = range/(TRIESPERWEIGHT+1)/(TRIESPERWEIGHT+1) % (TRIESPERWEIGHT+1);
w3 = range/(TRIESPERWEIGHT+1)/(TRIESPERWEIGHT+1)/(TRIESPERWEIGHT+1) % (TRIESPERWEIGHT+1);
sprintf( str, "[ %2d/%d %2d/%d %2d/%d %2d/%d ]",w0,TRIESPERWEIGHT,w1,TRIESPERWEIGHT,w2,TRIESPERWEIGHT,w3,TRIESPERWEIGHT );
return str;
}
static void print_weights( float weights[STBIR_RESIZE_CLASSIFICATIONS][4], int channel_count_index, int * tots, double * errs )
{
int th;
printf("ChInd: %d Weights:\n",channel_count_index);
for(th=0;th<STBIR_RESIZE_CLASSIFICATIONS;th++)
{
float * w = weights[th];
printf(" %d: [%1.5f %1.5f %1.5f %1.5f] (%d %.4f)\n",th, w[0], w[1], w[2], w[3], tots[th], errs[th] );
}
printf("\n");
}
static int windowranges[ 16 ];
static int windowstatus = 0;
static DWORD trainstart = 0;
static void opt_channel( float best_output_weights[STBIR_RESIZE_CLASSIFICATIONS][4], int channel_count_index )
{
int newbest = 0;
float weights[STBIR_RESIZE_CLASSIFICATIONS][4] = {0};
double besterr[STBIR_RESIZE_CLASSIFICATIONS];
int besttot[STBIR_RESIZE_CLASSIFICATIONS];
int best[STBIR_RESIZE_CLASSIFICATIONS]={0};
double curerr[STBIR_RESIZE_CLASSIFICATIONS];
int curtot[STBIR_RESIZE_CLASSIFICATIONS];
int th, range;
DWORD lasttick = 0;
for(th=0;th<STBIR_RESIZE_CLASSIFICATIONS;th++)
{
besterr[th]=1000000000000.0;
besttot[th]=0x7fffffff;
}
newbest = 0;
// try the whole range
range = MAXRANGE;
do
{
for(th=0;th<STBIR_RESIZE_CLASSIFICATIONS;th++)
expand_to_floats( weights[th], range );
calc_errors( weights, curtot, curerr, channel_count_index );
for(th=0;th<STBIR_RESIZE_CLASSIFICATIONS;th++)
{
if ( curerr[th] < besterr[th] )
{
besterr[th] = curerr[th];
besttot[th] = curtot[th];
best[th] = range;
expand_to_floats( best_output_weights[th], best[th] );
newbest = 1;
}
}
{
DWORD t = GetTickCount();
if ( range == 0 )
goto do_bitmap;
if ( newbest )
{
if ( ( GetTickCount() - lasttick ) > 200 )
{
int findex;
do_bitmap:
lasttick = t;
newbest = 0;
for( findex = 0 ; findex < numfileinfo ; findex++ )
build_bitmap( best_output_weights, channel_count_index, findex );
lasttick = GetTickCount();
}
}
}
windowranges[ channel_count_index ] = range;
// advance all the weights and loop
--range;
} while( ( range >= 0 ) && ( !windowstatus ) );
// if we hit here, then we tried all weights for this opt, so save them
}
static void print_struct( float weight[5][STBIR_RESIZE_CLASSIFICATIONS][4], char const * name )
{
printf("\n\nstatic float %s[5][STBIR_RESIZE_CLASSIFICATIONS][4]=\n{", name );
{
int i;
for(i=0;i<5;i++)
{
int th;
for(th=0;th<STBIR_RESIZE_CLASSIFICATIONS;th++)
{
int j;
printf("\n ");
for(j=0;j<4;j++)
printf("%1.5ff, ", weight[i][th][j] );
}
printf("\n");
}
printf("\n};\n");
}
}
static float retrain_weights[5][STBIR_RESIZE_CLASSIFICATIONS][4];
static DWORD __stdcall retrain_shim( LPVOID p )
{
int chanind = (int) (size_t)p;
opt_channel( retrain_weights[chanind], chanind );
return 0;
}
static char const * gettime( int ms )
{
static char time[32];
if (ms > 60000)
sprintf( time, "%dm %ds",ms/60000, (ms/1000)%60 );
else
sprintf( time, "%ds",ms/1000 );
return time;
}
static BITMAPINFOHEADER bmiHeader;
static DWORD extrawindoww, extrawindowh;
static HINSTANCE instance;
static int curzoom = 1;
static LRESULT WINAPI WindowProc( HWND window,
UINT message,
WPARAM wparam,
LPARAM lparam )
{
switch( message )
{
case WM_CHAR:
if ( wparam != 27 )
break;
// falls through
case WM_CLOSE:
{
int i;
int max = 0;
for( i = 0 ; i < fi[0].numtypes ; i++ )
if( windowranges[i] > max ) max = windowranges[i];
if ( ( max == 0 ) || ( MessageBox( window, "Cancel before training is finished?", "Vertical First Training", MB_OKCANCEL|MB_ICONSTOP ) == IDOK ) )
{
for( i = 0 ; i < fi[0].numtypes ; i++ )
if( windowranges[i] > max ) max = windowranges[i];
if ( max )
windowstatus = 1;
DestroyWindow( window );
}
}
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC dc;
dc = BeginPaint( window, &ps );
StretchDIBits( dc,
0, 0, bitmapw*curzoom, bitmaph*curzoom,
0, 0, bitmapw, bitmaph,
bitmap, (BITMAPINFO*)&bmiHeader, DIB_RGB_COLORS, SRCCOPY );
PatBlt( dc, bitmapw*curzoom, 0, 4096, 4096, WHITENESS );
PatBlt( dc, 0, bitmaph*curzoom, 4096, 4096, WHITENESS );
SetTextColor( dc, RGB(0,0,0) );
SetBkColor( dc, RGB(255,255,255) );
SetBkMode( dc, OPAQUE );
{
int i, l = 0, max = 0;
char buf[1024];
RECT rc;
POINT p;
for( i = 0 ; i < fi[0].numtypes ; i++ )
{
l += sprintf( buf + l, "channels: %d %s\n", fi[0].effective[i], windowranges[i] ? expand_to_string( windowranges[i] ) : "Done." );
if ( windowranges[i] > max ) max = windowranges[i];
}
rc.left = 32; rc.top = bitmaph*curzoom+10;
rc.right = 512; rc.bottom = rc.top + 512;
DrawText( dc, buf, -1, &rc, DT_TOP );
l = 0;
if ( max == 0 )
{
static DWORD traindone = 0;
if ( traindone == 0 ) traindone = GetTickCount();
l = sprintf( buf, "Finished in %s.", gettime( traindone - trainstart ) );
}
else if ( max != MAXRANGE )
l = sprintf( buf, "Done in %s...", gettime( (int) ( ( ( (int64)max * ( (int64)GetTickCount() - (int64)trainstart ) ) ) / (int64) ( MAXRANGE - max ) ) ) );
GetCursorPos( &p );
ScreenToClient( window, &p );
if ( ( p.x >= 0 ) && ( p.y >= 0 ) && ( p.x < (bitmapw*curzoom) ) && ( p.y < (bitmaph*curzoom) ) )
{
int findex;
int x, y, w, h, sx, sy, ix, iy, ox, oy;
int ir, chanind;
int * ts;
char badstr[64];
STBIR__V_FIRST_INFO v_info={0};
p.x /= curzoom;
p.y /= curzoom;
for( findex = 0 ; findex < numfileinfo ; findex++ )
{
x = fi[findex].bitmapx;
y = fi[findex].bitmapy;
w = x + ( fi[findex].dimensionx + 1 ) * fi[findex].numtypes;
h = y + ( fi[findex].dimensiony + 1 ) * fi[findex].numinputrects;
if ( ( p.x >= x ) && ( p.y >= y ) && ( p.x < w ) && ( p.y < h ) )
goto found;
}
goto nope;
found:
ir = ( p.y - y ) / ( fi[findex].dimensiony + 1 );
sy = ( p.y - y ) % ( fi[findex].dimensiony + 1 );
if ( sy >= fi[findex].dimensiony ) goto nope;
chanind = ( p.x - x ) / ( fi[findex].dimensionx + 1 );
sx = ( p.x - x ) % ( fi[findex].dimensionx + 1 );
if ( sx >= fi[findex].dimensionx ) goto nope;
ix = fi[findex].inputrects[ir*2];
iy = fi[findex].inputrects[ir*2+1];
ts = fi[findex].timings + ( ( fi[findex].dimensionx * fi[findex].dimensiony * fi[findex].numtypes * ir ) + ( fi[findex].dimensionx * fi[findex].dimensiony * chanind ) + ( fi[findex].dimensionx * sy ) + sx ) * 2;
ox = 1+fi[findex].outputscalex*sx;
oy = 1+fi[findex].outputscaley*sy;
if ( windowstatus != 2 )
{
int VF, HF, v_first, good;
VF = ts[0];
HF = ts[1];
v_first = vert_first( retrain_weights[chanind], ox, oy, ix, iy, STBIR_FILTER_MITCHELL, &v_info );
good = ( ((HF<=VF) && (!v_first)) || ((VF<=HF) && (v_first)));
if ( good )
badstr[0] = 0;
else
{
double r;
if ( HF < VF )
r = (double)(VF-HF)/(double)HF;
else
r = (double)(HF-VF)/(double)VF;
sprintf( badstr, " %.1f%% off", r*100 );
}
sprintf( buf + l, "\n\n%s\nCh: %d Resize: %dx%d to %dx%d\nV: %d H: %d Order: %c (%s%s)\nClass: %d Scale: %.2f %s", fi[findex].filename,fi[findex].effective[chanind], ix,iy,ox,oy, VF, HF, v_first?'V':'H', good?"Good":"Wrong", badstr, v_info.v_resize_classification, (double)oy/(double)iy, v_info.is_gather ? "Gather" : "Scatter" );
}
else
{
int v_first, time0, time1;
float (* weights)[4] = stbir__compute_weights[chanind];
int * ts1;
char b0[32], b1[32];
ts1 = fi[1].timings + ( ts - fi[0].timings );
v_first = vert_first( weights, ox, oy, ix, iy, STBIR_FILTER_MITCHELL, &v_info );
time0 = ( v_first ) ? ts[0] : ts[1];
time1 = ( v_first ) ? ts1[0] : ts1[1];
b0[0] = b1[0] = 0;
if ( time0 < time1 )
sprintf( b0," (%.f%% better)", ((double)time1-(double)time0)*100.0f/(double)time0);
else
sprintf( b1," (%.f%% better)", ((double)time0-(double)time1)*100.0f/(double)time1);
sprintf( buf + l, "\n\n0: %s\n1: %s\nCh: %d Resize: %dx%d to %dx%d\nClass: %d Scale: %.2f %s\nTime0: %d%s\nTime1: %d%s", fi[0].filename, fi[1].filename, fi[0].effective[chanind], ix,iy,ox,oy, v_info.v_resize_classification, (double)oy/(double)iy, v_info.is_gather ? "Gather" : "Scatter", time0, b0, time1, b1 );
}
}
nope:
rc.left = 32+320; rc.right = 512+320;
SetTextColor( dc, RGB(0,0,128) );
DrawText( dc, buf, -1, &rc, DT_TOP );
}
EndPaint( window, &ps );
return 0;
}
case WM_TIMER:
InvalidateRect( window, 0, 0 );
return 0;
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
}
return DefWindowProc( window, message, wparam, lparam );
}
static void SetHighDPI(void)
{
typedef HRESULT WINAPI setdpitype(int v);
HMODULE h=LoadLibrary("Shcore.dll");
if (h)
{
setdpitype * sd = (setdpitype*)GetProcAddress(h,"SetProcessDpiAwareness");
if (sd )
sd(1);
}
}
static void draw_window()
{
WNDCLASS wc;
HWND w;
MSG msg;
instance = GetModuleHandle(NULL);
wc.style = 0;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = instance;
wc.hIcon = 0;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = 0;
wc.lpszMenuName = 0;
wc.lpszClassName = "WHTrain";
if ( !RegisterClass( &wc ) )
exit(1);
SetHighDPI();
bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmiHeader.biWidth = bitmapp/3;
bmiHeader.biHeight = -bitmaph;
bmiHeader.biPlanes = 1;
bmiHeader.biBitCount = 24;
bmiHeader.biCompression = BI_RGB;
w = CreateWindow( "WHTrain",
"Vertical First Training",
WS_CAPTION | WS_POPUP| WS_CLIPCHILDREN |
WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX,
CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,
0, 0, instance, 0 );
{
RECT r, c;
GetWindowRect( w, &r );
GetClientRect( w, &c );
extrawindoww = ( r.right - r.left ) - ( c.right - c.left );
extrawindowh = ( r.bottom - r.top ) - ( c.bottom - c.top );
SetWindowPos( w, 0, 0, 0, bitmapw * curzoom + extrawindoww, bitmaph * curzoom + extrawindowh + 164, SWP_NOMOVE );
}
ShowWindow( w, SW_SHOWNORMAL );
SetTimer( w, 1, 250, 0 );
{
BOOL ret;
while( ( ret = GetMessage( &msg, w, 0, 0 ) ) != 0 )
{
if ( ret == -1 )
break;
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
}
static void retrain()
{
HANDLE threads[ 16 ];
int chanind;
trainstart = GetTickCount();
for( chanind = 0 ; chanind < fi[0].numtypes ; chanind++ )
threads[ chanind ] = CreateThread( 0, 2048*1024, retrain_shim, (LPVOID)(size_t)chanind, 0, 0 );
draw_window();
for( chanind = 0 ; chanind < fi[0].numtypes ; chanind++ )
{
WaitForSingleObject( threads[ chanind ], INFINITE );
CloseHandle( threads[ chanind ] );
}
write_bitmap();
print_struct( retrain_weights, "retained_weights" );
if ( windowstatus ) printf( "CANCELLED!\n" );
}
static void info()
{
int findex;
// display info about each input file
for( findex = 0 ; findex < numfileinfo ; findex++ )
{
int i, h,m,s;
if ( findex ) printf( "\n" );
printf( "Timing file: %s\n", fi[findex].filename );
printf( "CPU type: %d %s\n", fi[findex].cpu, fi[findex].simd?(fi[findex].simd==2?"SIMD8":"SIMD4"):"Scalar" );
h = fi[findex].milliseconds/3600000;
m = (fi[findex].milliseconds-h*3600000)/60000;
s = (fi[findex].milliseconds-h*3600000-m*60000)/1000;
printf( "Total time in test: %dh %dm %ds Cycles/sec: %.f\n", h,m,s, 1000.0/fi[findex].scale_time );
printf( "Each tile of samples is %dx%d, and is scaled by %dx%d.\n", fi[findex].dimensionx,fi[findex].dimensiony, fi[findex].outputscalex,fi[findex].outputscaley );
printf( "So the x coords are: " );
for( i=0; i < fi[findex].dimensionx ; i++ ) printf( "%d ",1+i*fi[findex].outputscalex );
printf( "\n" );
printf( "And the y coords are: " );
for( i=0; i < fi[findex].dimensiony ; i++ ) printf( "%d ",1+i*fi[findex].outputscaley );
printf( "\n" );
printf( "There are %d channel counts and they are: ", fi[findex].numtypes );
for( i=0; i < fi[findex].numtypes ; i++ ) printf( "%d ",fi[findex].effective[i] );
printf( "\n" );
printf( "There are %d input rect sizes and they are: ", fi[findex].numinputrects );
for( i=0; i < fi[findex].numtypes ; i++ ) printf( "%dx%d ",fi[findex].inputrects[i*2],fi[findex].inputrects[i*2+1] );
printf( "\n" );
}
}
static void current( int do_win, int do_bitmap )
{
int i, findex;
trainstart = GetTickCount();
// clear progress
memset( windowranges, 0, sizeof( windowranges ) );
// copy in appropriate weights
memcpy( retrain_weights, stbir__compute_weights, sizeof( retrain_weights ) );
// build and print current errors and build current bitmap
for( i = 0 ; i < fi[0].numtypes ; i++ )
{
double curerr[STBIR_RESIZE_CLASSIFICATIONS];
int curtot[STBIR_RESIZE_CLASSIFICATIONS];
float (* weights)[4] = retrain_weights[i];
calc_errors( weights, curtot, curerr, i );
if ( !do_bitmap )
print_weights( weights, i, curtot, curerr );
for( findex = 0 ; findex < numfileinfo ; findex++ )
build_bitmap( weights, i, findex );
}
if ( do_win )
draw_window();
if ( do_bitmap )
write_bitmap();
}
static void compare()
{
int i;
trainstart = GetTickCount();
windowstatus = 2; // comp mode
// clear progress
memset( windowranges, 0, sizeof( windowranges ) );
if ( ( fi[0].numtypes != fi[1].numtypes ) || ( fi[0].numinputrects != fi[1].numinputrects ) ||
( fi[0].dimensionx != fi[1].dimensionx ) || ( fi[0].dimensiony != fi[1].dimensiony ) ||
( fi[0].outputscalex != fi[1].outputscalex ) || ( fi[0].outputscaley != fi[1].outputscaley ) )
{
err:
printf( "Timing files don't match.\n" );
exit(5);
}
for( i=0; i < fi[0].numtypes ; i++ )
{
if ( fi[0].effective[i] != fi[1].effective[i] ) goto err;
if ( fi[0].inputrects[i*2] != fi[1].inputrects[i*2] ) goto err;
if ( fi[0].inputrects[i*2+1] != fi[1].inputrects[i*2+1] ) goto err;
}
alloc_bitmap( 1 );
for( i = 0 ; i < fi[0].numtypes ; i++ )
{
float (* weights)[4] = stbir__compute_weights[i];
build_comp_bitmap( weights, i );
}
draw_window();
}
static void load_files( char ** args, int count )
{
int i;
if ( count == 0 )
{
printf( "No timing files listed!" );
exit(3);
}
for ( i = 0 ; i < count ; i++ )
{
if ( !use_timing_file( args[i], i ) )
{
printf( "Bad timing file %s\n", args[i] );
exit(2);
}
}
numfileinfo = count;
}
int main( int argc, char ** argv )
{
int check;
if ( argc < 3 )
{
err:
printf( "vf_train retrain [timing_filenames....] - recalcs weights for all the files on the command line.\n");
printf( "vf_train info [timing_filenames....] - shows info about each timing file.\n");
printf( "vf_train check [timing_filenames...] - show results for the current weights for all files listed.\n");
printf( "vf_train compare <timing file1> <timing file2> - compare two timing files (must only be two files and same resolution).\n");
printf( "vf_train bitmap [timing_filenames...] - write out results.png, comparing against the current weights for all files listed.\n");
exit(1);
}
check = ( strcmp( argv[1], "check" ) == 0 );
if ( ( check ) || ( strcmp( argv[1], "bitmap" ) == 0 ) )
{
load_files( argv + 2, argc - 2 );
alloc_bitmap( numfileinfo );
current( check, !check );
}
else if ( strcmp( argv[1], "info" ) == 0 )
{
load_files( argv + 2, argc - 2 );
info();
}
else if ( strcmp( argv[1], "compare" ) == 0 )
{
if ( argc != 4 )
{
printf( "You must specify two files to compare.\n" );
exit(4);
}
load_files( argv + 2, argc - 2 );
compare();
}
else if ( strcmp( argv[1], "retrain" ) == 0 )
{
load_files( argv + 2, argc - 2 );
alloc_bitmap( numfileinfo );
retrain();
}
else
{
goto err;
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* stb_image_write - v1.15 - public domain - http://nothings.org/stb
/* stb_image_write - v1.16 - public domain - http://nothings.org/stb
writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
no warranty implied; use at your own risk
@ -140,6 +140,7 @@ CREDITS:
Ivan Tikhonov
github:ignotion
Adam Schackart
Andrew Kensler
LICENSE
@ -166,9 +167,9 @@ LICENSE
#endif
#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations
extern int stbi_write_tga_with_rle;
extern int stbi_write_png_compression_level;
extern int stbi_write_force_png_filter;
STBIWDEF int stbi_write_tga_with_rle;
STBIWDEF int stbi_write_png_compression_level;
STBIWDEF int stbi_write_force_png_filter;
#endif
#ifndef STBI_WRITE_NO_STDIO
@ -178,7 +179,7 @@ STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const
STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
#ifdef STBI_WINDOWS_UTF8
#ifdef STBIW_WINDOWS_UTF8
STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
#endif
#endif
@ -285,7 +286,7 @@ static void stbi__stdio_write(void *context, void *data, int size)
fwrite(data,1,size,(FILE*) context);
}
#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)
#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
#ifdef __cplusplus
#define STBIW_EXTERN extern "C"
#else
@ -296,25 +297,25 @@ STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned in
STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
{
return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
}
#endif
static FILE *stbiw__fopen(char const *filename, char const *mode)
{
FILE *f;
#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)
#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
wchar_t wMode[64];
wchar_t wFilename[1024];
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))
return 0;
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))
return 0;
#if defined(_MSC_VER) && _MSC_VER >= 1400
if (0 != _wfopen_s(&f, wFilename, wMode))
f = 0;
if (0 != _wfopen_s(&f, wFilename, wMode))
f = 0;
#else
f = _wfopen(wFilename, wMode);
#endif
@ -490,11 +491,22 @@ static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x,
static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
{
int pad = (-x*3) & 3;
return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
"11 4 22 4" "4 44 22 444444",
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
if (comp != 4) {
// write RGB bitmap
int pad = (-x*3) & 3;
return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
"11 4 22 4" "4 44 22 444444",
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
} else {
// RGBA bitmaps need a v4 header
// use BI_BITFIELDS mode with 32bpp and alpha mask
// (straight BI_RGB with alpha mask doesn't work in most readers)
return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0,
"11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444",
'B', 'M', 14+108+x*y*4, 0, 0, 14+108, // file header
108, 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
}
}
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
@ -622,6 +634,8 @@ STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const
#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
#ifndef STBI_WRITE_NO_STDIO
static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
{
int exponent;
@ -756,7 +770,7 @@ 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";
s->func(s->context, header, sizeof(header)-1);
#ifdef __STDC_WANT_SECURE_LIB__
#ifdef __STDC_LIB_EXT1__
len = sprintf_s(buffer, sizeof(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);
@ -777,7 +791,6 @@ STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x,
return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
}
#ifndef STBI_WRITE_NO_STDIO
STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
{
stbi__write_context s = { 0 };
@ -968,6 +981,23 @@ STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, i
(void) stbiw__sbfree(hash_table[i]);
STBIW_FREE(hash_table);
// store uncompressed instead if compression was worse
if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) {
stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1
for (j = 0; j < data_len;) {
int blocklen = data_len - j;
if (blocklen > 32767) blocklen = 32767;
stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression
stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN
stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8));
stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN
stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8));
memcpy(out+stbiw__sbn(out), data+j, blocklen);
stbiw__sbn(out) += blocklen;
j += blocklen;
}
}
{
// compute adler32 on input
unsigned int s1=1, s2=0;
@ -1598,6 +1628,10 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const
#endif // STB_IMAGE_WRITE_IMPLEMENTATION
/* Revision history
1.16 (2021-07-11)
make Deflate code emit uncompressed blocks when it would otherwise expand
support writing BMPs with alpha channel
1.15 (2020-07-13) unknown
1.14 (2020-02-02) updated JPEG writer to downsample chroma channels
1.13
1.12
@ -1635,7 +1669,7 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const
add HDR output
fix monochrome BMP
0.95 (2014-08-17)
add monochrome TGA output
add monochrome TGA output
0.94 (2014-05-31)
rename private functions to avoid conflicts with stb_image.h
0.93 (2014-05-27)

View File

@ -1,9 +1,15 @@
// stb_rect_pack.h - v1.00 - public domain - rectangle packing
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
// Sean Barrett 2014
//
// Useful for e.g. packing rectangular textures into an atlas.
// Does not do rotation.
//
// Before #including,
//
// #define STB_RECT_PACK_IMPLEMENTATION
//
// in the file that you want to have the implementation.
//
// Not necessarily the awesomest packing method, but better than
// the totally naive one in stb_truetype (which is primarily what
// this is meant to replace).
@ -35,6 +41,7 @@
//
// Version history:
//
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
// 0.99 (2019-02-07) warning fixes
// 0.11 (2017-03-03) return packing success/fail result
@ -75,11 +82,10 @@ typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect;
#ifdef STBRP_LARGE_RECTS
typedef int stbrp_coord;
#else
typedef unsigned short stbrp_coord;
#endif
#define STBRP__MAXVAL 0x7fffffff
// Mostly for internal use, but this is the maximum supported coordinate value.
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
// Assign packed locations to rectangles. The rectangles are of type
@ -209,8 +215,10 @@ struct stbrp_context
#ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v)
#define STBRP__CDECL __cdecl
#else
#define STBRP__NOTUSED(v) (void)sizeof(v)
#define STBRP__CDECL
#endif
enum
@ -253,9 +261,6 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_ou
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{
int i;
#ifndef STBRP_LARGE_RECTS
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
#endif
for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1];
@ -274,11 +279,7 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
context->extra[0].y = 0;
context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width;
#ifdef STBRP_LARGE_RECTS
context->extra[1].y = (1<<30);
#else
context->extra[1].y = 65535;
#endif
context->extra[1].next = NULL;
}
@ -520,7 +521,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
return res;
}
static int rect_height_compare(const void *a, const void *b)
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
@ -531,19 +532,13 @@ static int rect_height_compare(const void *a, const void *b)
return (p->w > q->w) ? -1 : (p->w < q->w);
}
static int rect_original_order(const void *a, const void *b)
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
}
#ifdef STBRP_LARGE_RECTS
#define STBRP__MAXVAL 0xffffffff
#else
#define STBRP__MAXVAL 0xffff
#endif
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{
int i, all_rects_packed = 1;

View File

@ -1,4 +1,4 @@
// stb_sprintf - v1.09 - public domain snprintf() implementation
// stb_sprintf - v1.10 - public domain snprintf() implementation
// originally by Jeff Roberts / RAD Game Tools, 2015/10/20
// http://github.com/nothings/stb
//
@ -154,8 +154,8 @@ PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC):
#endif
#endif
#endif
#elif __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
#if __SANITIZE_ADDRESS__
#elif defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
#if defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__
#define STBSP__ASAN __attribute__((__no_sanitize_address__))
#endif
#endif
@ -187,6 +187,12 @@ PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC):
#define STBSP__ATTRIBUTE_FORMAT(fmt,va)
#endif
#ifdef _MSC_VER
#define STBSP__NOTUSED(v) (void)(v)
#else
#define STBSP__NOTUSED(v) (void)sizeof(v)
#endif
#include <stdarg.h> // for va_arg(), va_list()
#include <stddef.h> // size_t, ptrdiff_t
@ -199,13 +205,13 @@ typedef char *STBSP_SPRINTFCB(const char *buf, void *user, int len);
#define STB_SPRINTF_DECORATE(name) stbsp_##name // define this before including if you want to change the names
#endif
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va);
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsnprintf)(char *buf, int count, char const *fmt, va_list va);
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3);
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(3,4);
STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va);
STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsnprintf)(char *buf, int count, char const *fmt, va_list va);
STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3);
STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(3,4);
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va);
STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char comma, char period);
STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va);
STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char period);
#endif // STB_SPRINTF_H_INCLUDE
@ -300,6 +306,46 @@ static void stbsp__lead_sign(stbsp__uint32 fl, char *sign)
}
}
static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uint32 limit)
{
char const * sn = s;
// get up to 4-byte alignment
for (;;) {
if (((stbsp__uintptr)sn & 3) == 0)
break;
if (!limit || *sn == 0)
return (stbsp__uint32)(sn - s);
++sn;
--limit;
}
// scan over 4 bytes at a time to find terminating 0
// this will intentionally scan up to 3 bytes past the end of buffers,
// but becase it works 4B aligned, it will never cross page boundaries
// (hence the STBSP__ASAN markup; the over-read here is intentional
// and harmless)
while (limit >= 4) {
stbsp__uint32 v = *(stbsp__uint32 *)sn;
// bit hack to find if there's a 0 byte in there
if ((v - 0x01010101) & (~v) & 0x80808080UL)
break;
sn += 4;
limit -= 4;
}
// handle the last few characters to find actual size
while (limit && *sn) {
++sn;
--limit;
}
return (stbsp__uint32)(sn - s);
}
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va)
{
static char hex[] = "0123456789abcdefxp";
@ -543,37 +589,9 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback,
s = va_arg(va, char *);
if (s == 0)
s = (char *)"null";
// get the length
sn = s;
for (;;) {
if ((((stbsp__uintptr)sn) & 3) == 0)
break;
lchk:
if (sn[0] == 0)
goto ld;
++sn;
}
n = 0xffffffff;
if (pr >= 0) {
n = (stbsp__uint32)(sn - s);
if (n >= (stbsp__uint32)pr)
goto ld;
n = ((stbsp__uint32)(pr - n)) >> 2;
}
while (n) {
stbsp__uint32 v = *(stbsp__uint32 *)sn;
if ((v - 0x01010101) & (~v) & 0x80808080UL)
goto lchk;
sn += 4;
--n;
}
goto lchk;
ld:
l = (stbsp__uint32)(sn - s);
// clamp to precision
if (l > (stbsp__uint32)pr)
l = pr;
// get the length, limited to desired precision
// always limit to ~0u chars since our counts are 32b
l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u);
lead[0] = 0;
tail[0] = 0;
pr = 0;
@ -614,8 +632,8 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback,
lead[0] = 0;
tail[0] = 0;
pr = 0;
dp = 0;
cs = 0;
STBSP__NOTUSED(dp);
goto scopy;
#else
case 'A': // hex float
@ -1010,7 +1028,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback,
lead[0] = 0;
if (pr == 0) {
l = 0;
cs = (((l >> 4) & 15)) << 24;
cs = 0;
goto scopy;
}
}

View File

@ -1,4 +1,4 @@
// stb_textedit.h - v1.13 - public domain - Sean Barrett
// stb_textedit.h - v1.14 - public domain - Sean Barrett
// Development of this library was sponsored by RAD Game Tools
//
// This C header file implements the guts of a multi-line text-editing
@ -29,6 +29,7 @@
//
// VERSION HISTORY
//
// 1.14 (2021-07-11) page up/down, various fixes
// 1.13 (2019-02-07) fix bug in undo size management
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
@ -52,6 +53,7 @@
// Ulf Winklemann: move-by-word in 1.1
// Fabian Giesen: secondary key inputs in 1.5
// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6
// Louis Schnellbach: page up/down in 1.14
//
// Bugfixes:
// Scott Graham
@ -142,6 +144,8 @@
// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right
// STB_TEXTEDIT_K_UP keyboard input to move cursor up
// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME
// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END
// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME
@ -164,10 +168,6 @@
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
//
// Todo:
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
//
// Keyboard input must be encoded as a single integer value; e.g. a character code
// and some bitflags that represent shift states. to simplify the interface, SHIFT must
// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
@ -331,6 +331,10 @@ typedef struct
// each textfield keeps its own insert mode state. to keep an app-wide
// insert mode, copy this value in/out of the app state
int row_count_per_page;
// page size in number of row.
// this value MUST be set to >0 for pageup or pagedown in multilines documents.
/////////////////////
//
// private data
@ -708,9 +712,7 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
state->has_preferred_x = 0;
return 1;
}
// remove the undo since we didn't actually insert the characters
if (state->undostate.undo_point)
--state->undostate.undo_point;
// note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details)
return 0;
}
@ -849,12 +851,16 @@ retry:
break;
case STB_TEXTEDIT_K_DOWN:
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: {
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT:
case STB_TEXTEDIT_K_PGDOWN:
case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT: {
StbFindState find;
StbTexteditRow row;
int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
int i, j, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGDOWN;
int row_count = is_page ? state->row_count_per_page : 1;
if (state->single_line) {
if (!is_page && state->single_line) {
// on windows, up&down in single-line behave like left&right
key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT);
goto retry;
@ -863,17 +869,20 @@ retry:
if (sel)
stb_textedit_prep_selection_at_cursor(state);
else if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_move_to_last(str,state);
stb_textedit_move_to_last(str, state);
// compute current position of cursor point
stb_textedit_clamp(str, state);
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
// now find character position down a row
if (find.length) {
float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
float x;
for (j = 0; j < row_count; ++j) {
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
int start = find.first_char + find.length;
if (find.length == 0)
break;
// now find character position down a row
state->cursor = start;
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
x = row.x0;
@ -895,17 +904,25 @@ retry:
if (sel)
state->select_end = state->cursor;
// go to next line
find.first_char = find.first_char + find.length;
find.length = row.num_chars;
}
break;
}
case STB_TEXTEDIT_K_UP:
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: {
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT:
case STB_TEXTEDIT_K_PGUP:
case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT: {
StbFindState find;
StbTexteditRow row;
int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
int i, j, prev_scan, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGUP;
int row_count = is_page ? state->row_count_per_page : 1;
if (state->single_line) {
if (!is_page && state->single_line) {
// on windows, up&down become left&right
key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT);
goto retry;
@ -920,11 +937,14 @@ retry:
stb_textedit_clamp(str, state);
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
// can only go up if there's a previous row
if (find.prev_first != find.first_char) {
for (j = 0; j < row_count; ++j) {
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
// can only go up if there's a previous row
if (find.prev_first == find.first_char)
break;
// now find character position up a row
float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
float x;
state->cursor = find.prev_first;
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
x = row.x0;
@ -946,6 +966,14 @@ retry:
if (sel)
state->select_end = state->cursor;
// go to previous line
// (we need to scan previous line the hard way. maybe we could expose this as a new API function?)
prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0;
while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE)
--prev_scan;
find.first_char = find.prev_first;
find.prev_first = prev_scan;
}
break;
}
@ -1069,10 +1097,6 @@ retry:
state->has_preferred_x = 0;
break;
}
// @TODO:
// STB_TEXTEDIT_K_PGUP - move cursor up a page
// STB_TEXTEDIT_K_PGDOWN - move cursor down a page
}
}
@ -1337,6 +1361,7 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
state->initialized = 1;
state->single_line = (unsigned char) is_single_line;
state->insert_mode = 0;
state->row_count_per_page = 0;
}
// API initialize

View File

@ -1,4 +1,4 @@
// stb_tilemap_editor.h - v0.41 - Sean Barrett - http://nothings.org/stb
// stb_tilemap_editor.h - v0.42 - Sean Barrett - http://nothings.org/stb
// placed in the public domain - not copyrighted - first released 2014-09
//
// Embeddable tilemap editor for C/C++
@ -275,6 +275,7 @@
// either approach allows cut&pasting between levels.)
//
// REVISION HISTORY
// 0.42 fix compilation errors
// 0.41 fix warnings
// 0.40 fix warning
// 0.39 fix warning
@ -317,6 +318,8 @@
// Bugfixes:
// Ryan Whitworth
// Eugene Opalev
// Rob Loach
// github:wernsey
//
// LICENSE
//
@ -1821,6 +1824,8 @@ static int stbte__button(int colormode, const char *label, int x, int y, int tex
int x0=x,y0=y, x1=x+width,y1=y+STBTE__BUTTON_HEIGHT;
int s = STBTE__BUTTON_INTERNAL_SPACING;
if(!disabled) stbte__hittest(x0,y0,x1,y1,id);
if (stbte__ui.event == STBTE__paint)
stbte__draw_textbox(x0,y0,x1,y1, (char*) label,s+textoff,s, colormode, STBTE__INDEX_FOR_ID(id,disabled,toggled));
if (disabled)
@ -1833,6 +1838,8 @@ static int stbte__button_icon(int colormode, char ch, int x, int y, int width, i
int x0=x,y0=y, x1=x+width,y1=y+STBTE__BUTTON_HEIGHT;
int s = STBTE__BUTTON_INTERNAL_SPACING;
stbte__hittest(x0,y0,x1,y1,id);
if (stbte__ui.event == STBTE__paint) {
char label[2] = { ch, 0 };
int pad = (9 - stbte__get_char_width(ch))/2;
@ -1846,6 +1853,7 @@ static int stbte__button_icon(int colormode, char ch, int x, int y, int width, i
static int stbte__minibutton(int colormode, int x, int y, int ch, int id)
{
int x0 = x, y0 = y, x1 = x+8, y1 = y+7;
stbte__hittest(x0,y0,x1,y1,id);
if (stbte__ui.event == STBTE__paint) {
char str[2] = { (char)ch, 0 };
stbte__draw_textbox(x0,y0,x1,y1, str,1,0,colormode, STBTE__INDEX_FOR_ID(id,0,0));
@ -1856,6 +1864,7 @@ static int stbte__minibutton(int colormode, int x, int y, int ch, int id)
static int stbte__layerbutton(int x, int y, int ch, int id, int toggled, int disabled, int colormode)
{
int x0 = x, y0 = y, x1 = x+10, y1 = y+11;
if(!disabled) stbte__hittest(x0,y0,x1,y1,id);
if (stbte__ui.event == STBTE__paint) {
char str[2] = { (char)ch, 0 };
int off = (9-stbte__get_char_width(ch))/2;
@ -1869,6 +1878,7 @@ static int stbte__layerbutton(int x, int y, int ch, int id, int toggled, int dis
static int stbte__microbutton(int x, int y, int size, int id, int colormode)
{
int x0 = x, y0 = y, x1 = x+size, y1 = y+size;
stbte__hittest(x0,y0,x1,y1,id);
if (stbte__ui.event == STBTE__paint) {
stbte__draw_box(x0,y0,x1,y1, colormode, STBTE__INDEX_FOR_ID(id,0,0));
}
@ -1878,6 +1888,7 @@ static int stbte__microbutton(int x, int y, int size, int id, int colormode)
static int stbte__microbutton_dragger(int x, int y, int size, int id, int *pos)
{
int x0 = x, y0 = y, x1 = x+size, y1 = y+size;
stbte__hittest(x0,y0,x1,y1,id);
switch (stbte__ui.event) {
case STBTE__paint:
stbte__draw_box(x0,y0,x1,y1, STBTE__cexpander, STBTE__INDEX_FOR_ID(id,0,0));
@ -1908,6 +1919,8 @@ static int stbte__category_button(const char *label, int x, int y, int width, in
int x0=x,y0=y, x1=x+width,y1=y+STBTE__BUTTON_HEIGHT;
int s = STBTE__BUTTON_INTERNAL_SPACING;
stbte__hittest(x0,y0,x1,y1,id);
if (stbte__ui.event == STBTE__paint)
stbte__draw_textbox(x0,y0,x1,y1, (char*) label, s,s, STBTE__ccategory_button, STBTE__INDEX_FOR_ID(id,0,toggled));
@ -1927,6 +1940,7 @@ static int stbte__slider(int x0, int w, int y, int range, int *value, int id)
{
int x1 = x0+w;
int pos = *value * w / (range+1);
stbte__hittest(x0,y-2,x1,y+3,id);
int event_mouse_move = STBTE__change;
switch (stbte__ui.event) {
case STBTE__paint:
@ -1969,6 +1983,7 @@ static int stbte__float_control(int x0, int y0, int w, float minv, float maxv, f
{
int x1 = x0+w;
int y1 = y0+11;
stbte__hittest(x0,y0,x1,y1,id);
switch (stbte__ui.event) {
case STBTE__paint: {
char text[32];
@ -1980,7 +1995,7 @@ static int stbte__float_control(int x0, int y0, int w, float minv, float maxv, f
case STBTE__rightdown:
if (STBTE__IS_HOT(id) && STBTE__INACTIVE())
stbte__activate(id);
return STBTE__begin;
return STBTE__begin;
break;
case STBTE__leftup:
case STBTE__rightup:
@ -2020,7 +2035,6 @@ static int stbte__float_control(int x0, int y0, int w, float minv, float maxv, f
static void stbte__scrollbar(int x, int y0, int y1, int *val, int v0, int v1, int num_vis, int id)
{
int over;
int thumbpos;
if (v1 - v0 <= num_vis)
return;
@ -2029,7 +2043,7 @@ static void stbte__scrollbar(int x, int y0, int y1, int *val, int v0, int v1, in
thumbpos = y0+2 + (y1-y0-4) * *val / (v1 - v0 - num_vis);
if (thumbpos < y0) thumbpos = y0;
if (thumbpos >= y1) thumbpos = y1;
over = stbte__hittest(x-1,y0,x+2,y1,id);
stbte__hittest(x-1,y0,x+2,y1,id);
switch (stbte__ui.event) {
case STBTE__paint:
stbte__draw_rect(x,y0,x+1,y1, stbte__color_table[STBTE__cscrollbar][STBTE__text][STBTE__idle]);
@ -2807,6 +2821,10 @@ static void stbte__drag_update(stbte_tilemap *tm, int mapx, int mapy, int copy_p
int ox,oy,i,deleted=0,written=0;
short temp[STBTE_MAX_LAYERS];
short *data = NULL;
STBTE__NOTUSED(deleted);
STBTE__NOTUSED(written);
if (!stbte__ui.shift) {
ox = mapx - stbte__ui.drag_x;
oy = mapy - stbte__ui.drag_y;
@ -2928,6 +2946,9 @@ static void stbte__tile_paint(stbte_tilemap *tm, int sx, int sy, int mapx, int m
{
int i;
int id = STBTE__IDMAP(mapx,mapy);
int x0=sx, y0=sy;
int x1=sx+tm->spacing_x, y1=sy+tm->spacing_y;
stbte__hittest(x0,y0,x1,y1, id);
short *data = tm->data[mapy][mapx];
short temp[STBTE_MAX_LAYERS];
@ -2996,7 +3017,7 @@ static void stbte__tile_paint(stbte_tilemap *tm, int sx, int sy, int mapx, int m
i = layer;
if (i == tm->solo_layer || (!tm->layerinfo[i].hidden && tm->solo_layer < 0))
if (data[i] >= 0)
STBTE_DRAW_TILE(x0,y0, (unsigned short) data[i], 0, tm->props[mapy][mapx]);
STBTE_DRAW_TILE(sx,sy, (unsigned short) data[i], 0, tm->props[mapy][mapx]);
}
}
@ -3492,11 +3513,14 @@ static void stbte__categories(stbte_tilemap *tm, int x0, int y0, int w, int h)
static void stbte__tile_in_palette(stbte_tilemap *tm, int x, int y, int slot)
{
stbte__tileinfo *t = &tm->tiles[slot];
int x0=x, y0=y, x1 = x+tm->palette_spacing_x - 1, y1 = y+tm->palette_spacing_y;
int id = STBTE__ID(STBTE__palette, slot);
stbte__hittest(x0,y0,x1,y1, id);
switch (stbte__ui.event) {
case STBTE__paint:
stbte__draw_rect(x,y,x+tm->palette_spacing_x-1,y+tm->palette_spacing_x-1, STBTE_COLOR_TILEPALETTE_BACKGROUND);
STBTE_DRAW_TILE(x,y,t->id, slot == tm->cur_tile,0);
STBTE_DRAW_TILE(x,y,id, slot == tm->cur_tile,0);
if (slot == tm->cur_tile)
stbte__draw_frame_delayed(x-1,y-1,x+tm->palette_spacing_x,y+tm->palette_spacing_y, STBTE_COLOR_TILEPALETTE_OUTLINE);
break;
@ -3565,6 +3589,7 @@ static void stbte__props_panel(stbte_tilemap *tm, int x0, int y0, int w, int h)
my = stbte__ui.select_y0;
p = tm->props[my][mx];
data = tm->data[my][mx];
STBTE__NOTUSED(data);
for (i=0; i < STBTE_MAX_PROPERTIES; ++i) {
unsigned int n = STBTE_PROP_TYPE(i, data, p);
if (n) {
@ -3644,8 +3669,9 @@ static void stbte__props_panel(stbte_tilemap *tm, int x0, int y0, int w, int h)
}
}
static int stbte__cp_mode, stbte__cp_aspect, stbte__cp_state, stbte__cp_index, stbte__save, stbte__cp_altered, stbte__color_copy;
static int stbte__cp_mode, stbte__cp_aspect, stbte__save, stbte__cp_altered;
#ifdef STBTE__COLORPICKER
static int stbte__cp_state, stbte__cp_index, stbte__color_copy;
static void stbte__dump_colorstate(void)
{
int i,j,k;

View File

@ -1,5 +1,5 @@
// stb_truetype.h - v1.24 - public domain
// authored from 2009-2020 by Sean Barrett / RAD Game Tools
// stb_truetype.h - v1.26 - public domain
// authored from 2009-2021 by Sean Barrett / RAD Game Tools
//
// =======================================================================
//
@ -58,6 +58,8 @@
//
// VERSION HISTORY
//
// 1.26 (2021-08-28) fix broken rasterizer
// 1.25 (2021-07-11) many fixes
// 1.24 (2020-02-05) fix warning
// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
@ -270,8 +272,8 @@
//// SAMPLE PROGRAMS
////
//
// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
//
// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless.
// See "tests/truetype_demo_win32.c" for a complete version.
#if 0
#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
#include "stb_truetype.h"
@ -306,10 +308,10 @@ void my_stbtt_print(float x, float y, char *text)
if (*text >= 32 && *text < 128) {
stbtt_aligned_quad q;
stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0);
glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0);
glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1);
glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1);
}
++text;
}
@ -855,6 +857,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
// frees the data allocated above
STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
// fills svg with the character's SVG data.
@ -1873,7 +1876,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
if (comp_verts) STBTT_free(comp_verts, info->userdata);
return 0;
}
if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
if (vertices) STBTT_free(vertices, info->userdata);
vertices = tmp;
@ -2136,7 +2139,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
has_subrs = 1;
}
// fallthrough
// FALLTHROUGH
case 0x1D: // callgsubr
if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
v = (int) s[--sp];
@ -2241,7 +2244,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
} break;
default:
if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254))
if (b0 != 255 && b0 != 28 && b0 < 32)
return STBTT__CSERR("reserved operator");
// push immediate
@ -2353,7 +2356,7 @@ STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningent
return length;
}
static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
{
stbtt_uint8 *data = info->data + info->kern;
stbtt_uint32 needle, straw;
@ -2383,243 +2386,225 @@ static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph
return 0;
}
static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
{
stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
switch(coverageFormat) {
case 1: {
stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
switch (coverageFormat) {
case 1: {
stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
// Binary search.
stbtt_int32 l=0, r=glyphCount-1, m;
int straw, needle=glyph;
while (l <= r) {
stbtt_uint8 *glyphArray = coverageTable + 4;
stbtt_uint16 glyphID;
m = (l + r) >> 1;
glyphID = ttUSHORT(glyphArray + 2 * m);
straw = glyphID;
if (needle < straw)
r = m - 1;
else if (needle > straw)
l = m + 1;
else {
return m;
}
// Binary search.
stbtt_int32 l=0, r=glyphCount-1, m;
int straw, needle=glyph;
while (l <= r) {
stbtt_uint8 *glyphArray = coverageTable + 4;
stbtt_uint16 glyphID;
m = (l + r) >> 1;
glyphID = ttUSHORT(glyphArray + 2 * m);
straw = glyphID;
if (needle < straw)
r = m - 1;
else if (needle > straw)
l = m + 1;
else {
return m;
}
} break;
}
break;
}
case 2: {
stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
stbtt_uint8 *rangeArray = coverageTable + 4;
case 2: {
stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
stbtt_uint8 *rangeArray = coverageTable + 4;
// Binary search.
stbtt_int32 l=0, r=rangeCount-1, m;
int strawStart, strawEnd, needle=glyph;
while (l <= r) {
stbtt_uint8 *rangeRecord;
m = (l + r) >> 1;
rangeRecord = rangeArray + 6 * m;
strawStart = ttUSHORT(rangeRecord);
strawEnd = ttUSHORT(rangeRecord + 2);
if (needle < strawStart)
r = m - 1;
else if (needle > strawEnd)
l = m + 1;
else {
stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
return startCoverageIndex + glyph - strawStart;
}
// Binary search.
stbtt_int32 l=0, r=rangeCount-1, m;
int strawStart, strawEnd, needle=glyph;
while (l <= r) {
stbtt_uint8 *rangeRecord;
m = (l + r) >> 1;
rangeRecord = rangeArray + 6 * m;
strawStart = ttUSHORT(rangeRecord);
strawEnd = ttUSHORT(rangeRecord + 2);
if (needle < strawStart)
r = m - 1;
else if (needle > strawEnd)
l = m + 1;
else {
stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
return startCoverageIndex + glyph - strawStart;
}
} break;
}
break;
}
default: {
// There are no other cases.
STBTT_assert(0);
} break;
}
default: return -1; // unsupported
}
return -1;
return -1;
}
static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
{
stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
switch(classDefFormat)
{
case 1: {
stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
switch (classDefFormat)
{
case 1: {
stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
break;
}
classDefTable = classDef1ValueArray + 2 * glyphCount;
} break;
case 2: {
stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
stbtt_uint8 *classRangeRecords = classDefTable + 4;
case 2: {
stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
stbtt_uint8 *classRangeRecords = classDefTable + 4;
// Binary search.
stbtt_int32 l=0, r=classRangeCount-1, m;
int strawStart, strawEnd, needle=glyph;
while (l <= r) {
stbtt_uint8 *classRangeRecord;
m = (l + r) >> 1;
classRangeRecord = classRangeRecords + 6 * m;
strawStart = ttUSHORT(classRangeRecord);
strawEnd = ttUSHORT(classRangeRecord + 2);
if (needle < strawStart)
r = m - 1;
else if (needle > strawEnd)
l = m + 1;
else
return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
}
break;
}
// Binary search.
stbtt_int32 l=0, r=classRangeCount-1, m;
int strawStart, strawEnd, needle=glyph;
while (l <= r) {
stbtt_uint8 *classRangeRecord;
m = (l + r) >> 1;
classRangeRecord = classRangeRecords + 6 * m;
strawStart = ttUSHORT(classRangeRecord);
strawEnd = ttUSHORT(classRangeRecord + 2);
if (needle < strawStart)
r = m - 1;
else if (needle > strawEnd)
l = m + 1;
else
return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
}
default:
return -1; // Unsupported definition type, return an error.
}
classDefTable = classRangeRecords + 6 * classRangeCount;
} break;
default: {
// There are no other cases.
STBTT_assert(0);
} break;
}
return -1;
// "All glyphs not assigned to a class fall into class 0". (OpenType spec)
return 0;
}
// Define to STBTT_assert(x) if you want to break on unimplemented formats.
#define STBTT_GPOS_TODO_assert(x)
static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
{
stbtt_uint16 lookupListOffset;
stbtt_uint8 *lookupList;
stbtt_uint16 lookupCount;
stbtt_uint8 *data;
stbtt_int32 i;
stbtt_uint16 lookupListOffset;
stbtt_uint8 *lookupList;
stbtt_uint16 lookupCount;
stbtt_uint8 *data;
stbtt_int32 i, sti;
if (!info->gpos) return 0;
if (!info->gpos) return 0;
data = info->data + info->gpos;
data = info->data + info->gpos;
if (ttUSHORT(data+0) != 1) return 0; // Major version 1
if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
if (ttUSHORT(data+0) != 1) return 0; // Major version 1
if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
lookupListOffset = ttUSHORT(data+8);
lookupList = data + lookupListOffset;
lookupCount = ttUSHORT(lookupList);
lookupListOffset = ttUSHORT(data+8);
lookupList = data + lookupListOffset;
lookupCount = ttUSHORT(lookupList);
for (i=0; i<lookupCount; ++i) {
stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
stbtt_uint8 *lookupTable = lookupList + lookupOffset;
for (i=0; i<lookupCount; ++i) {
stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
stbtt_uint8 *lookupTable = lookupList + lookupOffset;
stbtt_uint16 lookupType = ttUSHORT(lookupTable);
stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
stbtt_uint8 *subTableOffsets = lookupTable + 6;
switch(lookupType) {
case 2: { // Pair Adjustment Positioning Subtable
stbtt_int32 sti;
for (sti=0; sti<subTableCount; sti++) {
stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
stbtt_uint8 *table = lookupTable + subtableOffset;
stbtt_uint16 posFormat = ttUSHORT(table);
stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
if (coverageIndex == -1) continue;
stbtt_uint16 lookupType = ttUSHORT(lookupTable);
stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
stbtt_uint8 *subTableOffsets = lookupTable + 6;
if (lookupType != 2) // Pair Adjustment Positioning Subtable
continue;
switch (posFormat) {
case 1: {
stbtt_int32 l, r, m;
int straw, needle;
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
stbtt_int32 valueRecordPairSizeInBytes = 2;
stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
stbtt_uint8 *pairValueTable = table + pairPosOffset;
stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
stbtt_uint8 *pairValueArray = pairValueTable + 2;
// TODO: Support more formats.
STBTT_GPOS_TODO_assert(valueFormat1 == 4);
if (valueFormat1 != 4) return 0;
STBTT_GPOS_TODO_assert(valueFormat2 == 0);
if (valueFormat2 != 0) return 0;
for (sti=0; sti<subTableCount; sti++) {
stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
stbtt_uint8 *table = lookupTable + subtableOffset;
stbtt_uint16 posFormat = ttUSHORT(table);
stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
if (coverageIndex == -1) continue;
STBTT_assert(coverageIndex < pairSetCount);
STBTT__NOTUSED(pairSetCount);
switch (posFormat) {
case 1: {
stbtt_int32 l, r, m;
int straw, needle;
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
stbtt_int32 valueRecordPairSizeInBytes = 2;
stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
stbtt_uint8 *pairValueTable = table + pairPosOffset;
stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
stbtt_uint8 *pairValueArray = pairValueTable + 2;
needle=glyph2;
r=pairValueCount-1;
l=0;
if (coverageIndex >= pairSetCount) return 0;
// Binary search.
while (l <= r) {
stbtt_uint16 secondGlyph;
stbtt_uint8 *pairValue;
m = (l + r) >> 1;
pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
secondGlyph = ttUSHORT(pairValue);
straw = secondGlyph;
if (needle < straw)
r = m - 1;
else if (needle > straw)
l = m + 1;
else {
stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
return xAdvance;
}
}
} break;
needle=glyph2;
r=pairValueCount-1;
l=0;
case 2: {
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
// Binary search.
while (l <= r) {
stbtt_uint16 secondGlyph;
stbtt_uint8 *pairValue;
m = (l + r) >> 1;
pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
secondGlyph = ttUSHORT(pairValue);
straw = secondGlyph;
if (needle < straw)
r = m - 1;
else if (needle > straw)
l = m + 1;
else {
stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
return xAdvance;
}
}
} else
return 0;
break;
}
stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
case 2: {
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
stbtt_uint16 class1Count = ttUSHORT(table + 12);
stbtt_uint16 class2Count = ttUSHORT(table + 14);
STBTT_assert(glyph1class < class1Count);
STBTT_assert(glyph2class < class2Count);
stbtt_uint16 class1Count = ttUSHORT(table + 12);
stbtt_uint16 class2Count = ttUSHORT(table + 14);
stbtt_uint8 *class1Records, *class2Records;
stbtt_int16 xAdvance;
// TODO: Support more formats.
STBTT_GPOS_TODO_assert(valueFormat1 == 4);
if (valueFormat1 != 4) return 0;
STBTT_GPOS_TODO_assert(valueFormat2 == 0);
if (valueFormat2 != 0) return 0;
if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed
if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed
if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
stbtt_uint8 *class1Records = table + 16;
stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
return xAdvance;
}
} break;
default: {
// There are no other cases.
STBTT_assert(0);
break;
};
}
}
break;
};
class1Records = table + 16;
class2Records = class1Records + 2 * (glyph1class * class2Count);
xAdvance = ttSHORT(class2Records + 2 * glyph2class);
return xAdvance;
} else
return 0;
break;
}
default:
// TODO: Implement other stuff.
break;
}
}
return 0; // Unsupported position format
}
}
}
return 0;
return 0;
}
STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
@ -3077,6 +3062,23 @@ static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edg
}
}
static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
{
STBTT_assert(top_width >= 0);
STBTT_assert(bottom_width >= 0);
return (top_width + bottom_width) / 2.0f * height;
}
static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
{
return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
}
static float stbtt__sized_triangle_area(float height, float width)
{
return height * width / 2;
}
static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
{
float y_bottom = y_top+1;
@ -3131,13 +3133,13 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
float height;
// simple case, only spans one pixel
int x = (int) x_top;
height = sy1 - sy0;
height = (sy1 - sy0) * e->direction;
STBTT_assert(x >= 0 && x < len);
scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);
scanline_fill[x] += height; // everything right of this pixel is filled
} else {
int x,x1,x2;
float y_crossing, step, sign, area;
float y_crossing, y_final, step, sign, area;
// covers 2+ pixels
if (x_top > x_bottom) {
// flip scanline vertically; signed area is the same
@ -3150,29 +3152,79 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
dy = -dy;
t = x0, x0 = xb, xb = t;
}
STBTT_assert(dy >= 0);
STBTT_assert(dx >= 0);
x1 = (int) x_top;
x2 = (int) x_bottom;
// compute intersection with y axis at x1+1
y_crossing = (x1+1 - x0) * dy + y_top;
y_crossing = y_top + dy * (x1+1 - x0);
// compute intersection with y axis at x2
y_final = y_top + dy * (x2 - x0);
// x1 x_top x2 x_bottom
// y_top +------|-----+------------+------------+--------|---+------------+
// | | | | | |
// | | | | | |
// sy0 | Txxxxx|............|............|............|............|
// y_crossing | *xxxxx.......|............|............|............|
// | | xxxxx..|............|............|............|
// | | /- xx*xxxx........|............|............|
// | | dy < | xxxxxx..|............|............|
// y_final | | \- | xx*xxx.........|............|
// sy1 | | | | xxxxxB...|............|
// | | | | | |
// | | | | | |
// y_bottom +------------+------------+------------+------------+------------+
//
// goal is to measure the area covered by '.' in each pixel
// if x2 is right at the right edge of x1, y_crossing can blow up, github #1057
// @TODO: maybe test against sy1 rather than y_bottom?
if (y_crossing > y_bottom)
y_crossing = y_bottom;
sign = e->direction;
// area of the rectangle covered from y0..y_crossing
area = sign * (y_crossing-sy0);
// area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
step = sign * dy;
// area of the rectangle covered from sy0..y_crossing
area = sign * (y_crossing-sy0);
// area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing)
scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);
// check if final y_crossing is blown up; no test case for this
if (y_final > y_bottom) {
y_final = y_bottom;
dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom
}
// in second pixel, area covered by line segment found in first pixel
// is always a rectangle 1 wide * the height of that line segment; this
// is exactly what the variable 'area' stores. it also gets a contribution
// from the line segment within it. the THIRD pixel will get the first
// pixel's rectangle contribution, the second pixel's rectangle contribution,
// and its own contribution. the 'own contribution' is the same in every pixel except
// the leftmost and rightmost, a trapezoid that slides down in each pixel.
// the second pixel's contribution to the third pixel will be the
// rectangle 1 wide times the height change in the second pixel, which is dy.
step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x,
// which multiplied by 1-pixel-width is how much pixel area changes for each step in x
// so the area advances by 'step' every time
for (x = x1+1; x < x2; ++x) {
scanline[x] += area + step/2;
scanline[x] += area + step/2; // area of trapezoid is 1*step/2
area += step;
}
y_crossing += dy * (x2 - (x1+1));
STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down
STBTT_assert(sy1 > y_final-0.01f);
STBTT_assert(STBTT_fabs(area) <= 1.01f);
scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
// area covered in the last pixel is the rectangle from all the pixels to the left,
// plus the trapezoid filled by the line segment in this pixel all the way to the right edge
scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);
// the rest of the line is filled based on the total height of the line segment in this pixel
scanline_fill[x2] += sign * (sy1-sy0);
}
} else {
@ -3180,6 +3232,9 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
// clipping logic. since this does not match the intended use
// of this library, we use a different, very slow brute
// force implementation
// note though that this does happen some of the time because
// x_top and x_bottom can be extrapolated at the top & bottom of
// the shape and actually lie outside the bounding box
int x;
for (x=0; x < len; ++x) {
// cases:
@ -4416,15 +4471,14 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
float y_frac;
int winding = 0;
orig[0] = x;
orig[1] = y;
// make sure y never passes through a vertex of the shape
y_frac = (float) STBTT_fmod(y, 1.0f);
if (y_frac < 0.01f)
y += 0.01f;
else if (y_frac > 0.99f)
y -= 0.01f;
orig[0] = x;
orig[1] = y;
// test a ray from (-infinity,y) to (x,y)
@ -4486,35 +4540,35 @@ static float stbtt__cuberoot( float x )
return (float) STBTT_pow( x,1.0f/3.0f);
}
// x^3 + c*x^2 + b*x + a = 0
// x^3 + a*x^2 + b*x + c = 0
static int stbtt__solve_cubic(float a, float b, float c, float* r)
{
float s = -a / 3;
float p = b - a*a / 3;
float q = a * (2*a*a - 9*b) / 27 + c;
float s = -a / 3;
float p = b - a*a / 3;
float q = a * (2*a*a - 9*b) / 27 + c;
float p3 = p*p*p;
float d = q*q + 4*p3 / 27;
if (d >= 0) {
float z = (float) STBTT_sqrt(d);
float u = (-q + z) / 2;
float v = (-q - z) / 2;
u = stbtt__cuberoot(u);
v = stbtt__cuberoot(v);
r[0] = s + u + v;
return 1;
} else {
float u = (float) STBTT_sqrt(-p/3);
float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
float m = (float) STBTT_cos(v);
float d = q*q + 4*p3 / 27;
if (d >= 0) {
float z = (float) STBTT_sqrt(d);
float u = (-q + z) / 2;
float v = (-q - z) / 2;
u = stbtt__cuberoot(u);
v = stbtt__cuberoot(v);
r[0] = s + u + v;
return 1;
} else {
float u = (float) STBTT_sqrt(-p/3);
float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
float m = (float) STBTT_cos(v);
float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
r[0] = s + u * 2 * m;
r[1] = s - u * (m + n);
r[2] = s - u * (m - n);
r[0] = s + u * 2 * m;
r[1] = s - u * (m + n);
r[2] = s - u * (m - n);
//STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe?
//STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
//STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
return 3;
return 3;
}
}
@ -4593,18 +4647,17 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
for (i=0; i < num_verts; ++i) {
float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
// check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve
float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
if (dist2 < min_dist*min_dist)
min_dist = (float) STBTT_sqrt(dist2);
if (verts[i].type == STBTT_vline) {
if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
if (dist2 < min_dist*min_dist)
min_dist = (float) STBTT_sqrt(dist2);
// coarse culling against bbox
//if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
// sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
STBTT_assert(i != 0);
if (dist < min_dist) {
// check position along line
@ -4631,7 +4684,8 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
float ax = x1-x0, ay = y1-y0;
float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
float mx = x0 - sx, my = y0 - sy;
float res[3],px,py,t,it;
float res[3] = {0.f,0.f,0.f};
float px,py,t,it,dist2;
float a_inv = precompute[i];
if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
float a = 3*(ax*bx + ay*by);
@ -4658,6 +4712,10 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
float d = (mx*ax+my*ay) * a_inv;
num = stbtt__solve_cubic(b, c, d, res);
}
dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
if (dist2 < min_dist*min_dist)
min_dist = (float) STBTT_sqrt(dist2);
if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
t = res[0], it = 1.0f - t;
px = it*it*x0 + 2*t*it*x1 + t*t*x2;
@ -4917,6 +4975,12 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const
// FULL VERSION HISTORY
//
// 1.25 (2021-07-11) many fixes
// 1.24 (2020-02-05) fix warning
// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
// 1.21 (2019-02-25) fix warning
// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
// 1.18 (2018-01-29) add missing function
// 1.17 (2017-07-23) make more arguments const; doc fix

View File

@ -1,4 +1,4 @@
// Ogg Vorbis audio decoder - v1.21 - public domain
// Ogg Vorbis audio decoder - v1.22 - public domain
// http://nothings.org/stb_vorbis/
//
// Original version written by Sean Barrett in 2007.
@ -29,13 +29,14 @@
// Bernhard Wodo Evan Balster github:alxprd
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// Phillip Bennefall Rohit Thiago Goulart
// github:manxorist saga musix github:infatum
// github:manxorist Saga Musix github:infatum
// Timur Gagiev Maxwell Koo Peter Waller
// github:audinowho Dougall Johnson David Reid
// github:Clownacy Pedro J. Estebanez Remi Verschelde
// AnthoFoxo
// AnthoFoxo github:morlat Gabriel Ravier
//
// Partial history:
// 1.22 - 2021-07-11 - various small fixes
// 1.21 - 2021-07-02 - fix bug for files with no comments
// 1.20 - 2020-07-11 - several small fixes
// 1.19 - 2020-02-05 - warnings
@ -222,6 +223,12 @@ extern int stb_vorbis_decode_frame_pushdata(
// channel. In other words, (*output)[0][0] contains the first sample from
// the first channel, and (*output)[1][0] contains the first sample from
// the second channel.
//
// *output points into stb_vorbis's internal output buffer storage; these
// buffers are owned by stb_vorbis and application code should not free
// them or modify their contents. They are transient and will be overwritten
// once you ask for more data to get decoded, so be sure to grab any data
// you need before then.
extern void stb_vorbis_flush_pushdata(stb_vorbis *f);
// inform stb_vorbis that your next datablock will not be contiguous with
@ -581,7 +588,7 @@ enum STBVorbisError
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <malloc.h>
#endif
#if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) || defined(__NEWLIB__)
#if defined(__linux__) || defined(__linux) || defined(__sun__) || defined(__EMSCRIPTEN__) || defined(__NEWLIB__)
#include <alloca.h>
#endif
#else // STB_VORBIS_NO_CRT
@ -648,6 +655,12 @@ typedef signed int int32;
typedef float codetype;
#ifdef _MSC_VER
#define STBV_NOTUSED(v) (void)(v)
#else
#define STBV_NOTUSED(v) (void)sizeof(v)
#endif
// @NOTE
//
// Some arrays below are tagged "//varies", which means it's actually
@ -1048,7 +1061,7 @@ static float float32_unpack(uint32 x)
uint32 sign = x & 0x80000000;
uint32 exp = (x & 0x7fe00000) >> 21;
double res = sign ? -(double)mantissa : (double)mantissa;
return (float) ldexp((float)res, exp-788);
return (float) ldexp((float)res, (int)exp-788);
}
@ -1079,6 +1092,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
// find the first entry
for (k=0; k < n; ++k) if (len[k] < NO_CODE) break;
if (k == n) { assert(c->sorted_entries == 0); return TRUE; }
assert(len[k] < 32); // no error return required, code reading lens checks this
// add to the list
add_entry(c, 0, k, m++, len[k], values);
// add all available leaves
@ -1092,6 +1106,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
uint32 res;
int z = len[i], y;
if (z == NO_CODE) continue;
assert(z < 32); // no error return required, code reading lens checks this
// find lowest available leaf (should always be earliest,
// which is what the specification calls for)
// note that this property, and the fact we can never have
@ -1101,12 +1116,10 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
while (z > 0 && !available[z]) --z;
if (z == 0) { return FALSE; }
res = available[z];
assert(z >= 0 && z < 32);
available[z] = 0;
add_entry(c, bit_reverse(res), i, m++, len[i], values);
// propagate availability up the tree
if (z != len[i]) {
assert(len[i] >= 0 && len[i] < 32);
for (y=len[i]; y > z; --y) {
assert(available[y] == 0);
available[y] = res + (1 << (32-y));
@ -2579,34 +2592,33 @@ static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A,
while (z > base) {
float k00,k11;
float l00,l11;
k00 = z[-0] - z[-8];
k11 = z[-1] - z[-9];
z[-0] = z[-0] + z[-8];
z[-1] = z[-1] + z[-9];
z[-8] = k00;
z[-9] = k11 ;
k00 = z[-0] - z[ -8];
k11 = z[-1] - z[ -9];
l00 = z[-2] - z[-10];
l11 = z[-3] - z[-11];
z[ -0] = z[-0] + z[ -8];
z[ -1] = z[-1] + z[ -9];
z[ -2] = z[-2] + z[-10];
z[ -3] = z[-3] + z[-11];
z[ -8] = k00;
z[ -9] = k11;
z[-10] = (l00+l11) * A2;
z[-11] = (l11-l00) * A2;
k00 = z[ -2] - z[-10];
k11 = z[ -3] - z[-11];
z[ -2] = z[ -2] + z[-10];
z[ -3] = z[ -3] + z[-11];
z[-10] = (k00+k11) * A2;
z[-11] = (k11-k00) * A2;
k00 = z[-12] - z[ -4]; // reverse to avoid a unary negation
k00 = z[ -4] - z[-12];
k11 = z[ -5] - z[-13];
l00 = z[ -6] - z[-14];
l11 = z[ -7] - z[-15];
z[ -4] = z[ -4] + z[-12];
z[ -5] = z[ -5] + z[-13];
z[-12] = k11;
z[-13] = k00;
k00 = z[-14] - z[ -6]; // reverse to avoid a unary negation
k11 = z[ -7] - z[-15];
z[ -6] = z[ -6] + z[-14];
z[ -7] = z[ -7] + z[-15];
z[-14] = (k00+k11) * A2;
z[-15] = (k00-k11) * A2;
z[-12] = k11;
z[-13] = -k00;
z[-14] = (l11-l00) * A2;
z[-15] = (l00+l11) * -A2;
iter_54(z);
iter_54(z-8);
@ -3071,6 +3083,7 @@ static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *f
for (q=1; q < g->values; ++q) {
j = g->sorted_order[q];
#ifndef STB_VORBIS_NO_DEFER_FLOOR
STBV_NOTUSED(step2_flag);
if (finalY[j] >= 0)
#else
if (step2_flag[j])
@ -3173,6 +3186,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
// WINDOWING
STBV_NOTUSED(left_end);
n = f->blocksize[m->blockflag];
map = &f->mapping[m->mapping];
@ -3370,7 +3384,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
// this isn't to spec, but spec would require us to read ahead
// and decode the size of all current frames--could be done,
// but presumably it's not a commonly used feature
f->current_loc = -n2; // start of first frame is positioned for discard
f->current_loc = 0u - n2; // start of first frame is positioned for discard (NB this is an intentional unsigned overflow/wrap-around)
// we might have to discard samples "from" the next frame too,
// if we're lapping a large block then a small at the start?
f->discard_samples_deferred = n - right_end;
@ -3871,8 +3885,7 @@ static int start_decoder(vorb *f)
unsigned int div=1;
for (k=0; k < c->dimensions; ++k) {
int off = (z / div) % c->lookup_values;
float val = mults[off];
val = mults[off]*c->delta_value + c->minimum_value + last;
float val = mults[off]*c->delta_value + c->minimum_value + last;
c->multiplicands[j*c->dimensions + k] = val;
if (c->sequence_p)
last = val;
@ -3955,7 +3968,7 @@ static int start_decoder(vorb *f)
if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
}
for (k=0; k < 1 << g->class_subclasses[j]; ++k) {
g->subclass_books[j][k] = get_bits(f,8)-1;
g->subclass_books[j][k] = (int16)get_bits(f,8)-1;
if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
}
}
@ -4513,6 +4526,7 @@ stb_vorbis *stb_vorbis_open_pushdata(
*error = VORBIS_need_more_data;
else
*error = p.error;
vorbis_deinit(&p);
return NULL;
}
f = vorbis_alloc(&p);
@ -4570,7 +4584,7 @@ static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last)
header[i] = get8(f);
if (f->eof) return 0;
if (header[4] != 0) goto invalid;
goal = header[22] + (header[23] << 8) + (header[24]<<16) + (header[25]<<24);
goal = header[22] + (header[23] << 8) + (header[24]<<16) + ((uint32)header[25]<<24);
for (i=22; i < 26; ++i)
header[i] = 0;
crc = 0;
@ -4974,7 +4988,7 @@ unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f)
// set. whoops!
break;
}
previous_safe = last_page_loc+1;
//previous_safe = last_page_loc+1; // NOTE: not used after this point, but note for debugging
last_page_loc = stb_vorbis_get_file_offset(f);
}
@ -5085,7 +5099,10 @@ stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const st
stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc)
{
stb_vorbis *f, p;
if (data == NULL) return NULL;
if (!data) {
if (error) *error = VORBIS_unexpected_eof;
return NULL;
}
vorbis_init(&p, alloc);
p.stream = (uint8 *) data;
p.stream_end = (uint8 *) data + len;
@ -5160,11 +5177,11 @@ static void copy_samples(short *dest, float *src, int len)
static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len)
{
#define BUFFER_SIZE 32
float buffer[BUFFER_SIZE];
int i,j,o,n = BUFFER_SIZE;
#define STB_BUFFER_SIZE 32
float buffer[STB_BUFFER_SIZE];
int i,j,o,n = STB_BUFFER_SIZE;
check_endianness();
for (o = 0; o < len; o += BUFFER_SIZE) {
for (o = 0; o < len; o += STB_BUFFER_SIZE) {
memset(buffer, 0, sizeof(buffer));
if (o + n > len) n = len - o;
for (j=0; j < num_c; ++j) {
@ -5181,16 +5198,17 @@ static void compute_samples(int mask, short *output, int num_c, float **data, in
output[o+i] = v;
}
}
#undef STB_BUFFER_SIZE
}
static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len)
{
#define BUFFER_SIZE 32
float buffer[BUFFER_SIZE];
int i,j,o,n = BUFFER_SIZE >> 1;
#define STB_BUFFER_SIZE 32
float buffer[STB_BUFFER_SIZE];
int i,j,o,n = STB_BUFFER_SIZE >> 1;
// o is the offset in the source data
check_endianness();
for (o = 0; o < len; o += BUFFER_SIZE >> 1) {
for (o = 0; o < len; o += STB_BUFFER_SIZE >> 1) {
// o2 is the offset in the output data
int o2 = o << 1;
memset(buffer, 0, sizeof(buffer));
@ -5220,6 +5238,7 @@ static void compute_stereo_samples(short *output, int num_c, float **data, int d
output[o2+i] = v;
}
}
#undef STB_BUFFER_SIZE
}
static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples)
@ -5292,8 +5311,6 @@ int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short
float **outputs;
int len = num_shorts / channels;
int n=0;
int z = f->channels;
if (z > channels) z = channels;
while (n < len) {
int k = f->channel_buffer_end - f->channel_buffer_start;
if (n+k >= len) k = len - n;
@ -5312,8 +5329,6 @@ int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, in
{
float **outputs;
int n=0;
int z = f->channels;
if (z > channels) z = channels;
while (n < len) {
int k = f->channel_buffer_end - f->channel_buffer_start;
if (n+k >= len) k = len - n;

View File

@ -39,9 +39,10 @@ RSC=rc.exe
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
# ADD CPP /nologo /W3 /GX /Zi /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
@ -50,7 +51,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
!ELSEIF "$(CFG)" == "image_test - Win32 Debug"

View File

@ -15,11 +15,15 @@ find $SRC/stb/tests/pngsuite -name "*.png" | \
cp $SRC/stb/tests/stb_png.dict $OUT/stb_png_read_fuzzer.dict
tar xvzf $SRC/stb/jpg.tar.gz --directory $SRC/stb/tests
tar xvzf $SRC/stb/gif.tar.gz --directory $SRC/stb/tests
tar xvzf $SRC/stbi/jpg.tar.gz --directory $SRC/stb/tests
tar xvzf $SRC/stbi/gif.tar.gz --directory $SRC/stb/tests
unzip $SRC/stbi/bmp.zip -d $SRC/stb/tests
unzip $SRC/stbi/tga.zip -d $SRC/stb/tests
find $SRC/stb/tests -name "*.png" -o -name "*.jpg" -o -name ".gif" | \
xargs zip $OUT/stbi_read_fuzzer_seed_corpus.zip
find $SRC/stb/tests -name "*.png" -o -name "*.jpg" -o -name "*.gif" \
-o -name "*.bmp" -o -name "*.tga" -o -name "*.TGA" \
-o -name "*.ppm" -o -name "*.pgm" \
| xargs zip $OUT/stbi_read_fuzzer_seed_corpus.zip
echo "" >> $SRC/stb/tests/gif.dict
cat $SRC/stb/tests/gif.dict $SRC/stb/tests/stb_png.dict > $OUT/stbi_read_fuzzer.dict
echo "" >> $SRC/stbi/gif.dict
cat $SRC/stbi/gif.dict $SRC/stb/tests/stb_png.dict > $OUT/stbi_read_fuzzer.dict

BIN
tests/pbm/basi0g16.pgm Normal file

Binary file not shown.

BIN
tests/pbm/basi2c16.ppm Normal file

Binary file not shown.

BIN
tests/pbm/cdfn2c08.ppm Normal file

Binary file not shown.

BIN
tests/pbm/cdun2c08.ppm Normal file

Binary file not shown.

BIN
tests/pbm/comment.pgm Normal file

Binary file not shown.

BIN
tests/pbm/ctfn0g04.pgm Normal file

Binary file not shown.

View File

@ -0,0 +1,259 @@
filename,width,height,ncomp,error,hash
pngsuite/16bit/basi0g16.png,32,32,1,,0xfc8f2f99
pngsuite/16bit/basi2c16.png,32,32,3,,0x65567ed5
pngsuite/16bit/basi4a16.png,32,32,2,,0x198cf245
pngsuite/16bit/basi6a16.png,32,32,4,,0x3016e9b5
pngsuite/16bit/basn0g16.png,32,32,1,,0xfc8f2f99
pngsuite/16bit/basn2c16.png,32,32,3,,0x65567ed5
pngsuite/16bit/basn4a16.png,32,32,2,,0x198cf245
pngsuite/16bit/basn6a16.png,32,32,4,,0x3016e9b5
pngsuite/16bit/bgai4a16.png,32,32,2,,0x198cf245
pngsuite/16bit/bgan6a16.png,32,32,4,,0x3016e9b5
pngsuite/16bit/bggn4a16.png,32,32,2,,0x198cf245
pngsuite/16bit/bgyn6a16.png,32,32,4,,0x3016e9b5
pngsuite/16bit/oi1n0g16.png,32,32,1,,0xfc8f2f99
pngsuite/16bit/oi1n2c16.png,32,32,3,,0x65567ed5
pngsuite/16bit/oi2n0g16.png,32,32,1,,0xfc8f2f99
pngsuite/16bit/oi2n2c16.png,32,32,3,,0x65567ed5
pngsuite/16bit/oi4n0g16.png,32,32,1,,0xfc8f2f99
pngsuite/16bit/oi4n2c16.png,32,32,3,,0x65567ed5
pngsuite/16bit/oi9n0g16.png,32,32,1,,0xfc8f2f99
pngsuite/16bit/oi9n2c16.png,32,32,3,,0x65567ed5
pngsuite/16bit/tbbn2c16.png,32,32,4,,0xaa9bfe44
pngsuite/16bit/tbgn2c16.png,32,32,4,,0xaa9bfe44
pngsuite/16bit/tbwn0g16.png,32,32,2,,0x075e519a
pngsuite/corrupt/xc1n0g08.png,32,32,2,bad ctype,0x00000000
pngsuite/corrupt/xc9n2c08.png,32,32,2,bad ctype,0x00000000
pngsuite/corrupt/xcrn0g04.png,32,32,2,unknown image type,0x00000000
pngsuite/corrupt/xcsn0g01.png,32,32,1,,0x43b9891f
pngsuite/corrupt/xd0n2c08.png,32,32,1,1/2/4/8/16-bit only,0x00000000
pngsuite/corrupt/xd3n2c08.png,32,32,1,1/2/4/8/16-bit only,0x00000000
pngsuite/corrupt/xd9n2c08.png,32,32,1,1/2/4/8/16-bit only,0x00000000
pngsuite/corrupt/xdtn0g01.png,32,32,1,no IDAT,0x00000000
pngsuite/corrupt/xhdn0g08.png,32,32,1,,0x414f1ca9
pngsuite/corrupt/xlfn0g04.png,32,32,1,unknown image type,0x00000000
pngsuite/corrupt/xs1n0g01.png,32,32,1,unknown image type,0x00000000
pngsuite/corrupt/xs2n0g01.png,32,32,1,unknown image type,0x00000000
pngsuite/corrupt/xs4n0g01.png,32,32,1,unknown image type,0x00000000
pngsuite/corrupt/xs7n0g01.png,32,32,1,unknown image type,0x00000000
pngsuite/iphone/iphone_basi0g01.png,32,32,4,,0x5fb33cfd
pngsuite/iphone/iphone_basi0g02.png,32,32,4,,0x5bbe95c5
pngsuite/iphone/iphone_basi3p02.png,32,32,4,,0x50ba29c5
pngsuite/iphone/iphone_bgwn6a08.png,32,32,4,,0x45d8548a
pngsuite/iphone/iphone_bgyn6a16.png,32,32,4,,0x4b2b7545
pngsuite/iphone/iphone_tbyn3p08.png,32,32,4,,0x8ea9aaaf
pngsuite/iphone/iphone_z06n2c08.png,32,32,4,,0xb5dd034b
pngsuite/primary/basi0g01.png,32,32,1,,0x43b9891f
pngsuite/primary/basi0g02.png,32,32,1,,0xaf0bb3c5
pngsuite/primary/basi0g04.png,32,32,1,,0x6fbaeb45
pngsuite/primary/basi0g08.png,32,32,1,,0x414f1ca9
pngsuite/primary/basi2c08.png,32,32,3,,0x522345c5
pngsuite/primary/basi3p01.png,32,32,3,,0x9c5b75c5
pngsuite/primary/basi3p02.png,32,32,3,,0x46f26ec5
pngsuite/primary/basi3p04.png,32,32,3,,0x35b2e4a5
pngsuite/primary/basi3p08.png,32,32,3,,0xfe066865
pngsuite/primary/basi4a08.png,32,32,2,,0x77cbbfa5
pngsuite/primary/basi6a08.png,32,32,4,,0xb472197d
pngsuite/primary/basn0g01.png,32,32,1,,0x43b9891f
pngsuite/primary/basn0g02.png,32,32,1,,0xaf0bb3c5
pngsuite/primary/basn0g04.png,32,32,1,,0x6fbaeb45
pngsuite/primary/basn0g08.png,32,32,1,,0x414f1ca9
pngsuite/primary/basn2c08.png,32,32,3,,0x522345c5
pngsuite/primary/basn3p01.png,32,32,3,,0x9c5b75c5
pngsuite/primary/basn3p02.png,32,32,3,,0x46f26ec5
pngsuite/primary/basn3p04.png,32,32,3,,0x35b2e4a5
pngsuite/primary/basn3p08.png,32,32,3,,0xfe066865
pngsuite/primary/basn4a08.png,32,32,2,,0x77cbbfa5
pngsuite/primary/basn6a08.png,32,32,4,,0xb472197d
pngsuite/primary/bgai4a08.png,32,32,2,,0x77cbbfa5
pngsuite/primary/bgan6a08.png,32,32,4,,0xb472197d
pngsuite/primary/bgbn4a08.png,32,32,2,,0x77cbbfa5
pngsuite/primary/bgwn6a08.png,32,32,4,,0xb472197d
pngsuite/primary/s01i3p01.png,1,1,3,,0xafb003b6
pngsuite/primary/s01n3p01.png,1,1,3,,0xafb003b6
pngsuite/primary/s02i3p01.png,2,2,3,,0x96f3dd85
pngsuite/primary/s02n3p01.png,2,2,3,,0x96f3dd85
pngsuite/primary/s03i3p01.png,3,3,3,,0xb0cf1241
pngsuite/primary/s03n3p01.png,3,3,3,,0xb0cf1241
pngsuite/primary/s04i3p01.png,4,4,3,,0xbfcedd75
pngsuite/primary/s04n3p01.png,4,4,3,,0xbfcedd75
pngsuite/primary/s05i3p02.png,5,5,3,,0xc322cedd
pngsuite/primary/s05n3p02.png,5,5,3,,0xc322cedd
pngsuite/primary/s06i3p02.png,6,6,3,,0x46916799
pngsuite/primary/s06n3p02.png,6,6,3,,0x46916799
pngsuite/primary/s07i3p02.png,7,7,3,,0xfdabc297
pngsuite/primary/s07n3p02.png,7,7,3,,0xfdabc297
pngsuite/primary/s08i3p02.png,8,8,3,,0x8f036d09
pngsuite/primary/s08n3p02.png,8,8,3,,0x8f036d09
pngsuite/primary/s09i3p02.png,9,9,3,,0x16a46830
pngsuite/primary/s09n3p02.png,9,9,3,,0x16a46830
pngsuite/primary/s32i3p04.png,32,32,3,,0x4bd4fbd3
pngsuite/primary/s32n3p04.png,32,32,3,,0x4bd4fbd3
pngsuite/primary/s33i3p04.png,33,33,3,,0x51aa005e
pngsuite/primary/s33n3p04.png,33,33,3,,0x51aa005e
pngsuite/primary/s34i3p04.png,34,34,3,,0x84818775
pngsuite/primary/s34n3p04.png,34,34,3,,0x84818775
pngsuite/primary/s35i3p04.png,35,35,3,,0x6359ec75
pngsuite/primary/s35n3p04.png,35,35,3,,0x6359ec75
pngsuite/primary/s36i3p04.png,36,36,3,,0xe4878065
pngsuite/primary/s36n3p04.png,36,36,3,,0xe4878065
pngsuite/primary/s37i3p04.png,37,37,3,,0x3cefc423
pngsuite/primary/s37n3p04.png,37,37,3,,0x3cefc423
pngsuite/primary/s38i3p04.png,38,38,3,,0xffc55a2b
pngsuite/primary/s38n3p04.png,38,38,3,,0xffc55a2b
pngsuite/primary/s39i3p04.png,39,39,3,,0x0c790240
pngsuite/primary/s39n3p04.png,39,39,3,,0x0c790240
pngsuite/primary/s40i3p04.png,40,40,3,,0x951a316d
pngsuite/primary/s40n3p04.png,40,40,3,,0x951a316d
pngsuite/primary/tbbn0g04.png,32,32,2,,0x9c8410ea
pngsuite/primary/tbbn3p08.png,32,32,4,,0x82bf9a57
pngsuite/primary/tbgn3p08.png,32,32,4,,0x82bf9a57
pngsuite/primary/tbrn2c08.png,32,32,4,,0xaa9bfe44
pngsuite/primary/tbwn3p08.png,32,32,4,,0x82bf9a57
pngsuite/primary/tbyn3p08.png,32,32,4,,0x82bf9a57
pngsuite/primary/tm3n3p02.png,32,32,4,,0xf59745c5
pngsuite/primary/tp0n0g08.png,32,32,1,,0xbac0864c
pngsuite/primary/tp0n2c08.png,32,32,3,,0x82687c37
pngsuite/primary/tp0n3p08.png,32,32,3,,0x61f54e37
pngsuite/primary/tp1n3p08.png,32,32,4,,0x82bf9a57
pngsuite/primary/z00n2c08.png,32,32,3,,0x65b4a72f
pngsuite/primary/z03n2c08.png,32,32,3,,0x65b4a72f
pngsuite/primary/z06n2c08.png,32,32,3,,0x65b4a72f
pngsuite/primary/z09n2c08.png,32,32,3,,0x65b4a72f
pngsuite/primary_check/basi0g01.png,32,32,4,,0x5fb33cfd
pngsuite/primary_check/basi0g02.png,32,32,4,,0x5bbe95c5
pngsuite/primary_check/basi0g04.png,32,32,4,,0x3468b9c5
pngsuite/primary_check/basi0g08.png,32,32,4,,0x262ef46d
pngsuite/primary_check/basi2c08.png,32,32,4,,0x1fc92bc5
pngsuite/primary_check/basi3p01.png,32,32,4,,0x28a3e1c5
pngsuite/primary_check/basi3p02.png,32,32,4,,0x803be5c5
pngsuite/primary_check/basi3p04.png,32,32,4,,0xf3fc60e5
pngsuite/primary_check/basi3p08.png,32,32,4,,0x30ef4f45
pngsuite/primary_check/basi4a08.png,32,32,4,,0x23c8536d
pngsuite/primary_check/basi6a08.png,32,32,4,,0xb472197d
pngsuite/primary_check/basn0g01.png,32,32,4,,0x5fb33cfd
pngsuite/primary_check/basn0g02.png,32,32,4,,0x5bbe95c5
pngsuite/primary_check/basn0g04.png,32,32,4,,0x3468b9c5
pngsuite/primary_check/basn0g08.png,32,32,4,,0x262ef46d
pngsuite/primary_check/basn2c08.png,32,32,4,,0x1fc92bc5
pngsuite/primary_check/basn3p01.png,32,32,4,,0x28a3e1c5
pngsuite/primary_check/basn3p02.png,32,32,4,,0x803be5c5
pngsuite/primary_check/basn3p04.png,32,32,4,,0xf3fc60e5
pngsuite/primary_check/basn3p08.png,32,32,4,,0x30ef4f45
pngsuite/primary_check/basn4a08.png,32,32,4,,0x23c8536d
pngsuite/primary_check/basn6a08.png,32,32,4,,0xb472197d
pngsuite/primary_check/bgai4a08.png,32,32,4,,0x23c8536d
pngsuite/primary_check/bgan6a08.png,32,32,4,,0xb472197d
pngsuite/primary_check/bgbn4a08.png,32,32,4,,0x23c8536d
pngsuite/primary_check/bgwn6a08.png,32,32,4,,0xb472197d
pngsuite/primary_check/s01i3p01.png,1,1,4,,0xdb152beb
pngsuite/primary_check/s01n3p01.png,1,1,4,,0xdb152beb
pngsuite/primary_check/s02i3p01.png,2,2,4,,0xa344a3a5
pngsuite/primary_check/s02n3p01.png,2,2,4,,0xa344a3a5
pngsuite/primary_check/s03i3p01.png,3,3,4,,0x594d3bfa
pngsuite/primary_check/s03n3p01.png,3,3,4,,0x594d3bfa
pngsuite/primary_check/s04i3p01.png,4,4,4,,0xd59d4605
pngsuite/primary_check/s04n3p01.png,4,4,4,,0xd59d4605
pngsuite/primary_check/s05i3p02.png,5,5,4,,0x41e58366
pngsuite/primary_check/s05n3p02.png,5,5,4,,0x41e58366
pngsuite/primary_check/s06i3p02.png,6,6,4,,0xcad1a885
pngsuite/primary_check/s06n3p02.png,6,6,4,,0xcad1a885
pngsuite/primary_check/s07i3p02.png,7,7,4,,0x09184108
pngsuite/primary_check/s07n3p02.png,7,7,4,,0x09184108
pngsuite/primary_check/s08i3p02.png,8,8,4,,0x4fd11cad
pngsuite/primary_check/s08n3p02.png,8,8,4,,0x4fd11cad
pngsuite/primary_check/s09i3p02.png,9,9,4,,0xc50dbecd
pngsuite/primary_check/s09n3p02.png,9,9,4,,0xc50dbecd
pngsuite/primary_check/s32i3p04.png,32,32,4,,0x95cbb1d3
pngsuite/primary_check/s32n3p04.png,32,32,4,,0x95cbb1d3
pngsuite/primary_check/s33i3p04.png,33,33,4,,0x6649fc5b
pngsuite/primary_check/s33n3p04.png,33,33,4,,0x6649fc5b
pngsuite/primary_check/s34i3p04.png,34,34,4,,0x35b98e15
pngsuite/primary_check/s34n3p04.png,34,34,4,,0x35b98e15
pngsuite/primary_check/s35i3p04.png,35,35,4,,0xc9ddf938
pngsuite/primary_check/s35n3p04.png,35,35,4,,0xc9ddf938
pngsuite/primary_check/s36i3p04.png,36,36,4,,0x7bb4e1cd
pngsuite/primary_check/s36n3p04.png,36,36,4,,0x7bb4e1cd
pngsuite/primary_check/s37i3p04.png,37,37,4,,0xee50001c
pngsuite/primary_check/s37n3p04.png,37,37,4,,0xee50001c
pngsuite/primary_check/s38i3p04.png,38,38,4,,0x51b76813
pngsuite/primary_check/s38n3p04.png,38,38,4,,0x51b76813
pngsuite/primary_check/s39i3p04.png,39,39,4,,0x42f23327
pngsuite/primary_check/s39n3p04.png,39,39,4,,0x42f23327
pngsuite/primary_check/s40i3p04.png,40,40,4,,0xf91b6a7d
pngsuite/primary_check/s40n3p04.png,40,40,4,,0xf91b6a7d
pngsuite/primary_check/tbbn0g04.png,32,32,4,,0x8a0117a4
pngsuite/primary_check/tbbn3p08.png,32,32,4,,0x82bf9a57
pngsuite/primary_check/tbgn3p08.png,32,32,4,,0x82bf9a57
pngsuite/primary_check/tbrn2c08.png,32,32,4,,0xaa9bfe44
pngsuite/primary_check/tbwn3p08.png,32,32,4,,0x82bf9a57
pngsuite/primary_check/tbyn3p08.png,32,32,4,,0x82bf9a57
pngsuite/primary_check/tm3n3p02.png,32,32,4,,0xf59745c5
pngsuite/primary_check/tp0n0g08.png,32,32,4,,0xd405ad2e
pngsuite/primary_check/tp0n2c08.png,32,32,4,,0x5a66ca09
pngsuite/primary_check/tp0n3p08.png,32,32,4,,0x06e81adf
pngsuite/primary_check/tp1n3p08.png,32,32,4,,0x82bf9a57
pngsuite/primary_check/z00n2c08.png,32,32,4,,0xaa698493
pngsuite/primary_check/z03n2c08.png,32,32,4,,0xaa698493
pngsuite/primary_check/z06n2c08.png,32,32,4,,0xaa698493
pngsuite/primary_check/z09n2c08.png,32,32,4,,0xaa698493
pngsuite/unused/ccwn2c08.png,32,32,3,,0xbb576418
pngsuite/unused/ccwn3p08.png,32,32,3,,0x5c4df060
pngsuite/unused/cdfn2c08.png,8,32,3,,0xe30ed48f
pngsuite/unused/cdhn2c08.png,32,8,3,,0x999321f5
pngsuite/unused/cdsn2c08.png,8,8,3,,0x7f63fa01
pngsuite/unused/cdun2c08.png,32,32,3,,0xbd325d71
pngsuite/unused/ch1n3p04.png,32,32,3,,0x35b2e4a5
pngsuite/unused/ch2n3p08.png,32,32,3,,0xfe066865
pngsuite/unused/cm0n0g04.png,32,32,1,,0xe9f53e6c
pngsuite/unused/cm7n0g04.png,32,32,1,,0xe9f53e6c
pngsuite/unused/cm9n0g04.png,32,32,1,,0xe9f53e6c
pngsuite/unused/cs3n2c16.png,32,32,3,,0x7f0fa2c5
pngsuite/unused/cs3n3p08.png,32,32,3,,0x5533bac5
pngsuite/unused/cs5n2c08.png,32,32,3,,0x8a80f8c5
pngsuite/unused/cs5n3p08.png,32,32,3,,0x8a80f8c5
pngsuite/unused/cs8n2c08.png,32,32,3,,0x7f0fa2c5
pngsuite/unused/cs8n3p08.png,32,32,3,,0x7f0fa2c5
pngsuite/unused/ct0n0g04.png,32,32,1,,0xe9f53e6c
pngsuite/unused/ct1n0g04.png,32,32,1,,0xe9f53e6c
pngsuite/unused/cten0g04.png,32,32,1,,0x1c073b45
pngsuite/unused/ctfn0g04.png,32,32,1,,0xfa9fd205
pngsuite/unused/ctgn0g04.png,32,32,1,,0xf28c8085
pngsuite/unused/cthn0g04.png,32,32,1,,0x7c039595
pngsuite/unused/ctjn0g04.png,32,32,1,,0xc520f455
pngsuite/unused/ctzn0g04.png,32,32,1,,0xe9f53e6c
pngsuite/unused/f00n0g08.png,32,32,1,,0x21db411b
pngsuite/unused/f00n2c08.png,32,32,3,,0x1f25ded0
pngsuite/unused/f01n0g08.png,32,32,1,,0x7437b32a
pngsuite/unused/f01n2c08.png,32,32,3,,0x0d4507ae
pngsuite/unused/f02n0g08.png,32,32,1,,0x6b633c7c
pngsuite/unused/f02n2c08.png,32,32,3,,0x4b278986
pngsuite/unused/f03n0g08.png,32,32,1,,0x2f31c08e
pngsuite/unused/f03n2c08.png,32,32,3,,0x843ecc7e
pngsuite/unused/f04n0g08.png,32,32,1,,0xfd3a0b73
pngsuite/unused/f04n2c08.png,32,32,3,,0x557174bc
pngsuite/unused/f99n0g04.png,32,32,1,,0xb79aa6e1
pngsuite/unused/g03n0g16.png,32,32,1,,0xecd13817
pngsuite/unused/g03n2c08.png,32,32,3,,0x242407a8
pngsuite/unused/g03n3p04.png,32,32,3,,0xe801ecc8
pngsuite/unused/g04n0g16.png,32,32,1,,0xc11bc972
pngsuite/unused/g04n2c08.png,32,32,3,,0xdf843cc4
pngsuite/unused/g04n3p04.png,32,32,3,,0x60e41f3b
pngsuite/unused/g05n0g16.png,32,32,1,,0xbe6615a5
pngsuite/unused/g05n2c08.png,32,32,3,,0x5c312116
pngsuite/unused/g05n3p04.png,32,32,3,,0x2e0fbf86
pngsuite/unused/g07n0g16.png,32,32,1,,0x2b54a398
pngsuite/unused/g07n2c08.png,32,32,3,,0xf765fb10
pngsuite/unused/g07n3p04.png,32,32,3,,0x9a8c3338
pngsuite/unused/g10n0g16.png,32,32,1,,0xb08a92e1
pngsuite/unused/g10n2c08.png,32,32,3,,0xa43f2291
pngsuite/unused/g10n3p04.png,32,32,3,,0xb733194c
pngsuite/unused/g25n0g16.png,32,32,1,,0xa6b1f5dd
pngsuite/unused/g25n2c08.png,32,32,3,,0x767aee0c
pngsuite/unused/g25n3p04.png,32,32,3,,0x4cf349a8
pngsuite/unused/pp0n2c16.png,32,32,3,,0x65567ed5
pngsuite/unused/pp0n6a08.png,32,32,4,,0x3188c645
pngsuite/unused/ps1n0g08.png,32,32,1,,0x414f1ca9
pngsuite/unused/ps1n2c16.png,32,32,3,,0x65567ed5
pngsuite/unused/ps2n0g08.png,32,32,1,,0x414f1ca9
pngsuite/unused/ps2n2c16.png,32,32,3,,0x65567ed5
1 filename width height ncomp error hash
2 pngsuite/16bit/basi0g16.png 32 32 1 0xfc8f2f99
3 pngsuite/16bit/basi2c16.png 32 32 3 0x65567ed5
4 pngsuite/16bit/basi4a16.png 32 32 2 0x198cf245
5 pngsuite/16bit/basi6a16.png 32 32 4 0x3016e9b5
6 pngsuite/16bit/basn0g16.png 32 32 1 0xfc8f2f99
7 pngsuite/16bit/basn2c16.png 32 32 3 0x65567ed5
8 pngsuite/16bit/basn4a16.png 32 32 2 0x198cf245
9 pngsuite/16bit/basn6a16.png 32 32 4 0x3016e9b5
10 pngsuite/16bit/bgai4a16.png 32 32 2 0x198cf245
11 pngsuite/16bit/bgan6a16.png 32 32 4 0x3016e9b5
12 pngsuite/16bit/bggn4a16.png 32 32 2 0x198cf245
13 pngsuite/16bit/bgyn6a16.png 32 32 4 0x3016e9b5
14 pngsuite/16bit/oi1n0g16.png 32 32 1 0xfc8f2f99
15 pngsuite/16bit/oi1n2c16.png 32 32 3 0x65567ed5
16 pngsuite/16bit/oi2n0g16.png 32 32 1 0xfc8f2f99
17 pngsuite/16bit/oi2n2c16.png 32 32 3 0x65567ed5
18 pngsuite/16bit/oi4n0g16.png 32 32 1 0xfc8f2f99
19 pngsuite/16bit/oi4n2c16.png 32 32 3 0x65567ed5
20 pngsuite/16bit/oi9n0g16.png 32 32 1 0xfc8f2f99
21 pngsuite/16bit/oi9n2c16.png 32 32 3 0x65567ed5
22 pngsuite/16bit/tbbn2c16.png 32 32 4 0xaa9bfe44
23 pngsuite/16bit/tbgn2c16.png 32 32 4 0xaa9bfe44
24 pngsuite/16bit/tbwn0g16.png 32 32 2 0x075e519a
25 pngsuite/corrupt/xc1n0g08.png 32 32 2 bad ctype 0x00000000
26 pngsuite/corrupt/xc9n2c08.png 32 32 2 bad ctype 0x00000000
27 pngsuite/corrupt/xcrn0g04.png 32 32 2 unknown image type 0x00000000
28 pngsuite/corrupt/xcsn0g01.png 32 32 1 0x43b9891f
29 pngsuite/corrupt/xd0n2c08.png 32 32 1 1/2/4/8/16-bit only 0x00000000
30 pngsuite/corrupt/xd3n2c08.png 32 32 1 1/2/4/8/16-bit only 0x00000000
31 pngsuite/corrupt/xd9n2c08.png 32 32 1 1/2/4/8/16-bit only 0x00000000
32 pngsuite/corrupt/xdtn0g01.png 32 32 1 no IDAT 0x00000000
33 pngsuite/corrupt/xhdn0g08.png 32 32 1 0x414f1ca9
34 pngsuite/corrupt/xlfn0g04.png 32 32 1 unknown image type 0x00000000
35 pngsuite/corrupt/xs1n0g01.png 32 32 1 unknown image type 0x00000000
36 pngsuite/corrupt/xs2n0g01.png 32 32 1 unknown image type 0x00000000
37 pngsuite/corrupt/xs4n0g01.png 32 32 1 unknown image type 0x00000000
38 pngsuite/corrupt/xs7n0g01.png 32 32 1 unknown image type 0x00000000
39 pngsuite/iphone/iphone_basi0g01.png 32 32 4 0x5fb33cfd
40 pngsuite/iphone/iphone_basi0g02.png 32 32 4 0x5bbe95c5
41 pngsuite/iphone/iphone_basi3p02.png 32 32 4 0x50ba29c5
42 pngsuite/iphone/iphone_bgwn6a08.png 32 32 4 0x45d8548a
43 pngsuite/iphone/iphone_bgyn6a16.png 32 32 4 0x4b2b7545
44 pngsuite/iphone/iphone_tbyn3p08.png 32 32 4 0x8ea9aaaf
45 pngsuite/iphone/iphone_z06n2c08.png 32 32 4 0xb5dd034b
46 pngsuite/primary/basi0g01.png 32 32 1 0x43b9891f
47 pngsuite/primary/basi0g02.png 32 32 1 0xaf0bb3c5
48 pngsuite/primary/basi0g04.png 32 32 1 0x6fbaeb45
49 pngsuite/primary/basi0g08.png 32 32 1 0x414f1ca9
50 pngsuite/primary/basi2c08.png 32 32 3 0x522345c5
51 pngsuite/primary/basi3p01.png 32 32 3 0x9c5b75c5
52 pngsuite/primary/basi3p02.png 32 32 3 0x46f26ec5
53 pngsuite/primary/basi3p04.png 32 32 3 0x35b2e4a5
54 pngsuite/primary/basi3p08.png 32 32 3 0xfe066865
55 pngsuite/primary/basi4a08.png 32 32 2 0x77cbbfa5
56 pngsuite/primary/basi6a08.png 32 32 4 0xb472197d
57 pngsuite/primary/basn0g01.png 32 32 1 0x43b9891f
58 pngsuite/primary/basn0g02.png 32 32 1 0xaf0bb3c5
59 pngsuite/primary/basn0g04.png 32 32 1 0x6fbaeb45
60 pngsuite/primary/basn0g08.png 32 32 1 0x414f1ca9
61 pngsuite/primary/basn2c08.png 32 32 3 0x522345c5
62 pngsuite/primary/basn3p01.png 32 32 3 0x9c5b75c5
63 pngsuite/primary/basn3p02.png 32 32 3 0x46f26ec5
64 pngsuite/primary/basn3p04.png 32 32 3 0x35b2e4a5
65 pngsuite/primary/basn3p08.png 32 32 3 0xfe066865
66 pngsuite/primary/basn4a08.png 32 32 2 0x77cbbfa5
67 pngsuite/primary/basn6a08.png 32 32 4 0xb472197d
68 pngsuite/primary/bgai4a08.png 32 32 2 0x77cbbfa5
69 pngsuite/primary/bgan6a08.png 32 32 4 0xb472197d
70 pngsuite/primary/bgbn4a08.png 32 32 2 0x77cbbfa5
71 pngsuite/primary/bgwn6a08.png 32 32 4 0xb472197d
72 pngsuite/primary/s01i3p01.png 1 1 3 0xafb003b6
73 pngsuite/primary/s01n3p01.png 1 1 3 0xafb003b6
74 pngsuite/primary/s02i3p01.png 2 2 3 0x96f3dd85
75 pngsuite/primary/s02n3p01.png 2 2 3 0x96f3dd85
76 pngsuite/primary/s03i3p01.png 3 3 3 0xb0cf1241
77 pngsuite/primary/s03n3p01.png 3 3 3 0xb0cf1241
78 pngsuite/primary/s04i3p01.png 4 4 3 0xbfcedd75
79 pngsuite/primary/s04n3p01.png 4 4 3 0xbfcedd75
80 pngsuite/primary/s05i3p02.png 5 5 3 0xc322cedd
81 pngsuite/primary/s05n3p02.png 5 5 3 0xc322cedd
82 pngsuite/primary/s06i3p02.png 6 6 3 0x46916799
83 pngsuite/primary/s06n3p02.png 6 6 3 0x46916799
84 pngsuite/primary/s07i3p02.png 7 7 3 0xfdabc297
85 pngsuite/primary/s07n3p02.png 7 7 3 0xfdabc297
86 pngsuite/primary/s08i3p02.png 8 8 3 0x8f036d09
87 pngsuite/primary/s08n3p02.png 8 8 3 0x8f036d09
88 pngsuite/primary/s09i3p02.png 9 9 3 0x16a46830
89 pngsuite/primary/s09n3p02.png 9 9 3 0x16a46830
90 pngsuite/primary/s32i3p04.png 32 32 3 0x4bd4fbd3
91 pngsuite/primary/s32n3p04.png 32 32 3 0x4bd4fbd3
92 pngsuite/primary/s33i3p04.png 33 33 3 0x51aa005e
93 pngsuite/primary/s33n3p04.png 33 33 3 0x51aa005e
94 pngsuite/primary/s34i3p04.png 34 34 3 0x84818775
95 pngsuite/primary/s34n3p04.png 34 34 3 0x84818775
96 pngsuite/primary/s35i3p04.png 35 35 3 0x6359ec75
97 pngsuite/primary/s35n3p04.png 35 35 3 0x6359ec75
98 pngsuite/primary/s36i3p04.png 36 36 3 0xe4878065
99 pngsuite/primary/s36n3p04.png 36 36 3 0xe4878065
100 pngsuite/primary/s37i3p04.png 37 37 3 0x3cefc423
101 pngsuite/primary/s37n3p04.png 37 37 3 0x3cefc423
102 pngsuite/primary/s38i3p04.png 38 38 3 0xffc55a2b
103 pngsuite/primary/s38n3p04.png 38 38 3 0xffc55a2b
104 pngsuite/primary/s39i3p04.png 39 39 3 0x0c790240
105 pngsuite/primary/s39n3p04.png 39 39 3 0x0c790240
106 pngsuite/primary/s40i3p04.png 40 40 3 0x951a316d
107 pngsuite/primary/s40n3p04.png 40 40 3 0x951a316d
108 pngsuite/primary/tbbn0g04.png 32 32 2 0x9c8410ea
109 pngsuite/primary/tbbn3p08.png 32 32 4 0x82bf9a57
110 pngsuite/primary/tbgn3p08.png 32 32 4 0x82bf9a57
111 pngsuite/primary/tbrn2c08.png 32 32 4 0xaa9bfe44
112 pngsuite/primary/tbwn3p08.png 32 32 4 0x82bf9a57
113 pngsuite/primary/tbyn3p08.png 32 32 4 0x82bf9a57
114 pngsuite/primary/tm3n3p02.png 32 32 4 0xf59745c5
115 pngsuite/primary/tp0n0g08.png 32 32 1 0xbac0864c
116 pngsuite/primary/tp0n2c08.png 32 32 3 0x82687c37
117 pngsuite/primary/tp0n3p08.png 32 32 3 0x61f54e37
118 pngsuite/primary/tp1n3p08.png 32 32 4 0x82bf9a57
119 pngsuite/primary/z00n2c08.png 32 32 3 0x65b4a72f
120 pngsuite/primary/z03n2c08.png 32 32 3 0x65b4a72f
121 pngsuite/primary/z06n2c08.png 32 32 3 0x65b4a72f
122 pngsuite/primary/z09n2c08.png 32 32 3 0x65b4a72f
123 pngsuite/primary_check/basi0g01.png 32 32 4 0x5fb33cfd
124 pngsuite/primary_check/basi0g02.png 32 32 4 0x5bbe95c5
125 pngsuite/primary_check/basi0g04.png 32 32 4 0x3468b9c5
126 pngsuite/primary_check/basi0g08.png 32 32 4 0x262ef46d
127 pngsuite/primary_check/basi2c08.png 32 32 4 0x1fc92bc5
128 pngsuite/primary_check/basi3p01.png 32 32 4 0x28a3e1c5
129 pngsuite/primary_check/basi3p02.png 32 32 4 0x803be5c5
130 pngsuite/primary_check/basi3p04.png 32 32 4 0xf3fc60e5
131 pngsuite/primary_check/basi3p08.png 32 32 4 0x30ef4f45
132 pngsuite/primary_check/basi4a08.png 32 32 4 0x23c8536d
133 pngsuite/primary_check/basi6a08.png 32 32 4 0xb472197d
134 pngsuite/primary_check/basn0g01.png 32 32 4 0x5fb33cfd
135 pngsuite/primary_check/basn0g02.png 32 32 4 0x5bbe95c5
136 pngsuite/primary_check/basn0g04.png 32 32 4 0x3468b9c5
137 pngsuite/primary_check/basn0g08.png 32 32 4 0x262ef46d
138 pngsuite/primary_check/basn2c08.png 32 32 4 0x1fc92bc5
139 pngsuite/primary_check/basn3p01.png 32 32 4 0x28a3e1c5
140 pngsuite/primary_check/basn3p02.png 32 32 4 0x803be5c5
141 pngsuite/primary_check/basn3p04.png 32 32 4 0xf3fc60e5
142 pngsuite/primary_check/basn3p08.png 32 32 4 0x30ef4f45
143 pngsuite/primary_check/basn4a08.png 32 32 4 0x23c8536d
144 pngsuite/primary_check/basn6a08.png 32 32 4 0xb472197d
145 pngsuite/primary_check/bgai4a08.png 32 32 4 0x23c8536d
146 pngsuite/primary_check/bgan6a08.png 32 32 4 0xb472197d
147 pngsuite/primary_check/bgbn4a08.png 32 32 4 0x23c8536d
148 pngsuite/primary_check/bgwn6a08.png 32 32 4 0xb472197d
149 pngsuite/primary_check/s01i3p01.png 1 1 4 0xdb152beb
150 pngsuite/primary_check/s01n3p01.png 1 1 4 0xdb152beb
151 pngsuite/primary_check/s02i3p01.png 2 2 4 0xa344a3a5
152 pngsuite/primary_check/s02n3p01.png 2 2 4 0xa344a3a5
153 pngsuite/primary_check/s03i3p01.png 3 3 4 0x594d3bfa
154 pngsuite/primary_check/s03n3p01.png 3 3 4 0x594d3bfa
155 pngsuite/primary_check/s04i3p01.png 4 4 4 0xd59d4605
156 pngsuite/primary_check/s04n3p01.png 4 4 4 0xd59d4605
157 pngsuite/primary_check/s05i3p02.png 5 5 4 0x41e58366
158 pngsuite/primary_check/s05n3p02.png 5 5 4 0x41e58366
159 pngsuite/primary_check/s06i3p02.png 6 6 4 0xcad1a885
160 pngsuite/primary_check/s06n3p02.png 6 6 4 0xcad1a885
161 pngsuite/primary_check/s07i3p02.png 7 7 4 0x09184108
162 pngsuite/primary_check/s07n3p02.png 7 7 4 0x09184108
163 pngsuite/primary_check/s08i3p02.png 8 8 4 0x4fd11cad
164 pngsuite/primary_check/s08n3p02.png 8 8 4 0x4fd11cad
165 pngsuite/primary_check/s09i3p02.png 9 9 4 0xc50dbecd
166 pngsuite/primary_check/s09n3p02.png 9 9 4 0xc50dbecd
167 pngsuite/primary_check/s32i3p04.png 32 32 4 0x95cbb1d3
168 pngsuite/primary_check/s32n3p04.png 32 32 4 0x95cbb1d3
169 pngsuite/primary_check/s33i3p04.png 33 33 4 0x6649fc5b
170 pngsuite/primary_check/s33n3p04.png 33 33 4 0x6649fc5b
171 pngsuite/primary_check/s34i3p04.png 34 34 4 0x35b98e15
172 pngsuite/primary_check/s34n3p04.png 34 34 4 0x35b98e15
173 pngsuite/primary_check/s35i3p04.png 35 35 4 0xc9ddf938
174 pngsuite/primary_check/s35n3p04.png 35 35 4 0xc9ddf938
175 pngsuite/primary_check/s36i3p04.png 36 36 4 0x7bb4e1cd
176 pngsuite/primary_check/s36n3p04.png 36 36 4 0x7bb4e1cd
177 pngsuite/primary_check/s37i3p04.png 37 37 4 0xee50001c
178 pngsuite/primary_check/s37n3p04.png 37 37 4 0xee50001c
179 pngsuite/primary_check/s38i3p04.png 38 38 4 0x51b76813
180 pngsuite/primary_check/s38n3p04.png 38 38 4 0x51b76813
181 pngsuite/primary_check/s39i3p04.png 39 39 4 0x42f23327
182 pngsuite/primary_check/s39n3p04.png 39 39 4 0x42f23327
183 pngsuite/primary_check/s40i3p04.png 40 40 4 0xf91b6a7d
184 pngsuite/primary_check/s40n3p04.png 40 40 4 0xf91b6a7d
185 pngsuite/primary_check/tbbn0g04.png 32 32 4 0x8a0117a4
186 pngsuite/primary_check/tbbn3p08.png 32 32 4 0x82bf9a57
187 pngsuite/primary_check/tbgn3p08.png 32 32 4 0x82bf9a57
188 pngsuite/primary_check/tbrn2c08.png 32 32 4 0xaa9bfe44
189 pngsuite/primary_check/tbwn3p08.png 32 32 4 0x82bf9a57
190 pngsuite/primary_check/tbyn3p08.png 32 32 4 0x82bf9a57
191 pngsuite/primary_check/tm3n3p02.png 32 32 4 0xf59745c5
192 pngsuite/primary_check/tp0n0g08.png 32 32 4 0xd405ad2e
193 pngsuite/primary_check/tp0n2c08.png 32 32 4 0x5a66ca09
194 pngsuite/primary_check/tp0n3p08.png 32 32 4 0x06e81adf
195 pngsuite/primary_check/tp1n3p08.png 32 32 4 0x82bf9a57
196 pngsuite/primary_check/z00n2c08.png 32 32 4 0xaa698493
197 pngsuite/primary_check/z03n2c08.png 32 32 4 0xaa698493
198 pngsuite/primary_check/z06n2c08.png 32 32 4 0xaa698493
199 pngsuite/primary_check/z09n2c08.png 32 32 4 0xaa698493
200 pngsuite/unused/ccwn2c08.png 32 32 3 0xbb576418
201 pngsuite/unused/ccwn3p08.png 32 32 3 0x5c4df060
202 pngsuite/unused/cdfn2c08.png 8 32 3 0xe30ed48f
203 pngsuite/unused/cdhn2c08.png 32 8 3 0x999321f5
204 pngsuite/unused/cdsn2c08.png 8 8 3 0x7f63fa01
205 pngsuite/unused/cdun2c08.png 32 32 3 0xbd325d71
206 pngsuite/unused/ch1n3p04.png 32 32 3 0x35b2e4a5
207 pngsuite/unused/ch2n3p08.png 32 32 3 0xfe066865
208 pngsuite/unused/cm0n0g04.png 32 32 1 0xe9f53e6c
209 pngsuite/unused/cm7n0g04.png 32 32 1 0xe9f53e6c
210 pngsuite/unused/cm9n0g04.png 32 32 1 0xe9f53e6c
211 pngsuite/unused/cs3n2c16.png 32 32 3 0x7f0fa2c5
212 pngsuite/unused/cs3n3p08.png 32 32 3 0x5533bac5
213 pngsuite/unused/cs5n2c08.png 32 32 3 0x8a80f8c5
214 pngsuite/unused/cs5n3p08.png 32 32 3 0x8a80f8c5
215 pngsuite/unused/cs8n2c08.png 32 32 3 0x7f0fa2c5
216 pngsuite/unused/cs8n3p08.png 32 32 3 0x7f0fa2c5
217 pngsuite/unused/ct0n0g04.png 32 32 1 0xe9f53e6c
218 pngsuite/unused/ct1n0g04.png 32 32 1 0xe9f53e6c
219 pngsuite/unused/cten0g04.png 32 32 1 0x1c073b45
220 pngsuite/unused/ctfn0g04.png 32 32 1 0xfa9fd205
221 pngsuite/unused/ctgn0g04.png 32 32 1 0xf28c8085
222 pngsuite/unused/cthn0g04.png 32 32 1 0x7c039595
223 pngsuite/unused/ctjn0g04.png 32 32 1 0xc520f455
224 pngsuite/unused/ctzn0g04.png 32 32 1 0xe9f53e6c
225 pngsuite/unused/f00n0g08.png 32 32 1 0x21db411b
226 pngsuite/unused/f00n2c08.png 32 32 3 0x1f25ded0
227 pngsuite/unused/f01n0g08.png 32 32 1 0x7437b32a
228 pngsuite/unused/f01n2c08.png 32 32 3 0x0d4507ae
229 pngsuite/unused/f02n0g08.png 32 32 1 0x6b633c7c
230 pngsuite/unused/f02n2c08.png 32 32 3 0x4b278986
231 pngsuite/unused/f03n0g08.png 32 32 1 0x2f31c08e
232 pngsuite/unused/f03n2c08.png 32 32 3 0x843ecc7e
233 pngsuite/unused/f04n0g08.png 32 32 1 0xfd3a0b73
234 pngsuite/unused/f04n2c08.png 32 32 3 0x557174bc
235 pngsuite/unused/f99n0g04.png 32 32 1 0xb79aa6e1
236 pngsuite/unused/g03n0g16.png 32 32 1 0xecd13817
237 pngsuite/unused/g03n2c08.png 32 32 3 0x242407a8
238 pngsuite/unused/g03n3p04.png 32 32 3 0xe801ecc8
239 pngsuite/unused/g04n0g16.png 32 32 1 0xc11bc972
240 pngsuite/unused/g04n2c08.png 32 32 3 0xdf843cc4
241 pngsuite/unused/g04n3p04.png 32 32 3 0x60e41f3b
242 pngsuite/unused/g05n0g16.png 32 32 1 0xbe6615a5
243 pngsuite/unused/g05n2c08.png 32 32 3 0x5c312116
244 pngsuite/unused/g05n3p04.png 32 32 3 0x2e0fbf86
245 pngsuite/unused/g07n0g16.png 32 32 1 0x2b54a398
246 pngsuite/unused/g07n2c08.png 32 32 3 0xf765fb10
247 pngsuite/unused/g07n3p04.png 32 32 3 0x9a8c3338
248 pngsuite/unused/g10n0g16.png 32 32 1 0xb08a92e1
249 pngsuite/unused/g10n2c08.png 32 32 3 0xa43f2291
250 pngsuite/unused/g10n3p04.png 32 32 3 0xb733194c
251 pngsuite/unused/g25n0g16.png 32 32 1 0xa6b1f5dd
252 pngsuite/unused/g25n2c08.png 32 32 3 0x767aee0c
253 pngsuite/unused/g25n3p04.png 32 32 3 0x4cf349a8
254 pngsuite/unused/pp0n2c16.png 32 32 3 0x65567ed5
255 pngsuite/unused/pp0n6a08.png 32 32 4 0x3188c645
256 pngsuite/unused/ps1n0g08.png 32 32 1 0x414f1ca9
257 pngsuite/unused/ps1n2c16.png 32 32 3 0x65567ed5
258 pngsuite/unused/ps2n0g08.png 32 32 1 0x414f1ca9
259 pngsuite/unused/ps2n2c16.png 32 32 3 0x65567ed5

View File

@ -64,7 +64,7 @@ void stbir_progress(float p)
#define STBIR_PROGRESS_REPORT stbir_progress
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#define STB_IMAGE_RESIZE_STATIC
#include "stb_image_resize.h"
#include "stb_image_resize2.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
@ -143,7 +143,7 @@ void resizer(int argc, char **argv)
out_h = h*3;
output_pixels = (unsigned char*) malloc(out_w*out_h*n);
//stbir_resize_uint8_srgb(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, n, -1,0);
stbir_resize_uint8(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, n);
stbir_resize_uint8_linear(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, (stbir_pixel_layout) n);
stbi_write_png("output.png", out_w, out_h, n, output_pixels, 0);
exit(0);
}
@ -171,9 +171,9 @@ void performance(int argc, char **argv)
output_pixels = (unsigned char*) malloc(out_w*out_h*n);
for (i=0; i < count; ++i)
if (srgb)
stbir_resize_uint8_srgb(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, n,-1,0);
stbir_resize_uint8_srgb(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, (stbir_pixel_layout) n);
else
stbir_resize(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, STBIR_TYPE_UINT8, n,-1, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, STBIR_COLORSPACE_LINEAR, NULL);
stbir_resize_uint8_linear(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, (stbir_pixel_layout) n);
exit(0);
}
@ -188,6 +188,7 @@ int main(int argc, char** argv)
return 0;
}
#if 0
void resize_image(const char* filename, float width_percent, float height_percent, stbir_filter filter, stbir_edge edge, stbir_colorspace colorspace, const char* output_filename)
{
int w, h, n;
@ -1120,3 +1121,7 @@ void test_suite(int argc, char **argv)
resize_image("gamma_2.2.jpg", .5f, .5f, STBIR_FILTER_CATMULLROM, STBIR_EDGE_REFLECT, STBIR_COLORSPACE_SRGB, "test-output/gamma_2.2.jpg");
resize_image("gamma_dalai_lama_gray.jpg", .5f, .5f, STBIR_FILTER_CATMULLROM, STBIR_EDGE_REFLECT, STBIR_COLORSPACE_SRGB, "test-output/gamma_dalai_lama_gray.jpg");
}
#endif
void test_suite(int argc, char **argv)
{
}

View File

@ -88,7 +88,7 @@ SOURCE=.\resample_test.cpp
# End Source File
# Begin Source File
SOURCE=..\stb_image_resize.h
SOURCE=..\stb_image_resize2.h
# End Source File
# End Target
# End Project

View File

@ -66,7 +66,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "DS_TEST" /FR /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "TT_TEST" /FR /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
@ -130,7 +130,7 @@ SOURCE=..\stb_image.h
# End Source File
# Begin Source File
SOURCE=..\stb_image_resize.h
SOURCE=..\stb_image_resize2.h
# End Source File
# Begin Source File
@ -154,14 +154,6 @@ SOURCE=..\stb_perlin.h
# End Source File
# Begin Source File
SOURCE=..\stb_pg.h
# End Source File
# Begin Source File
SOURCE=.\stb_query.h
# End Source File
# Begin Source File
SOURCE=..\stb_rect_pack.h
# End Source File
# Begin Source File

View File

@ -1,3 +1,6 @@
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize2.h"
#define STB_SPRINTF_IMPLEMENTATION
#include "stb_sprintf.h"
@ -7,7 +10,6 @@
#define STB_DIVIDE_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_HERRINGBONE_WANG_TILE_IMEPLEMENTATIOn
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#define STB_RECT_PACK_IMPLEMENTATION
#define STB_VOXEL_RENDER_IMPLEMENTATION
#define STB_EASY_FONT_IMPLEMENTATION
@ -20,7 +22,6 @@
#include "stb_perlin.h"
#include "stb_c_lexer.h"
#include "stb_divide.h"
#include "stb_image_resize.h"
#include "stb_rect_pack.h"
#include "stb_dxt.h"
#include "stb_include.h"

View File

@ -1 +1,50 @@
#include "stb_c_lexer.h"
#include "stb_c_lexer.h"
#define STB_C_LEX_C_DECIMAL_INTS Y // "0|[1-9][0-9]*" CLEX_intlit
#define STB_C_LEX_C_HEX_INTS Y // "0x[0-9a-fA-F]+" CLEX_intlit
#define STB_C_LEX_C_OCTAL_INTS Y // "[0-7]+" CLEX_intlit
#define STB_C_LEX_C_DECIMAL_FLOATS Y // "[0-9]*(.[0-9]*([eE][-+]?[0-9]+)?) CLEX_floatlit
#define STB_C_LEX_C99_HEX_FLOATS N // "0x{hex}+(.{hex}*)?[pP][-+]?{hex}+ CLEX_floatlit
#define STB_C_LEX_C_IDENTIFIERS Y // "[_a-zA-Z][_a-zA-Z0-9]*" CLEX_id
#define STB_C_LEX_C_DQ_STRINGS Y // double-quote-delimited strings with escapes CLEX_dqstring
#define STB_C_LEX_C_SQ_STRINGS N // single-quote-delimited strings with escapes CLEX_ssstring
#define STB_C_LEX_C_CHARS Y // single-quote-delimited character with escape CLEX_charlits
#define STB_C_LEX_C_COMMENTS Y // "/* comment */"
#define STB_C_LEX_CPP_COMMENTS Y // "// comment to end of line\n"
#define STB_C_LEX_C_COMPARISONS Y // "==" CLEX_eq "!=" CLEX_noteq "<=" CLEX_lesseq ">=" CLEX_greatereq
#define STB_C_LEX_C_LOGICAL Y // "&&" CLEX_andand "||" CLEX_oror
#define STB_C_LEX_C_SHIFTS Y // "<<" CLEX_shl ">>" CLEX_shr
#define STB_C_LEX_C_INCREMENTS Y // "++" CLEX_plusplus "--" CLEX_minusminus
#define STB_C_LEX_C_ARROW Y // "->" CLEX_arrow
#define STB_C_LEX_EQUAL_ARROW N // "=>" CLEX_eqarrow
#define STB_C_LEX_C_BITWISEEQ Y // "&=" CLEX_andeq "|=" CLEX_oreq "^=" CLEX_xoreq
#define STB_C_LEX_C_ARITHEQ Y // "+=" CLEX_pluseq "-=" CLEX_minuseq
// "*=" CLEX_muleq "/=" CLEX_diveq "%=" CLEX_modeq
// if both STB_C_LEX_SHIFTS & STB_C_LEX_ARITHEQ:
// "<<=" CLEX_shleq ">>=" CLEX_shreq
#define STB_C_LEX_PARSE_SUFFIXES N // letters after numbers are parsed as part of those numbers, and must be in suffix list below
#define STB_C_LEX_DECIMAL_SUFFIXES "" // decimal integer suffixes e.g. "uUlL" -- these are returned as-is in string storage
#define STB_C_LEX_HEX_SUFFIXES "" // e.g. "uUlL"
#define STB_C_LEX_OCTAL_SUFFIXES "" // e.g. "uUlL"
#define STB_C_LEX_FLOAT_SUFFIXES "" //
#define STB_C_LEX_0_IS_EOF Y // if Y, ends parsing at '\0'; if N, returns '\0' as token
#define STB_C_LEX_INTEGERS_AS_DOUBLES N // parses integers as doubles so they can be larger than 'int', but only if STB_C_LEX_STDLIB==N
#define STB_C_LEX_MULTILINE_DSTRINGS N // allow newlines in double-quoted strings
#define STB_C_LEX_MULTILINE_SSTRINGS N // allow newlines in single-quoted strings
#define STB_C_LEX_USE_STDLIB Y // use strtod,strtol for parsing #s; otherwise inaccurate hack
#define STB_C_LEX_DOLLAR_IDENTIFIER Y // allow $ as an identifier character
#define STB_C_LEX_FLOAT_NO_DECIMAL Y // allow floats that have no decimal point if they have an exponent
#define STB_C_LEX_DEFINE_ALL_TOKEN_NAMES N // if Y, all CLEX_ token names are defined, even if never returned
// leaving it as N should help you catch config bugs
#define STB_C_LEX_DISCARD_PREPROCESSOR Y // discard C-preprocessor directives (e.g. after prepocess
// still have #line, #pragma, etc)
//#define STB_C_LEX_ISWHITE(str) ... // return length in bytes of whitespace characters if first char is whitespace
#define STB_C_LEXER_DEFINITIONS // This line prevents the header file from replacing your definitions
#include "stb_c_lexer.h"

View File

@ -5,9 +5,9 @@
#include "stb_rect_pack.h"
#include "stb_truetype.h"
#include "stb_image_write.h"
#include "stb_c_lexer.h"
#include "stb_perlin.h"
#include "stb_dxt.h"
#include "stb_c_lexer.h"
#include "stb_divide.h"
#include "stb_herringbone_wang_tile.h"
#include "stb_ds.h"
@ -47,7 +47,6 @@ void my_free(void *) { }
#include "stb_image_write.h"
#include "stb_perlin.h"
#include "stb_dxt.h"
#include "stb_c_lexer.h"
#include "stb_divide.h"
#include "stb_herringbone_wang_tile.h"
#include "stb_ds.h"
@ -71,7 +70,7 @@ void my_free(void *) { }
#include "stb_leakcheck.h"
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize.h"
#include "stb_image_resize2.h"
//#include "stretchy_buffer.h" // deprecating
@ -183,3 +182,5 @@ void dummy3(void)
stb_textedit_initialize_state(0,0);
stb_textedit_paste(0,0,0,0);
}
#include "stb_c_lexer.h"

47
tests/test_png_paeth.c Normal file
View File

@ -0,0 +1,47 @@
#include <stdio.h>
#include <stdlib.h>
// Reference Paeth filter as per PNG spec
static int ref_paeth(int a, int b, int c)
{
int p = a + b - c;
int pa = abs(p-a);
int pb = abs(p-b);
int pc = abs(p-c);
if (pa <= pb && pa <= pc) return a;
if (pb <= pc) return b;
return c;
}
// Optimized Paeth filter
static int opt_paeth(int a, int b, int c)
{
int thresh = c*3 - (a + b);
int lo = a < b ? a : b;
int hi = a < b ? b : a;
int t0 = (hi <= thresh) ? lo : c;
int t1 = (thresh <= lo) ? hi : t0;
return t1;
}
int main()
{
// Exhaustively test the functions match for all byte inputs a, b,c in [0,255]
for (int i = 0; i < (1 << 24); ++i) {
int a = i & 0xff;
int b = (i >> 8) & 0xff;
int c = (i >> 16) & 0xff;
int ref = ref_paeth(a, b, c);
int opt = opt_paeth(a, b, c);
if (ref != opt) {
fprintf(stderr, "mismatch at a=%3d b=%3d c=%3d: ref=%3d opt=%3d\n", a, b, c, ref, opt);
return 1;
}
}
printf("all ok!\n");
return 0;
}
// vim:sw=3:sts=3:et

75
tests/test_png_regress.c Normal file
View File

@ -0,0 +1,75 @@
#include <stdio.h>
#include <stdlib.h>
#define STBI_WINDOWS_UTF8
#ifdef _WIN32
#define WIN32 // what stb.h checks
#pragma comment(lib, "advapi32.lib")
#endif
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_DEFINE
#include "deprecated/stb.h"
static unsigned int fnv1a_hash32(const stbi_uc *bytes, size_t len)
{
unsigned int hash = 0x811c9dc5;
unsigned int mul = 0x01000193;
size_t i;
for (i = 0; i < len; ++i)
hash = (hash ^ bytes[i]) * mul;
return hash;
}
// The idea for this test is to leave pngsuite/ref_results.csv checked in,
// and then you can run this test after making PNG loader changes. If the
// ref results change (as per git diff), confirm that the change was
// intentional. If so, commit them as well; if not, undo.
int main()
{
char **files;
FILE *csv_file;
int i;
files = stb_readdir_recursive("pngsuite", "*.png");
if (!files) {
fprintf(stderr, "pngsuite files not found!\n");
return 1;
}
// sort files by name
qsort(files, stb_arr_len(files), sizeof(char*), stb_qsort_strcmp(0));
csv_file = fopen("pngsuite/ref_results.csv", "w");
if (!csv_file) {
fprintf(stderr, "error opening ref results for writing!\n");
stb_readdir_free(files);
return 1;
}
fprintf(csv_file, "filename,width,height,ncomp,error,hash\n");
for (i = 0; i < stb_arr_len(files); ++i) {
char *filename = files[i];
int width, height, ncomp;
stbi_uc *pixels = stbi_load(filename, &width, &height, &ncomp, 0);
const char *error = "";
unsigned int hash = 0;
if (!pixels)
error = stbi_failure_reason();
else {
hash = fnv1a_hash32(pixels, width * height * ncomp);
stbi_image_free(pixels);
}
fprintf(csv_file, "%s,%d,%d,%d,%s,0x%08x\n", filename, width, height, ncomp, error, hash);
}
fclose(csv_file);
stb_readdir_free(files);
}

View File

@ -37,14 +37,37 @@ int main(int argc, char **argv)
{
stbtt_fontinfo font;
unsigned char *bitmap;
int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 34807), s = (argc > 2 ? atoi(argv[2]) : 32);
int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : '@'), s = (argc > 2 ? atoi(argv[2]) : 32);
//debug();
// @TODO: why is minglui.ttc failing?
fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/mingliu.ttc", "rb"));
//fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/mingliu.ttc", "rb"));
//fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/x/DroidSansMono.ttf", "rb"));
fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/DejaVuSans.ttf", "rb"));
stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
#if 0
{
stbtt__bitmap b;
stbtt__point p[2];
int wcount[2] = { 2,0 };
p[0].x = 0.2f;
p[0].y = 0.3f;
p[1].x = 3.8f;
p[1].y = 0.8f;
b.w = 16;
b.h = 2;
b.stride = 16;
b.pixels = malloc(b.w*b.h);
stbtt__rasterize(&b, p, wcount, 1, 1, 1, 0, 0, 0, 0, 0, NULL);
for (i=0; i < 8; ++i)
printf("%f\n", b.pixels[i]/255.0);
}
#endif
#if 1
{
static stbtt_pack_context pc;
static stbtt_packedchar cd[256];
@ -54,6 +77,25 @@ int main(int argc, char **argv)
stbtt_PackFontRange(&pc, ttf_buffer, 0, 32.0, 0, 256, cd);
stbtt_PackEnd(&pc);
}
#endif
#if 1
{
static stbtt_pack_context pc;
static stbtt_packedchar cd[256];
static unsigned char atlas[1024*1024];
unsigned char *data;
data = stbtt_GetCodepointSDF(&font, stbtt_ScaleForPixelHeight(&font,32.0), 'u', 4, 128, 128/4, &w,&h,&i,&j);
for (j=0; j < h; ++j) {
for (i=0; i < w; ++i) {
putchar(" .:ioVM@"[data[j*w+i]>>5]);
}
putchar('\n');
}
}
#endif
#if 0
stbtt_BakeFontBitmap(ttf_buffer,stbtt_GetFontOffsetForIndex(ttf_buffer,0), 40.0, temp_bitmap[0],BITMAP_W,BITMAP_H, 32,96, cdata); // no guarantee this fits!
@ -92,9 +134,16 @@ int main(int argc, char **argv)
return 0;
#endif
stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, (float)s), c, &w, &h, 0,0);
(void)stbtt_GetCodepointBitmapSubpixel(&font,
0.4972374737262726f,
0.4986416995525360f,
0.2391788959503174f,
0.1752119064331055f,
'd',
&w, &h,
0,0);
bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, (float)s), c, &w, &h, 0,0);
for (j=0; j < h; ++j) {
for (i=0; i < w; ++i)
putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);

184
tests/truetype_test_win32.c Normal file
View File

@ -0,0 +1,184 @@
// tested in VC6 (1998) and VS 2019
#define _CRT_SECURE_NO_WARNINGS
#define WIN32_MEAN_AND_LEAN
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
#include <gl/gl.h>
#include <gl/glu.h>
int screen_x=1024, screen_y=768;
GLuint tex;
unsigned char ttf_buffer[1<<20];
unsigned char temp_bitmap[1024*1024];
stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
void init(void)
{
fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
stbtt_BakeFontBitmap(ttf_buffer,0, 64.0, temp_bitmap,1024,1024, 32,96, cdata);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 1024,1024,0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
void print(float x, float y, char *text)
{
// assume orthographic projection with units = screen pixels, origin at top left
glBindTexture(GL_TEXTURE_2D, tex);
glBegin(GL_QUADS);
while (*text) {
if (*text >= 32 && *text < 128) {
stbtt_aligned_quad q;
stbtt_GetBakedQuad(cdata, 1024,1024, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0);
glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0);
glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1);
glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1);
}
++text;
}
glEnd();
}
void draw(void)
{
glViewport(0,0,screen_x,screen_y);
glClearColor(0.45f,0.45f,0.75f,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,screen_x,screen_y,0,-1,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor3f(1,1,1);
print(100,150, "This is a simple test!");
// show font bitmap
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex2f(256,200+0);
glTexCoord2f(1,0); glVertex2f(768,200+0);
glTexCoord2f(1,1); glVertex2f(768,200+512);
glTexCoord2f(0,1); glVertex2f(256,200+512);
glEnd();
}
///////////////////////////////////////////////////////////////////////
///
///
/// Windows OpenGL setup
///
///
HINSTANCE app;
HWND window;
HGLRC rc;
HDC dc;
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "winmm.lib")
int mySetPixelFormat(HWND win)
{
PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd), 1, PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA };
int pixel_format;
pfd.dwLayerMask = PFD_MAIN_PLANE;
pfd.cColorBits = 24;
pfd.cAlphaBits = 8;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
pixel_format = ChoosePixelFormat(dc, &pfd);
if (!pixel_format) return FALSE;
if (!DescribePixelFormat(dc, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd))
return FALSE;
SetPixelFormat(dc, pixel_format, &pfd);
return TRUE;
}
static int WINAPI WinProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg) {
case WM_CREATE: {
LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lparam;
dc = GetDC(wnd);
if (mySetPixelFormat(wnd)) {
rc = wglCreateContext(dc);
if (rc) {
wglMakeCurrent(dc, rc);
return 0;
}
}
return -1;
}
case WM_DESTROY:
wglMakeCurrent(NULL, NULL);
if (rc) wglDeleteContext(rc);
PostQuitMessage (0);
return 0;
default:
return DefWindowProc (wnd, msg, wparam, lparam);
}
return DefWindowProc (wnd, msg, wparam, lparam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
DWORD dwstyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_OWNDC;
wndclass.lpfnWndProc = (WNDPROC) WinProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance, _T("appicon"));
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = GetStockObject(NULL_BRUSH);
wndclass.lpszMenuName = _T("truetype-test");
wndclass.lpszClassName = _T("truetype-test");
wndclass.hIconSm = NULL;
app = hInstance;
if (!RegisterClassEx(&wndclass))
return 0;
window = CreateWindow(_T("truetype-test"), _T("truetype test"), dwstyle,
CW_USEDEFAULT,0, screen_x, screen_y,
NULL, NULL, app, NULL);
ShowWindow(window, SW_SHOWNORMAL);
init();
for(;;) {
MSG msg;
if (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
return 1; // WM_QUIT
}
wglMakeCurrent(dc, rc);
draw();
SwapBuffers(dc);
}
return 0;
}

View File

@ -12,6 +12,24 @@ They are also licensed under the MIT open source license, if you have lawyers
who are unhappy with public domain. Every source file includes an explicit
dual-license for you to choose from.
#### How do I use these libraries?
The idea behind single-header file libraries is that they're easy to distribute and deploy
because all the code is contained in a single file. By default, the .h files in here act as
their own header files, i.e. they declare the functions contained in the file but don't
actually result in any code getting compiled.
So in addition, you should select _exactly one_ C/C++ source file that actually instantiates
the code, preferably a file you're not editing frequently. This file should define a
specific macro (this is documented per-library) to actually enable the function definitions.
For example, to use stb_image, you should have exactly one C/C++ file that doesn't
include stb_image.h regularly, but instead does
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
The right macro to define is pointed out right at the top of each of these libraries.
#### <a name="other_libs"></a> Are there other single-file public-domain/open source libraries with minimal dependencies out there?
[Yes.](https://github.com/nothings/single_file_libs)

View File

@ -3,16 +3,18 @@ stb
single-file public domain (or MIT licensed) libraries for C/C++
# This project discusses security-relevant bugs in public in Github Issues and Pull Requests, and it may take significant time for security fixes to be implemented or merged. If this poses an unreasonable risk to your project, do not use stb libraries.
Noteworthy:
* image loader: [stb_image.h](stb_image.h)
* image writer: [stb_image_write.h](stb_image_write.h)
* image resizer: [stb_image_resize.h](stb_image_resize.h)
* image resizer: [stb_image_resize2.h](stb_image_resize2.h)
* font text rasterizer: [stb_truetype.h](stb_truetype.h)
* typesafe containers: [stb_ds.h](stb_ds.h)
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, stb_image_resize
by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts.
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, original stb_image_resize
by Jorge L. "VinoBS" Rodriguez, and stb_image_resize2 and stb_sprintf by Jeff Roberts.
<a name="stb_libs"></a>

View File

@ -1,21 +1,21 @@
stb_vorbis.c | audio | decode ogg vorbis files from file/memory to float/16-bit signed output
stb_hexwave.h | audio | audio waveform synthesizer
stb_image.h | graphics | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
stb_truetype.h | graphics | parse, decode, and rasterize characters from truetype fonts
stb_image_write.h | graphics | image writing to disk: PNG, TGA, BMP
stb_image_resize.h | graphics | resize images larger/smaller with good quality
stb_image_resize2.h | graphics | resize images larger/smaller with good quality
stb_rect_pack.h | graphics | simple 2D rectangle packer with decent quality
stb_perlin.h | graphics | perlin's revised simplex noise w/ different seeds
stb_ds.h | utility | typesafe dynamic array and hash tables for C, will compile in C++
stb_sprintf.h | utility | fast sprintf, snprintf for C/C++
stb_textedit.h | user interface | guts of a text editor for games etc implementing them from scratch
stb_voxel_render.h | 3D graphics | Minecraft-esque voxel rendering "engine" with many more features
stb_dxt.h | 3D graphics | Fabian "ryg" Giesen's real-time DXT compressor
stb_perlin.h | 3D graphics | revised Perlin noise (3D input, 1D output)
stb_easy_font.h | 3D graphics | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
stb_tilemap_editor.h | game dev | embeddable tilemap editor
stb_herringbone_wang_tile.h | game dev | herringbone Wang tile map generator
stb_c_lexer.h | parsing | simplify writing parsers for C-like languages
stb_divide.h | math | more useful 32-bit modulus e.g. "euclidean divide"
stb_connected_components.h | misc | incrementally compute reachability on grids
stb.h | misc | helper functions for C, mostly redundant in C++; basically author's personal stuff
stb_leakcheck.h | misc | quick-and-dirty malloc/free leak-checking
stb_include.h | misc | implement recursive #include support, particularly for GLSL

View File

@ -20,6 +20,7 @@ int main(int argc, char **argv)
int num_lines;
char **lines = stb_stringfile(stb_sprintf("../%s", tokens[0]), &num_lines);
char *s1, *s2,*s3;
if (lines == NULL) stb_fatal("Couldn't open '%s'", tokens[0]);
s1 = strchr(lines[0], '-');
if (!s1) stb_fatal("Couldn't find '-' before version number in %s", tokens[0]); // stb_fatal -- print error message & exit
s2 = strchr(s1+2, '-');