f25872538cfbab612efeebe5dc809eeef0110a8e
[blender.git] / source / blender / imbuf / intern / imageprocess.c
1 /**
2  *
3  * ***** BEGIN GPL 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.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  * This file was moved here from the src/ directory. It is meant to
28  * deal with endianness. It resided in a general blending lib. The
29  * other functions were only used during rendering. This single
30  * function remained. It should probably move to imbuf/intern/util.c,
31  * but we'll keep it here for the time being. (nzc)*/
32
33 /*  imageprocess.c        MIXED MODEL
34  * 
35  *  april 95
36  * 
37  * $Id$
38  */
39
40 #include "IMB_imbuf_types.h"
41 #include "IMB_imbuf.h"
42 #include "math.h"
43
44 /* This define should be relocated to a global header some where  Kent Mein 
45 I stole it from util.h in the plugins api */
46 #define MAX2(x,y)                ( (x)>(y) ? (x) : (y) )
47
48 /* Only this one is used liberally here, and in imbuf */
49 void IMB_convert_rgba_to_abgr(struct ImBuf *ibuf)
50 {
51         int size;
52         unsigned char rt, *cp = (unsigned char *)ibuf->rect;
53         float rtf, *cpf = ibuf->rect_float;
54
55         if (ibuf->rect) {
56                 size = ibuf->x * ibuf->y;
57
58                 while(size-- > 0) {
59                         rt= cp[0];
60                         cp[0]= cp[3];
61                         cp[3]= rt;
62                         rt= cp[1];
63                         cp[1]= cp[2];
64                         cp[2]= rt;
65                         cp+= 4;
66                 }
67         }
68
69         if (ibuf->rect_float) {
70                 size = ibuf->x * ibuf->y;
71
72                 while(size-- > 0) {
73                         rtf= cpf[0];
74                         cpf[0]= cpf[3];
75                         cpf[3]= rtf;
76                         rtf= cpf[1];
77                         cpf[1]= cpf[2];
78                         cpf[2]= rtf;
79                         cpf+= 4;
80                 }
81         }
82 }
83 static void pixel_from_buffer(struct ImBuf *ibuf, unsigned char *outI, float *outF, int x, int y)
84
85 {
86         int offset = ibuf->x * y * 4 + 4*x;
87         
88         if (ibuf->rect)
89                 outI= (unsigned char *)ibuf->rect + offset;
90         
91         if (ibuf->rect_float)
92                 outF= (float *)ibuf->rect_float + offset;
93 }
94
95 /**************************************************************************
96 *                            INTERPOLATIONS 
97 *
98 * Reference and docs:
99 * http://wiki.blender.org/index.php/User:Damiles#Interpolations_Algorithms
100 ***************************************************************************/
101
102 /* BICUBIC Interpolation functions */
103 /*  More info: http://wiki.blender.org/index.php/User:Damiles#Bicubic_pixel_interpolation
104 */
105 /* function assumes out to be zero'ed, only does RGBA */
106
107 static float P(float k){
108         float p1, p2, p3, p4;
109         p1 = MAX2(k+2.0f,0);
110         p2 = MAX2(k+1.0f,0);
111         p3 = MAX2(k,0);
112         p4 = MAX2(k-1.0f,0);
113         return (float)(1.0f/6.0f)*( p1*p1*p1 - 4.0f * p2*p2*p2 + 6.0f * p3*p3*p3 - 4.0f * p4*p4*p4);
114 }
115
116
117 #if 0
118 /* older, slower function, works the same as above */
119 static float P(float k){
120         return (float)(1.0f/6.0f)*( pow( MAX2(k+2.0f,0) , 3.0f ) - 4.0f * pow( MAX2(k+1.0f,0) , 3.0f ) + 6.0f * pow( MAX2(k,0) , 3.0f ) - 4.0f * pow( MAX2(k-1.0f,0) , 3.0f));
121 }
122 #endif
123
124 void bicubic_interpolation_color(struct ImBuf *in, unsigned char *outI, float *outF, float u, float v)
125 {
126         int i,j,n,m,x1,y1;
127         unsigned char *dataI;
128         float a,b,w,wx,wy[4], outR,outG,outB,outA,*dataF;
129
130         /* ImBuf in must have a valid rect or rect_float, assume this is alredy checked */
131
132         i= (int)floor(u);
133         j= (int)floor(v);
134         a= u - i;
135         b= v - j;
136
137         outR = outG = outB = outA = 0.0f;
138         
139 /* Optimized and not so easy to read */
140         
141         /* avoid calling multiple times */
142         wy[0] = P(b-(-1));
143         wy[1] = P(b-  0);
144         wy[2] = P(b-  1);
145         wy[3] = P(b-  2);
146         
147         for(n= -1; n<= 2; n++){
148                 x1= i+n;
149                 if (x1>0 && x1 < in->x) {
150                         wx = P(n-a);
151                         for(m= -1; m<= 2; m++){
152                                 y1= j+m;
153                                 if (y1>0 && y1<in->y) {
154                                         /* normally we could do this */
155                                         /* w = P(n-a) * P(b-m); */
156                                         /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */
157                                         w = wx * wy[m+1];
158                                         
159                                         if (outF) {
160                                                 dataF= in->rect_float + in->x * y1 * 4 + 4*x1;
161                                                 outR+= dataF[0] * w;
162                                                 outG+= dataF[1] * w;
163                                                 outB+= dataF[2] * w;
164                                                 outA+= dataF[3] * w;
165                                         }
166                                         if (outI) {
167                                                 dataI= (unsigned char*)in->rect + in->x * y1 * 4 + 4*x1;
168                                                 outR+= dataI[0] * w;
169                                                 outG+= dataI[1] * w;
170                                                 outB+= dataI[2] * w;
171                                                 outA+= dataI[3] * w;
172                                         }
173                                 }
174                         }
175                 }
176         }
177
178 /* Done with optimized part */
179         
180 #if 0 
181         /* older, slower function, works the same as above */
182         for(n= -1; n<= 2; n++){
183                 for(m= -1; m<= 2; m++){
184                         x1= i+n;
185                         y1= j+m;
186                         if (x1>0 && x1 < in->x && y1>0 && y1<in->y) {
187                                 if (do_float) {
188                                         dataF= in->rect_float + in->x * y1 * 4 + 4*x1;
189                                         outR+= dataF[0] * P(n-a) * P(b-m);
190                                         outG+= dataF[1] * P(n-a) * P(b-m);
191                                         outB+= dataF[2] * P(n-a) * P(b-m);
192                                         outA+= dataF[3] * P(n-a) * P(b-m);
193                                 }
194                                 if (do_rect) {
195                                         dataI= (unsigned char*)in->rect + in->x * y1 * 4 + 4*x1;
196                                         outR+= dataI[0] * P(n-a) * P(b-m);
197                                         outG+= dataI[1] * P(n-a) * P(b-m);
198                                         outB+= dataI[2] * P(n-a) * P(b-m);
199                                         outA+= dataI[3] * P(n-a) * P(b-m);
200                                 }
201                         }
202                 }
203         }
204 #endif
205         
206         if (outI) {
207                 outI[0]= (int)outR;
208                 outI[1]= (int)outG;
209                 outI[2]= (int)outB;
210                 outI[3]= (int)outA;
211         }
212         if (outF) {
213                 outF[0]= outR;
214                 outF[1]= outG;
215                 outF[2]= outB;
216                 outF[3]= outA;
217         }
218 }
219
220
221 void bicubic_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, int yout)
222 {
223         
224         unsigned char *outI = NULL;
225         float *outF = NULL;
226         
227         if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) return;
228         
229         pixel_from_buffer(out, outI, outF, xout, yout); /* gcc warns these could be uninitialized, but its ok */
230         
231         bicubic_interpolation_color(in, outI, outF, u, v);
232 }
233
234 /* function assumes out to be zero'ed, only does RGBA */
235 /* BILINEAR INTERPOLATION */
236 void bilinear_interpolation_color(struct ImBuf *in, unsigned char *outI, float *outF, float u, float v)
237 {
238         float *row1, *row2, *row3, *row4, a, b;
239         unsigned char *row1I, *row2I, *row3I, *row4I;
240         float a_b, ma_b, a_mb, ma_mb;
241         float empty[4]= {0.0f, 0.0f, 0.0f, 0.0f};
242         unsigned char emptyI[4]= {0, 0, 0, 0};
243         int y1, y2, x1, x2;
244         
245         
246         /* ImBuf in must have a valid rect or rect_float, assume this is alredy checked */
247
248         x1= (int)floor(u);
249         x2= (int)ceil(u);
250         y1= (int)floor(v);
251         y2= (int)ceil(v);
252
253         // sample area entirely outside image? 
254         if (x2<0 || x1>in->x-1 || y2<0 || y1>in->y-1) return;
255
256         if (outF) {
257                 // sample including outside of edges of image 
258                 if (x1<0 || y1<0) row1= empty;
259                 else row1= (float *)in->rect_float + in->x * y1 * 4 + 4*x1;
260                 
261                 if (x1<0 || y2>in->y-1) row2= empty;
262                 else row2= (float *)in->rect_float + in->x * y2 * 4 + 4*x1;
263                 
264                 if (x2>in->x-1 || y1<0) row3= empty;
265                 else row3= (float *)in->rect_float + in->x * y1 * 4 + 4*x2;
266                 
267                 if (x2>in->x-1 || y2>in->y-1) row4= empty;
268                 else row4= (float *)in->rect_float + in->x * y2 * 4 + 4*x2;
269                 
270                 a= u-floor(u);
271                 b= v-floor(v);
272                 a_b= a*b; ma_b= (1.0f-a)*b; a_mb= a*(1.0f-b); ma_mb= (1.0f-a)*(1.0f-b);
273                 
274                 outF[0]= ma_mb*row1[0] + a_mb*row3[0] + ma_b*row2[0]+ a_b*row4[0];
275                 outF[1]= ma_mb*row1[1] + a_mb*row3[1] + ma_b*row2[1]+ a_b*row4[1];
276                 outF[2]= ma_mb*row1[2] + a_mb*row3[2] + ma_b*row2[2]+ a_b*row4[2];
277                 outF[3]= ma_mb*row1[3] + a_mb*row3[3] + ma_b*row2[3]+ a_b*row4[3];
278         }
279         if (outI) {
280                 // sample including outside of edges of image 
281                 if (x1<0 || y1<0) row1I= emptyI;
282                 else row1I= (unsigned char *)in->rect + in->x * y1 * 4 + 4*x1;
283                 
284                 if (x1<0 || y2>in->y-1) row2I= emptyI;
285                 else row2I= (unsigned char *)in->rect + in->x * y2 * 4 + 4*x1;
286                 
287                 if (x2>in->x-1 || y1<0) row3I= emptyI;
288                 else row3I= (unsigned char *)in->rect + in->x * y1 * 4 + 4*x2;
289                 
290                 if (x2>in->x-1 || y2>in->y-1) row4I= emptyI;
291                 else row4I= (unsigned char *)in->rect + in->x * y2 * 4 + 4*x2;
292                 
293                 a= u-floor(u);
294                 b= v-floor(v);
295                 a_b= a*b; ma_b= (1.0f-a)*b; a_mb= a*(1.0f-b); ma_mb= (1.0f-a)*(1.0f-b);
296                 
297                 outI[0]= ma_mb*row1I[0] + a_mb*row3I[0] + ma_b*row2I[0]+ a_b*row4I[0];
298                 outI[1]= ma_mb*row1I[1] + a_mb*row3I[1] + ma_b*row2I[1]+ a_b*row4I[1];
299                 outI[2]= ma_mb*row1I[2] + a_mb*row3I[2] + ma_b*row2I[2]+ a_b*row4I[2];
300                 outI[3]= ma_mb*row1I[3] + a_mb*row3I[3] + ma_b*row2I[3]+ a_b*row4I[3];
301         }
302 }
303
304 void bilinear_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, int yout)
305 {
306         
307         unsigned char *outI = NULL;
308         float *outF = NULL;
309         
310         if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) return;
311         
312         pixel_from_buffer(out, outI, outF, xout, yout); /* gcc warns these could be uninitialized, but its ok */
313         
314         bilinear_interpolation_color(in, outI, outF, u, v);
315 }
316
317 /* function assumes out to be zero'ed, only does RGBA */
318 /* NEAREST INTERPOLATION */
319 void neareast_interpolation_color(struct ImBuf *in, unsigned char *outI, float *outF, float u, float v)
320 {
321         float *dataF;
322         unsigned char *dataI;
323         int y1, x1;
324
325         /* ImBuf in must have a valid rect or rect_float, assume this is alredy checked */
326         
327         x1= (int)(u);
328         y1= (int)(v);
329
330         // sample area entirely outside image? 
331         if (x1<0 || x1>in->x-1 || y1<0 || y1>in->y-1) return;
332         
333         // sample including outside of edges of image 
334         if (x1<0 || y1<0) {
335                 if (outI) {
336                         outI[0]= 0;
337                         outI[1]= 0;
338                         outI[2]= 0;
339                         outI[3]= 0;
340                 }
341                 if (outF) {
342                         outF[0]= 0.0f;
343                         outF[1]= 0.0f;
344                         outF[2]= 0.0f;
345                         outF[3]= 0.0f;
346                 }
347         } else {
348                 dataI= (unsigned char *)in->rect + in->x * y1 * 4 + 4*x1;
349                 if (outI) {
350                         outI[0]= dataI[0];
351                         outI[1]= dataI[1];
352                         outI[2]= dataI[2];
353                         outI[3]= dataI[3];
354                 }
355                 dataF= in->rect_float + in->x * y1 * 4 + 4*x1;
356                 if (outF) {
357                         outF[0]= dataF[0];
358                         outF[1]= dataF[1];
359                         outF[2]= dataF[2];
360                         outF[3]= dataF[3];
361                 }
362         }       
363 }
364
365 void neareast_interpolation(ImBuf *in, ImBuf *out, float x, float y, int xout, int yout)
366 {
367         
368         unsigned char *outI = NULL;
369         float *outF = NULL;
370
371         if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) return;
372         
373         pixel_from_buffer(out, outI, outF, xout, yout); /* gcc warns these could be uninitialized, but its ok */
374         
375         neareast_interpolation_color(in, outI, outF, x, y);
376 }