fix for compiling with the c90 standard, support for non-static variable initializers...
[blender.git] / source / blender / imbuf / intern / divers.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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  * allocimbuf.c
28  *
29  * $Id$
30  */
31
32 #include "BLI_blenlib.h"
33 #include "BLI_rand.h"
34 #include "BLI_math.h"
35
36 #include "imbuf.h"
37 #include "IMB_imbuf_types.h"
38 #include "IMB_imbuf.h"
39 #include "IMB_allocimbuf.h"
40 #include "BKE_utildefines.h"
41 #include "BKE_colortools.h"
42
43 void IMB_de_interlace(struct ImBuf *ibuf)
44 {
45         struct ImBuf * tbuf1, * tbuf2;
46         
47         if (ibuf == 0) return;
48         if (ibuf->flags & IB_fields) return;
49         ibuf->flags |= IB_fields;
50         
51         if (ibuf->rect) {
52                 /* make copies */
53                 tbuf1 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect);
54                 tbuf2 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect);
55                 
56                 ibuf->x *= 2;   
57                 IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
58                 IMB_rectcpy(tbuf2, ibuf, 0, 0, tbuf2->x, 0, ibuf->x, ibuf->y);
59         
60                 ibuf->x /= 2;
61                 IMB_rectcpy(ibuf, tbuf1, 0, 0, 0, 0, tbuf1->x, tbuf1->y);
62                 IMB_rectcpy(ibuf, tbuf2, 0, tbuf2->y, 0, 0, tbuf2->x, tbuf2->y);
63                 
64                 IMB_freeImBuf(tbuf1);
65                 IMB_freeImBuf(tbuf2);
66         }
67         ibuf->y /= 2;
68 }
69
70 void IMB_interlace(struct ImBuf *ibuf)
71 {
72         struct ImBuf * tbuf1, * tbuf2;
73
74         if (ibuf == 0) return;
75         ibuf->flags &= ~IB_fields;
76
77         ibuf->y *= 2;
78
79         if (ibuf->rect) {
80                 /* make copies */
81                 tbuf1 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect);
82                 tbuf2 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect);
83
84                 IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
85                 IMB_rectcpy(tbuf2, ibuf, 0, 0, 0, tbuf2->y, ibuf->x, ibuf->y);
86
87                 ibuf->x *= 2;
88                 IMB_rectcpy(ibuf, tbuf1, 0, 0, 0, 0, tbuf1->x, tbuf1->y);
89                 IMB_rectcpy(ibuf, tbuf2, tbuf2->x, 0, 0, 0, tbuf2->x, tbuf2->y);
90                 ibuf->x /= 2;
91
92                 IMB_freeImBuf(tbuf1);
93                 IMB_freeImBuf(tbuf2);
94         }
95 }
96
97
98 /* assume converting from linear float to sRGB byte */
99 void IMB_rect_from_float(struct ImBuf *ibuf)
100 {
101         /* quick method to convert floatbuf to byte */
102         float *tof = (float *)ibuf->rect_float;
103 //      int do_dither = ibuf->dither != 0.f;
104         float dither= ibuf->dither / 255.0;
105         float srgb[4];
106         int i, channels= ibuf->channels;
107         short profile= ibuf->profile;
108         unsigned char *to = (unsigned char *) ibuf->rect;
109         
110         if(tof==NULL) return;
111         if(to==NULL) {
112                 imb_addrectImBuf(ibuf);
113                 to = (unsigned char *) ibuf->rect;
114         }
115         
116         if(channels==1) {
117                 for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof++)
118                         to[1]= to[2]= to[3]= to[0] = FTOCHAR(tof[0]);
119         }
120         else if (profile == IB_PROFILE_LINEAR_RGB) {
121                 if(channels == 3) {
122                         for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) {
123                                 srgb[0]= linearrgb_to_srgb(tof[0]);
124                                 srgb[1]= linearrgb_to_srgb(tof[1]);
125                                 srgb[2]= linearrgb_to_srgb(tof[2]);
126
127                                 to[0] = FTOCHAR(srgb[0]);
128                                 to[1] = FTOCHAR(srgb[1]);
129                                 to[2] = FTOCHAR(srgb[2]);
130                                 to[3] = 255;
131                         }
132                 }
133                 else if (channels == 4) {
134                         if (dither != 0.f) {
135                                 for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
136                                         const float d = (BLI_frand()-0.5)*dither;
137                                         
138                                         srgb[0]= d + linearrgb_to_srgb(tof[0]);
139                                         srgb[1]= d + linearrgb_to_srgb(tof[1]);
140                                         srgb[2]= d + linearrgb_to_srgb(tof[2]);
141                                         srgb[3]= d + tof[3]; 
142                                         
143                                         to[0] = FTOCHAR(srgb[0]);
144                                         to[1] = FTOCHAR(srgb[1]);
145                                         to[2] = FTOCHAR(srgb[2]);
146                                         to[3] = FTOCHAR(srgb[3]);
147                                 }
148                         } else {
149                                 floatbuf_to_srgb_byte(tof, to, 0, ibuf->x, 0, ibuf->y, ibuf->x);
150                         }
151                 }
152         }
153         else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) {
154                 if(channels==3) {
155                         for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) {
156                                 to[0] = FTOCHAR(tof[0]);
157                                 to[1] = FTOCHAR(tof[1]);
158                                 to[2] = FTOCHAR(tof[2]);
159                                 to[3] = 255;
160                         }
161                 }
162                 else {
163                         if (dither != 0.f) {
164                                 for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
165                                         const float d = (BLI_frand()-0.5)*dither;
166                                         float col[4];
167
168                                         col[0]= d + tof[0];
169                                         col[1]= d + tof[1];
170                                         col[2]= d + tof[2];
171                                         col[3]= d + tof[3];
172
173                                         to[0] = FTOCHAR(col[0]);
174                                         to[1] = FTOCHAR(col[1]);
175                                         to[2] = FTOCHAR(col[2]);
176                                         to[3] = FTOCHAR(col[3]);
177                                 }
178                         } else {
179                                 for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
180                                         to[0] = FTOCHAR(tof[0]);
181                                         to[1] = FTOCHAR(tof[1]);
182                                         to[2] = FTOCHAR(tof[2]);
183                                         to[3] = FTOCHAR(tof[3]);
184                                 }
185                         }
186                 }
187         }
188 }
189
190 void IMB_float_from_rect(struct ImBuf *ibuf)
191 {
192         /* quick method to convert byte to floatbuf */
193         float *tof = ibuf->rect_float;
194         int i;
195         unsigned char *to = (unsigned char *) ibuf->rect;
196         
197         if(to==NULL) return;
198         if(tof==NULL) {
199                 if (imb_addrectfloatImBuf(ibuf) == 0) return;
200                 tof = ibuf->rect_float;
201         }
202         
203         /* Float bufs should be stored linear */
204
205         if (ibuf->profile != IB_PROFILE_NONE) {
206                 /* if the image has been given a profile then we're working 
207                  * with color management in mind, so convert it to linear space */
208                 
209                 for (i = ibuf->x * ibuf->y; i > 0; i--) 
210                 {
211                         tof[0] = srgb_to_linearrgb(((float)to[0])*(1.0f/255.0f));
212                         tof[1] = srgb_to_linearrgb(((float)to[1])*(1.0f/255.0f));
213                         tof[2] = srgb_to_linearrgb(((float)to[2])*(1.0f/255.0f));
214                         tof[3] = ((float)to[3])*(1.0f/255.0f);
215                         to += 4; 
216                         tof += 4;
217                 }
218         } else {
219                 for (i = ibuf->x * ibuf->y; i > 0; i--) 
220                 {
221                         tof[0] = ((float)to[0])*(1.0f/255.0f);
222                         tof[1] = ((float)to[1])*(1.0f/255.0f);
223                         tof[2] = ((float)to[2])*(1.0f/255.0f);
224                         tof[3] = ((float)to[3])*(1.0f/255.0f);
225                         to += 4; 
226                         tof += 4;
227                 }
228         }
229 }
230
231 /* no profile conversion */
232 void IMB_float_from_rect_simple(struct ImBuf *ibuf)
233 {
234         int profile = IB_PROFILE_NONE;
235
236         /* no color management:
237          * don't disturb the existing profiles */
238         SWAP(int, ibuf->profile, profile);
239
240         IMB_float_from_rect(ibuf);
241
242         SWAP(int, ibuf->profile, profile);
243 }
244
245 void IMB_convert_profile(struct ImBuf *ibuf, int profile)
246 {
247         int ok= FALSE;
248         int i;
249
250         unsigned char *rct= (unsigned char *)ibuf->rect;
251         float *rctf= ibuf->rect_float;
252
253         if(ibuf->profile == profile)
254                 return;
255
256         if(ELEM(ibuf->profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* from */
257                 if(profile == IB_PROFILE_LINEAR_RGB) { /* to */
258                         if(ibuf->rect_float) {
259                                 for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
260                                         rctf[0]= srgb_to_linearrgb(rctf[0]);
261                                         rctf[1]= srgb_to_linearrgb(rctf[1]);
262                                         rctf[2]= srgb_to_linearrgb(rctf[2]);
263                                 }
264                         }
265                         if(ibuf->rect) {
266                                 for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
267                                         rctf[0]= (unsigned char)((srgb_to_linearrgb((float)rctf[0]/255.0f) * 255.0f) + 0.5f);
268                                         rctf[1]= (unsigned char)((srgb_to_linearrgb((float)rctf[1]/255.0f) * 255.0f) + 0.5f);
269                                         rctf[2]= (unsigned char)((srgb_to_linearrgb((float)rctf[2]/255.0f) * 255.0f) + 0.5f);
270                                 }
271                         }
272                         ok= TRUE;
273                 }
274         }
275         else if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { /* from */
276                 if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* to */
277                         if(ibuf->rect_float) {
278                                 for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
279                                         rctf[0]= linearrgb_to_srgb(rctf[0]);
280                                         rctf[1]= linearrgb_to_srgb(rctf[1]);
281                                         rctf[2]= linearrgb_to_srgb(rctf[2]);
282                                 }
283                         }
284                         if(ibuf->rect) {
285                                 for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
286                                         rctf[0]= (unsigned char)((linearrgb_to_srgb((float)rctf[0]/255.0f) * 255.0f) + 0.5f);
287                                         rctf[1]= (unsigned char)((linearrgb_to_srgb((float)rctf[1]/255.0f) * 255.0f) + 0.5f);
288                                         rctf[2]= (unsigned char)((linearrgb_to_srgb((float)rctf[2]/255.0f) * 255.0f) + 0.5f);
289                                 }
290                         }
291                         ok= TRUE;
292                 }
293         }
294
295         if(ok==FALSE){
296                 printf("IMB_convert_profile: failed profile conversion %d -> %d\n", ibuf->profile, profile);
297                 return;
298         }
299
300         ibuf->profile= profile;
301 }