Blender  V3.3
divers.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include "BLI_math.h"
9 #include "BLI_rect.h"
10 #include "BLI_utildefines.h"
11 
12 #include "IMB_filter.h"
13 #include "IMB_imbuf.h"
14 #include "IMB_imbuf_types.h"
15 #include "imbuf.h"
16 
17 #include "IMB_colormanagement.h"
19 
20 #include "MEM_guardedalloc.h"
21 
22 /* -------------------------------------------------------------------- */
26 typedef struct DitherContext {
27  float dither;
29 
30 static DitherContext *create_dither_context(float dither)
31 {
32  DitherContext *di;
33 
34  di = MEM_mallocN(sizeof(DitherContext), "dithering context");
35  di->dither = dither;
36 
37  return di;
38 }
39 
41 {
42  MEM_freeN(di);
43 }
44 
47 /* -------------------------------------------------------------------- */
51 MINLINE void ushort_to_byte_v4(uchar b[4], const unsigned short us[4])
52 {
53  b[0] = unit_ushort_to_uchar(us[0]);
54  b[1] = unit_ushort_to_uchar(us[1]);
55  b[2] = unit_ushort_to_uchar(us[2]);
56  b[3] = unit_ushort_to_uchar(us[3]);
57 }
58 
59 MINLINE unsigned char ftochar(float value)
60 {
61  return unit_float_to_uchar_clamp(value);
62 }
63 
65  uchar b[4], const unsigned short us[4], DitherContext *di, float s, float t)
66 {
67 #define USHORTTOFLOAT(val) ((float)val / 65535.0f)
68  float dither_value = dither_random_value(s, t) * 0.0033f * di->dither;
69 
70  b[0] = ftochar(dither_value + USHORTTOFLOAT(us[0]));
71  b[1] = ftochar(dither_value + USHORTTOFLOAT(us[1]));
72  b[2] = ftochar(dither_value + USHORTTOFLOAT(us[2]));
73  b[3] = unit_ushort_to_uchar(us[3]);
74 
75 #undef USHORTTOFLOAT
76 }
77 
79  uchar b[4], const float f[4], DitherContext *di, float s, float t)
80 {
81  float dither_value = dither_random_value(s, t) * 0.0033f * di->dither;
82 
83  b[0] = ftochar(dither_value + f[0]);
84  b[1] = ftochar(dither_value + f[1]);
85  b[2] = ftochar(dither_value + f[2]);
86  b[3] = unit_float_to_uchar_clamp(f[3]);
87 }
88 
89 bool IMB_alpha_affects_rgb(const ImBuf *ibuf)
90 {
91  return ibuf && (ibuf->flags & IB_alphamode_channel_packed) == 0;
92 }
93 
95  const float *rect_from,
96  int channels_from,
97  float dither,
98  int profile_to,
99  int profile_from,
100  bool predivide,
101  int width,
102  int height,
103  int stride_to,
104  int stride_from)
105 {
106  float tmp[4];
107  int x, y;
108  DitherContext *di = NULL;
109  float inv_width = 1.0f / width;
110  float inv_height = 1.0f / height;
111 
112  /* we need valid profiles */
113  BLI_assert(profile_to != IB_PROFILE_NONE);
114  BLI_assert(profile_from != IB_PROFILE_NONE);
115 
116  if (dither) {
117  di = create_dither_context(dither);
118  }
119 
120  for (y = 0; y < height; y++) {
121  float t = y * inv_height;
122 
123  if (channels_from == 1) {
124  /* single channel input */
125  const float *from = rect_from + ((size_t)stride_from) * y;
126  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
127 
128  for (x = 0; x < width; x++, from++, to += 4) {
129  to[0] = to[1] = to[2] = to[3] = unit_float_to_uchar_clamp(from[0]);
130  }
131  }
132  else if (channels_from == 3) {
133  /* RGB input */
134  const float *from = rect_from + ((size_t)stride_from) * y * 3;
135  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
136 
137  if (profile_to == profile_from) {
138  /* no color space conversion */
139  for (x = 0; x < width; x++, from += 3, to += 4) {
141  to[3] = 255;
142  }
143  }
144  else if (profile_to == IB_PROFILE_SRGB) {
145  /* convert from linear to sRGB */
146  for (x = 0; x < width; x++, from += 3, to += 4) {
148  rgb_float_to_uchar(to, tmp);
149  to[3] = 255;
150  }
151  }
152  else if (profile_to == IB_PROFILE_LINEAR_RGB) {
153  /* convert from sRGB to linear */
154  for (x = 0; x < width; x++, from += 3, to += 4) {
156  rgb_float_to_uchar(to, tmp);
157  to[3] = 255;
158  }
159  }
160  }
161  else if (channels_from == 4) {
162  /* RGBA input */
163  const float *from = rect_from + ((size_t)stride_from) * y * 4;
164  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
165 
166  if (profile_to == profile_from) {
167  float straight[4];
168 
169  /* no color space conversion */
170  if (dither && predivide) {
171  for (x = 0; x < width; x++, from += 4, to += 4) {
172  premul_to_straight_v4_v4(straight, from);
173  float_to_byte_dither_v4(to, straight, di, (float)x * inv_width, t);
174  }
175  }
176  else if (dither) {
177  for (x = 0; x < width; x++, from += 4, to += 4) {
178  float_to_byte_dither_v4(to, from, di, (float)x * inv_width, t);
179  }
180  }
181  else if (predivide) {
182  for (x = 0; x < width; x++, from += 4, to += 4) {
183  premul_to_straight_v4_v4(straight, from);
184  rgba_float_to_uchar(to, straight);
185  }
186  }
187  else {
188  for (x = 0; x < width; x++, from += 4, to += 4) {
190  }
191  }
192  }
193  else if (profile_to == IB_PROFILE_SRGB) {
194  /* convert from linear to sRGB */
195  unsigned short us[4];
196  float straight[4];
197 
198  if (dither && predivide) {
199  for (x = 0; x < width; x++, from += 4, to += 4) {
200  premul_to_straight_v4_v4(straight, from);
202  ushort_to_byte_dither_v4(to, us, di, (float)x * inv_width, t);
203  }
204  }
205  else if (dither) {
206  for (x = 0; x < width; x++, from += 4, to += 4) {
208  ushort_to_byte_dither_v4(to, us, di, (float)x * inv_width, t);
209  }
210  }
211  else if (predivide) {
212  for (x = 0; x < width; x++, from += 4, to += 4) {
213  premul_to_straight_v4_v4(straight, from);
215  ushort_to_byte_v4(to, us);
216  }
217  }
218  else {
219  for (x = 0; x < width; x++, from += 4, to += 4) {
221  ushort_to_byte_v4(to, us);
222  }
223  }
224  }
225  else if (profile_to == IB_PROFILE_LINEAR_RGB) {
226  /* convert from sRGB to linear */
227  if (dither && predivide) {
228  for (x = 0; x < width; x++, from += 4, to += 4) {
230  float_to_byte_dither_v4(to, tmp, di, (float)x * inv_width, t);
231  }
232  }
233  else if (dither) {
234  for (x = 0; x < width; x++, from += 4, to += 4) {
236  float_to_byte_dither_v4(to, tmp, di, (float)x * inv_width, t);
237  }
238  }
239  else if (predivide) {
240  for (x = 0; x < width; x++, from += 4, to += 4) {
242  rgba_float_to_uchar(to, tmp);
243  }
244  }
245  else {
246  for (x = 0; x < width; x++, from += 4, to += 4) {
248  rgba_float_to_uchar(to, tmp);
249  }
250  }
251  }
252  }
253  }
254 
255  if (dither) {
257  }
258 }
259 
261  const float *rect_from,
262  int channels_from,
263  float dither,
264  bool predivide,
265  int width,
266  int height,
267  int stride_to,
268  int stride_from,
269  char *mask)
270 {
271  int x, y;
272  DitherContext *di = NULL;
273  float inv_width = 1.0f / width, inv_height = 1.0f / height;
274 
275  if (dither) {
276  di = create_dither_context(dither);
277  }
278 
279  for (y = 0; y < height; y++) {
280  float t = y * inv_height;
281 
282  if (channels_from == 1) {
283  /* single channel input */
284  const float *from = rect_from + ((size_t)stride_from) * y;
285  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
286 
287  for (x = 0; x < width; x++, from++, to += 4) {
288  if (*mask++ == FILTER_MASK_USED) {
289  to[0] = to[1] = to[2] = to[3] = unit_float_to_uchar_clamp(from[0]);
290  }
291  }
292  }
293  else if (channels_from == 3) {
294  /* RGB input */
295  const float *from = rect_from + ((size_t)stride_from) * y * 3;
296  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
297 
298  for (x = 0; x < width; x++, from += 3, to += 4) {
299  if (*mask++ == FILTER_MASK_USED) {
301  to[3] = 255;
302  }
303  }
304  }
305  else if (channels_from == 4) {
306  /* RGBA input */
307  const float *from = rect_from + ((size_t)stride_from) * y * 4;
308  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
309 
310  float straight[4];
311 
312  if (dither && predivide) {
313  for (x = 0; x < width; x++, from += 4, to += 4) {
314  if (*mask++ == FILTER_MASK_USED) {
315  premul_to_straight_v4_v4(straight, from);
316  float_to_byte_dither_v4(to, straight, di, (float)x * inv_width, t);
317  }
318  }
319  }
320  else if (dither) {
321  for (x = 0; x < width; x++, from += 4, to += 4) {
322  if (*mask++ == FILTER_MASK_USED) {
323  float_to_byte_dither_v4(to, from, di, (float)x * inv_width, t);
324  }
325  }
326  }
327  else if (predivide) {
328  for (x = 0; x < width; x++, from += 4, to += 4) {
329  if (*mask++ == FILTER_MASK_USED) {
330  premul_to_straight_v4_v4(straight, from);
331  rgba_float_to_uchar(to, straight);
332  }
333  }
334  }
335  else {
336  for (x = 0; x < width; x++, from += 4, to += 4) {
337  if (*mask++ == FILTER_MASK_USED) {
339  }
340  }
341  }
342  }
343  }
344 
345  if (dither) {
347  }
348 }
349 
350 void IMB_buffer_float_from_byte(float *rect_to,
351  const uchar *rect_from,
352  int profile_to,
353  int profile_from,
354  bool predivide,
355  int width,
356  int height,
357  int stride_to,
358  int stride_from)
359 {
360  float tmp[4];
361  int x, y;
362 
363  /* we need valid profiles */
364  BLI_assert(profile_to != IB_PROFILE_NONE);
365  BLI_assert(profile_from != IB_PROFILE_NONE);
366 
367  /* RGBA input */
368  for (y = 0; y < height; y++) {
369  const uchar *from = rect_from + ((size_t)stride_from) * y * 4;
370  float *to = rect_to + ((size_t)stride_to) * y * 4;
371 
372  if (profile_to == profile_from) {
373  /* no color space conversion */
374  for (x = 0; x < width; x++, from += 4, to += 4) {
376  }
377  }
378  else if (profile_to == IB_PROFILE_LINEAR_RGB) {
379  /* convert sRGB to linear */
380  if (predivide) {
381  for (x = 0; x < width; x++, from += 4, to += 4) {
383  }
384  }
385  else {
386  for (x = 0; x < width; x++, from += 4, to += 4) {
388  }
389  }
390  }
391  else if (profile_to == IB_PROFILE_SRGB) {
392  /* convert linear to sRGB */
393  if (predivide) {
394  for (x = 0; x < width; x++, from += 4, to += 4) {
397  }
398  }
399  else {
400  for (x = 0; x < width; x++, from += 4, to += 4) {
402  linearrgb_to_srgb_v4(to, tmp);
403  }
404  }
405  }
406  }
407 }
408 
409 void IMB_buffer_float_from_float(float *rect_to,
410  const float *rect_from,
411  int channels_from,
412  int profile_to,
413  int profile_from,
414  bool predivide,
415  int width,
416  int height,
417  int stride_to,
418  int stride_from)
419 {
420  int x, y;
421 
422  /* we need valid profiles */
423  BLI_assert(profile_to != IB_PROFILE_NONE);
424  BLI_assert(profile_from != IB_PROFILE_NONE);
425 
426  if (channels_from == 1) {
427  /* single channel input */
428  for (y = 0; y < height; y++) {
429  const float *from = rect_from + ((size_t)stride_from) * y;
430  float *to = rect_to + ((size_t)stride_to) * y * 4;
431 
432  for (x = 0; x < width; x++, from++, to += 4) {
433  to[0] = to[1] = to[2] = to[3] = from[0];
434  }
435  }
436  }
437  else if (channels_from == 3) {
438  /* RGB input */
439  for (y = 0; y < height; y++) {
440  const float *from = rect_from + ((size_t)stride_from) * y * 3;
441  float *to = rect_to + ((size_t)stride_to) * y * 4;
442 
443  if (profile_to == profile_from) {
444  /* no color space conversion */
445  for (x = 0; x < width; x++, from += 3, to += 4) {
446  copy_v3_v3(to, from);
447  to[3] = 1.0f;
448  }
449  }
450  else if (profile_to == IB_PROFILE_LINEAR_RGB) {
451  /* convert from sRGB to linear */
452  for (x = 0; x < width; x++, from += 3, to += 4) {
454  to[3] = 1.0f;
455  }
456  }
457  else if (profile_to == IB_PROFILE_SRGB) {
458  /* convert from linear to sRGB */
459  for (x = 0; x < width; x++, from += 3, to += 4) {
461  to[3] = 1.0f;
462  }
463  }
464  }
465  }
466  else if (channels_from == 4) {
467  /* RGBA input */
468  for (y = 0; y < height; y++) {
469  const float *from = rect_from + ((size_t)stride_from) * y * 4;
470  float *to = rect_to + ((size_t)stride_to) * y * 4;
471 
472  if (profile_to == profile_from) {
473  /* same profile, copy */
474  memcpy(to, from, sizeof(float) * ((size_t)4) * width);
475  }
476  else if (profile_to == IB_PROFILE_LINEAR_RGB) {
477  /* convert to sRGB to linear */
478  if (predivide) {
479  for (x = 0; x < width; x++, from += 4, to += 4) {
481  }
482  }
483  else {
484  for (x = 0; x < width; x++, from += 4, to += 4) {
486  }
487  }
488  }
489  else if (profile_to == IB_PROFILE_SRGB) {
490  /* convert from linear to sRGB */
491  if (predivide) {
492  for (x = 0; x < width; x++, from += 4, to += 4) {
494  }
495  }
496  else {
497  for (x = 0; x < width; x++, from += 4, to += 4) {
499  }
500  }
501  }
502  }
503  }
504 }
505 
506 typedef struct FloatToFloatThreadData {
507  float *rect_to;
508  const float *rect_from;
512  bool predivide;
513  int width;
517 
518 static void imb_buffer_float_from_float_thread_do(void *data_v, int scanline)
519 {
520  const int num_scanlines = 1;
522  size_t offset_from = ((size_t)scanline) * data->stride_from * data->channels_from;
523  size_t offset_to = ((size_t)scanline) * data->stride_to * data->channels_from;
524  IMB_buffer_float_from_float(data->rect_to + offset_to,
525  data->rect_from + offset_from,
526  data->channels_from,
527  data->profile_to,
528  data->profile_from,
529  data->predivide,
530  data->width,
531  num_scanlines,
532  data->stride_to,
533  data->stride_from);
534 }
535 
537  const float *rect_from,
538  int channels_from,
539  int profile_to,
540  int profile_from,
541  bool predivide,
542  int width,
543  int height,
544  int stride_to,
545  int stride_from)
546 {
547  if (((size_t)width) * height < 64 * 64) {
549  rect_from,
550  channels_from,
551  profile_to,
552  profile_from,
553  predivide,
554  width,
555  height,
556  stride_to,
557  stride_from);
558  }
559  else {
561  data.rect_to = rect_to;
562  data.rect_from = rect_from;
563  data.channels_from = channels_from;
564  data.profile_to = profile_to;
565  data.profile_from = profile_from;
566  data.predivide = predivide;
567  data.width = width;
568  data.stride_to = stride_to;
569  data.stride_from = stride_from;
571  }
572 }
573 
575  const float *rect_from,
576  int channels_from,
577  int width,
578  int height,
579  int stride_to,
580  int stride_from,
581  char *mask)
582 {
583  int x, y;
584 
585  if (channels_from == 1) {
586  /* single channel input */
587  for (y = 0; y < height; y++) {
588  const float *from = rect_from + ((size_t)stride_from) * y;
589  float *to = rect_to + ((size_t)stride_to) * y * 4;
590 
591  for (x = 0; x < width; x++, from++, to += 4) {
592  if (*mask++ == FILTER_MASK_USED) {
593  to[0] = to[1] = to[2] = to[3] = from[0];
594  }
595  }
596  }
597  }
598  else if (channels_from == 3) {
599  /* RGB input */
600  for (y = 0; y < height; y++) {
601  const float *from = rect_from + ((size_t)stride_from) * y * 3;
602  float *to = rect_to + ((size_t)stride_to) * y * 4;
603 
604  for (x = 0; x < width; x++, from += 3, to += 4) {
605  if (*mask++ == FILTER_MASK_USED) {
606  copy_v3_v3(to, from);
607  to[3] = 1.0f;
608  }
609  }
610  }
611  }
612  else if (channels_from == 4) {
613  /* RGBA input */
614  for (y = 0; y < height; y++) {
615  const float *from = rect_from + ((size_t)stride_from) * y * 4;
616  float *to = rect_to + ((size_t)stride_to) * y * 4;
617 
618  for (x = 0; x < width; x++, from += 4, to += 4) {
619  if (*mask++ == FILTER_MASK_USED) {
620  copy_v4_v4(to, from);
621  }
622  }
623  }
624  }
625 }
626 
628  const uchar *rect_from,
629  int profile_to,
630  int profile_from,
631  bool predivide,
632  int width,
633  int height,
634  int stride_to,
635  int stride_from)
636 {
637  float tmp[4];
638  int x, y;
639 
640  /* we need valid profiles */
641  BLI_assert(profile_to != IB_PROFILE_NONE);
642  BLI_assert(profile_from != IB_PROFILE_NONE);
643 
644  /* always RGBA input */
645  for (y = 0; y < height; y++) {
646  const uchar *from = rect_from + ((size_t)stride_from) * y * 4;
647  uchar *to = rect_to + ((size_t)stride_to) * y * 4;
648 
649  if (profile_to == profile_from) {
650  /* same profile, copy */
651  memcpy(to, from, sizeof(uchar[4]) * width);
652  }
653  else if (profile_to == IB_PROFILE_LINEAR_RGB) {
654  /* convert to sRGB to linear */
655  if (predivide) {
656  for (x = 0; x < width; x++, from += 4, to += 4) {
659  rgba_float_to_uchar(to, tmp);
660  }
661  }
662  else {
663  for (x = 0; x < width; x++, from += 4, to += 4) {
665  srgb_to_linearrgb_v4(tmp, tmp);
666  rgba_float_to_uchar(to, tmp);
667  }
668  }
669  }
670  else if (profile_to == IB_PROFILE_SRGB) {
671  /* convert from linear to sRGB */
672  if (predivide) {
673  for (x = 0; x < width; x++, from += 4, to += 4) {
676  rgba_float_to_uchar(to, tmp);
677  }
678  }
679  else {
680  for (x = 0; x < width; x++, from += 4, to += 4) {
682  linearrgb_to_srgb_v4(tmp, tmp);
683  rgba_float_to_uchar(to, tmp);
684  }
685  }
686  }
687  }
688 }
689 
692 /* -------------------------------------------------------------------- */
697 {
698  /* verify we have a float buffer */
699  if (ibuf->rect_float == NULL) {
700  return;
701  }
702 
703  /* create byte rect if it didn't exist yet */
704  if (ibuf->rect == NULL) {
705  if (imb_addrectImBuf(ibuf) == 0) {
706  return;
707  }
708  }
709 
710  const char *from_colorspace = (ibuf->float_colorspace == NULL) ?
713  ibuf->float_colorspace->name;
714  const char *to_colorspace = (ibuf->rect_colorspace == NULL) ?
717  ibuf->rect_colorspace->name;
718 
719  float *buffer = MEM_dupallocN(ibuf->rect_float);
720 
721  /* first make float buffer in byte space */
722  const bool predivide = IMB_alpha_affects_rgb(ibuf);
724  buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, predivide);
725 
726  /* convert from float's premul alpha to byte's straight alpha */
727  if (IMB_alpha_affects_rgb(ibuf)) {
728  IMB_unpremultiply_rect_float(buffer, ibuf->channels, ibuf->x, ibuf->y);
729  }
730 
731  /* convert float to byte */
732  IMB_buffer_byte_from_float((unsigned char *)ibuf->rect,
733  buffer,
734  ibuf->channels,
735  ibuf->dither,
738  false,
739  ibuf->x,
740  ibuf->y,
741  ibuf->x,
742  ibuf->x);
743 
744  MEM_freeN(buffer);
745 
746  /* ensure user flag is reset */
747  ibuf->userflags &= ~IB_RECT_INVALID;
748 }
749 
750 void IMB_float_from_rect_ex(struct ImBuf *dst,
751  const struct ImBuf *src,
752  const rcti *region_to_update)
753 {
755  "Destination buffer should have a float buffer assigned.");
756  BLI_assert_msg(src->rect != NULL, "Source buffer should have a byte buffer assigned.");
757  BLI_assert_msg(dst->x == src->x, "Source and destination buffer should have the same dimension");
758  BLI_assert_msg(dst->y == src->y, "Source and destination buffer should have the same dimension");
759  BLI_assert_msg(dst->channels = 4, "Destination buffer should have 4 channels.");
760  BLI_assert_msg(region_to_update->xmin >= 0,
761  "Region to update should be clipped to the given buffers.");
762  BLI_assert_msg(region_to_update->ymin >= 0,
763  "Region to update should be clipped to the given buffers.");
764  BLI_assert_msg(region_to_update->xmax <= dst->x,
765  "Region to update should be clipped to the given buffers.");
766  BLI_assert_msg(region_to_update->ymax <= dst->y,
767  "Region to update should be clipped to the given buffers.");
768 
769  float *rect_float = dst->rect_float;
770  rect_float += (region_to_update->xmin + region_to_update->ymin * dst->x) * 4;
771  unsigned char *rect = (unsigned char *)src->rect;
772  rect += (region_to_update->xmin + region_to_update->ymin * dst->x) * 4;
773  const int region_width = BLI_rcti_size_x(region_to_update);
774  const int region_height = BLI_rcti_size_y(region_to_update);
775 
776  /* Convert byte buffer to float buffer without color or alpha conversion. */
777  IMB_buffer_float_from_byte(rect_float,
778  rect,
781  false,
782  region_width,
783  region_height,
784  src->x,
785  dst->x);
786 
787  /* Perform color space conversion from rect color space to linear. */
788  float *float_ptr = rect_float;
789  for (int i = 0; i < region_height; i++) {
791  float_ptr, region_width, 1, dst->channels, src->rect_colorspace, false);
792  float_ptr += 4 * dst->x;
793  }
794 
795  /* Perform alpha conversion. */
796  if (IMB_alpha_affects_rgb(src)) {
797  float_ptr = rect_float;
798  for (int i = 0; i < region_height; i++) {
799  IMB_premultiply_rect_float(float_ptr, dst->channels, region_width, 1);
800  float_ptr += 4 * dst->x;
801  }
802  }
803 }
804 
806 {
807  float *rect_float;
808 
809  /* verify if we byte and float buffers */
810  if (ibuf->rect == NULL) {
811  return;
812  }
813 
814  /* allocate float buffer outside of image buffer,
815  * so work-in-progress color space conversion doesn't
816  * interfere with other parts of blender
817  */
818  rect_float = ibuf->rect_float;
819  if (rect_float == NULL) {
820  const size_t size = IMB_get_rect_len(ibuf) * sizeof(float[4]);
821  rect_float = MEM_callocN(size, "IMB_float_from_rect");
822 
823  if (rect_float == NULL) {
824  return;
825  }
826 
827  ibuf->channels = 4;
828  ibuf->rect_float = rect_float;
829  ibuf->mall |= IB_rectfloat;
830  ibuf->flags |= IB_rectfloat;
831  }
832 
833  rcti region_to_update;
834  BLI_rcti_init(&region_to_update, 0, ibuf->x, 0, ibuf->y);
835  IMB_float_from_rect_ex(ibuf, ibuf, &region_to_update);
836 }
837 
840 /* -------------------------------------------------------------------- */
845 {
846  float *rct_fl = ibuf->rect_float;
847  uchar *rct = (uchar *)ibuf->rect;
848  size_t i;
849 
850  if (rct_fl) {
851  for (i = IMB_get_rect_len(ibuf); i > 0; i--, rct_fl += 4) {
852  rct_fl[0] = rct_fl[1] = rct_fl[2] = IMB_colormanagement_get_luminance(rct_fl);
853  }
854  }
855 
856  if (rct) {
857  for (i = IMB_get_rect_len(ibuf); i > 0; i--, rct += 4) {
858  rct[0] = rct[1] = rct[2] = IMB_colormanagement_get_luminance_byte(rct);
859  }
860  }
861 }
862 
863 void IMB_buffer_float_unpremultiply(float *buf, int width, int height)
864 {
865  size_t total = ((size_t)width) * height;
866  float *fp = buf;
867  while (total--) {
869  fp += 4;
870  }
871 }
872 
873 void IMB_buffer_float_premultiply(float *buf, int width, int height)
874 {
875  size_t total = ((size_t)width) * height;
876  float *fp = buf;
877  while (total--) {
879  fp += 4;
880  }
881 }
882 
885 /* -------------------------------------------------------------------- */
889 void IMB_saturation(ImBuf *ibuf, float sat)
890 {
891  size_t i;
892  unsigned char *rct = (unsigned char *)ibuf->rect;
893  float *rct_fl = ibuf->rect_float;
894  float hsv[3];
895 
896  if (rct) {
897  float rgb[3];
898  for (i = IMB_get_rect_len(ibuf); i > 0; i--, rct += 4) {
899  rgb_uchar_to_float(rgb, rct);
900  rgb_to_hsv_v(rgb, hsv);
901  hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb + 1, rgb + 2);
902  rgb_float_to_uchar(rct, rgb);
903  }
904  }
905 
906  if (rct_fl) {
907  for (i = IMB_get_rect_len(ibuf); i > 0; i--, rct_fl += 4) {
908  rgb_to_hsv_v(rct_fl, hsv);
909  hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rct_fl, rct_fl + 1, rct_fl + 2);
910  }
911  }
912 }
913 
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
Definition: math_color.c:232
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:13
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:383
void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
Definition: math_color.c:396
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:376
void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3])
Definition: math_color.c:391
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])
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
Definition: rct.c:417
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
unsigned char uchar
Definition: BLI_sys_types.h:70
_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 width
_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)
@ COLOR_ROLE_DEFAULT_BYTE
@ COLOR_ROLE_SCENE_LINEAR
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)
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:459
void IMB_processor_apply_threaded_scanlines(int total_scanlines, ScanlineThreadFunc do_thread, void *custom_data)
Definition: imageprocess.c:415
size_t IMB_get_rect_len(const struct ImBuf *ibuf)
Get the length of the rect of the given image buffer in terms of pixels.
bool imb_addrectImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:387
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:574
#define USHORTTOFLOAT(val)
void IMB_float_from_rect_ex(struct ImBuf *dst, const struct ImBuf *src, const rcti *region_to_update)
Definition: divers.c:750
void IMB_rect_from_float(ImBuf *ibuf)
Definition: divers.c:696
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:94
MINLINE void ushort_to_byte_dither_v4(uchar b[4], const unsigned short us[4], DitherContext *di, float s, float t)
Definition: divers.c:64
MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], DitherContext *di, float s, float t)
Definition: divers.c:78
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:260
bool IMB_alpha_affects_rgb(const ImBuf *ibuf)
Definition: divers.c:89
static DitherContext * create_dither_context(float dither)
Definition: divers.c:30
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:409
struct FloatToFloatThreadData FloatToFloatThreadData
void IMB_buffer_float_premultiply(float *buf, int width, int height)
Definition: divers.c:873
void IMB_color_to_bw(ImBuf *ibuf)
Definition: divers.c:844
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:350
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:536
void IMB_buffer_float_unpremultiply(float *buf, int width, int height)
Definition: divers.c:863
void IMB_saturation(ImBuf *ibuf, float sat)
Definition: divers.c:889
MINLINE unsigned char ftochar(float value)
Definition: divers.c:59
MINLINE void ushort_to_byte_v4(uchar b[4], const unsigned short us[4])
Definition: divers.c:51
static void imb_buffer_float_from_float_thread_do(void *data_v, int scanline)
Definition: divers.c:518
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:627
static void clear_dither_context(DitherContext *di)
Definition: divers.c:40
void IMB_float_from_rect(ImBuf *ibuf)
Definition: divers.c:805
SyclQueue void void * src
void IMB_unpremultiply_rect_float(float *rect_float, int channels, int w, int h)
Definition: filter.c:706
void IMB_premultiply_rect_float(float *rect_float, int channels, int w, int h)
Definition: filter.c:644
ccl_global float * buffer
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
MINLINE unsigned char unit_ushort_to_uchar(unsigned short val)
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const pxr::TfToken rgb("rgb", pxr::TfToken::Immortal)
char name[MAX_COLORSPACE_NAME]
float dither
Definition: divers.c:27
const float * rect_from
Definition: divers.c:508
int channels
int userflags
struct ColorSpace * rect_colorspace
float dither
unsigned int * rect
float * rect_float
struct ColorSpace * float_colorspace
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63