Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/basis_universal/encoder/basisu_resampler.h
9903 views
1
// basisu_resampler.h
2
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
3
//
4
// Licensed under the Apache License, Version 2.0 (the "License");
5
// you may not use this file except in compliance with the License.
6
// You may obtain a copy of the License at
7
//
8
// http://www.apache.org/licenses/LICENSE-2.0
9
//
10
// Unless required by applicable law or agreed to in writing, software
11
// distributed under the License is distributed on an "AS IS" BASIS,
12
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
// See the License for the specific language governing permissions and
14
// limitations under the License.
15
#pragma once
16
#include "../transcoder/basisu.h"
17
18
#define BASISU_RESAMPLER_DEBUG_OPS (0)
19
#define BASISU_RESAMPLER_DEFAULT_FILTER "lanczos4"
20
#define BASISU_RESAMPLER_MAX_DIMENSION (16384)
21
22
namespace basisu
23
{
24
// float or double
25
typedef float Resample_Real;
26
27
class Resampler
28
{
29
public:
30
typedef Resample_Real Sample;
31
32
struct Contrib
33
{
34
Resample_Real weight;
35
uint16_t pixel;
36
};
37
38
struct Contrib_List
39
{
40
uint16_t n;
41
Contrib *p;
42
};
43
44
enum Boundary_Op
45
{
46
BOUNDARY_WRAP = 0,
47
BOUNDARY_REFLECT = 1,
48
BOUNDARY_CLAMP = 2
49
};
50
51
enum Status
52
{
53
STATUS_OKAY = 0,
54
STATUS_OUT_OF_MEMORY = 1,
55
STATUS_BAD_FILTER_NAME = 2,
56
STATUS_SCAN_BUFFER_FULL = 3
57
};
58
59
// src_x/src_y - Input dimensions
60
// dst_x/dst_y - Output dimensions
61
// boundary_op - How to sample pixels near the image boundaries
62
// sample_low/sample_high - Clamp output samples to specified range, or disable clamping if sample_low >= sample_high
63
// Pclist_x/Pclist_y - Optional pointers to contributor lists from another instance of a Resampler
64
// src_x_ofs/src_y_ofs - Offset input image by specified amount (fractional values okay)
65
Resampler(
66
int src_x, int src_y,
67
int dst_x, int dst_y,
68
Boundary_Op boundary_op = BOUNDARY_CLAMP,
69
Resample_Real sample_low = 0.0f, Resample_Real sample_high = 0.0f,
70
const char *Pfilter_name = BASISU_RESAMPLER_DEFAULT_FILTER,
71
Contrib_List *Pclist_x = NULL,
72
Contrib_List *Pclist_y = NULL,
73
Resample_Real filter_x_scale = 1.0f,
74
Resample_Real filter_y_scale = 1.0f,
75
Resample_Real src_x_ofs = 0.0f,
76
Resample_Real src_y_ofs = 0.0f);
77
78
~Resampler();
79
80
// Reinits resampler so it can handle another frame.
81
void restart();
82
83
// false on out of memory.
84
bool put_line(const Sample *Psrc);
85
86
// NULL if no scanlines are currently available (give the resampler more scanlines!)
87
const Sample *get_line();
88
89
Status status() const
90
{
91
return m_status;
92
}
93
94
// Returned contributor lists can be shared with another Resampler.
95
void get_clists(Contrib_List **ptr_clist_x, Contrib_List **ptr_clist_y);
96
Contrib_List *get_clist_x() const
97
{
98
return m_Pclist_x;
99
}
100
Contrib_List *get_clist_y() const
101
{
102
return m_Pclist_y;
103
}
104
105
// Filter accessors.
106
static int get_filter_num();
107
static const char *get_filter_name(int filter_num);
108
109
static Contrib_List *make_clist(
110
int src_x, int dst_x, Boundary_Op boundary_op,
111
Resample_Real(*Pfilter)(Resample_Real),
112
Resample_Real filter_support,
113
Resample_Real filter_scale,
114
Resample_Real src_ofs);
115
116
static void free_clist(Contrib_List* p) { if (p) { free(p->p); free(p); } }
117
118
private:
119
Resampler();
120
Resampler(const Resampler &o);
121
Resampler &operator=(const Resampler &o);
122
123
#ifdef BASISU_RESAMPLER_DEBUG_OPS
124
int total_ops;
125
#endif
126
127
int m_intermediate_x;
128
129
int m_resample_src_x;
130
int m_resample_src_y;
131
int m_resample_dst_x;
132
int m_resample_dst_y;
133
134
Boundary_Op m_boundary_op;
135
136
Sample *m_Pdst_buf;
137
Sample *m_Ptmp_buf;
138
139
Contrib_List *m_Pclist_x;
140
Contrib_List *m_Pclist_y;
141
142
bool m_clist_x_forced;
143
bool m_clist_y_forced;
144
145
bool m_delay_x_resample;
146
147
int *m_Psrc_y_count;
148
uint8_t *m_Psrc_y_flag;
149
150
// The maximum number of scanlines that can be buffered at one time.
151
enum
152
{
153
MAX_SCAN_BUF_SIZE = BASISU_RESAMPLER_MAX_DIMENSION
154
};
155
156
struct Scan_Buf
157
{
158
int scan_buf_y[MAX_SCAN_BUF_SIZE];
159
Sample *scan_buf_l[MAX_SCAN_BUF_SIZE];
160
};
161
162
Scan_Buf *m_Pscan_buf;
163
164
int m_cur_src_y;
165
int m_cur_dst_y;
166
167
Status m_status;
168
169
void resample_x(Sample *Pdst, const Sample *Psrc);
170
void scale_y_mov(Sample *Ptmp, const Sample *Psrc, Resample_Real weight, int dst_x);
171
void scale_y_add(Sample *Ptmp, const Sample *Psrc, Resample_Real weight, int dst_x);
172
void clamp(Sample *Pdst, int n);
173
void resample_y(Sample *Pdst);
174
175
static int reflect(const int j, const int src_x, const Boundary_Op boundary_op);
176
177
inline int count_ops(Contrib_List *Pclist, int k)
178
{
179
int i, t = 0;
180
for (i = 0; i < k; i++)
181
t += Pclist[i].n;
182
return (t);
183
}
184
185
Resample_Real m_lo;
186
Resample_Real m_hi;
187
188
inline Resample_Real clamp_sample(Resample_Real f) const
189
{
190
if (f < m_lo)
191
f = m_lo;
192
else if (f > m_hi)
193
f = m_hi;
194
return f;
195
}
196
};
197
198
} // namespace basisu
199
200