blob: ee7a8134213b223b1bdb0e975d55d3aa95afa602 [file] [log] [blame]
Brian Paulcc8e37f2000-07-12 13:00:09 +00001/* $Id: convolve.c,v 1.1 2000/07/12 13:00:09 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28/*
29 * Image convolution functions.
30 *
31 * Notes: filter kernel elements are indexed by <n> and <m> as in
32 * the GL spec.
33 */
34
35
36#ifdef PC_HEADER
37#include "all.h"
38#else
39#include "glheader.h"
40#include "types.h"
41#endif
42
43
44void
45_mesa_convolve_1d_reduce(GLint srcWidth, const GLfloat src[][4],
46 GLint filterWidth, const GLfloat filter[][4],
47 GLfloat dest[][4])
48{
49 const GLint dstWidth = srcWidth - (filterWidth - 1);
50 GLint i, n;
51
52 if (dstWidth <= 0)
53 return; /* null result */
54
55 for (i = 0; i < dstWidth; i++) {
56 GLfloat sumR = 0.0;
57 GLfloat sumG = 0.0;
58 GLfloat sumB = 0.0;
59 GLfloat sumA = 0.0;
60 for (n = 0; n < filterWidth; n++) {
61 sumR += src[i + n][RCOMP] * filter[n][RCOMP];
62 sumG += src[i + n][GCOMP] * filter[n][GCOMP];
63 sumB += src[i + n][BCOMP] * filter[n][BCOMP];
64 sumA += src[i + n][ACOMP] * filter[n][ACOMP];
65 }
66 dest[i][RCOMP] = sumR;
67 dest[i][GCOMP] = sumG;
68 dest[i][BCOMP] = sumB;
69 dest[i][ACOMP] = sumA;
70 }
71}
72
73
74void
75_mesa_convolve_1d_constant(GLint srcWidth, const GLfloat src[][4],
76 GLint filterWidth, const GLfloat filter[][4],
77 const GLfloat borderColor[4], GLfloat dest[][4])
78{
79 const GLint halfFilterWidth = filterWidth / 2;
80 GLint i, n;
81
82 for (i = 0; i < srcWidth; i++) {
83 GLfloat sumR = 0.0;
84 GLfloat sumG = 0.0;
85 GLfloat sumB = 0.0;
86 GLfloat sumA = 0.0;
87 for (n = 0; n < filterWidth; n++) {
88 if (i + n < halfFilterWidth || i + n - halfFilterWidth >= srcWidth) {
89 sumR += borderColor[RCOMP] * filter[n][RCOMP];
90 sumG += borderColor[GCOMP] * filter[n][GCOMP];
91 sumB += borderColor[BCOMP] * filter[n][BCOMP];
92 sumA += borderColor[ACOMP] * filter[n][ACOMP];
93 }
94 else {
95 sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP];
96 sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP];
97 sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP];
98 sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP];
99 }
100 }
101 dest[i][RCOMP] = sumR;
102 dest[i][GCOMP] = sumG;
103 dest[i][BCOMP] = sumB;
104 dest[i][ACOMP] = sumA;
105 }
106}
107
108
109void
110_mesa_convolve_1d_replicate(GLint srcWidth, const GLfloat src[][4],
111 GLint filterWidth, const GLfloat filter[][4],
112 GLfloat dest[][4])
113{
114 const GLint halfFilterWidth = filterWidth / 2;
115 GLint i, n;
116
117 for (i = 0; i < srcWidth; i++) {
118 GLfloat sumR = 0.0;
119 GLfloat sumG = 0.0;
120 GLfloat sumB = 0.0;
121 GLfloat sumA = 0.0;
122 for (n = 0; n < filterWidth; n++) {
123 if (i + n < halfFilterWidth) {
124 sumR += src[0][RCOMP] * filter[n][RCOMP];
125 sumG += src[0][GCOMP] * filter[n][GCOMP];
126 sumB += src[0][BCOMP] * filter[n][BCOMP];
127 sumA += src[0][ACOMP] * filter[n][ACOMP];
128 }
129 else if (i + n - halfFilterWidth >= srcWidth) {
130 sumR += src[srcWidth - 1][RCOMP] * filter[n][RCOMP];
131 sumG += src[srcWidth - 1][GCOMP] * filter[n][GCOMP];
132 sumB += src[srcWidth - 1][BCOMP] * filter[n][BCOMP];
133 sumA += src[srcWidth - 1][ACOMP] * filter[n][ACOMP];
134 }
135 else {
136 sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP];
137 sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP];
138 sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP];
139 sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP];
140 }
141 }
142 dest[i][RCOMP] = sumR;
143 dest[i][GCOMP] = sumG;
144 dest[i][BCOMP] = sumB;
145 dest[i][ACOMP] = sumA;
146 }
147}
148
149
150/*
151 * <src> is the source image width width = srcWidth, height = filterHeight.
152 * <filter> has width <filterWidth> and height <filterHeight>.
153 * <dst> is a 1-D image span of width <srcWidth> - (<filterWidth> - 1).
154 */
155void
156_mesa_convolve_2d_reduce(GLint srcWidth, GLint srcHeight,
157 const GLfloat src[][4],
158 GLint filterWidth, GLint filterHeight,
159 const GLfloat filter[][4],
160 GLfloat dest[][4])
161{
162 const GLint dstWidth = srcWidth - (filterWidth - 1);
163 GLint i, n, m;
164
165 if (dstWidth <= 0)
166 return; /* null result */
167
168 /* XXX todo */
169 for (i = 0; i < dstWidth; i++) {
170 GLfloat sumR = 0.0;
171 GLfloat sumG = 0.0;
172 GLfloat sumB = 0.0;
173 GLfloat sumA = 0.0;
174 for (n = 0; n < filterHeight; n++) {
175 for (m = 0; m < filterWidth; m++) {
176 const GLint k = n * srcWidth + i + m;
177 sumR += src[k][RCOMP] * filter[n][RCOMP];
178 sumG += src[k][GCOMP] * filter[n][GCOMP];
179 sumB += src[k][BCOMP] * filter[n][BCOMP];
180 sumA += src[k][ACOMP] * filter[n][ACOMP];
181 }
182 }
183 dest[i][RCOMP] = sumR;
184 dest[i][GCOMP] = sumG;
185 dest[i][BCOMP] = sumB;
186 dest[i][ACOMP] = sumA;
187 }
188}
189
190
191void
192_mesa_convolve_2d_constant(GLint srcWidth, GLint srcHeight,
193 const GLfloat src[][4],
194 GLint filterWidth, GLint filterHeight,
195 const GLfloat filter[][4],
196 GLfloat dest[][4],
197 const GLfloat borderColor[4])
198{
199 const GLint halfFilterWidth = filterWidth / 2;
200 GLint i, n, m;
201
202 for (i = 0; i < srcWidth; i++) {
203 GLfloat sumR = 0.0;
204 GLfloat sumG = 0.0;
205 GLfloat sumB = 0.0;
206 GLfloat sumA = 0.0;
207 for (m = 0; m < filterHeight; m++) {
208 const GLfloat (*filterRow)[4] = filter + m * filterWidth;
209 for (n = 0; n < filterWidth; n++) {
210 if (i + n < halfFilterWidth ||
211 i + n - halfFilterWidth >= srcWidth) {
212 sumR += borderColor[RCOMP] * filterRow[n][RCOMP];
213 sumG += borderColor[GCOMP] * filterRow[n][GCOMP];
214 sumB += borderColor[BCOMP] * filterRow[n][BCOMP];
215 sumA += borderColor[ACOMP] * filterRow[n][ACOMP];
216 }
217 else {
218 const GLint k = m * srcWidth + i + n - halfFilterWidth;
219 sumR += src[k][RCOMP] * filterRow[n][RCOMP];
220 sumG += src[k][GCOMP] * filterRow[n][GCOMP];
221 sumB += src[k][BCOMP] * filterRow[n][BCOMP];
222 sumA += src[k][ACOMP] * filterRow[n][ACOMP];
223 }
224 }
225 }
226 dest[i][RCOMP] = sumR;
227 dest[i][GCOMP] = sumG;
228 dest[i][BCOMP] = sumB;
229 dest[i][ACOMP] = sumA;
230 }
231}
232
233
234void
235_mesa_convolve_2d_replicate(GLint srcWidth, GLint srcHeight,
236 const GLfloat src[][4],
237 GLint filterWidth, GLint filterHeight,
238 const GLfloat filter[][4],
239 GLfloat dest[][4])
240{
241 const GLint halfFilterWidth = filterWidth / 2;
242 GLint i, n, m;
243
244 for (i = 0; i < srcWidth; i++) {
245 GLfloat sumR = 0.0;
246 GLfloat sumG = 0.0;
247 GLfloat sumB = 0.0;
248 GLfloat sumA = 0.0;
249 for (m = 0; m < filterHeight; m++) {
250 const GLfloat (*filterRow)[4] = filter + m * filterWidth;
251 for (n = 0; n < filterWidth; n++) {
252 if (i + n < halfFilterWidth) {
253 const GLint k = m * srcWidth + 0;
254 sumR += src[k][RCOMP] * filterRow[n][RCOMP];
255 sumG += src[k][GCOMP] * filterRow[n][GCOMP];
256 sumB += src[k][BCOMP] * filterRow[n][BCOMP];
257 sumA += src[k][ACOMP] * filterRow[n][ACOMP];
258 }
259 else if (i + n - halfFilterWidth >= srcWidth) {
260 const GLint k = m * srcWidth + srcWidth - 1;
261 sumR += src[k][RCOMP] * filterRow[n][RCOMP];
262 sumG += src[k][GCOMP] * filterRow[n][GCOMP];
263 sumB += src[k][BCOMP] * filterRow[n][BCOMP];
264 sumA += src[k][ACOMP] * filterRow[n][ACOMP];
265 }
266 else {
267 const GLint k = m * srcWidth + i + n - halfFilterWidth;
268 sumR += src[k][RCOMP] * filterRow[n][RCOMP];
269 sumG += src[k][GCOMP] * filterRow[n][GCOMP];
270 sumB += src[k][BCOMP] * filterRow[n][BCOMP];
271 sumA += src[k][ACOMP] * filterRow[n][ACOMP];
272 }
273 }
274 }
275 dest[i][RCOMP] = sumR;
276 dest[i][GCOMP] = sumG;
277 dest[i][BCOMP] = sumB;
278 dest[i][ACOMP] = sumA;
279 }
280}
281
282
283void
284_mesa_convolve_sep_constant(GLint srcWidth, GLint srcHeight,
285 const GLfloat src[][4],
286 GLint filterWidth, GLint filterHeight,
287 const GLfloat rowFilt[][4],
288 const GLfloat colFilt[][4],
289 GLfloat dest[][4],
290 const GLfloat borderColor[4])
291{
292 const GLint halfFilterWidth = filterWidth / 2;
293 GLint i, n, m;
294
295 for (i = 0; i < srcWidth; i++) {
296 GLfloat sumR = 0.0;
297 GLfloat sumG = 0.0;
298 GLfloat sumB = 0.0;
299 GLfloat sumA = 0.0;
300 for (m = 0; m < filterHeight; m++) {
301 for (n = 0; n < filterWidth; n++) {
302 if (i + n < halfFilterWidth ||
303 i + n - halfFilterWidth >= srcWidth) {
304 sumR += borderColor[RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
305 sumG += borderColor[GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
306 sumB += borderColor[BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
307 sumA += borderColor[ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
308 }
309 else {
310 const GLint k = m * srcWidth + i + n - halfFilterWidth;
311 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
312 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
313 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
314 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
315 }
316 }
317 }
318 dest[i][RCOMP] = sumR;
319 dest[i][GCOMP] = sumG;
320 dest[i][BCOMP] = sumB;
321 dest[i][ACOMP] = sumA;
322 }
323}
324
325
326void
327_mesa_convolve_sep_reduce(GLint srcWidth, GLint srcHeight,
328 const GLfloat src[][4],
329 GLint filterWidth, GLint filterHeight,
330 const GLfloat rowFilt[][4],
331 const GLfloat colFilt[][4],
332 GLfloat dest[][4])
333{
334#if 00
335 const GLint halfFilterWidth = filterWidth / 2;
336 GLint i, n, m;
337
338 for (i = 0; i < srcWidth; i++) {
339 GLfloat sumR = 0.0;
340 GLfloat sumG = 0.0;
341 GLfloat sumB = 0.0;
342 GLfloat sumA = 0.0;
343 for (m = 0; m < filterHeight; m++) {
344 for (n = 0; n < filterWidth; n++) {
345 if (i + n < halfFilterWidth ||
346 i + n - halfFilterWidth >= srcWidth) {
347 sumR += borderColor[RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
348 sumG += borderColor[GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
349 sumB += borderColor[BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
350 sumA += borderColor[ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
351 }
352 else {
353 const GLint k = m * srcWidth + i + n - halfFilterWidth;
354 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
355 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
356 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
357 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
358 }
359 }
360 }
361 dest[i][RCOMP] = sumR;
362 dest[i][GCOMP] = sumG;
363 dest[i][BCOMP] = sumB;
364 dest[i][ACOMP] = sumA;
365 }
366#endif
367}
368
369
370void
371_mesa_convolve_sep_replicate(GLint srcWidth, GLint srcHeight,
372 const GLfloat src[][4],
373 GLint filterWidth, GLint filterHeight,
374 const GLfloat rowFilt[][4],
375 const GLfloat colFilt[][4],
376 GLfloat dest[][4])
377{
378 const GLint halfFilterWidth = filterWidth / 2;
379 GLint i, n, m;
380
381 for (i = 0; i < srcWidth; i++) {
382 GLfloat sumR = 0.0;
383 GLfloat sumG = 0.0;
384 GLfloat sumB = 0.0;
385 GLfloat sumA = 0.0;
386 for (m = 0; m < filterHeight; m++) {
387 for (n = 0; n < filterWidth; n++) {
388 if (i + n < halfFilterWidth) {
389 const GLint k = m * srcWidth + 0;
390 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
391 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
392 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
393 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
394 }
395 else if (i + n - halfFilterWidth >= srcWidth) {
396 const GLint k = m * srcWidth + srcWidth - 1;
397 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
398 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
399 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
400 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
401 }
402 else {
403 const GLint k = m * srcWidth + i + n - halfFilterWidth;
404 sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
405 sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
406 sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
407 sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
408 }
409 }
410 }
411 dest[i][RCOMP] = sumR;
412 dest[i][GCOMP] = sumG;
413 dest[i][BCOMP] = sumB;
414 dest[i][ACOMP] = sumA;
415 }
416}