]> git.cworth.org Git - vogl/blob - src/voglcore/vogl_resampler.h
Initial vogl checkin
[vogl] / src / voglcore / vogl_resampler.h
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 // File: vogl_resampler.h
28 // RG: This is public domain code, originally derived from Graphics Gems 3, see: http://code.google.com/p/imageresampler/
29 #pragma once
30
31 #include "vogl_core.h"
32
33 namespace vogl
34 {
35 #define VOGL_RESAMPLER_DEBUG_OPS 0
36 #define VOGL_RESAMPLER_DEFAULT_FILTER "lanczos4"
37
38 #define VOGL_RESAMPLER_MAX_DIMENSION 16384
39
40     // float or double
41     typedef float Resample_Real;
42
43     class Resampler
44     {
45     public:
46         typedef Resample_Real Sample;
47
48         struct Contrib
49         {
50             Resample_Real weight;
51             unsigned short pixel;
52         };
53
54         struct Contrib_List
55         {
56             unsigned short n;
57             Contrib *p;
58         };
59
60         enum Boundary_Op
61         {
62             BOUNDARY_WRAP = 0,
63             BOUNDARY_REFLECT = 1,
64             BOUNDARY_CLAMP = 2
65         };
66
67         enum Status
68         {
69             STATUS_OKAY = 0,
70             STATUS_OUT_OF_MEMORY = 1,
71             STATUS_BAD_FILTER_NAME = 2,
72             STATUS_SCAN_BUFFER_FULL = 3
73         };
74
75         // src_x/src_y - Input dimensions
76         // dst_x/dst_y - Output dimensions
77         // boundary_op - How to sample pixels near the image boundaries
78         // sample_low/sample_high - Clamp output samples to specified range, or disable clamping if sample_low >= sample_high
79         // Pclist_x/Pclist_y - Optional pointers to contributor lists from another instance of a Resampler
80         // src_x_ofs/src_y_ofs - Offset input image by specified amount (fractional values okay)
81         Resampler(
82             int src_x, int src_y,
83             int dst_x, int dst_y,
84             Boundary_Op boundary_op = BOUNDARY_CLAMP,
85             Resample_Real sample_low = 0.0f, Resample_Real sample_high = 0.0f,
86             const char *Pfilter_name = VOGL_RESAMPLER_DEFAULT_FILTER,
87             Contrib_List *Pclist_x = NULL,
88             Contrib_List *Pclist_y = NULL,
89             Resample_Real filter_x_scale = 1.0f,
90             Resample_Real filter_y_scale = 1.0f,
91             Resample_Real src_x_ofs = 0.0f,
92             Resample_Real src_y_ofs = 0.0f);
93
94         ~Resampler();
95
96         // Reinits resampler so it can handle another frame.
97         void restart();
98
99         // false on out of memory.
100         bool put_line(const Sample *Psrc);
101
102         // NULL if no scanlines are currently available (give the resampler more scanlines!)
103         const Sample *get_line();
104
105         Status status() const
106         {
107             return m_status;
108         }
109
110         // Returned contributor lists can be shared with another Resampler.
111         void get_clists(Contrib_List **ptr_clist_x, Contrib_List **ptr_clist_y);
112         Contrib_List *get_clist_x() const
113         {
114             return m_Pclist_x;
115         }
116         Contrib_List *get_clist_y() const
117         {
118             return m_Pclist_y;
119         }
120
121         // Filter accessors.
122         static int get_filter_num();
123         static const char *get_filter_name(int filter_num);
124
125         static Contrib_List *make_clist(
126             int src_x, int dst_x, Boundary_Op boundary_op,
127             Resample_Real (*Pfilter)(Resample_Real),
128             Resample_Real filter_support,
129             Resample_Real filter_scale,
130             Resample_Real src_ofs);
131
132     private:
133         Resampler();
134         Resampler(const Resampler &o);
135         Resampler &operator=(const Resampler &o);
136
137 #ifdef VOGL_RESAMPLER_DEBUG_OPS
138         int total_ops;
139 #endif
140
141         int m_intermediate_x;
142
143         int m_resample_src_x;
144         int m_resample_src_y;
145         int m_resample_dst_x;
146         int m_resample_dst_y;
147
148         Boundary_Op m_boundary_op;
149
150         Sample *m_Pdst_buf;
151         Sample *m_Ptmp_buf;
152
153         Contrib_List *m_Pclist_x;
154         Contrib_List *m_Pclist_y;
155
156         bool m_clist_x_forced;
157         bool m_clist_y_forced;
158
159         bool m_delay_x_resample;
160
161         int *m_Psrc_y_count;
162         unsigned char *m_Psrc_y_flag;
163
164         // The maximum number of scanlines that can be buffered at one time.
165         enum
166         {
167             MAX_SCAN_BUF_SIZE = VOGL_RESAMPLER_MAX_DIMENSION
168         };
169
170         struct Scan_Buf
171         {
172             int scan_buf_y[MAX_SCAN_BUF_SIZE];
173             Sample *scan_buf_l[MAX_SCAN_BUF_SIZE];
174         };
175
176         Scan_Buf *m_Pscan_buf;
177
178         int m_cur_src_y;
179         int m_cur_dst_y;
180
181         Status m_status;
182
183         void resample_x(Sample *Pdst, const Sample *Psrc);
184         void scale_y_mov(Sample *Ptmp, const Sample *Psrc, Resample_Real weight, int dst_x);
185         void scale_y_add(Sample *Ptmp, const Sample *Psrc, Resample_Real weight, int dst_x);
186         void clamp(Sample *Pdst, int n);
187         void resample_y(Sample *Pdst);
188
189         static int reflect(const int j, const int src_x, const Boundary_Op boundary_op);
190
191         inline int count_ops(Contrib_List *Pclist, int k)
192         {
193             int i, t = 0;
194             for (i = 0; i < k; i++)
195                 t += Pclist[i].n;
196             return (t);
197         }
198
199         Resample_Real m_lo;
200         Resample_Real m_hi;
201
202         inline Resample_Real clamp_sample(Resample_Real f) const
203         {
204             if (f < m_lo)
205                 f = m_lo;
206             else if (f > m_hi)
207                 f = m_hi;
208             return f;
209         }
210     };
211
212 } // namespace vogl