Blender  V2.93
divers.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  * allocimbuf.c
19  */
20 
25 #include "BLI_math.h"
26 #include "BLI_utildefines.h"
27 
28 #include "IMB_filter.h"
29 #include "IMB_imbuf.h"
30 #include "IMB_imbuf_types.h"
31 #include "imbuf.h"
32 
33 #include "IMB_colormanagement.h"
35 
36 #include "MEM_guardedalloc.h"
37 
38 /* -------------------------------------------------------------------- */
42 typedef struct DitherContext {
43  float dither;
45 
46 static DitherContext *create_dither_context(float dither)
47 {
48  DitherContext *di;
49 
50  di = MEM_mallocN(sizeof(DitherContext), "dithering context");
51  di->dither = dither;
52 
53  return di;
54 }
55 
57 {
58  MEM_freeN(di);
59 }
60 
63 /* -------------------------------------------------------------------- */
67 MINLINE void ushort_to_byte_v4(uchar b[4], const unsigned short us[4])
68 {
69  b[0] = unit_ushort_to_uchar(us[0]);
70  b[1] = unit_ushort_to_uchar(us[1]);
71  b[2] = unit_ushort_to_uchar(us[2]);
72  b[3] = unit_ushort_to_uchar(us[3]);
73 }
74 
75 MINLINE unsigned char ftochar(float value)
76 {
77  return unit_float_to_uchar_clamp(value);
78 }
79 
81  uchar b[4], const unsigned short us[4], DitherContext *di, float s, float t)
82 {
83 #define USHORTTOFLOAT(val) ((float)val / 65535.0f)
84  float dither_value = dither_random_value(s, t) * 0.0033f * di->dither;
85 
86  b[0] = ftochar(dither_value + USHORTTOFLOAT(us[0]));
87  b[1] = ftochar(dither_value + USHORTTOFLOAT(us[1]));
88  b[2] = ftochar(dither_value + USHORTTOFLOAT(us[2]));
89  b[3] = unit_ushort_to_uchar(us[3]);
90 
91 #undef USHORTTOFLOAT
92 }
93 
95  uchar b[4], const float f[4], DitherContext *di, float s, float t)
96 {
97  float dither_value = dither_random_value(s, t) * 0.0033f * di->dither;
98 
99  b[0] = ftochar(dither_value + f[0]);
100  b[1] = ftochar(dither_value + f[1]);
101  b[2] = ftochar(dither_value + f[2]);
102  b[3] = unit_float_to_uchar_clamp(f[3]);
103 }
104 
105 /* Test if colorspace conversions of pixels in buffer need to take into account alpha. */
106 bool IMB_alpha_affects_rgb(const ImBuf *ibuf)
107 {
108  return (ibuf->flags & IB_alphamode_channel_packed) == 0;
109 }
110 
111 /* float to byte pixels, output 4-channel RGBA */
113  const float *rect_from,
114  int channels_from,
115  float dither,
116  int profile_to,
117  int profile_from,
118  bool predivide,
119  int width,
120  int height,
121  int stride_to,
122  int stride_from)
123 {
124  float tmp[4];
125  int x, y;
126  DitherContext *di = NULL;
127  float inv_width = 1.0f / width;
128  float inv_height = 1.0f / height;
129 
130  /* we need valid profiles */
131  BLI_assert(profile_to != IB_PROFILE_NONE);
132  BLI_assert(profile_from != IB_PROFILE_NONE);
133 
134  if (dither) {
135  di = create_dither_context(dither);
136  }
137 
138  for (y = 0; y < height; y++) {
139  float t = y * inv_height;
140 
141  if (channels_from == 1) {
142  /* single channel input */
143  const float *from = rect_from + ((size_t)stride_from) * y;
144  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
145 
146  for (x = 0; x < width; x++, from++, to += 4) {
147  to[0] = to[1] = to[2] = to[3] = unit_float_to_uchar_clamp(from[0]);
148  }
149  }
150  else if (channels_from == 3) {
151  /* RGB input */
152  const float *from = rect_from + ((size_t)stride_from) * y * 3;
153  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
154 
155  if (profile_to == profile_from) {
156  /* no color space conversion */
157  for (x = 0; x < width; x++, from += 3, to += 4) {
159  to[3] = 255;
160  }
161  }
162  else if (profile_to == IB_PROFILE_SRGB) {
163  /* convert from linear to sRGB */
164  for (x = 0; x < width; x++, from += 3, to += 4) {
166  rgb_float_to_uchar(to, tmp);
167  to[3] = 255;
168  }
169  }
170  else if (profile_to == IB_PROFILE_LINEAR_RGB) {
171  /* convert from sRGB to linear */
172  for (x = 0; x < width; x++, from += 3, to += 4) {
174  rgb_float_to_uchar(to, tmp);
175  to[3] = 255;
176  }
177  }
178  }
179  else if (channels_from == 4) {
180  /* RGBA input */
181  const float *from = rect_from + ((size_t)stride_from) * y * 4;
182  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
183 
184  if (profile_to == profile_from) {
185  float straight[4];
186 
187  /* no color space conversion */
188  if (dither && predivide) {
189  for (x = 0; x < width; x++, from += 4, to += 4) {
190  premul_to_straight_v4_v4(straight, from);
191  float_to_byte_dither_v4(to, straight, di, (float)x * inv_width, t);
192  }
193  }
194  else if (dither) {
195  for (x = 0; x < width; x++, from += 4, to += 4) {
196  float_to_byte_dither_v4(to, from, di, (float)x * inv_width, t);
197  }
198  }
199  else if (predivide) {
200  for (x = 0; x < width; x++, from += 4, to += 4) {
201  premul_to_straight_v4_v4(straight, from);
202  rgba_float_to_uchar(to, straight);
203  }
204  }
205  else {
206  for (x = 0; x < width; x++, from += 4, to += 4) {
208  }
209  }
210  }
211  else if (profile_to == IB_PROFILE_SRGB) {
212  /* convert from linear to sRGB */
213  unsigned short us[4];
214  float straight[4];
215 
216  if (dither && predivide) {
217  for (x = 0; x < width; x++, from += 4, to += 4) {
218  premul_to_straight_v4_v4(straight, from);
220  ushort_to_byte_dither_v4(to, us, di, (float)x * inv_width, t);
221  }
222  }
223  else if (dither) {
224  for (x = 0; x < width; x++, from += 4, to += 4) {
226  ushort_to_byte_dither_v4(to, us, di, (float)x * inv_width, t);
227  }
228  }
229  else if (predivide) {
230  for (x = 0; x < width; x++, from += 4, to += 4) {
231  premul_to_straight_v4_v4(straight, from);
233  ushort_to_byte_v4(to, us);
234  }
235  }
236  else {
237  for (x = 0; x < width; x++, from += 4, to += 4) {
239  ushort_to_byte_v4(to, us);
240  }
241  }
242  }
243  else if (profile_to == IB_PROFILE_LINEAR_RGB) {
244  /* convert from sRGB to linear */
245  if (dither && predivide) {
246  for (x = 0; x < width; x++, from += 4, to += 4) {
248  float_to_byte_dither_v4(to, tmp, di, (float)x * inv_width, t);
249  }
250  }
251  else if (dither) {
252  for (x = 0; x < width; x++, from += 4, to += 4) {
254  float_to_byte_dither_v4(to, tmp, di, (float)x * inv_width, t);
255  }
256  }
257  else if (predivide) {
258  for (x = 0; x < width; x++, from += 4, to += 4) {
260  rgba_float_to_uchar(to, tmp);
261  }
262  }
263  else {
264  for (x = 0; x < width; x++, from += 4, to += 4) {
266  rgba_float_to_uchar(to, tmp);
267  }
268  }
269  }
270  }
271  }
272 
273  if (dither) {
275  }
276 }
277 
278 /* float to byte pixels, output 4-channel RGBA */
280  const float *rect_from,
281  int channels_from,
282  float dither,
283  bool predivide,
284  int width,
285  int height,
286  int stride_to,
287  int stride_from,
288  char *mask)
289 {
290  int x, y;
291  DitherContext *di = NULL;
292  float inv_width = 1.0f / width, inv_height = 1.0f / height;
293 
294  if (dither) {
295  di = create_dither_context(dither);
296  }
297 
298  for (y = 0; y < height; y++) {
299  float t = y * inv_height;
300 
301  if (channels_from == 1) {
302  /* single channel input */
303  const float *from = rect_from + ((size_t)stride_from) * y;
304  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
305 
306  for (x = 0; x < width; x++, from++, to += 4) {
307  if (*mask++ == FILTER_MASK_USED) {
308  to[0] = to[1] = to[2] = to[3] = unit_float_to_uchar_clamp(from[0]);
309  }
310  }
311  }
312  else if (channels_from == 3) {
313  /* RGB input */
314  const float *from = rect_from + ((size_t)stride_from) * y * 3;
315  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
316 
317  for (x = 0; x < width; x++, from += 3, to += 4) {
318  if (*mask++ == FILTER_MASK_USED) {
320  to[3] = 255;
321  }
322  }
323  }
324  else if (channels_from == 4) {
325  /* RGBA input */
326  const float *from = rect_from + ((size_t)stride_from) * y * 4;
327  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
328 
329  float straight[4];
330 
331  if (dither && predivide) {
332  for (x = 0; x < width; x++, from += 4, to += 4) {
333  if (*mask++ == FILTER_MASK_USED) {
334  premul_to_straight_v4_v4(straight, from);
335  float_to_byte_dither_v4(to, straight, di, (float)x * inv_width, t);
336  }
337  }
338  }
339  else if (dither) {
340  for (x = 0; x < width; x++, from += 4, to += 4) {
341  if (*mask++ == FILTER_MASK_USED) {
342  float_to_byte_dither_v4(to, from, di, (float)x * inv_width, t);
343  }
344  }
345  }
346  else if (predivide) {
347  for (x = 0; x < width; x++, from += 4, to += 4) {
348  if (*mask++ == FILTER_MASK_USED) {
349  premul_to_straight_v4_v4(straight, from);
350  rgba_float_to_uchar(to, straight);
351  }
352  }
353  }
354  else {
355  for (x = 0; x < width; x++, from += 4, to += 4) {
356  if (*mask++ == FILTER_MASK_USED) {
358  }
359  }
360  }
361  }
362  }
363 
364  if (dither) {
366  }
367 }
368 
369 /* byte to float pixels, input and output 4-channel RGBA */
370 void IMB_buffer_float_from_byte(float *rect_to,
371  const uchar *rect_from,
372  int profile_to,
373  int profile_from,
374  bool predivide,
375  int width,
376  int height,
377  int stride_to,
378  int stride_from)
379 {
380  float tmp[4];
381  int x, y;
382 
383  /* we need valid profiles */
384  BLI_assert(profile_to != IB_PROFILE_NONE);
385  BLI_assert(profile_from != IB_PROFILE_NONE);
386 
387  /* RGBA input */
388  for (y = 0; y < height; y++) {
389  const uchar *from = rect_from + stride_from * y * 4;
390  float *to = rect_to + ((size_t)stride_to) * y * 4;
391 
392  if (profile_to == profile_from) {
393  /* no color space conversion */
394  for (x = 0; x < width; x++, from += 4, to += 4) {
396  }
397  }
398  else if (profile_to == IB_PROFILE_LINEAR_RGB) {
399  /* convert sRGB to linear */
400  if (predivide) {
401  for (x = 0; x < width; x++, from += 4, to += 4) {
403  }
404  }
405  else {
406  for (x = 0; x < width; x++, from += 4, to += 4) {
408  }
409  }
410  }
411  else if (profile_to == IB_PROFILE_SRGB) {
412  /* convert linear to sRGB */
413  if (predivide) {
414  for (x = 0; x < width; x++, from += 4, to += 4) {
417  }
418  }
419  else {
420  for (x = 0; x < width; x++, from += 4, to += 4) {
422  linearrgb_to_srgb_v4(to, tmp);
423  }
424  }
425  }
426  }
427 }
428 
429 /* float to float pixels, output 4-channel RGBA */
430 void IMB_buffer_float_from_float(float *rect_to,
431  const float *rect_from,
432  int channels_from,
433  int profile_to,
434  int profile_from,
435  bool predivide,
436  int width,
437  int height,
438  int stride_to,
439  int stride_from)
440 {
441  int x, y;
442 
443  /* we need valid profiles */
444  BLI_assert(profile_to != IB_PROFILE_NONE);
445  BLI_assert(profile_from != IB_PROFILE_NONE);
446 
447  if (channels_from == 1) {
448  /* single channel input */
449  for (y = 0; y < height; y++) {
450  const float *from = rect_from + ((size_t)stride_from) * y;
451  float *to = rect_to + ((size_t)stride_to) * y * 4;
452 
453  for (x = 0; x < width; x++, from++, to += 4) {
454  to[0] = to[1] = to[2] = to[3] = from[0];
455  }
456  }
457  }
458  else if (channels_from == 3) {
459  /* RGB input */
460  for (y = 0; y < height; y++) {
461  const float *from = rect_from + ((size_t)stride_from) * y * 3;
462  float *to = rect_to + ((size_t)stride_to) * y * 4;
463 
464  if (profile_to == profile_from) {
465  /* no color space conversion */
466  for (x = 0; x < width; x++, from += 3, to += 4) {
467  copy_v3_v3(to, from);
468  to[3] = 1.0f;
469  }
470  }
471  else if (profile_to == IB_PROFILE_LINEAR_RGB) {
472  /* convert from sRGB to linear */
473  for (x = 0; x < width; x++, from += 3, to += 4) {
475  to[3] = 1.0f;
476  }
477  }
478  else if (profile_to == IB_PROFILE_SRGB) {
479  /* convert from linear to sRGB */
480  for (x = 0; x < width; x++, from += 3, to += 4) {
482  to[3] = 1.0f;
483  }
484  }
485  }
486  }
487  else if (channels_from == 4) {
488  /* RGBA input */
489  for (y = 0; y < height; y++) {
490  const float *from = rect_from + ((size_t)stride_from) * y * 4;
491  float *to = rect_to + ((size_t)stride_to) * y * 4;
492 
493  if (profile_to == profile_from) {
494  /* same profile, copy */
495  memcpy(to, from, sizeof(float) * ((size_t)4) * width);
496  }
497  else if (profile_to == IB_PROFILE_LINEAR_RGB) {
498  /* convert to sRGB to linear */
499  if (predivide) {
500  for (x = 0; x < width; x++, from += 4, to += 4) {
502  }
503  }
504  else {
505  for (x = 0; x < width; x++, from += 4, to += 4) {
507  }
508  }
509  }
510  else if (profile_to == IB_PROFILE_SRGB) {
511  /* convert from linear to sRGB */
512  if (predivide) {
513  for (x = 0; x < width; x++, from += 4, to += 4) {
515  }
516  }
517  else {
518  for (x = 0; x < width; x++, from += 4, to += 4) {
520  }
521  }
522  }
523  }
524  }
525 }
526 
527 typedef struct FloatToFloatThreadData {
528  float *rect_to;
529  const float *rect_from;
533  bool predivide;
534  int width;
538 
539 static void imb_buffer_float_from_float_thread_do(void *data_v,
540  int start_scanline,
541  int num_scanlines)
542 {
544  size_t offset_from = ((size_t)start_scanline) * data->stride_from * data->channels_from;
545  size_t offset_to = ((size_t)start_scanline) * data->stride_to * data->channels_from;
546  IMB_buffer_float_from_float(data->rect_to + offset_to,
547  data->rect_from + offset_from,
548  data->channels_from,
549  data->profile_to,
550  data->profile_from,
551  data->predivide,
552  data->width,
553  num_scanlines,
554  data->stride_to,
555  data->stride_from);
556 }
557 
559  const float *rect_from,
560  int channels_from,
561  int profile_to,
562  int profile_from,
563  bool predivide,
564  int width,
565  int height,
566  int stride_to,
567  int stride_from)
568 {
569  if (((size_t)width) * height < 64 * 64) {
571  rect_from,
572  channels_from,
573  profile_to,
574  profile_from,
575  predivide,
576  width,
577  height,
578  stride_to,
579  stride_from);
580  }
581  else {
583  data.rect_to = rect_to;
584  data.rect_from = rect_from;
585  data.channels_from = channels_from;
586  data.profile_to = profile_to;
587  data.profile_from = profile_from;
588  data.predivide = predivide;
589  data.width = width;
590  data.stride_to = stride_to;
591  data.stride_from = stride_from;
593  }
594 }
595 
596 /* float to float pixels, output 4-channel RGBA */
598  const float *rect_from,
599  int channels_from,
600  int width,
601  int height,
602  int stride_to,
603  int stride_from,
604  char *mask)
605 {
606  int x, y;
607 
608  if (channels_from == 1) {
609  /* single channel input */
610  for (y = 0; y < height; y++) {
611  const float *from = rect_from + ((size_t)stride_from) * y;
612  float *to = rect_to + ((size_t)stride_to) * y * 4;
613 
614  for (x = 0; x < width; x++, from++, to += 4) {
615  if (*mask++ == FILTER_MASK_USED) {
616  to[0] = to[1] = to[2] = to[3] = from[0];
617  }
618  }
619  }
620  }
621  else if (channels_from == 3) {
622  /* RGB input */
623  for (y = 0; y < height; y++) {
624  const float *from = rect_from + ((size_t)stride_from) * y * 3;
625  float *to = rect_to + ((size_t)stride_to) * y * 4;
626 
627  for (x = 0; x < width; x++, from += 3, to += 4) {
628  if (*mask++ == FILTER_MASK_USED) {
629  copy_v3_v3(to, from);
630  to[3] = 1.0f;
631  }
632  }
633  }
634  }
635  else if (channels_from == 4) {
636  /* RGBA input */
637  for (y = 0; y < height; y++) {
638  const float *from = rect_from + ((size_t)stride_from) * y * 4;
639  float *to = rect_to + ((size_t)stride_to) * y * 4;
640 
641  for (x = 0; x < width; x++, from += 4, to += 4) {
642  if (*mask++ == FILTER_MASK_USED) {
643  copy_v4_v4(to, from);
644  }
645  }
646  }
647  }
648 }
649 
650 /* byte to byte pixels, input and output 4-channel RGBA */
652  const uchar *rect_from,
653  int profile_to,
654  int profile_from,
655  bool predivide,
656  int width,
657  int height,
658  int stride_to,
659  int stride_from)
660 {
661  float tmp[4];
662  int x, y;
663 
664  /* we need valid profiles */
665  BLI_assert(profile_to != IB_PROFILE_NONE);
666  BLI_assert(profile_from != IB_PROFILE_NONE);
667 
668  /* always RGBA input */
669  for (y = 0; y < height; y++) {
670  const uchar *from = rect_from + ((size_t)stride_from) * y * 4;
671  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
672 
673  if (profile_to == profile_from) {
674  /* same profile, copy */
675  memcpy(to, from, sizeof(uchar[4]) * width);
676  }
677  else if (profile_to == IB_PROFILE_LINEAR_RGB) {
678  /* convert to sRGB to linear */
679  if (predivide) {
680  for (x = 0; x < width; x++, from += 4, to += 4) {
683  rgba_float_to_uchar(to, tmp);
684  }
685  }
686  else {
687  for (x = 0; x < width; x++, from += 4, to += 4) {
689  srgb_to_linearrgb_v4(tmp, tmp);
690  rgba_float_to_uchar(to, tmp);
691  }
692  }
693  }
694  else if (profile_to == IB_PROFILE_SRGB) {
695  /* convert from linear to sRGB */
696  if (predivide) {
697  for (x = 0; x < width; x++, from += 4, to += 4) {
700  rgba_float_to_uchar(to, tmp);
701  }
702  }
703  else {
704  for (x = 0; x < width; x++, from += 4, to += 4) {
706  linearrgb_to_srgb_v4(tmp, tmp);
707  rgba_float_to_uchar(to, tmp);
708  }
709  }
710  }
711  }
712 }
713 
716 /* -------------------------------------------------------------------- */
721 {
722  float *buffer;
723  const char *from_colorspace;
724 
725  /* verify we have a float buffer */
726  if (ibuf->rect_float == NULL) {
727  return;
728  }
729 
730  /* create byte rect if it didn't exist yet */
731  if (ibuf->rect == NULL) {
732  if (imb_addrectImBuf(ibuf) == 0) {
733  return;
734  }
735  }
736 
737  if (ibuf->float_colorspace == NULL) {
739  }
740  else {
741  from_colorspace = ibuf->float_colorspace->name;
742  }
743 
745 
746  /* first make float buffer in byte space */
747  const bool predivide = IMB_alpha_affects_rgb(ibuf);
749  ibuf->x,
750  ibuf->y,
751  ibuf->channels,
752  from_colorspace,
753  ibuf->rect_colorspace->name,
754  predivide);
755 
756  /* convert from float's premul alpha to byte's straight alpha */
757  if (IMB_alpha_affects_rgb(ibuf)) {
758  IMB_unpremultiply_rect_float(buffer, ibuf->channels, ibuf->x, ibuf->y);
759  }
760 
761  /* convert float to byte */
762  IMB_buffer_byte_from_float((unsigned char *)ibuf->rect,
763  buffer,
764  ibuf->channels,
765  ibuf->dither,
768  false,
769  ibuf->x,
770  ibuf->y,
771  ibuf->x,
772  ibuf->x);
773 
774  MEM_freeN(buffer);
775 
776  /* ensure user flag is reset */
777  ibuf->userflags &= ~IB_RECT_INVALID;
778 }
779 
781 {
782  float *rect_float;
783 
784  /* verify if we byte and float buffers */
785  if (ibuf->rect == NULL) {
786  return;
787  }
788 
789  /* allocate float buffer outside of image buffer,
790  * so work-in-progress color space conversion doesn't
791  * interfere with other parts of blender
792  */
793  rect_float = ibuf->rect_float;
794  if (rect_float == NULL) {
795  size_t size;
796 
797  size = ((size_t)ibuf->x) * ibuf->y;
798  size = sizeof(float[4]) * size;
799  ibuf->channels = 4;
800 
801  rect_float = MEM_callocN(size, "IMB_float_from_rect");
802 
803  if (rect_float == NULL) {
804  return;
805  }
806  }
807 
808  /* first, create float buffer in non-linear space */
809  IMB_buffer_float_from_byte(rect_float,
810  (unsigned char *)ibuf->rect,
813  false,
814  ibuf->x,
815  ibuf->y,
816  ibuf->x,
817  ibuf->x);
818 
819  /* then make float be in linear space */
821  rect_float, ibuf->x, ibuf->y, ibuf->channels, ibuf->rect_colorspace, false);
822 
823  /* byte buffer is straight alpha, float should always be premul */
824  if (IMB_alpha_affects_rgb(ibuf)) {
825  IMB_premultiply_rect_float(rect_float, ibuf->channels, ibuf->x, ibuf->y);
826  }
827 
828  if (ibuf->rect_float == NULL) {
829  ibuf->rect_float = rect_float;
830  ibuf->mall |= IB_rectfloat;
831  ibuf->flags |= IB_rectfloat;
832  }
833 }
834 
837 /* -------------------------------------------------------------------- */
841 /* no profile conversion */
843 {
844  float *rct_fl = ibuf->rect_float;
845  uchar *rct = (uchar *)ibuf->rect;
846  size_t i;
847 
848  if (rct_fl) {
849  for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4) {
850  rct_fl[0] = rct_fl[1] = rct_fl[2] = IMB_colormanagement_get_luminance(rct_fl);
851  }
852  }
853 
854  if (rct) {
855  for (i = ((size_t)ibuf->x * ibuf->y); i > 0; i--, rct += 4) {
856  rct[0] = rct[1] = rct[2] = IMB_colormanagement_get_luminance_byte(rct);
857  }
858  }
859 }
860 
861 void IMB_buffer_float_unpremultiply(float *buf, int width, int height)
862 {
863  size_t total = ((size_t)width) * height;
864  float *fp = buf;
865  while (total--) {
867  fp += 4;
868  }
869 }
870 
871 void IMB_buffer_float_premultiply(float *buf, int width, int height)
872 {
873  size_t total = ((size_t)width) * height;
874  float *fp = buf;
875  while (total--) {
877  fp += 4;
878  }
879 }
880 
883 /* -------------------------------------------------------------------- */
887 void IMB_saturation(ImBuf *ibuf, float sat)
888 {
889  size_t i;
890  unsigned char *rct = (unsigned char *)ibuf->rect;
891  float *rct_fl = ibuf->rect_float;
892  float hsv[3];
893 
894  if (rct) {
895  float rgb[3];
896  for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct += 4) {
897  rgb_uchar_to_float(rgb, rct);
898  rgb_to_hsv_v(rgb, hsv);
899  hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb + 1, rgb + 2);
900  rgb_float_to_uchar(rct, rgb);
901  }
902  }
903 
904  if (rct_fl) {
905  for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4) {
906  rgb_to_hsv_v(rct_fl, hsv);
907  hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rct_fl, rct_fl + 1, rct_fl + 2);
908  }
909  }
910 }
911 
#define BLI_assert(a)
Definition: BLI_assert.h:58
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
Definition: math_color.c:254
MINLINE void srgb_to_linearrgb_uchar4_predivide(float linear[4], const unsigned char srgb[4])
MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3])
MINLINE void premul_to_straight_v4(float color[4])
MINLINE void straight_to_premul_v4(float color[4])
MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linear[4])
MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4])
void hsv_to_rgb(float h, float s, float v, float *r_r, float *r_g, float *r_b)
Definition: math_color.c:31
MINLINE void srgb_to_linearrgb_uchar4(float linear[4], const unsigned char srgb[4])
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
Definition: math_color.c:414
void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
Definition: math_color.c:427
MINLINE void premul_to_straight_v4_v4(float straight[4], const float premul[4])
MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4])
void rgb_uchar_to_float(float r_col[3], const unsigned char col_ub[3])
Definition: math_color.c:407
void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3])
Definition: math_color.c:422
MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4])
MINLINE float dither_random_value(float s, float t)
#define MINLINE
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
unsigned char uchar
Definition: BLI_sys_types.h:86
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, bool predivide)
BLI_INLINE unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char[3])
BLI_INLINE float IMB_colormanagement_get_luminance(const float rgb[3])
const char * IMB_colormanagement_role_colorspace_name_get(int role)
@ COLOR_ROLE_SCENE_LINEAR
void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide)
Function declarations for filter.c.
#define FILTER_MASK_USED
Definition: IMB_imbuf.h:421
void IMB_processor_apply_threaded_scanlines(int total_scanlines, ScanlineThreadFunc do_thread, void *custom_data)
Definition: imageprocess.c:424
bool imb_addrectImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:407
Contains defines and structs used throughout the imbuf module.
@ IB_RECT_INVALID
#define IB_PROFILE_NONE
#define IB_PROFILE_SRGB
#define IB_PROFILE_LINEAR_RGB
@ IB_alphamode_channel_packed
@ IB_rectfloat
Read Guarded memory(de)allocation.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
StackEntry * from
void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, int channels_from, int width, int height, int stride_to, int stride_from, char *mask)
Definition: divers.c:597
#define USHORTTOFLOAT(val)
void IMB_rect_from_float(ImBuf *ibuf)
Definition: divers.c:720
void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, int channels_from, float dither, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from)
Definition: divers.c:112
MINLINE void ushort_to_byte_dither_v4(uchar b[4], const unsigned short us[4], DitherContext *di, float s, float t)
Definition: divers.c:80
MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], DitherContext *di, float s, float t)
Definition: divers.c:94
void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from, int channels_from, float dither, bool predivide, int width, int height, int stride_to, int stride_from, char *mask)
Definition: divers.c:279
bool IMB_alpha_affects_rgb(const ImBuf *ibuf)
Definition: divers.c:106
static DitherContext * create_dither_context(float dither)
Definition: divers.c:46
void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, int channels_from, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from)
Definition: divers.c:430
struct FloatToFloatThreadData FloatToFloatThreadData
void IMB_buffer_float_premultiply(float *buf, int width, int height)
Definition: divers.c:871
void IMB_color_to_bw(ImBuf *ibuf)
Definition: divers.c:842
struct DitherContext DitherContext
void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from)
Definition: divers.c:370
void IMB_buffer_float_from_float_threaded(float *rect_to, const float *rect_from, int channels_from, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from)
Definition: divers.c:558
void IMB_buffer_float_unpremultiply(float *buf, int width, int height)
Definition: divers.c:861
void IMB_saturation(ImBuf *ibuf, float sat)
Definition: divers.c:887
MINLINE unsigned char ftochar(float value)
Definition: divers.c:75
MINLINE void ushort_to_byte_v4(uchar b[4], const unsigned short us[4])
Definition: divers.c:67
static void imb_buffer_float_from_float_thread_do(void *data_v, int start_scanline, int num_scanlines)
Definition: divers.c:539
void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from)
Definition: divers.c:651
static void clear_dither_context(DitherContext *di)
Definition: divers.c:56
void IMB_float_from_rect(ImBuf *ibuf)
Definition: divers.c:780
void IMB_unpremultiply_rect_float(float *rect_float, int channels, int w, int h)
Definition: filter.c:731
void IMB_premultiply_rect_float(float *rect_float, int channels, int w, int h)
Definition: filter.c:669
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
MINLINE unsigned char unit_ushort_to_uchar(unsigned short val)
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
char name[MAX_COLORSPACE_NAME]
float dither
Definition: divers.c:43
const float * rect_from
Definition: divers.c:529
int channels
int userflags
struct ColorSpace * rect_colorspace
float dither
unsigned int * rect
float * rect_float
struct ColorSpace * float_colorspace
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)