Orange: more exr & imbuf cleanup
[blender.git] / source / blender / imbuf / intern / filter.c
1 /**
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  * filter.c
31  *
32  * $Id$
33  */
34
35 #include "BLI_blenlib.h"
36
37 #include "imbuf.h"
38 #include "imbuf_patch.h"
39 #include "IMB_imbuf_types.h"
40 #include "IMB_imbuf.h"
41 #include "IMB_filter.h"
42
43
44 /************************************************************************/
45 /*                              FILTERS                                 */
46 /************************************************************************/
47
48 static void filtrow(unsigned char *point, int x)
49 {
50         unsigned int c1,c2,c3,error;
51
52         if (x>1){
53                 c1 = c2 = *point;
54                 error = 2;
55                 for(x--;x>0;x--){
56                         c3 = point[4];
57                         c1 += (c2<<1) + c3 + error;
58                         error = c1 & 3;
59                         *point = c1 >> 2;
60                         point += 4;
61                         c1=c2;
62                         c2=c3;
63                 }
64                 *point = (c1 + (c2<<1) + c2 + error) >> 2;
65         }
66 }
67
68 static void filtrowf(float *point, int x)
69 {
70         float c1,c2,c3,error;
71         
72         if (x>1){
73                 c1 = c2 = *point;
74                 error = 2;
75                 for(x--;x>0;x--){
76                         c3 = point[4];
77                         c1 += (c2 * 2) + c3 + error;
78                         *point = c1 / 4.0;
79                         point += 4;
80                         c1=c2;
81                         c2=c3;
82                 }
83                 *point = (c1 + (c2 * 2) + c2 + error) / 4.0;
84         }
85 }
86
87
88
89 static void filtcolum(unsigned char *point, int y, int skip)
90 {
91         unsigned int c1,c2,c3,error;
92         unsigned char *point2;
93
94         if (y>1){
95                 c1 = c2 = *point;
96                 point2 = point;
97                 error = 2;
98                 for(y--;y>0;y--){
99                         point2 += skip;
100                         c3 = *point2;
101                         c1 += (c2<<1) + c3 +error;
102                         error = c1 & 3;
103                         *point = c1 >> 2;
104                         point=point2;
105                         c1=c2;
106                         c2=c3;
107                 }
108                 *point = (c1 + (c2<<1) + c2 + error) >> 2;
109         }
110 }
111
112 static void filtcolumf(float *point, int y, int skip)
113 {
114         float c1,c2,c3,error, *point2;
115         
116         if (y>1){
117                 c1 = c2 = *point;
118                 point2 = point;
119                 error = 2;
120                 for(y--;y>0;y--){
121                         point2 += skip;
122                         c3 = *point2;
123                         c1 += (c2 * 2) + c3 +error;
124                         *point = c1 / 4;
125                         point=point2;
126                         c1=c2;
127                         c2=c3;
128                 }
129                 *point = (c1 + (c2 * 2) + c2 + error) / 4;
130         }
131 }
132
133 void IMB_filtery(struct ImBuf *ibuf)
134 {
135         unsigned char *point;
136         float *pointf;
137         int x, y, skip, do_float = 0;
138
139         point = (unsigned char *)ibuf->rect;
140         pointf = ibuf->rect_float;
141
142         if (ibuf->rect_float != NULL) do_float = 1;
143
144         x = ibuf->x;
145         y = ibuf->y;
146         skip = x<<2;
147
148         for (;x>0;x--){
149                 if (ibuf->depth > 24) filtcolum(point,y,skip);
150                 point++;
151                 filtcolum(point,y,skip);
152                 point++;
153                 filtcolum(point,y,skip);
154                 point++;
155                 filtcolum(point,y,skip);
156                 point++;
157                 if (do_float) {
158                         if (ibuf->depth > 24) filtcolumf(pointf,y,skip);
159                         pointf++;
160                         filtcolumf(pointf,y,skip);
161                         pointf++;
162                         filtcolumf(pointf,y,skip);
163                         pointf++;
164                         filtcolumf(pointf,y,skip);
165                         pointf++;
166                 }
167         }
168 }
169
170
171 void imb_filterx(struct ImBuf *ibuf)
172 {
173         unsigned char *point;
174         float *pointf;
175         int x, y, skip, do_float =0;
176
177         point = (unsigned char *)ibuf->rect;
178         pointf = ibuf->rect_float;
179
180         if (ibuf->rect_float != NULL) do_float = 1;
181
182         x = ibuf->x;
183         y = ibuf->y;
184         skip = (x<<2) - 3;
185
186         for (;y>0;y--){
187                 if (ibuf->depth > 24) filtrow(point,x);
188                 point++;
189                 filtrow(point,x);
190                 point++;
191                 filtrow(point,x);
192                 point++;
193                 filtrow(point,x);
194                 point+=skip;
195                 if (do_float) {
196                         if (ibuf->depth > 24) filtrowf(pointf,x);
197                         pointf++;
198                         filtrowf(pointf,x);
199                         pointf++;
200                         filtrowf(pointf,x);
201                         pointf++;
202                         filtrowf(pointf,x);
203                         pointf+=skip;
204                 }
205         }
206 }
207
208
209 void IMB_filter(struct ImBuf *ibuf)
210 {
211         IMB_filtery(ibuf);
212         imb_filterx(ibuf);
213 }