static void paint_2d_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const bool is_torus, const float rgb[4]) { if (is_torus) { x %= ibuf->x; if (x < 0) x += ibuf->x; y %= ibuf->y; if (y < 0) y += ibuf->y; } if (ibuf->rect_float) { float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4; float map_alpha = (rgb[3] == 0.0f) ? rrgbf[3] : rrgbf[3] / rgb[3]; mul_v3_v3fl(rrgbf, rgb, map_alpha); } else { unsigned char straight[4]; unsigned char *rrgb = (unsigned char *)ibuf->rect + (ibuf->x * y + x) * 4; premul_float_to_straight_uchar(straight, rgb); rrgb[0] = straight[0]; rrgb[1] = straight[1]; rrgb[2] = straight[2]; } }
static void tonemapmodifier_apply_threaded_simple(int width, int height, unsigned char *rect, float *rect_float, unsigned char *mask_rect, float *mask_rect_float, void *data_v) { AvgLogLum *avg = (AvgLogLum *)data_v; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int pixel_index = (y * width + x) * 4; float input[4], output[4], mask[3] = {1.0f, 1.0f, 1.0f}; /* Get input value. */ if (rect_float) { copy_v4_v4(input, &rect_float[pixel_index]); } else { straight_uchar_to_premul_float(input, &rect[pixel_index]); } IMB_colormanagement_colorspace_to_scene_linear_v3(input, avg->colorspace); copy_v4_v4(output, input); /* Get mask value. */ if (mask_rect_float) { copy_v3_v3(mask, mask_rect_float + pixel_index); } else if (mask_rect) { rgb_uchar_to_float(mask, mask_rect + pixel_index); } /* Apply correction. */ mul_v3_fl(output, avg->al); float dr = output[0] + avg->tmmd->offset; float dg = output[1] + avg->tmmd->offset; float db = output[2] + avg->tmmd->offset; output[0] /= ((dr == 0.0f) ? 1.0f : dr); output[1] /= ((dg == 0.0f) ? 1.0f : dg); output[2] /= ((db == 0.0f) ? 1.0f : db); const float igm = avg->igm; if (igm != 0.0f) { output[0] = powf(max_ff(output[0], 0.0f), igm); output[1] = powf(max_ff(output[1], 0.0f), igm); output[2] = powf(max_ff(output[2], 0.0f), igm); } /* Apply mask. */ output[0] = input[0] * (1.0f - mask[0]) + output[0] * mask[0]; output[1] = input[1] * (1.0f - mask[1]) + output[1] * mask[1]; output[2] = input[2] * (1.0f - mask[2]) + output[2] * mask[2]; /* Copy result back. */ IMB_colormanagement_scene_linear_to_colorspace_v3(output, avg->colorspace); if (rect_float) { copy_v4_v4(&rect_float[pixel_index], output); } else { premul_float_to_straight_uchar(&rect[pixel_index], output); } } } }
static void curves_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, unsigned char *mask_rect, float *mask_rect_float, void *data_v) { CurveMapping *curve_mapping = (CurveMapping *) data_v; int x, y; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { int pixel_index = (y * width + x) * 4; if (rect_float) { float *pixel = rect_float + pixel_index; float result[3]; curvemapping_evaluate_premulRGBF(curve_mapping, result, pixel); if (mask_rect_float) { const float *m = mask_rect_float + pixel_index; pixel[0] = pixel[0] * (1.0f - m[0]) + result[0] * m[0]; pixel[1] = pixel[1] * (1.0f - m[1]) + result[1] * m[1]; pixel[2] = pixel[2] * (1.0f - m[2]) + result[2] * m[2]; } else { pixel[0] = result[0]; pixel[1] = result[1]; pixel[2] = result[2]; } } if (rect) { unsigned char *pixel = rect + pixel_index; float result[3], tempc[4]; straight_uchar_to_premul_float(tempc, pixel); curvemapping_evaluate_premulRGBF(curve_mapping, result, tempc); if (mask_rect) { float t[3]; rgb_uchar_to_float(t, mask_rect + pixel_index); tempc[0] = tempc[0] * (1.0f - t[0]) + result[0] * t[0]; tempc[1] = tempc[1] * (1.0f - t[1]) + result[1] * t[1]; tempc[2] = tempc[2] * (1.0f - t[2]) + result[2] * t[2]; } else { tempc[0] = result[0]; tempc[1] = result[1]; tempc[2] = result[2]; } premul_float_to_straight_uchar(pixel, tempc); } } } }
static void whiteBalance_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, unsigned char *mask_rect, float *mask_rect_float, void *data_v) { int x, y; float multiplier[3]; WhiteBalanceThreadData *data = (WhiteBalanceThreadData *) data_v; multiplier[0] = (data->white[0] != 0.0f) ? 1.0f / data->white[0] : FLT_MAX; multiplier[1] = (data->white[1] != 0.0f) ? 1.0f / data->white[1] : FLT_MAX; multiplier[2] = (data->white[2] != 0.0f) ? 1.0f / data->white[2] : FLT_MAX; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { int pixel_index = (y * width + x) * 4; float rgba[4], result[4], mask[3] = {1.0f, 1.0f, 1.0f}; if (rect_float) { copy_v3_v3(rgba, rect_float + pixel_index); } else { straight_uchar_to_premul_float(rgba, rect + pixel_index); } copy_v4_v4(result, rgba); #if 0 mul_v3_v3(result, multiplier); #else /* similar to division without the clipping */ for (int i = 0; i < 3; i++) { result[i] = 1.0f - powf(1.0f - rgba[i], multiplier[i]); } #endif if (mask_rect_float) { copy_v3_v3(mask, mask_rect_float + pixel_index); } else if (mask_rect) { rgb_uchar_to_float(mask, mask_rect + pixel_index); } result[0] = rgba[0] * (1.0f - mask[0]) + result[0] * mask[0]; result[1] = rgba[1] * (1.0f - mask[1]) + result[1] * mask[1]; result[2] = rgba[2] * (1.0f - mask[2]) + result[2] * mask[2]; if (rect_float) { copy_v3_v3(rect_float + pixel_index, result); } else { premul_float_to_straight_uchar(rect + pixel_index, result); } } } }
static void whiteBalance_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, unsigned char *mask_rect, float *mask_rect_float, void *data_v) { int x, y; float multiplier[3]; WhiteBalanceThreadData *data = (WhiteBalanceThreadData *) data_v; multiplier[0] = 1.0f / data->white[0]; multiplier[1] = 1.0f / data->white[1]; multiplier[2] = 1.0f / data->white[2]; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { int pixel_index = (y * width + x) * 4; float result[3], mask[3] = {1.0f, 1.0f, 1.0f}; if (rect_float) { copy_v3_v3(result, rect_float + pixel_index); } else { straight_uchar_to_premul_float(result, rect + pixel_index); IMB_colormanagement_colorspace_to_scene_linear_v3(result, data->colorspace); } mul_v3_v3(result, multiplier); if (mask_rect_float) copy_v3_v3(mask, mask_rect_float + pixel_index); else if (mask_rect) rgb_uchar_to_float(mask, mask_rect + pixel_index); result[0] = result[0] * (1.0f - mask[0]) + result[0] * mask[0]; result[1] = result[1] * (1.0f - mask[1]) + result[1] * mask[1]; result[2] = result[2] * (1.0f - mask[2]) + result[2] * mask[2]; if (rect_float) copy_v3_v3(rect_float + pixel_index, result); else IMB_colormanagement_scene_linear_to_colorspace_v3(result, data->colorspace); premul_float_to_straight_uchar(rect + pixel_index, result); } } }
static void tonemapmodifier_apply_threaded_photoreceptor(int width, int height, unsigned char *rect, float *rect_float, unsigned char *mask_rect, float *mask_rect_float, void *data_v) { AvgLogLum *avg = (AvgLogLum *)data_v; const float f = expf(-avg->tmmd->intensity); const float m = (avg->tmmd->contrast > 0.0f) ? avg->tmmd->contrast : (0.3f + 0.7f * powf(avg->auto_key, 1.4f)); const float ic = 1.0f - avg->tmmd->correction, ia = 1.0f - avg->tmmd->adaptation; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int pixel_index = (y * width + x) * 4; float input[4], output[4], mask[3] = {1.0f, 1.0f, 1.0f}; /* Get input value. */ if (rect_float) { copy_v4_v4(input, &rect_float[pixel_index]); } else { straight_uchar_to_premul_float(input, &rect[pixel_index]); } IMB_colormanagement_colorspace_to_scene_linear_v3(input, avg->colorspace); copy_v4_v4(output, input); /* Get mask value. */ if (mask_rect_float) { copy_v3_v3(mask, mask_rect_float + pixel_index); } else if (mask_rect) { rgb_uchar_to_float(mask, mask_rect + pixel_index); } /* Apply correction. */ const float L = IMB_colormanagement_get_luminance(output); float I_l = output[0] + ic * (L - output[0]); float I_g = avg->cav[0] + ic * (avg->lav - avg->cav[0]); float I_a = I_l + ia * (I_g - I_l); output[0] /= (output[0] + powf(f * I_a, m)); I_l = output[1] + ic * (L - output[1]); I_g = avg->cav[1] + ic * (avg->lav - avg->cav[1]); I_a = I_l + ia * (I_g - I_l); output[1] /= (output[1] + powf(f * I_a, m)); I_l = output[2] + ic * (L - output[2]); I_g = avg->cav[2] + ic * (avg->lav - avg->cav[2]); I_a = I_l + ia * (I_g - I_l); output[2] /= (output[2] + powf(f * I_a, m)); /* Apply mask. */ output[0] = input[0] * (1.0f - mask[0]) + output[0] * mask[0]; output[1] = input[1] * (1.0f - mask[1]) + output[1] * mask[1]; output[2] = input[2] * (1.0f - mask[2]) + output[2] * mask[2]; /* Copy result back. */ IMB_colormanagement_scene_linear_to_colorspace_v3(output, avg->colorspace); if (rect_float) { copy_v4_v4(&rect_float[pixel_index], output); } else { premul_float_to_straight_uchar(&rect[pixel_index], output); } } } }