Color Management: add View as Render to image datablocks
This is need since some images (like normal maps, textures and so) would want to be viewed without any tone map applied on them. On the same time it's possible that some images would want to be affected by tone maps, and renders would always want to be affected by tone maps. After long discussion with Brecht we decided less painful and most clear way would be to simply add "View as Render" option to image datablocks. If this option is enabled for image, both settings from Display and Render blocks of color management settings would be applied on display. If this option is disabled, only display transform with default view and no exposure/gamma/curves would be applied. Render result and compositor viewers would always have "View as Render" enabled. There's separated setting when image is saving which says whether saved image should be affected by render part of color management settings. This option is enabled by default for render result/node viewer and disabled by default for all the rest images. This option wouldn't have affect when saving to float formats such as EXR.
This commit is contained in:
@@ -246,6 +246,9 @@ static Image *image_alloc(const char *name, short source, short type)
|
||||
ima->source = source;
|
||||
ima->type = type;
|
||||
|
||||
if (source == IMA_SRC_VIEWER)
|
||||
ima->flag |= IMA_VIEW_AS_RENDER;
|
||||
|
||||
BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings);
|
||||
}
|
||||
return ima;
|
||||
|
||||
@@ -7926,6 +7926,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
/* color management pipeline changes compatibility code */
|
||||
{
|
||||
Scene *scene;
|
||||
Image *ima;
|
||||
|
||||
for (scene = main->scene.first; scene; scene = scene->id.next) {
|
||||
if ((scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) == 0) {
|
||||
@@ -7936,6 +7937,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ima = main->image.first; ima; ima = ima->id.next) {
|
||||
if (ima->source == IMA_SRC_VIEWER)
|
||||
ima->flag |= IMA_VIEW_AS_RENDER;
|
||||
}
|
||||
}
|
||||
|
||||
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
|
||||
|
||||
@@ -80,7 +80,7 @@ int ED_space_image_maskedit_mask_poll(struct bContext *C);
|
||||
/* UI level image (texture) updating... render calls own stuff (too) */
|
||||
void ED_image_update_frame(const struct Main *mainp, int cfra);
|
||||
|
||||
void ED_image_draw_info(struct Scene *scene, struct ARegion *ar, int color_manage, int channels, int x, int y,
|
||||
void ED_image_draw_info(struct Scene *scene, struct ARegion *ar, int color_manage, int use_default_view, int channels, int x, int y,
|
||||
const unsigned char cp[4], const float fp[4], int *zp, float *zpf);
|
||||
|
||||
#endif /* __ED_IMAGE_H__ */
|
||||
|
||||
@@ -692,6 +692,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
|
||||
|
||||
col = uiLayoutColumn(layout, FALSE);
|
||||
uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings");
|
||||
uiItemR(col, &imaptr, "view_as_render", 0, NULL, ICON_NONE);
|
||||
|
||||
if (ima->source != IMA_SRC_GENERATED) {
|
||||
if (compact == 0) { /* background image view doesnt need these */
|
||||
|
||||
@@ -94,7 +94,7 @@ static void draw_render_info(Scene *scene, Image *ima, ARegion *ar)
|
||||
}
|
||||
|
||||
/* used by node view too */
|
||||
void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int channels, int x, int y,
|
||||
void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_default_view, int channels, int x, int y,
|
||||
const unsigned char cp[4], const float fp[4], int *zp, float *zpf)
|
||||
{
|
||||
char str[256];
|
||||
@@ -195,7 +195,10 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int channel
|
||||
if (color_manage && channels == 4) {
|
||||
float pixel[4];
|
||||
|
||||
IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, &scene->view_settings, &scene->display_settings);
|
||||
if (use_default_view)
|
||||
IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, NULL, &scene->display_settings);
|
||||
else
|
||||
IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, &scene->view_settings, &scene->display_settings);
|
||||
|
||||
BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", pixel[0], pixel[1], pixel[2]);
|
||||
BLF_position(blf_mono_font, dx, 6, 0);
|
||||
@@ -245,7 +248,10 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int channel
|
||||
}
|
||||
|
||||
if (color_manage) {
|
||||
IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings);
|
||||
if (use_default_view)
|
||||
IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings);
|
||||
else
|
||||
IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings);
|
||||
}
|
||||
else {
|
||||
copy_v4_v4(finalcol, col);
|
||||
@@ -491,7 +497,8 @@ static unsigned int *get_part_from_buffer(unsigned int *buffer, int width, short
|
||||
|
||||
static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
|
||||
{
|
||||
unsigned int *display_buffer, *rect;
|
||||
unsigned char *display_buffer;
|
||||
unsigned int *rect;
|
||||
int dx, dy, sx, sy, x, y;
|
||||
void *cache_handle;
|
||||
|
||||
@@ -499,8 +506,10 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
|
||||
if (ima->xrep < 1) return;
|
||||
if (ima->yrep < 1) return;
|
||||
|
||||
display_buffer = (unsigned int *) IMB_display_buffer_acquire(ibuf, &scene->view_settings,
|
||||
&scene->display_settings, &cache_handle);
|
||||
if (ima->flag & IMA_VIEW_AS_RENDER)
|
||||
display_buffer = IMB_display_buffer_acquire(ibuf, &scene->view_settings, &scene->display_settings, &cache_handle);
|
||||
else
|
||||
display_buffer = IMB_display_buffer_acquire(ibuf, NULL, &scene->display_settings, &cache_handle);
|
||||
|
||||
if (!display_buffer)
|
||||
return;
|
||||
@@ -515,7 +524,7 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
|
||||
dy = ibuf->y / ima->yrep;
|
||||
sx = (sima->curtile % ima->xrep) * dx;
|
||||
sy = (sima->curtile / ima->xrep) * dy;
|
||||
rect = get_part_from_buffer(display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy);
|
||||
rect = get_part_from_buffer((unsigned int*)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy);
|
||||
|
||||
/* draw repeated */
|
||||
for (sy = 0; sy + dy <= ibuf->y; sy += dy) {
|
||||
|
||||
@@ -1183,6 +1183,8 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
|
||||
static void save_image_options_from_op(SaveImageOptions *simopts, wmOperator *op)
|
||||
{
|
||||
if (op->customdata) {
|
||||
BKE_color_managed_view_settings_free(&simopts->im_format.view_settings);
|
||||
|
||||
simopts->im_format = *(ImageFormatData *)op->customdata;
|
||||
}
|
||||
|
||||
@@ -1195,13 +1197,15 @@ static void save_image_options_from_op(SaveImageOptions *simopts, wmOperator *op
|
||||
static void save_image_options_to_op(SaveImageOptions *simopts, wmOperator *op)
|
||||
{
|
||||
if (op->customdata) {
|
||||
BKE_color_managed_view_settings_free(&((ImageFormatData *)op->customdata)->view_settings);
|
||||
|
||||
*(ImageFormatData *)op->customdata = simopts->im_format;
|
||||
}
|
||||
|
||||
RNA_string_set(op->ptr, "filepath", simopts->filepath);
|
||||
}
|
||||
|
||||
static ImBuf *save_image_colormanaged_imbuf_acquire(ImBuf *ibuf, SaveImageOptions *simopts, void **cache_handle)
|
||||
static ImBuf *save_image_colormanaged_imbuf_acquire(ImBuf *ibuf, SaveImageOptions *simopts, int save_as_render, void **cache_handle)
|
||||
{
|
||||
ImageFormatData *imf = &simopts->im_format;
|
||||
ImBuf *colormanaged_ibuf;
|
||||
@@ -1211,8 +1215,12 @@ static ImBuf *save_image_colormanaged_imbuf_acquire(ImBuf *ibuf, SaveImageOption
|
||||
do_colormanagement = !BKE_imtype_supports_float(imf->imtype);
|
||||
|
||||
if (do_colormanagement) {
|
||||
unsigned char *display_buffer =
|
||||
IMB_display_buffer_acquire(ibuf, &imf->view_settings, &imf->display_settings, cache_handle);
|
||||
unsigned char *display_buffer;
|
||||
|
||||
if (save_as_render)
|
||||
display_buffer = IMB_display_buffer_acquire(ibuf, &imf->view_settings, &imf->display_settings, cache_handle);
|
||||
else
|
||||
display_buffer = IMB_display_buffer_acquire(ibuf, NULL, &imf->display_settings, cache_handle);
|
||||
|
||||
if (*cache_handle) {
|
||||
colormanaged_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0);
|
||||
@@ -1247,6 +1255,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
|
||||
const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id);
|
||||
const short relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path"));
|
||||
const short save_copy = (RNA_struct_find_property(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy"));
|
||||
const short save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render"));
|
||||
short ok = FALSE;
|
||||
|
||||
/* old global to ensure a 2nd save goes to same dir */
|
||||
@@ -1271,7 +1280,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
|
||||
}
|
||||
}
|
||||
|
||||
colormanaged_ibuf = save_image_colormanaged_imbuf_acquire(ibuf, simopts, &cache_handle);
|
||||
colormanaged_ibuf = save_image_colormanaged_imbuf_acquire(ibuf, simopts, save_as_render, &cache_handle);
|
||||
|
||||
if (simopts->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
@@ -1350,6 +1359,9 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
|
||||
static void image_save_as_free(wmOperator *op)
|
||||
{
|
||||
if (op->customdata) {
|
||||
ImageFormatData *im_format = (ImageFormatData *)op->customdata;
|
||||
BKE_color_managed_view_settings_free(&im_format->view_settings);
|
||||
|
||||
MEM_freeN(op->customdata);
|
||||
op->customdata = NULL;
|
||||
}
|
||||
@@ -1402,6 +1414,11 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve
|
||||
RNA_boolean_set(op->ptr, "copy", TRUE);
|
||||
}
|
||||
|
||||
if (ima->source == IMA_SRC_VIEWER)
|
||||
RNA_boolean_set(op->ptr, "save_as_render", TRUE);
|
||||
else
|
||||
RNA_boolean_set(op->ptr, "save_as_render", FALSE);
|
||||
|
||||
op->customdata = MEM_mallocN(sizeof(simopts.im_format), __func__);
|
||||
memcpy(op->customdata, &simopts.im_format, sizeof(simopts.im_format));
|
||||
|
||||
@@ -1437,7 +1454,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
|
||||
|
||||
/* image template */
|
||||
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &ptr);
|
||||
uiTemplateImageSettings(layout, &ptr, TRUE);
|
||||
uiTemplateImageSettings(layout, &ptr, FALSE);
|
||||
|
||||
/* main draw call */
|
||||
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
|
||||
@@ -1465,6 +1482,7 @@ void IMAGE_OT_save_as(wmOperatorType *ot)
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_boolean(ot->srna, "save_as_render", 0, "Save As Render", "Apply render part of display transform when saving byte image");
|
||||
RNA_def_boolean(ot->srna, "copy", 0, "Copy", "Create a new image file without modifying the current image in blender");
|
||||
|
||||
WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_SAVE,
|
||||
@@ -1989,6 +2007,7 @@ typedef struct ImageSampleInfo {
|
||||
|
||||
int draw;
|
||||
int color_manage;
|
||||
int use_default_view;
|
||||
} ImageSampleInfo;
|
||||
|
||||
static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info)
|
||||
@@ -1997,7 +2016,8 @@ static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info)
|
||||
if (info->draw) {
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
ED_image_draw_info(scene, ar, info->color_manage, info->channels, info->x, info->y, info->colp, info->colfp, info->zp, info->zfp);
|
||||
ED_image_draw_info(scene, ar, info->color_manage, info->use_default_view, info->channels,
|
||||
info->x, info->y, info->colp, info->colfp, info->zp, info->zfp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2070,6 +2090,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
|
||||
float *fp;
|
||||
unsigned char *cp;
|
||||
int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
|
||||
Image *image = ED_space_image(sima);
|
||||
|
||||
CLAMP(x, 0, ibuf->x - 1);
|
||||
CLAMP(y, 0, ibuf->y - 1);
|
||||
@@ -2083,7 +2104,9 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
|
||||
info->colfp = NULL;
|
||||
info->zp = NULL;
|
||||
info->zfp = NULL;
|
||||
|
||||
|
||||
info->use_default_view = (image->flag & IMA_VIEW_AS_RENDER) ? FALSE : TRUE;
|
||||
|
||||
if (ibuf->rect) {
|
||||
cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
|
||||
|
||||
|
||||
@@ -341,7 +341,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
|
||||
ImageSampleInfo *info = arg_info;
|
||||
|
||||
if (info->draw) {
|
||||
ED_image_draw_info(scene, ar, info->color_manage, info->channels,
|
||||
ED_image_draw_info(scene, ar, info->color_manage, FALSE, info->channels,
|
||||
info->x, info->y, info->col, info->colf,
|
||||
NULL, NULL /* zbuf - unused for nodes */
|
||||
);
|
||||
|
||||
@@ -80,7 +80,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
|
||||
ImageSampleInfo *info = arg_info;
|
||||
|
||||
if (info->draw) {
|
||||
ED_image_draw_info(scene, ar, info->color_manage, info->channels,
|
||||
ED_image_draw_info(scene, ar, info->color_manage, FALSE, info->channels,
|
||||
info->x, info->y, info->colp, info->colfp, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,9 +635,15 @@ static void display_transform_get_from_ctx(const bContext *C, ColorManagedViewSe
|
||||
ColorManagedDisplaySettings **display_settings_r)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
|
||||
*view_settings_r = &scene->view_settings;
|
||||
*display_settings_r = &scene->display_settings;
|
||||
|
||||
if (sima) {
|
||||
if ((sima->image->flag & IMA_VIEW_AS_RENDER) == 0)
|
||||
*view_settings_r = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_OCIO
|
||||
@@ -801,6 +807,26 @@ static ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedDispla
|
||||
|
||||
return (ConstProcessorRcPtr *) display->to_scene_linear;
|
||||
}
|
||||
|
||||
static void init_default_view_settings(const ColorManagedDisplaySettings *display_settings,
|
||||
ColorManagedViewSettings *view_settings)
|
||||
{
|
||||
ColorManagedDisplay *display;
|
||||
ColorManagedView *default_view;
|
||||
|
||||
display = colormanage_display_get_named(display_settings->display_device);
|
||||
default_view = colormanage_view_get_default(display);
|
||||
|
||||
if (default_view)
|
||||
BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform));
|
||||
else
|
||||
view_settings->view_transform[0] = '\0';
|
||||
|
||||
view_settings->flag = 0;
|
||||
view_settings->gamma = 1.0f;
|
||||
view_settings->exposure = 0.0f;
|
||||
view_settings->curve_mapping = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void curve_mapping_apply_pixel(CurveMapping *curve_mapping, float *pixel, int channels)
|
||||
@@ -1763,8 +1789,22 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
|
||||
int buffer_size;
|
||||
ColormanageCacheViewSettings cache_view_settings;
|
||||
ColormanageCacheDisplaySettings cache_display_settings;
|
||||
ColorManagedViewSettings default_view_settings;
|
||||
const ColorManagedViewSettings *applied_view_settings;
|
||||
|
||||
colormanage_view_settings_to_cache(&cache_view_settings, view_settings);
|
||||
if (view_settings) {
|
||||
applied_view_settings = view_settings;
|
||||
}
|
||||
else {
|
||||
/* if no view settings were specified, use default display transformation
|
||||
* this happens for images which don't want to be displayed with render settings
|
||||
*/
|
||||
|
||||
init_default_view_settings(display_settings, &default_view_settings);
|
||||
applied_view_settings = &default_view_settings;
|
||||
}
|
||||
|
||||
colormanage_view_settings_to_cache(&cache_view_settings, applied_view_settings);
|
||||
colormanage_display_settings_to_cache(&cache_display_settings, display_settings);
|
||||
|
||||
BLI_lock_thread(LOCK_COLORMANAGE);
|
||||
@@ -1793,7 +1833,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
|
||||
buffer_size = ibuf->channels * ibuf->x * ibuf->y * sizeof(float);
|
||||
display_buffer = MEM_callocN(buffer_size, "imbuf display buffer");
|
||||
|
||||
colormanage_display_buffer_process(ibuf, display_buffer, view_settings, display_settings);
|
||||
colormanage_display_buffer_process(ibuf, display_buffer, applied_view_settings, display_settings);
|
||||
|
||||
colormanage_cache_put(ibuf, &cache_view_settings, &cache_display_settings, display_buffer, cache_handle);
|
||||
|
||||
@@ -2415,12 +2455,25 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag
|
||||
cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor");
|
||||
|
||||
#ifdef WITH_OCIO
|
||||
cm_processor->processor = create_display_buffer_processor(view_settings->view_transform, display_settings->display_device,
|
||||
view_settings->exposure, view_settings->gamma);
|
||||
{
|
||||
ColorManagedViewSettings default_view_settings;
|
||||
const ColorManagedViewSettings *applied_view_settings;
|
||||
|
||||
if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) {
|
||||
cm_processor->curve_mapping = curvemapping_copy(view_settings->curve_mapping);
|
||||
curvemapping_premultiply(cm_processor->curve_mapping, FALSE);
|
||||
if (view_settings) {
|
||||
applied_view_settings = view_settings;
|
||||
}
|
||||
else {
|
||||
init_default_view_settings(display_settings, &default_view_settings);
|
||||
applied_view_settings = &default_view_settings;
|
||||
}
|
||||
|
||||
cm_processor->processor = create_display_buffer_processor(applied_view_settings->view_transform, display_settings->display_device,
|
||||
applied_view_settings->exposure, applied_view_settings->gamma);
|
||||
|
||||
if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) {
|
||||
cm_processor->curve_mapping = curvemapping_copy(applied_view_settings->curve_mapping);
|
||||
curvemapping_premultiply(cm_processor->curve_mapping, FALSE);
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void) view_settings;
|
||||
|
||||
@@ -127,6 +127,7 @@ typedef struct Image {
|
||||
#define IMA_CM_PREDIVIDE 256
|
||||
#define IMA_USED_FOR_RENDER 512
|
||||
#define IMA_USER_FRAME_IN_RANGE 1024 /* for image user, but these flags are mixed */
|
||||
#define IMA_VIEW_AS_RENDER 2048
|
||||
|
||||
/* Image.tpageflag */
|
||||
#define IMA_TILES 1
|
||||
|
||||
@@ -513,6 +513,11 @@ static void rna_def_image(BlenderRNA *brna)
|
||||
"to avoid fringing for images with light backgrounds");
|
||||
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_free_update");
|
||||
|
||||
prop = RNA_def_property(srna, "view_as_render", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_VIEW_AS_RENDER);
|
||||
RNA_def_property_ui_text(prop, "View as Render", "Apply render part of display transformation when displaying this image on the screen");
|
||||
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "is_dirty", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_Image_dirty_get", NULL);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
Reference in New Issue
Block a user