38609d0a342825cbe4711963948a56aa045e2836
[blender.git] / source / blender / imbuf / intern / filter.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Morten Mikkelsen.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  * filter.c
27  *
28  */
29
30 /** \file blender/imbuf/intern/filter.c
31  *  \ingroup imbuf
32  */
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_utildefines.h"
37
38 #include "IMB_imbuf_types.h"
39 #include "IMB_imbuf.h"
40 #include "IMB_filter.h"
41
42 #include "imbuf.h"
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;
71         
72         if (x > 1) {
73                 c1 = c2 = *point;
74                 for (x--; x > 0; x--) {
75                         c3 = point[4];
76                         c1 += (c2 * 2) + c3;
77                         *point = 0.25f * c1;
78                         point += 4;
79                         c1 = c2;
80                         c2 = c3;
81                 }
82                 *point = 0.25f * (c1 + (c2 * 2) + c2);
83         }
84 }
85
86
87
88 static void filtcolum(unsigned char *point, int y, int skip)
89 {
90         unsigned int c1, c2, c3, error;
91         unsigned char *point2;
92
93         if (y > 1) {
94                 c1 = c2 = *point;
95                 point2 = point;
96                 error = 2;
97                 for (y--; y > 0; y--) {
98                         point2 += skip;
99                         c3 = *point2;
100                         c1 += (c2 << 1) + c3 + error;
101                         error = c1 & 3;
102                         *point = c1 >> 2;
103                         point = point2;
104                         c1 = c2;
105                         c2 = c3;
106                 }
107                 *point = (c1 + (c2 << 1) + c2 + error) >> 2;
108         }
109 }
110
111 static void filtcolumf(float *point, int y, int skip)
112 {
113         float c1, c2, c3, *point2;
114         
115         if (y > 1) {
116                 c1 = c2 = *point;
117                 point2 = point;
118                 for (y--; y > 0; y--) {
119                         point2 += skip;
120                         c3 = *point2;
121                         c1 += (c2 * 2) + c3;
122                         *point = 0.25f * c1;
123                         point = point2;
124                         c1 = c2;
125                         c2 = c3;
126                 }
127                 *point = 0.25f * (c1 + (c2 * 2) + c2);
128         }
129 }
130
131 void IMB_filtery(struct ImBuf *ibuf)
132 {
133         unsigned char *point;
134         float *pointf;
135         int x, y, skip;
136
137         point = (unsigned char *)ibuf->rect;
138         pointf = ibuf->rect_float;
139
140         x = ibuf->x;
141         y = ibuf->y;
142         skip = x << 2;
143
144         for (; x > 0; x--) {
145                 if (point) {
146                         if (ibuf->planes > 24) filtcolum(point, y, skip);
147                         point++;
148                         filtcolum(point, y, skip);
149                         point++;
150                         filtcolum(point, y, skip);
151                         point++;
152                         filtcolum(point, y, skip);
153                         point++;
154                 }
155                 if (pointf) {
156                         if (ibuf->planes > 24) filtcolumf(pointf, y, skip);
157                         pointf++;
158                         filtcolumf(pointf, y, skip);
159                         pointf++;
160                         filtcolumf(pointf, y, skip);
161                         pointf++;
162                         filtcolumf(pointf, y, skip);
163                         pointf++;
164                 }
165         }
166 }
167
168
169 void imb_filterx(struct ImBuf *ibuf)
170 {
171         unsigned char *point;
172         float *pointf;
173         int x, y, skip;
174
175         point = (unsigned char *)ibuf->rect;
176         pointf = ibuf->rect_float;
177
178         x = ibuf->x;
179         y = ibuf->y;
180         skip = (x << 2) - 3;
181
182         for (; y > 0; y--) {
183                 if (point) {
184                         if (ibuf->planes > 24) filtrow(point, x);
185                         point++;
186                         filtrow(point, x);
187                         point++;
188                         filtrow(point, x);
189                         point++;
190                         filtrow(point, x);
191                         point += skip;
192                 }
193                 if (pointf) {
194                         if (ibuf->planes > 24) filtrowf(pointf, x);
195                         pointf++;
196                         filtrowf(pointf, x);
197                         pointf++;
198                         filtrowf(pointf, x);
199                         pointf++;
200                         filtrowf(pointf, x);
201                         pointf += skip;
202                 }
203         }
204 }
205
206 static void imb_filterN(ImBuf *out, ImBuf *in)
207 {
208         BLI_assert(out->channels == in->channels);
209         BLI_assert(out->x == in->x && out->y == in->y);
210
211         const int channels = in->channels;
212         const int rowlen = in->x;
213         
214         if (in->rect && out->rect) {
215                 for (int y = 0; y < in->y; y++) {
216                         /* setup rows */
217                         const char *row2 = (const char *)in->rect + y * channels * rowlen;
218                         const char *row1 = (y == 0) ? row2 : row2 - channels * rowlen;
219                         const char *row3 = (y == in->y - 1) ? row2 : row2 + channels * rowlen;
220
221                         char *cp = (char *)out->rect + y * channels * rowlen;
222
223                         for (int x = 0; x < rowlen; x++) {
224                                 const char *r11, *r13, *r21, *r23, *r31, *r33;
225
226                                 if (x == 0) {
227                                         r11 = row1;
228                                         r21 = row2;
229                                         r31 = row3;
230                                 }
231                                 else {
232                                         r11 = row1 - channels;
233                                         r21 = row2 - channels;
234                                         r31 = row3 - channels;
235                                 }
236
237                                 if (x == rowlen - 1) {
238                                         r13 = row1;
239                                         r23 = row2;
240                                         r33 = row3;
241                                 }
242                                 else {
243                                         r13 = row1 + channels;
244                                         r23 = row2 + channels;
245                                         r33 = row3 + channels;
246                                 }
247
248                                 cp[0] = (r11[0] + 2 * row1[0] + r13[0] + 2 * r21[0] + 4 * row2[0] + 2 * r23[0] + r31[0] + 2 * row3[0] + r33[0]) >> 4;
249                                 cp[1] = (r11[1] + 2 * row1[1] + r13[1] + 2 * r21[1] + 4 * row2[1] + 2 * r23[1] + r31[1] + 2 * row3[1] + r33[1]) >> 4;
250                                 cp[2] = (r11[2] + 2 * row1[2] + r13[2] + 2 * r21[2] + 4 * row2[2] + 2 * r23[2] + r31[2] + 2 * row3[2] + r33[2]) >> 4;
251                                 cp[3] = (r11[3] + 2 * row1[3] + r13[3] + 2 * r21[3] + 4 * row2[3] + 2 * r23[3] + r31[3] + 2 * row3[3] + r33[3]) >> 4;
252                                 cp += channels; row1 += channels; row2 += channels; row3 += channels;
253                         }
254                 }
255         }
256
257         if (in->rect_float && out->rect_float) {
258                 for (int y = 0; y < in->y; y++) {
259                         /* setup rows */
260                         const float *row2 = (const float *)in->rect_float + y * channels * rowlen;
261                         const float *row1 = (y == 0) ? row2 : row2 - channels * rowlen;
262                         const float *row3 = (y == in->y - 1) ? row2 : row2 + channels * rowlen;
263
264                         float *cp = (float *)out->rect_float + y * channels * rowlen;
265
266                         for (int x = 0; x < rowlen; x++) {
267                                 const float *r11, *r13, *r21, *r23, *r31, *r33;
268
269                                 if (x == 0) {
270                                         r11 = row1;
271                                         r21 = row2;
272                                         r31 = row3;
273                                 }
274                                 else {
275                                         r11 = row1 - channels;
276                                         r21 = row2 - channels;
277                                         r31 = row3 - channels;
278                                 }
279
280                                 if (x == rowlen - 1) {
281                                         r13 = row1;
282                                         r23 = row2;
283                                         r33 = row3;
284                                 }
285                                 else {
286                                         r13 = row1 + channels;
287                                         r23 = row2 + channels;
288                                         r33 = row3 + channels;
289                                 }
290
291                                 cp[0] = (r11[0] + 2 * row1[0] + r13[0] + 2 * r21[0] + 4 * row2[0] + 2 * r23[0] + r31[0] + 2 * row3[0] + r33[0]) * (1.0f / 16.0f);
292                                 cp[1] = (r11[1] + 2 * row1[1] + r13[1] + 2 * r21[1] + 4 * row2[1] + 2 * r23[1] + r31[1] + 2 * row3[1] + r33[1]) * (1.0f / 16.0f);
293                                 cp[2] = (r11[2] + 2 * row1[2] + r13[2] + 2 * r21[2] + 4 * row2[2] + 2 * r23[2] + r31[2] + 2 * row3[2] + r33[2]) * (1.0f / 16.0f);
294                                 cp[3] = (r11[3] + 2 * row1[3] + r13[3] + 2 * r21[3] + 4 * row2[3] + 2 * r23[3] + r31[3] + 2 * row3[3] + r33[3]) * (1.0f / 16.0f);
295                                 cp += channels; row1 += channels; row2 += channels; row3 += channels;
296                         }
297                 }
298         }
299 }
300
301 void IMB_filter(struct ImBuf *ibuf)
302 {
303         IMB_filtery(ibuf);
304         imb_filterx(ibuf);
305 }
306
307 void IMB_mask_filter_extend(char *mask, int width, int height)
308 {
309         const char *row1, *row2, *row3;
310         int rowlen, x, y;
311         char *temprect;
312
313         rowlen = width;
314
315         /* make a copy, to prevent flooding */
316         temprect = MEM_dupallocN(mask);
317
318         for (y = 1; y <= height; y++) {
319                 /* setup rows */
320                 row1 = (char *)(temprect + (y - 2) * rowlen);
321                 row2 = row1 + rowlen;
322                 row3 = row2 + rowlen;
323                 if (y == 1)
324                         row1 = row2;
325                 else if (y == height)
326                         row3 = row2;
327
328                 for (x = 0; x < rowlen; x++) {
329                         if (mask[((y - 1) * rowlen) + x] == 0) {
330                                 if (*row1 || *row2 || *row3 || *(row1 + 1) || *(row3 + 1) ) {
331                                         mask[((y - 1) * rowlen) + x] = FILTER_MASK_MARGIN;
332                                 }
333                                 else if ((x != rowlen - 1) && (*(row1 + 2) || *(row2 + 2) || *(row3 + 2)) ) {
334                                         mask[((y - 1) * rowlen) + x] = FILTER_MASK_MARGIN;
335                                 }
336                         }
337
338                         if (x != 0) {
339                                 row1++; row2++; row3++;
340                         }
341                 }
342         }
343
344         MEM_freeN(temprect);
345 }
346
347 void IMB_mask_clear(ImBuf *ibuf, char *mask, int val)
348 {
349         int x, y;
350         if (ibuf->rect_float) {
351                 for (x = 0; x < ibuf->x; x++) {
352                         for (y = 0; y < ibuf->y; y++) {
353                                 if (mask[ibuf->x * y + x] == val) {
354                                         float *col = ibuf->rect_float + 4 * (ibuf->x * y + x);
355                                         col[0] = col[1] = col[2] = col[3] = 0.0f;
356                                 }
357                         }
358                 }
359         }
360         else {
361                 /* char buffer */
362                 for (x = 0; x < ibuf->x; x++) {
363                         for (y = 0; y < ibuf->y; y++) {
364                                 if (mask[ibuf->x * y + x] == val) {
365                                         char *col = (char *)(ibuf->rect + ibuf->x * y + x);
366                                         col[0] = col[1] = col[2] = col[3] = 0;
367                                 }
368                         }
369                 }
370         }
371 }
372
373 static int filter_make_index(const int x, const int y, const int w, const int h)
374 {
375         if (x < 0 || x >= w || y < 0 || y >= h) return -1;  /* return bad index */
376         else return y * w + x;
377 }
378
379 static int check_pixel_assigned(const void *buffer, const char *mask, const int index, const int depth, const bool is_float)
380 {
381         int res = 0;
382
383         if (index >= 0) {
384                 const int alpha_index = depth * index + (depth - 1);
385
386                 if (mask != NULL) {
387                         res = mask[index] != 0 ? 1 : 0;
388                 }
389                 else if ((is_float  && ((const float *) buffer)[alpha_index] != 0.0f) ||
390                          (!is_float && ((const unsigned char *) buffer)[alpha_index] != 0) )
391                 {
392                         res = 1;
393                 }
394         }
395
396         return res;
397 }
398
399 /* if alpha is zero, it checks surrounding pixels and averages color. sets new alphas to 1.0
400  * 
401  * When a mask is given, only effect pixels with a mask value of 1, defined as BAKE_MASK_MARGIN in rendercore.c
402  * */
403 void IMB_filter_extend(struct ImBuf *ibuf, char *mask, int filter)
404 {
405         const int width = ibuf->x;
406         const int height = ibuf->y;
407         const int depth = 4;     /* always 4 channels */
408         const int chsize = ibuf->rect_float ? sizeof(float) : sizeof(unsigned char);
409         const size_t bsize = ((size_t)width) * height * depth * chsize;
410         const bool is_float = (ibuf->rect_float != NULL);
411         void *dstbuf = (void *) MEM_dupallocN(ibuf->rect_float ? (void *) ibuf->rect_float : (void *) ibuf->rect);
412         char *dstmask = mask == NULL ? NULL : (char *) MEM_dupallocN(mask);
413         void *srcbuf = ibuf->rect_float ? (void *) ibuf->rect_float : (void *) ibuf->rect;
414         char *srcmask = mask;
415         int cannot_early_out = 1, r, n, k, i, j, c;
416         float weight[25];
417
418         /* build a weights buffer */
419         n = 1;
420
421 #if 0
422         k = 0;
423         for (i = -n; i <= n; i++)
424                 for (j = -n; j <= n; j++)
425                         weight[k++] = sqrt((float) i * i + j * j);
426 #endif
427
428         weight[0] = 1; weight[1] = 2; weight[2] = 1;
429         weight[3] = 2; weight[4] = 0; weight[5] = 2;
430         weight[6] = 1; weight[7] = 2; weight[8] = 1;
431
432         /* run passes */
433         for (r = 0; cannot_early_out == 1 && r < filter; r++) {
434                 int x, y;
435                 cannot_early_out = 0;
436
437                 for (y = 0; y < height; y++) {
438                         for (x = 0; x < width; x++) {
439                                 const int index = filter_make_index(x, y, width, height);
440
441                                 /* only update unassigned pixels */
442                                 if (!check_pixel_assigned(srcbuf, srcmask, index, depth, is_float)) {
443                                         float tmp[4];
444                                         float wsum = 0;
445                                         float acc[4] = {0, 0, 0, 0};
446                                         k = 0;
447
448                                         if (check_pixel_assigned(srcbuf, srcmask, filter_make_index(x - 1, y, width, height), depth, is_float) ||
449                                             check_pixel_assigned(srcbuf, srcmask, filter_make_index(x + 1, y, width, height), depth, is_float) ||
450                                             check_pixel_assigned(srcbuf, srcmask, filter_make_index(x, y - 1, width, height), depth, is_float) ||
451                                             check_pixel_assigned(srcbuf, srcmask, filter_make_index(x, y + 1, width, height), depth, is_float))
452                                         {
453                                                 for (i = -n; i <= n; i++) {
454                                                         for (j = -n; j <= n; j++) {
455                                                                 if (i != 0 || j != 0) {
456                                                                         const int tmpindex = filter_make_index(x + i, y + j, width, height);
457
458                                                                         if (check_pixel_assigned(srcbuf, srcmask, tmpindex, depth, is_float)) {
459                                                                                 if (is_float) {
460                                                                                         for (c = 0; c < depth; c++)
461                                                                                                 tmp[c] = ((const float *) srcbuf)[depth * tmpindex + c];
462                                                                                 }
463                                                                                 else {
464                                                                                         for (c = 0; c < depth; c++)
465                                                                                                 tmp[c] = (float) ((const unsigned char *) srcbuf)[depth * tmpindex + c];
466                                                                                 }
467
468                                                                                 wsum += weight[k];
469
470                                                                                 for (c = 0; c < depth; c++)
471                                                                                         acc[c] += weight[k] * tmp[c];
472                                                                         }
473                                                                 }
474                                                                 k++;
475                                                         }
476                                                 }
477
478                                                 if (wsum != 0) {
479                                                         for (c = 0; c < depth; c++)
480                                                                 acc[c] /= wsum;
481
482                                                         if (is_float) {
483                                                                 for (c = 0; c < depth; c++)
484                                                                         ((float *) dstbuf)[depth * index + c] = acc[c];
485                                                         }
486                                                         else {
487                                                                 for (c = 0; c < depth; c++) {
488                                                                         ((unsigned char *) dstbuf)[depth * index + c] = acc[c] > 255 ? 255 : (acc[c] < 0 ? 0 : ((unsigned char) (acc[c] + 0.5f)));
489                                                                 }
490                                                         }
491
492                                                         if (dstmask != NULL) dstmask[index] = FILTER_MASK_MARGIN;  /* assigned */
493                                                         cannot_early_out = 1;
494                                                 }
495                                         }
496                                 }
497                         }
498                 }
499
500                 /* keep the original buffer up to date. */
501                 memcpy(srcbuf, dstbuf, bsize);
502                 if (dstmask != NULL) {
503                         memcpy(srcmask, dstmask, ((size_t)width) * height);
504                 }
505         }
506
507         /* free memory */
508         MEM_freeN(dstbuf);
509         if (dstmask != NULL) MEM_freeN(dstmask);
510 }
511
512 /* threadsafe version, only recreates existing maps */
513 void IMB_remakemipmap(ImBuf *ibuf, int use_filter)
514 {
515         ImBuf *hbuf = ibuf;
516         int curmap = 0;
517         
518         ibuf->miptot = 1;
519         
520         while (curmap < IMB_MIPMAP_LEVELS) {
521                 
522                 if (ibuf->mipmap[curmap]) {
523                         
524                         if (use_filter) {
525                                 ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, hbuf->planes, hbuf->flags);
526                                 imb_filterN(nbuf, hbuf);
527                                 imb_onehalf_no_alloc(ibuf->mipmap[curmap], nbuf);
528                                 IMB_freeImBuf(nbuf);
529                         }
530                         else
531                                 imb_onehalf_no_alloc(ibuf->mipmap[curmap], hbuf);
532                 }
533                 
534                 ibuf->miptot = curmap + 2;
535                 hbuf = ibuf->mipmap[curmap];
536                 if (hbuf)
537                         hbuf->miplevel = curmap + 1;
538                 
539                 if (!hbuf || (hbuf->x <= 2 && hbuf->y <= 2))
540                         break;
541                 
542                 curmap++;
543         }
544 }
545
546 /* frees too (if there) and recreates new data */
547 void IMB_makemipmap(ImBuf *ibuf, int use_filter)
548 {
549         ImBuf *hbuf = ibuf;
550         int curmap = 0;
551
552         imb_freemipmapImBuf(ibuf);
553         
554         /* no mipmap for non RGBA images */
555         if (ibuf->rect_float && ibuf->channels < 4)
556                 return;
557         
558         ibuf->miptot = 1;
559
560         while (curmap < IMB_MIPMAP_LEVELS) {
561                 if (use_filter) {
562                         ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, hbuf->planes, hbuf->flags);
563                         imb_filterN(nbuf, hbuf);
564                         ibuf->mipmap[curmap] = IMB_onehalf(nbuf);
565                         IMB_freeImBuf(nbuf);
566                 }
567                 else
568                         ibuf->mipmap[curmap] = IMB_onehalf(hbuf);
569
570                 ibuf->miptot = curmap + 2;
571                 hbuf = ibuf->mipmap[curmap];
572                 hbuf->miplevel = curmap + 1;
573
574                 if (hbuf->x < 2 && hbuf->y < 2)
575                         break;
576
577                 curmap++;
578         }
579 }
580
581 ImBuf *IMB_getmipmap(ImBuf *ibuf, int level)
582 {
583         CLAMP(level, 0, ibuf->miptot - 1);
584         return (level == 0) ? ibuf : ibuf->mipmap[level - 1];
585 }
586
587 void IMB_premultiply_rect(unsigned int *rect, char planes, int w, int h)
588 {
589         char *cp;
590         int x, y, val;
591
592         if (planes == 24) { /* put alpha at 255 */
593                 cp = (char *)(rect);
594
595                 for (y = 0; y < h; y++)
596                         for (x = 0; x < w; x++, cp += 4)
597                                 cp[3] = 255;
598         }
599         else {
600                 cp = (char *)(rect);
601
602                 for (y = 0; y < h; y++) {
603                         for (x = 0; x < w; x++, cp += 4) {
604                                 val = cp[3];
605                                 cp[0] = (cp[0] * val) >> 8;
606                                 cp[1] = (cp[1] * val) >> 8;
607                                 cp[2] = (cp[2] * val) >> 8;
608                         }
609                 }
610         }
611 }
612
613 void IMB_premultiply_rect_float(float *rect_float, int channels, int w, int h)
614 {
615         float val, *cp;
616         int x, y;
617
618         if (channels == 4) {
619                 cp = rect_float;
620                 for (y = 0; y < h; y++) {
621                         for (x = 0; x < w; x++, cp += 4) {
622                                 val = cp[3];
623                                 cp[0] = cp[0] * val;
624                                 cp[1] = cp[1] * val;
625                                 cp[2] = cp[2] * val;
626                         }
627                 }
628         }
629
630 }
631
632 void IMB_premultiply_alpha(ImBuf *ibuf)
633 {
634         if (ibuf == NULL)
635                 return;
636
637         if (ibuf->rect)
638                 IMB_premultiply_rect(ibuf->rect, ibuf->planes, ibuf->x, ibuf->y);
639
640         if (ibuf->rect_float)
641                 IMB_premultiply_rect_float(ibuf->rect_float, ibuf->channels, ibuf->x, ibuf->y);
642 }
643
644 void IMB_unpremultiply_rect(unsigned int *rect, char planes, int w, int h)
645 {
646         char *cp;
647         int x, y;
648         float val;
649
650         if (planes == 24) { /* put alpha at 255 */
651                 cp = (char *)(rect);
652
653                 for (y = 0; y < h; y++)
654                         for (x = 0; x < w; x++, cp += 4)
655                                 cp[3] = 255;
656         }
657         else {
658                 cp = (char *)(rect);
659
660                 for (y = 0; y < h; y++) {
661                         for (x = 0; x < w; x++, cp += 4) {
662                                 val = cp[3] != 0 ? 1.0f / (float)cp[3] : 1.0f;
663                                 cp[0] = FTOCHAR(cp[0] * val);
664                                 cp[1] = FTOCHAR(cp[1] * val);
665                                 cp[2] = FTOCHAR(cp[2] * val);
666                         }
667                 }
668         }
669 }
670
671 void IMB_unpremultiply_rect_float(float *rect_float, int channels, int w, int h)
672 {
673         float val, *fp;
674         int x, y;
675
676         if (channels == 4) {
677                 fp = rect_float;
678                 for (y = 0; y < h; y++) {
679                         for (x = 0; x < w; x++, fp += 4) {
680                                 val = fp[3] != 0.0f ? 1.0f / fp[3] : 1.0f;
681                                 fp[0] = fp[0] * val;
682                                 fp[1] = fp[1] * val;
683                                 fp[2] = fp[2] * val;
684                         }
685                 }
686         }
687
688 }
689
690 void IMB_unpremultiply_alpha(ImBuf *ibuf)
691 {
692         if (ibuf == NULL)
693                 return;
694
695         if (ibuf->rect)
696                 IMB_unpremultiply_rect(ibuf->rect, ibuf->planes, ibuf->x, ibuf->y);
697
698         if (ibuf->rect_float)
699                 IMB_unpremultiply_rect_float(ibuf->rect_float, ibuf->channels, ibuf->x, ibuf->y);
700 }