Merge branch 'master' into working
This commit is contained in:
commit
6e9f34d542
24
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
24
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal 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
4
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal 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
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal 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
23
.github/workflows/ci-fuzz.yml
vendored
Normal 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
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.o
|
||||
*.obj
|
||||
*.exe
|
@ -1,4 +1,7 @@
|
||||
language: C
|
||||
arch:
|
||||
- AMD64
|
||||
- ppc64le
|
||||
install: true
|
||||
script:
|
||||
- cd tests
|
||||
|
60
README.md
60
README.md
@ -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 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 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 graphics | 3807 | Minecraft-esque voxel rendering "engine" with many more features
|
||||
**[stb_dxt.h](stb_dxt.h)** | 1.10 | 3D graphics | 753 | Fabian "ryg" Giesen's real-time DXT compressor
|
||||
**[stb_perlin.h](stb_perlin.h)** | 0.5 | 3D graphics | 428 | revised Perlin noise (3D input, 1D output)
|
||||
**[stb_dxt.h](stb_dxt.h)** | 1.12 | 3D graphics | 719 | Fabian "ryg" Giesen's real-time DXT compressor
|
||||
**[stb_easy_font.h](stb_easy_font.h)** | 1.1 | 3D 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 dev | 4161 | embeddable tilemap editor
|
||||
**[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.42 | game dev | 4187 | embeddable tilemap editor
|
||||
**[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.7 | game 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)
|
||||
|
1371
deprecated/stb.h
1371
deprecated/stb.h
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
124
stb_c_lexer.h
124
stb_c_lexer.h
@ -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:
|
||||
|
21
stb_divide.h
21
stb_divide.h
@ -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
|
||||
|
44
stb_ds.h
44
stb_ds.h
@ -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
133
stb_dxt.h
@ -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
|
||||
|
597
stb_image.h
597
stb_image.h
File diff suppressed because it is too large
Load Diff
10366
stb_image_resize2.h
Normal file
10366
stb_image_resize2.h
Normal file
File diff suppressed because it is too large
Load Diff
224
stb_image_resize_test/dotimings.c
Normal file
224
stb_image_resize_test/dotimings.c
Normal 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;
|
||||
}
|
2738
stb_image_resize_test/old_image_resize.h
Normal file
2738
stb_image_resize_test/old_image_resize.h
Normal file
File diff suppressed because it is too large
Load Diff
56
stb_image_resize_test/oldir.c
Normal file
56
stb_image_resize_test/oldir.c
Normal 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();
|
||||
}
|
992
stb_image_resize_test/stbirtest.c
Normal file
992
stb_image_resize_test/stbirtest.c
Normal 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;
|
||||
}
|
999
stb_image_resize_test/vf_train.c
Normal file
999
stb_image_resize_test/vf_train.c
Normal 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;
|
||||
}
|
@ -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)
|
||||
|
@ -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;
|
||||
|
102
stb_sprintf.h
102
stb_sprintf.h
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
574
stb_truetype.h
574
stb_truetype.h
@ -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
|
||||
|
109
stb_vorbis.c
109
stb_vorbis.c
@ -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;
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
BIN
tests/pbm/basi0g16.pgm
Normal file
Binary file not shown.
BIN
tests/pbm/basi2c16.ppm
Normal file
BIN
tests/pbm/basi2c16.ppm
Normal file
Binary file not shown.
BIN
tests/pbm/cdfn2c08.ppm
Normal file
BIN
tests/pbm/cdfn2c08.ppm
Normal file
Binary file not shown.
BIN
tests/pbm/cdun2c08.ppm
Normal file
BIN
tests/pbm/cdun2c08.ppm
Normal file
Binary file not shown.
BIN
tests/pbm/comment.pgm
Normal file
BIN
tests/pbm/comment.pgm
Normal file
Binary file not shown.
BIN
tests/pbm/ctfn0g04.pgm
Normal file
BIN
tests/pbm/ctfn0g04.pgm
Normal file
Binary file not shown.
259
tests/pngsuite/ref_results.csv
Normal file
259
tests/pngsuite/ref_results.csv
Normal 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
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
47
tests/test_png_paeth.c
Normal 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
75
tests/test_png_regress.c
Normal 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);
|
||||
}
|
@ -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
184
tests/truetype_test_win32.c
Normal 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;
|
||||
}
|
@ -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)
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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, '-');
|
||||
|
Loading…
Reference in New Issue
Block a user