Index: release/ui/buttons_scene.py =================================================================== --- release/ui/buttons_scene.py (revision 21176) +++ release/ui/buttons_scene.py (working copy) @@ -19,6 +19,7 @@ sub.itemR(rd, "render_shadows", text="Shadows") sub.itemR(rd, "render_sss", text="Subsurface Scattering") sub.itemR(rd, "render_envmaps", text="Environment Map") + sub.itemR(rd, "color_management") # sub.itemR(rd, "render_radiosity", text="Radio") col = split.column() Index: source/blender/render/intern/source/texture.c =================================================================== --- source/blender/render/intern/source/texture.c (revision 21176) +++ source/blender/render/intern/source/texture.c (working copy) @@ -48,6 +48,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "BKE_colortools.h" #include "BKE_image.h" #include "BKE_node.h" #include "BKE_plugin_types.h" @@ -1808,6 +1809,11 @@ } else texres.tin= texres.ta; + /* inverse gamma correction */ + if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { + color_manage_linearize(tcol, tcol); + } + if(mtex->mapto & MAP_COL) { texture_rgb_blend(&shi->r, tcol, &shi->r, texres.tin, colfac, mtex->blendtype); } Index: source/blender/render/intern/source/rayshade.c =================================================================== --- source/blender/render/intern/source/rayshade.c (revision 21176) +++ source/blender/render/intern/source/rayshade.c (working copy) @@ -225,8 +225,7 @@ shi->obr= obi->obr; shi->vlr= vlr; shi->mat= vlr->mat; - memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); // note, keep this synced with render_types.h - shi->har= shi->mat->har; + shade_input_init_material(shi); // Osa structs we leave unchanged now SWAP(int, osatex, shi->osatex); Index: source/blender/render/intern/source/shadeinput.c =================================================================== --- source/blender/render/intern/source/shadeinput.c (revision 21176) +++ source/blender/render/intern/source/shadeinput.c (working copy) @@ -39,6 +39,7 @@ #include "DNA_meshdata_types.h" #include "DNA_material_types.h" +#include "BKE_colortools.h" #include "BKE_utildefines.h" #include "BKE_node.h" @@ -84,11 +85,45 @@ */ +/* initialise material variables in shadeinput, + * doing inverse gamma correction where applicable */ +void shade_input_init_material(ShadeInput *shi) +{ + if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { + color_manage_linearize(&shi->r, &shi->mat->r); + color_manage_linearize(&shi->specr, &shi->mat->specr); + color_manage_linearize(&shi->mirr, &shi->mat->mirr); + + /* material ambr / ambg / ambb is overwritten from world + color_manage_linearize(shi->ambr, shi->mat->ambr); + */ + + /* note, keep this synced with render_types.h */ + memcpy(&shi->amb, &shi->mat->amb, 11*sizeof(float)); + shi->har= shi->mat->har; + } else { + /* note, keep this synced with render_types.h */ + memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); + shi->har= shi->mat->har; + } +} + +static void shadeinput_colors_linearize(ShadeInput *shi) +{ + color_manage_linearize(&shi->r, &shi->r); + color_manage_linearize(&shi->specr, &shi->specr); + color_manage_linearize(&shi->mirr, &shi->mirr); +} + /* also used as callback for nodes */ /* delivers a fully filled in ShadeResult, for all passes */ void shade_material_loop(ShadeInput *shi, ShadeResult *shr) { + /* because node materials don't have access to rendering context, + * inverse gamma correction must happen here. evil. */ + if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT && shi->nodes == 1) + shadeinput_colors_linearize(shi); shade_lamp_loop(shi, shr); /* clears shr */ @@ -96,9 +131,7 @@ ShadeResult shr_t; float fac= shi->translucency; - /* gotta copy it again */ - memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); - shi->har= shi->mat->har; + shade_input_init_material(shi); VECCOPY(shi->vn, shi->vno); VECMUL(shi->vn, -1.0f); @@ -148,8 +181,7 @@ } else { /* copy all relevant material vars, note, keep this synced with render_types.h */ - memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); - shi->har= shi->mat->har; + shade_input_init_material(shi); shade_material_loop(shi, shr); } @@ -571,6 +603,13 @@ /* not supported */ } } + + if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { + if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)) { + color_manage_linearize(shi->vcol, shi->vcol); + } + } + } /* from scanline pixel coordinates to 3d coordinates, requires set_triangle */ @@ -1240,6 +1279,12 @@ } /* else { Note! For raytracing winco is not set, important because thus means all shader input's need to have their variables set to zero else in-initialized values are used */ + if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { + if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)) { + color_manage_linearize(shi->vcol, shi->vcol); + } + } + } /* ****************** ShadeSample ************************************** */ Index: source/blender/render/intern/source/pipeline.c =================================================================== --- source/blender/render/intern/source/pipeline.c (revision 21176) +++ source/blender/render/intern/source/pipeline.c (working copy) @@ -2540,13 +2540,16 @@ ImBuf *ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.planes, 0, 0); int ok; - /* if not exists, BKE_write_ibuf makes one */ + /* if not exists, BKE_write_ibuf makes one */ ibuf->rect= (unsigned int *)rres.rect32; ibuf->rect_float= rres.rectf; ibuf->zbuf_float= rres.rectz; /* float factor for random dither, imbuf takes care of it */ ibuf->dither= scene->r.dither_intensity; + /* gamma correct to sRGB color space */ + if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) + ibuf->profile = IB_PROFILE_SRGB; ok= BKE_write_ibuf(scene, ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality); Index: source/blender/render/intern/source/sss.c =================================================================== --- source/blender/render/intern/source/sss.c (revision 21176) +++ source/blender/render/intern/source/sss.c (working copy) @@ -55,6 +55,7 @@ #include "DNA_material_types.h" +#include "BKE_colortools.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_material.h" @@ -916,7 +917,7 @@ if(!re->test_break(re->tbh)) { SSSData *sss= MEM_callocN(sizeof(*sss), "SSSData"); float ior= mat->sss_ior, cfac= mat->sss_colfac; - float *col= mat->sss_col, *radius= mat->sss_radius; + float col[3], *radius= mat->sss_radius; float fw= mat->sss_front, bw= mat->sss_back; float error = mat->sss_error; @@ -924,6 +925,8 @@ if((re->r.scemode & R_PREVIEWBUTS) && error < 0.5f) error= 0.5f; + if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) color_manage_linearize(col, mat->sss_col); + sss->ss[0]= scatter_settings_new(col[0], radius[0], ior, cfac, fw, bw); sss->ss[1]= scatter_settings_new(col[1], radius[1], ior, cfac, fw, bw); sss->ss[2]= scatter_settings_new(col[2], radius[2], ior, cfac, fw, bw); Index: source/blender/render/intern/source/convertblender.c =================================================================== --- source/blender/render/intern/source/convertblender.c (revision 21176) +++ source/blender/render/intern/source/convertblender.c (working copy) @@ -5311,6 +5311,7 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob) { float mat[4][4]; + float amb[3]; unsigned int lay; int onlyselected, nolamps; @@ -5372,9 +5373,12 @@ /* still bad... doing all */ init_render_textures(re); - init_render_materials(re->r.mode, &re->wrld.ambr); + + if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) color_manage_linearize(amb, &re->wrld.ambr); + init_render_materials(re->r.mode, amb); + set_node_shader_lamp_loop(shade_material_loop); - + /* MAKE RENDER DATA */ nolamps= !ELEM3(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW); onlyselected= ELEM3(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT); Index: source/blender/render/intern/source/pixelshading.c =================================================================== --- source/blender/render/intern/source/pixelshading.c (revision 21176) +++ source/blender/render/intern/source/pixelshading.c (working copy) @@ -58,6 +58,7 @@ #include "rendercore.h" #include "shadbuf.h" #include "pixelshading.h" +#include "shading.h" #include "sunsky.h" /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -536,9 +537,11 @@ blend= fabs(0.5+ view[1]); } - hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb; - zen[0]= R.wrld.zenr; zen[1]= R.wrld.zeng; zen[2]= R.wrld.zenb; - + if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { + color_manage_linearize(hor, &R.wrld.horr); + color_manage_linearize(zen, &R.wrld.zenr); + } + /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If */ /* SKYBLEND is active, the texture and color blend are added. */ if(R.wrld.skytype & WO_SKYTEX) { Index: source/blender/render/intern/source/rendercore.c =================================================================== --- source/blender/render/intern/source/rendercore.c (revision 21176) +++ source/blender/render/intern/source/rendercore.c (working copy) @@ -1515,9 +1515,7 @@ shi->mat= mat; /* init material vars */ - // note, keep this synced with render_types.h - memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); - shi->har= shi->mat->har; + shade_input_init_material(shi); /* render */ shade_input_set_shade_texco(shi); @@ -1950,10 +1948,7 @@ if(shi->mat->nodetree && shi->mat->use_nodes) ntreeShaderExecTree(shi->mat->nodetree, shi, shr); else { - /* copy all relevant material vars, note, keep this synced with render_types.h */ - memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); - shi->har= shi->mat->har; - + shade_input_init_material(shi); shade_material_loop(shi, shr); } } @@ -2104,9 +2099,7 @@ ShadeResult shr; VlakRen *vlr= shi->vlr; - /* init material vars */ - memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); // note, keep this synced with render_types.h - shi->har= shi->mat->har; + shade_input_init_material(shi); if(bs->type==RE_BAKE_AO) { ambient_occlusion(shi); Index: source/blender/render/intern/source/strand.c =================================================================== --- source/blender/render/intern/source/strand.c (revision 21176) +++ source/blender/render/intern/source/strand.c (working copy) @@ -281,9 +281,7 @@ shade_input_set_strand_texco(shi, sseg->strand, sseg->v[1], spoint); /* init material vars */ - // note, keep this synced with render_types.h - memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); - shi->har= shi->mat->har; + shade_input_init_material(shi); /* shade */ shade_samples_do_AO(ssamp); Index: source/blender/render/intern/include/shading.h =================================================================== --- source/blender/render/intern/include/shading.h (revision 21176) +++ source/blender/render/intern/include/shading.h (working copy) @@ -66,6 +66,7 @@ void shade_input_set_strand_texco(struct ShadeInput *shi, struct StrandRen *strand, struct StrandVert *svert, struct StrandPoint *spoint); void shade_input_do_shade(struct ShadeInput *shi, struct ShadeResult *shr); +void shade_input_init_material(struct ShadeInput *shi); void shade_input_initialize(struct ShadeInput *shi, struct RenderPart *pa, struct RenderLayer *rl, int sample); void shade_sample_initialize(struct ShadeSample *ssamp, struct RenderPart *pa, struct RenderLayer *rl); Index: source/blender/blenkernel/intern/colortools.c =================================================================== --- source/blender/blenkernel/intern/colortools.c (revision 21176) +++ source/blender/blenkernel/intern/colortools.c (working copy) @@ -58,6 +58,86 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +/* ********************************* color transforms ********************************* */ + +/*Transform linear RGB values to nonlinear RGB values. Rec. + 709 is ITU-R Recommendation BT. 709 (1990) ``Basic + Parameter Values for the HDTV Standard for the Studio and + for International Programme Exchange'', formerly CCIR Rec. + 709.*/ +void gamma_correct_rec709(float *c, float gamma) +{ + /* Rec. 709 gamma correction. */ + float cc = 0.018f; + + if (*c < cc) + *c *= ((1.099f * (float)pow(cc, gamma)) - 0.099f) / cc; + else + *c = (1.099f * (float)pow(*c, gamma)) - 0.099f; +} + +void gamma_correct(float *c, float gamma) +{ + *c = pow((*c), gamma); +} + +float srgb_to_linearrgb(float c) +{ + if (c < 0.04045f) + return (c < 0.f)?0.f:c / 12.92; + else + return pow((c + 0.055)/1.055, 2.4); +} + +float linearrgb_to_srgb(float c) +{ + if (c < 0.0031308) + return (c < 0.f)?0.f:c * 12.92; + else + return 1.055 * pow(c, 1.0/2.4) - 0.055; +} + +/* utility function convert an RGB triplet from sRGB to linear RGB color space */ +void color_manage_linearize(float *col_to, float *col_from) +{ + col_to[0] = srgb_to_linearrgb(col_from[0]); + col_to[1] = srgb_to_linearrgb(col_from[1]); + col_to[2] = srgb_to_linearrgb(col_from[2]); +} + +void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w) +{ + int x, y; + float *rf= rectf; + unsigned char *rc= rectc; + + for(y=y1; yr.frs_sec= 25; sce->r.frs_sec_base= 1; sce->r.ocres = 128; + sce->r.color_mgt_flag |= R_COLOR_MANAGEMENT; sce->r.bake_mode= 1; /* prevent to include render stuff here */ sce->r.bake_filter= 2; Index: source/blender/blenkernel/BKE_colortools.h =================================================================== --- source/blender/blenkernel/BKE_colortools.h (revision 21176) +++ source/blender/blenkernel/BKE_colortools.h (working copy) @@ -33,7 +33,16 @@ struct CurveMap; struct ImBuf; struct rctf; - + +void gamma_correct_rec709(float *c, float gamma); +void gamma_correct(float *c, float gamma); +float srgb_to_linearrgb(float c); +float linearrgb_to_srgb(float c); +void color_manage_linearize(float *col_to, float *col_from); + +void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w); +void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w); + struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy); void curvemapping_free(struct CurveMapping *cumap); struct CurveMapping *curvemapping_copy(struct CurveMapping *cumap); @@ -60,5 +69,6 @@ void curvemapping_table_RGBA(struct CurveMapping *cumap, float **array, int *size); void colorcorrection_do_ibuf(struct ImBuf *ibuf, const char *profile); + #endif Index: source/blender/makesdna/DNA_scene_types.h =================================================================== --- source/blender/makesdna/DNA_scene_types.h (revision 21176) +++ source/blender/makesdna/DNA_scene_types.h (working copy) @@ -269,8 +269,12 @@ * Value used to define filter size for all filter options */ float gauss; + + /* color management settings - colour profiles, gamma correction, etc */ + int color_mgt_flag; + /** post-production settings. Depricated, but here for upwards compat (initialized to 1) */ - float postmul, postgamma, posthue, postsat; + float postgamma, posthue, postsat; /* Dither noise intensity */ float dither_intensity; @@ -708,6 +712,9 @@ #define R_PLANES32 32 #define R_PLANESBW 8 +/* color_mgt_flag */ +#define R_COLOR_MANAGEMENT 1 + /* imtype */ #define R_TARGA 0 #define R_IRIS 1 Index: source/blender/makesrna/intern/rna_texture.c =================================================================== --- source/blender/makesrna/intern/rna_texture.c (revision 21176) +++ source/blender/makesrna/intern/rna_texture.c (working copy) @@ -272,7 +272,7 @@ prop= RNA_def_property(srna, "no_rgb", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_RGBTOINT); - RNA_def_property_ui_text(prop, "No RGB", "Converts texture RGB values to intensity (gray) values."); + RNA_def_property_ui_text(prop, "RGB to Intensity", "Converts texture RGB values to intensity (gray) values."); RNA_def_property_update(prop, NC_TEXTURE, NULL); prop= RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_VECTOR); Index: source/blender/makesrna/intern/rna_scene.c =================================================================== --- source/blender/makesrna/intern/rna_scene.c (revision 21176) +++ source/blender/makesrna/intern/rna_scene.c (working copy) @@ -801,6 +801,11 @@ RNA_def_property_ui_text(prop, "Do Sequence", "Process the render (and composited) result through the video sequence editor pipeline"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + prop= RNA_def_property(srna, "color_management", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "color_mgt_flag", R_COLOR_MANAGEMENT); + RNA_def_property_ui_text(prop, "Color Management", "Use color profiles and gamma corrected imaging pipeline"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS|NC_MATERIAL|ND_SHADING, NULL); + prop= RNA_def_property(srna, "file_extensions", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_EXTENSION); RNA_def_property_ui_text(prop, "File Extensions", "Add the file format extensions to the rendered file name (eg: filename + .jpg)"); Index: source/blender/imbuf/intern/divers.c =================================================================== --- source/blender/imbuf/intern/divers.c (revision 21176) +++ source/blender/imbuf/intern/divers.c (working copy) @@ -39,6 +39,7 @@ #include "IMB_allocimbuf.h" #include "IMB_divers.h" #include "BKE_utildefines.h" +#include "BKE_colortools.h" void imb_checkncols(struct ImBuf *ibuf) { @@ -176,9 +177,10 @@ void IMB_rect_from_float(struct ImBuf *ibuf) { /* quick method to convert floatbuf to byte */ - float *tof = ibuf->rect_float; + float *tof = (float *)ibuf->rect_float; float dither= ibuf->dither; int i, channels= ibuf->channels; + short profile= ibuf->profile; unsigned char *to = (unsigned char *) ibuf->rect; if(tof==NULL) return; @@ -187,7 +189,20 @@ to = (unsigned char *) ibuf->rect; } - if(dither==0.0f || channels!=4) { + if (profile == IB_PROFILE_SRGB && (channels == 3 || channels == 4)) { + if(channels == 3) { + for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) { + to[0] = FTOCHAR(linearrgb_to_srgb(tof[0])); + to[1] = FTOCHAR(linearrgb_to_srgb(tof[1])); + to[2] = FTOCHAR(linearrgb_to_srgb(tof[2])); + to[3] = 255; + } + } + else if (channels == 4) { + floatbuf_to_srgb_byte(tof, to, 0, ibuf->x, 0, ibuf->y, ibuf->x); + } + } + else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_LINEAR_RGB) && (dither==0.0f || channels!=4)) { if(channels==1) { for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof++) to[1]= to[2]= to[3]= to[0] = FTOCHAR(tof[0]); @@ -242,14 +257,28 @@ tof = ibuf->rect_float; } - for (i = ibuf->x * ibuf->y; i > 0; i--) - { - tof[0] = ((float)to[0])*(1.0f/255.0f); - tof[1] = ((float)to[1])*(1.0f/255.0f); - tof[2] = ((float)to[2])*(1.0f/255.0f); - tof[3] = ((float)to[3])*(1.0f/255.0f); - to += 4; - tof += 4; + if (ibuf->profile == IB_PROFILE_SRGB) { + /* convert from srgb to linear rgb */ + + for (i = ibuf->x * ibuf->y; i > 0; i--) + { + tof[0] = srgb_to_linearrgb(((float)to[0])*(1.0f/255.0f)); + tof[1] = srgb_to_linearrgb(((float)to[1])*(1.0f/255.0f)); + tof[2] = srgb_to_linearrgb(((float)to[2])*(1.0f/255.0f)); + tof[3] = ((float)to[3])*(1.0f/255.0f); + to += 4; + tof += 4; + } + } else { + for (i = ibuf->x * ibuf->y; i > 0; i--) + { + tof[0] = ((float)to[0])*(1.0f/255.0f); + tof[1] = ((float)to[1])*(1.0f/255.0f); + tof[2] = ((float)to[2])*(1.0f/255.0f); + tof[3] = ((float)to[3])*(1.0f/255.0f); + to += 4; + tof += 4; + } } } Index: source/blender/imbuf/IMB_imbuf_types.h =================================================================== --- source/blender/imbuf/IMB_imbuf_types.h (revision 21176) +++ source/blender/imbuf/IMB_imbuf_types.h (working copy) @@ -98,9 +98,13 @@ unsigned int encodedsize; /**< Size of data written to encodedbuffer */ unsigned int encodedbuffersize; /**< Size of encodedbuffer */ - float *rect_float; /**< floating point Rect equivalent */ + float *rect_float; /**< floating point Rect equivalent + Linear RGB colour space - may need gamma correction to + sRGB when generating 8bit representations */ int channels; /**< amount of channels in rect_float (0 = 4 channel default) */ float dither; /**< random dither value, for conversion from float -> byte rect */ + short profile; /** colour space/profile preset that the byte rect buffer represents */ + char profile_filename[256]; /** to be implemented properly, specific filename for custom profiles */ struct MEM_CacheLimiterHandle_s * c_handle; /**< handle for cache limiter */ struct ImgInfo * img_info; @@ -213,6 +217,18 @@ #define AN_tanx (Anim | TANX) /**@}*/ +/** + * \name Imbuf preset profile tags + * \brief Some predefined color space profiles that 8 bit imbufs can represent + */ +/**@{*/ +#define IB_PROFILE_NONE 0 +#define IB_PROFILE_LINEAR_RGB 1 +#define IB_PROFILE_SRGB 2 +#define IB_PROFILE_CUSTOM 3 +/**@}*/ + + /** \name Imbuf File Type Tests * \brief These macros test if an ImBuf struct is the corresponding file type. */ Index: source/blender/blenlib/BLI_arithb.h =================================================================== --- source/blender/blenlib/BLI_arithb.h (revision 21176) +++ source/blender/blenlib/BLI_arithb.h (working copy) @@ -339,7 +339,6 @@ void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv); void xyz_to_rgb(float x, float y, float z, float *r, float *g, float *b, int colorspace); int constrain_rgb(float *r, float *g, float *b); -void gamma_correct_rgb(float *r, float *g, float *b); unsigned int hsv_to_cpack(float h, float s, float v); unsigned int rgb_to_cpack(float r, float g, float b); void cpack_to_rgb(unsigned int col, float *r, float *g, float *b); Index: source/blender/blenlib/intern/arithb.c =================================================================== --- source/blender/blenlib/intern/arithb.c (revision 21176) +++ source/blender/blenlib/intern/arithb.c (working copy) @@ -3548,30 +3548,7 @@ return 0; /* Colour within RGB gamut */ } -/*Transform linear RGB values to nonlinear RGB values. Rec. - 709 is ITU-R Recommendation BT. 709 (1990) ``Basic - Parameter Values for the HDTV Standard for the Studio and - for International Programme Exchange'', formerly CCIR Rec. - 709.*/ -static void gamma_correct(float *c) -{ - /* Rec. 709 gamma correction. */ - float cc = 0.018f; - - if (*c < cc) - *c *= ((1.099f * (float)pow(cc, 0.45)) - 0.099f) / cc; - else - *c = (1.099f * (float)pow(*c, 0.45)) - 0.099f; -} -void gamma_correct_rgb(float *r, float *g, float *b) -{ - gamma_correct(r); - gamma_correct(g); - gamma_correct(b); -} - - /* we define a 'cpack' here as a (3 byte color code) number that can be expressed like 0xFFAA66 or so. for that reason it is sensitive for endianness... with this function it works correctly */ Index: source/blender/nodes/intern/CMP_nodes/CMP_image.c =================================================================== --- source/blender/nodes/intern/CMP_nodes/CMP_image.c (revision 21176) +++ source/blender/nodes/intern/CMP_nodes/CMP_image.c (working copy) @@ -65,9 +65,28 @@ if(ibuf==NULL) return NULL; - if(ibuf->rect_float==NULL) + if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) { + if (ibuf->profile == IB_PROFILE_NONE) { + if (ibuf->rect_float != NULL) { + imb_freerectfloatImBuf(ibuf); + } + ibuf->profile = IB_PROFILE_SRGB; + IMB_float_from_rect(ibuf); + } + } else { + if (ibuf->profile == IB_PROFILE_SRGB) { + if (ibuf->rect_float != NULL) { + imb_freerectfloatImBuf(ibuf); + } + ibuf->profile = IB_PROFILE_NONE; + IMB_float_from_rect(ibuf); + } + } + + if (ibuf->rect_float == NULL) { IMB_float_from_rect(ibuf); - + } + type= ibuf->channels; if(rd->scemode & R_COMP_CROP) { Index: source/blender/editors/screen/glutil.c =================================================================== --- source/blender/editors/screen/glutil.c (revision 21176) +++ source/blender/editors/screen/glutil.c (working copy) @@ -35,6 +35,7 @@ #include "DNA_listBase.h" #include "BKE_utildefines.h" +#include "BKE_colortools.h" #include "BLI_arithb.h" #include "BLI_threads.h" @@ -482,27 +483,20 @@ glaDrawPixelsTexScaled(x, y, img_w, img_h, format, rect, 1.0f, 1.0f); } -void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int row_w, float *rectf) +void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int row_w, float *rectf, int gamma_correct) { - float *rf; - int x, y; - char *rect32, *rc; + unsigned char *rect32; /* copy imgw-imgh to a temporal 32 bits rect */ if(img_w<1 || img_h<1) return; - rc= rect32= MEM_mallocN(img_w*img_h*sizeof(int), "temp 32 bits"); + rect32= MEM_mallocN(img_w*img_h*sizeof(int), "temp 32 bits"); - for(y=0; yrectx*ymin + xmin); rectc= (char *)(ibuf->rect + ibuf->x*rymin + rxmin); - for(y1= 0; y1= (char *)(ibuf->rect)) { - for(x1= 0; x1scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) { + for(y1= 0; y1= (char *)(ibuf->rect)) { + for(x1= 0; x1rectx; + rectc += 4*ibuf->x; } - rectf += 4*rr->rectx; - rectc += 4*ibuf->x; + } else { + for(y1= 0; y1= (char *)(ibuf->rect)) { + for(x1= 0; x1rectx; + rectc += 4*ibuf->x; + } } /* make jobs timer to send notifier */ Index: source/blender/editors/preview/previewrender.c =================================================================== --- source/blender/editors/preview/previewrender.c (revision 21176) +++ source/blender/editors/preview/previewrender.c (working copy) @@ -293,6 +293,7 @@ sce->world->range= scene->world->range; } + sce->r.color_mgt_flag = scene->r.color_mgt_flag; sce->r.cfra= scene->r.cfra; if(id_type==ID_MA) { @@ -353,6 +354,9 @@ sce->lay= 1<r.color_mgt_flag &= ~R_COLOR_MANAGEMENT; + for(base= sce->base.first; base; base= base->next) { if(base->object->id.name[2]=='t') { Material *mat= give_current_material(base->object, base->object->actcol); @@ -404,21 +408,28 @@ return NULL; } - /* new UI convention: draw is in pixel space already. */ /* uses ROUNDBOX button in block to get the rect */ void ED_preview_draw(const bContext *C, void *idp, rcti *rect) { if(idp) { ScrArea *sa= CTX_wm_area(C); + Scene *sce = CTX_data_scene(C); + ID *id = (ID *)idp; SpaceButs *sbuts= sa->spacedata.first; RenderResult rres; int newx= rect->xmax-rect->xmin, newy= rect->ymax-rect->ymin; int ok= 0; char name[32]; + int gamma_correct=0; + + if (id && GS(id->name) != ID_TE) { + /* exception: don't colour manage texture previews - show the raw values */ + if (sce) gamma_correct = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT; + } sprintf(name, "Preview %p", sa); - BLI_lock_malloc_thread(); + //BLI_lock_malloc_thread(); RE_GetResultImage(RE_GetRender(name), &rres); if(rres.rectf) { @@ -428,11 +439,11 @@ rect->xmax= rect->xmin + rres.rectx; rect->ymax= rect->ymin + rres.recty; - glaDrawPixelsSafe(rect->xmin, rect->ymin, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_FLOAT, rres.rectf); + glaDrawPixelsSafe_to32(rect->xmin, rect->ymin, rres.rectx, rres.recty, rres.rectx, rres.rectf, gamma_correct); ok= 1; } } - BLI_unlock_malloc_thread(); + //BLI_unlock_malloc_thread(); /* check for spacetype... */ if(sbuts->spacetype==SPACE_BUTS && sbuts->preview) { @@ -468,7 +479,7 @@ glDrawBuffer(GL_FRONT); // glaDefine2DArea(&sa->winrct); - glaDrawPixelsSafe_to32(ofsx, ofsy, rr->rectx, rr->recty, rr->rectx, rl->rectf); + glaDrawPixelsSafe_to32(ofsx, ofsy, rr->rectx, rr->recty, rr->rectx, rl->rectf, 0); bglFlush(); glDrawBuffer(GL_BACK); Index: source/blender/editors/include/BIF_glutil.h =================================================================== --- source/blender/editors/include/BIF_glutil.h (revision 21176) +++ source/blender/editors/include/BIF_glutil.h (working copy) @@ -129,10 +129,11 @@ * is expected to be in RGBA byte or float format, and the * modelview and projection matrices are assumed to define a * 1-to-1 mapping to screen space. + * @param gamma_correct Optionally gamma correct float sources to sRGB for display */ /* only for float rects, converts to 32 bits and draws */ -void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int row_w, float *rectf); +void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int row_w, float *rectf, int gamma_correct); void glaDrawPixelsTex (float x, float y, int img_w, int img_h, int format, void *rect); Index: source/blender/editors/space_image/image_draw.c =================================================================== --- source/blender/editors/space_image/image_draw.c (revision 21176) +++ source/blender/editors/space_image/image_draw.c (working copy) @@ -106,7 +106,7 @@ return 0; } -static void image_verify_buffer_float(SpaceImage *sima, ImBuf *ibuf) +static void image_verify_buffer_float(SpaceImage *sima, Image *ima, ImBuf *ibuf, int color_manage) { /* detect if we need to redo the curve map. ibuf->rect is zero for compositor and render results after change @@ -121,6 +121,12 @@ curvemapping_do_ibuf(sima->cumap, ibuf); } else { + if (color_manage) { + if (ima && ima->source == IMA_SRC_VIEWER) + ibuf->profile = IB_PROFILE_SRGB; + } else { + ibuf->profile = IB_PROFILE_NONE; + } IMB_rect_from_float(ibuf); } } @@ -372,9 +378,10 @@ MEM_freeN(rectf); } -static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) +static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) { int x, y; + int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; /* set zoom */ glPixelZoom(zoomx, zoomy); @@ -399,7 +406,7 @@ } #ifdef WITH_LCMS else if(sima->flag & SI_COLOR_CORRECTION) { - image_verify_buffer_float(sima, ibuf); + image_verify_buffer_float(sima, ima, ibuf, color_manage); sima_draw_colorcorrected_pixels(x, y, ibuf); @@ -415,7 +422,7 @@ /* we don't draw floats buffers directly but * convert them, and optionally apply curves */ - image_verify_buffer_float(sima, ibuf); + image_verify_buffer_float(sima, ima, ibuf, color_manage); if(ibuf->rect) glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); @@ -452,10 +459,12 @@ return rectmain; } -static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) +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 *rect; int dx, dy, sx, sy, x, y; + int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; + /* verify valid values, just leave this a while */ if(ima->xrep<1) return; @@ -467,7 +476,7 @@ sima->curtile = ima->xrep*ima->yrep - 1; /* create char buffer from float if needed */ - image_verify_buffer_float(sima, ibuf); + image_verify_buffer_float(sima, ima, ibuf, color_manage); /* retrieve part of image buffer */ dx= ibuf->x/ima->xrep; @@ -500,9 +509,9 @@ for(x=floor(ar->v2d.cur.xmin); xv2d.cur.xmax; x += 1.0f) { for(y=floor(ar->v2d.cur.ymin); yv2d.cur.ymax; y += 1.0f) { if(ima && (ima->tpageflag & IMA_TILES)) - draw_image_buffer_tiled(sima, ar, ima, ibuf, x, y, zoomx, zoomy); + draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy); else - draw_image_buffer(sima, ar, scene, ibuf, x, y, zoomx, zoomy); + draw_image_buffer(sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy); /* only draw until running out of time */ if((PIL_check_seconds_timer() - time_current) > 0.25) @@ -674,9 +683,9 @@ else if(sima->flag & SI_DRAW_TILE) draw_image_buffer_repeated(sima, ar, scene, ima, ibuf, zoomx, zoomy); else if(ima && (ima->tpageflag & IMA_TILES)) - draw_image_buffer_tiled(sima, ar, ima, ibuf, 0.0f, 0.0, zoomx, zoomy); + draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy); else - draw_image_buffer(sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy); + draw_image_buffer(sima, ar, scene, ima, ibuf, 0.0f, 0.0f, zoomx, zoomy); /* grease pencil */ draw_image_grease_pencil(sima, ibuf); Index: source/blender/editors/space_image/image_render.c =================================================================== --- source/blender/editors/space_image/image_render.c (revision 21176) +++ source/blender/editors/space_image/image_render.c (working copy) @@ -119,7 +119,7 @@ if(rect32) glaDrawPixelsSafe(x1, y1, xmax, ymax, rr->rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect32); else - glaDrawPixelsSafe_to32(x1, y1, xmax, ymax, rr->rectx, rectf); + glaDrawPixelsSafe_to32(x1, y1, xmax, ymax, rr->rectx, rectf, 0); glPixelZoom(1.0, 1.0);