Code refactoring: add unified image buffer functions for doing float => byte,

byte => float, float => float, byte => byte conversions with profile, dither
and predivide. Previously code for this was spread out too much.

There should be no functional changes, this is so the predivide/table/dither
patches can work correctly.
This commit is contained in:
Brecht Van Lommel 2011-12-28 13:29:33 +00:00
parent 1f02209957
commit b9ff5840a6
13 changed files with 675 additions and 530 deletions

View File

@ -45,9 +45,6 @@ struct rctf;
# define DO_INLINE static inline
#endif
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);

View File

@ -52,45 +52,6 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w))
{
int x, y;
float *rf= rectf;
float srgb[3];
unsigned char *rc= rectc;
for(y=y1; y<y2; y++) {
for(x=x1; x<x2; x++, rf+=4, rc+=4) {
srgb[0]= linearrgb_to_srgb(rf[0]);
srgb[1]= linearrgb_to_srgb(rf[1]);
srgb[2]= linearrgb_to_srgb(rf[2]);
rc[0]= FTOCHAR(srgb[0]);
rc[1]= FTOCHAR(srgb[1]);
rc[2]= FTOCHAR(srgb[2]);
rc[3]= FTOCHAR(rf[3]);
}
}
}
void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w))
{
int x, y;
float *rf= rectf;
unsigned char *rc= rectc;
for(y=y1; y<y2; y++) {
for(x=x1; x<x2; x++, rf+=4, rc+=4) {
rc[0]= FTOCHAR(rf[0]);
rc[1]= FTOCHAR(rf[1]);
rc[2]= FTOCHAR(rf[2]);
rc[3]= FTOCHAR(rf[3]);
}
}
}
/* ********************************* color curve ********************* */
/* ***************** operations on full struct ************* */

View File

@ -34,6 +34,8 @@
extern "C" {
#endif
#include "BLI_math_inline.h"
/* primaries */
#define BLI_XYZ_SMPTE 0
#define BLI_XYZ_REC709_SRGB 1
@ -48,7 +50,7 @@ extern "C" {
#define BLI_YCC_ITU_BT601 0
#define BLI_YCC_ITU_BT709 1
#define BLI_YCC_JFIF_0_255 2
/******************* Conversion to RGB ********************/
void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b);
@ -70,22 +72,23 @@ unsigned int hsv_to_cpack(float h, float s, float v);
float rgb_to_grayscale(float rgb[3]);
unsigned char rgb_to_grayscale_byte(unsigned char rgb[3]);
/***************** Profile Transformations ********************/
/**************** Profile Transformations *****************/
void gamma_correct(float *c, float gamma);
float rec709_to_linearrgb(float c);
float linearrgb_to_rec709(float c);
float srgb_to_linearrgb(float c);
float linearrgb_to_srgb(float c);
void srgb_to_linearrgb_v3_v3(float *col_to, float *col_from);
void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from);
/* rgba buffer convenience functions */
void srgb_to_linearrgb_rgba_buf(float *col, int tot);
void linearrgb_to_srgb_rgba_buf(float *col, int tot);
void srgb_to_linearrgb_rgba_rgba_buf(float *col_to, float *col_from, int tot);
void linearrgb_to_srgb_rgba_rgba_buf(float *col_to, float *col_from, int tot);
MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3]);
MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3]);
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4]);
MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4]);
MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4]);
MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4]);
/************************** Other *************************/
int constrain_rgb(float *r, float *g, float *b);
@ -101,6 +104,10 @@ void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *o
void rgb_byte_to_float(const unsigned char *in, float *out);
void rgb_float_to_byte(const float *in, unsigned char *out);
#ifdef BLI_MATH_INLINE_H
#include "intern/math_color_inline.c"
#endif
#ifdef __cplusplus
}
#endif

View File

@ -393,57 +393,6 @@ float linearrgb_to_srgb(float c)
return 1.055f * powf(c, 1.0f/2.4f) - 0.055f;
}
void srgb_to_linearrgb_v3_v3(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 linearrgb_to_srgb_v3_v3(float *col_to, float *col_from)
{
col_to[0] = linearrgb_to_srgb(col_from[0]);
col_to[1] = linearrgb_to_srgb(col_from[1]);
col_to[2] = linearrgb_to_srgb(col_from[2]);
}
/* todo, should these be moved elsewhere?, they dont belong in imbuf */
void srgb_to_linearrgb_rgba_buf(float *col, int tot)
{
while(tot--) {
srgb_to_linearrgb_v3_v3(col, col);
col += 4;
}
}
void linearrgb_to_srgb_rgba_buf(float *col, int tot)
{
while(tot--) {
linearrgb_to_srgb_v3_v3(col, col);
col += 4;
}
}
void srgb_to_linearrgb_rgba_rgba_buf(float *col_to, float *col_from, int tot)
{
while(tot--) {
srgb_to_linearrgb_v3_v3(col_to, col_from);
col_to[3]= col_from[3];
col_to += 4;
col_from += 4;
}
}
void linearrgb_to_srgb_rgba_rgba_buf(float *col_to, float *col_from, int tot)
{
while(tot--) {
linearrgb_to_srgb_v3_v3(col_to, col_from);
col_to[3]= col_from[3];
col_to += 4;
col_from += 4;
}
}
void minmax_rgb(short c[])
{
if(c[0]>255) c[0]=255;

View File

@ -0,0 +1,109 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: some of this file.
*
* ***** END GPL LICENSE BLOCK *****
* */
/** \file blender/blenlib/intern/math_color_inline.c
* \ingroup bli
*/
#include "BLI_math_color.h"
#include "BLI_utildefines.h"
#ifndef BLI_MATH_COLOR_INLINE_H
#define BLI_MATH_COLOR_INLINE_H
/******************************** Color Space ********************************/
MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3])
{
linear[0] = srgb_to_linearrgb(srgb[0]);
linear[1] = srgb_to_linearrgb(srgb[1]);
linear[2] = srgb_to_linearrgb(srgb[2]);
}
MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
{
srgb[0] = linearrgb_to_srgb(linear[0]);
srgb[1] = linearrgb_to_srgb(linear[1]);
srgb[2] = linearrgb_to_srgb(linear[2]);
}
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
{
srgb_to_linearrgb_v3_v3(linear, srgb);
linear[3] = srgb[3];
}
MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4])
{
linearrgb_to_srgb_v3_v3(srgb, linear);
srgb[3] = linear[3];
}
/* predivide versions to work on associated/premultipled alpha. if this should
be done or not depends on the background the image will be composited over,
ideally you would never do color space conversion on an image with alpha
because it is ill defined */
MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4])
{
float alpha, inv_alpha;
if(srgb[3] == 1.0f || srgb[3] == 0.0f) {
alpha = 1.0f;
inv_alpha = 1.0f;
}
else {
alpha = srgb[3];
inv_alpha = 1.0f/alpha;
}
linear[0] = srgb_to_linearrgb(srgb[0] * inv_alpha) * alpha;
linear[1] = srgb_to_linearrgb(srgb[1] * inv_alpha) * alpha;
linear[2] = srgb_to_linearrgb(srgb[2] * inv_alpha) * alpha;
linear[3] = srgb[3];
}
MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4])
{
float alpha, inv_alpha;
if(linear[3] == 1.0f || linear[3] == 0.0f) {
alpha = 1.0f;
inv_alpha = 1.0f;
}
else {
alpha = linear[3];
inv_alpha = 1.0f/alpha;
}
srgb[0] = linearrgb_to_srgb(linear[0] * inv_alpha) * alpha;
srgb[1] = linearrgb_to_srgb(linear[1] * inv_alpha) * alpha;
srgb[2] = linearrgb_to_srgb(linear[2] * inv_alpha) * alpha;
srgb[3] = linear[3];
}
#endif /* BLI_MATH_COLOR_INLINE_H */

View File

@ -76,10 +76,10 @@
/* called inside thread! */
void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect)
{
float x1, y1, *rectf= NULL;
float *rectf= NULL;
int ymin, ymax, xmin, xmax;
int rymin, rxmin, do_color_management;
char *rectc;
int rymin, rxmin, predivide, profile_from;
unsigned char *rectc;
/* if renrect argument, we only refresh scanlines */
if(renrect) {
@ -136,50 +136,17 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat
imb_addrectImBuf(ibuf);
rectf+= 4*(rr->rectx*ymin + xmin);
rectc= (char *)(ibuf->rect + ibuf->x*rymin + rxmin);
rectc= (unsigned char*)(ibuf->rect + ibuf->x*rymin + rxmin);
do_color_management = (scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT));
/* XXX make nice consistent functions for this */
for(y1= 0; y1<ymax; y1++) {
float *rf= rectf;
float srgb[3];
char *rc= rectc;
const float dither = ibuf->dither / 255.0f;
if(scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT))
profile_from= IB_PROFILE_LINEAR_RGB;
else
profile_from= IB_PROFILE_SRGB;
predivide= 0;
/* XXX temp. because crop offset */
if(rectc >= (char *)(ibuf->rect)) {
for(x1= 0; x1<xmax; x1++, rf += 4, rc+=4) {
/* color management */
if(do_color_management) {
srgb[0]= linearrgb_to_srgb(rf[0]);
srgb[1]= linearrgb_to_srgb(rf[1]);
srgb[2]= linearrgb_to_srgb(rf[2]);
}
else {
copy_v3_v3(srgb, rf);
}
/* dither */
if(dither != 0.0f) {
const float d = (BLI_frand()-0.5f)*dither;
srgb[0] += d;
srgb[1] += d;
srgb[2] += d;
}
/* write */
rc[0]= FTOCHAR(srgb[0]);
rc[1]= FTOCHAR(srgb[1]);
rc[2]= FTOCHAR(srgb[2]);
rc[3]= FTOCHAR(rf[3]);
}
}
rectf += 4*rr->rectx;
rectc += 4*ibuf->x;
}
IMB_buffer_byte_from_float(rectc, rectf,
4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide,
xmax, ymax, ibuf->x, rr->rectx);
}
/* ****************************** render invoking ***************** */

View File

@ -206,14 +206,11 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
* float buffer. */
if(oglrender->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) {
float *rctf = rr->rectf;
int i;
int predivide= 0; /* no alpha */
for (i = oglrender->sizex * oglrender->sizey; i > 0; i--, rctf+=4) {
rctf[0]= srgb_to_linearrgb(rctf[0]);
rctf[1]= srgb_to_linearrgb(rctf[1]);
rctf[2]= srgb_to_linearrgb(rctf[2]);
}
IMB_buffer_float_from_float(rr->rectf, rr->rectf,
4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide,
oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex);
}
RE_ReleaseResult(oglrender->re);

View File

@ -45,6 +45,9 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#ifndef GL_CLAMP_TO_EDGE
#define GL_CLAMP_TO_EDGE 0x812F
#endif
@ -563,17 +566,17 @@ void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *
void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int UNUSED(row_w), float *rectf, int do_gamma_correct)
{
unsigned char *rect32;
int profile_from= (do_gamma_correct)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
int predivide= 0;
/* copy imgw-imgh to a temporal 32 bits rect */
if(img_w<1 || img_h<1) return;
rect32= MEM_mallocN(img_w*img_h*sizeof(int), "temp 32 bits");
if (do_gamma_correct) {
floatbuf_to_srgb_byte(rectf, rect32, 0, img_w, 0, img_h, img_w);
} else {
floatbuf_to_byte(rectf, rect32, 0, img_w, 0, img_h, img_w);
}
IMB_buffer_byte_from_float(rect32, rectf,
4, 0, IB_PROFILE_SRGB, profile_from, predivide,
img_w, img_h, img_w, img_w);
glaDrawPixelsSafe(fx, fy, img_w, img_h, img_w, GL_RGBA, GL_UNSIGNED_BYTE, rect32);

View File

@ -378,6 +378,20 @@ void IMB_convert_profile(struct ImBuf *ibuf, int profile);
float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc);
void IMB_color_to_bw(struct ImBuf *ibuf);
/* converting pixel buffers */
void IMB_buffer_byte_from_float(unsigned char *rect_to, const float *rect_from,
int channels_from, int dither, int profile_to, int profile_from, int predivide,
int width, int height, int stride_to, int stride_from);
void IMB_buffer_float_from_byte(float *rect_to, const unsigned char *rect_from,
int profile_to, int profile_from, int predivide,
int width, int height, int stride_to, int stride_from);
void IMB_buffer_float_from_float(float *rect_to, const float *rect_from,
int channels_from, int profile_to, int profile_from, int predivide,
int width, int height, int stride_to, int stride_from);
void IMB_buffer_byte_from_byte(unsigned char *rect_to, const unsigned char *rect_from,
int profile_to, int profile_from, int predivide,
int width, int height, int stride_to, int stride_from);
/**
* Change the ordering of the color bytes pointed to by rect from
* rgba to abgr. size * 4 color bytes are reordered.

View File

@ -42,10 +42,10 @@
#include "IMB_imbuf.h"
#include "IMB_allocimbuf.h"
#include "BKE_colortools.h"
#include "MEM_guardedalloc.h"
/**************************** Interlace/Deinterlace **************************/
void IMB_de_interlace(struct ImBuf *ibuf)
{
struct ImBuf * tbuf1, * tbuf2;
@ -100,347 +100,498 @@ void IMB_interlace(struct ImBuf *ibuf)
}
}
/************************* Generic Buffer Conversion *************************/
MINLINE void byte_to_float_v4(float f[4], const uchar b[4])
{
f[0] = b[0] * (1.0f/255.0f);
f[1] = b[1] * (1.0f/255.0f);
f[2] = b[2] * (1.0f/255.0f);
f[3] = b[3] * (1.0f/255.0f);
}
MINLINE void float_to_byte_v4(uchar b[4], const float f[4])
{
F4TOCHAR4(f, b);
}
MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], float dither)
{
float tmp[4] = {f[0]+dither, f[1]+dither, f[2]+dither, f[3]+dither};
float_to_byte_v4(b, tmp);
}
/* float to byte pixels, output 4-channel RGBA */
void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
int channels_from, int dither, int profile_to, int profile_from, int predivide,
int width, int height, int stride_to, int stride_from)
{
float tmp[4];
float dither_fac = dither/255.0f;
int x, y;
/* we need valid profiles */
BLI_assert(profile_to != IB_PROFILE_NONE);
BLI_assert(profile_from != IB_PROFILE_NONE);
if(channels_from==1) {
/* single channel input */
for(y = 0; y < height; y++) {
const float *from = rect_from + stride_from*y;
uchar *to = rect_to + stride_to*y*4;
for(x = 0; x < width; x++, from++, to+=4)
to[0] = to[1] = to[2] = to[3] = FTOCHAR(from[0]);
}
}
else if(channels_from == 3) {
/* RGB input */
for(y = 0; y < height; y++) {
const float *from = rect_from + stride_from*y*3;
uchar *to = rect_to + stride_to*y*4;
if(profile_to == profile_from) {
/* no color space conversion */
for(x = 0; x < width; x++, from+=3, to+=4) {
F3TOCHAR3(from, to);
to[3] = 255;
}
}
else if(profile_to == IB_PROFILE_SRGB) {
/* convert from linear to sRGB */
for(x = 0; x < width; x++, from+=3, to+=4) {
linearrgb_to_srgb_v3_v3(tmp, from);
F3TOCHAR3(tmp, to);
to[3] = 255;
}
}
else if(profile_to == IB_PROFILE_LINEAR_RGB) {
/* convert from sRGB to linear */
for(x = 0; x < width; x++, from+=3, to+=4) {
srgb_to_linearrgb_v3_v3(tmp, from);
F3TOCHAR3(tmp, to);
to[3] = 255;
}
}
}
}
else if(channels_from == 4) {
/* RGBA input */
for(y = 0; y < height; y++) {
const float *from = rect_from + stride_from*y*4;
uchar *to = rect_to + stride_to*y*4;
if(profile_to == profile_from) {
/* no color space conversion */
if(dither) {
for(x = 0; x < width; x++, from+=4, to+=4)
float_to_byte_dither_v4(to, from, (BLI_frand()-0.5f)*dither_fac);
}
else {
for(x = 0; x < width; x++, from+=4, to+=4)
float_to_byte_v4(to, from);
}
}
else if(profile_to == IB_PROFILE_SRGB) {
/* convert from linear to sRGB */
if(dither && predivide) {
for(x = 0; x < width; x++, from+=4, to+=4) {
linearrgb_to_srgb_predivide_v4(tmp, from);
float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac);
}
}
else if(dither) {
for(x = 0; x < width; x++, from+=4, to+=4) {
linearrgb_to_srgb_v4(tmp, from);
float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac);
}
}
else if(predivide) {
for(x = 0; x < width; x++, from+=4, to+=4) {
linearrgb_to_srgb_predivide_v4(tmp, from);
float_to_byte_v4(to, tmp);
}
}
else {
for(x = 0; x < width; x++, from+=4, to+=4) {
linearrgb_to_srgb_v4(tmp, from);
float_to_byte_v4(to, tmp);
}
}
}
else if(profile_to == IB_PROFILE_LINEAR_RGB) {
/* convert from sRGB to linear */
if(dither && predivide) {
for(x = 0; x < width; x++, from+=4, to+=4) {
srgb_to_linearrgb_predivide_v4(tmp, from);
float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac);
}
}
else if(dither) {
for(x = 0; x < width; x++, from+=4, to+=4) {
srgb_to_linearrgb_v4(tmp, from);
float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac);
}
}
else if(predivide) {
for(x = 0; x < width; x++, from+=4, to+=4) {
srgb_to_linearrgb_predivide_v4(tmp, from);
float_to_byte_v4(to, tmp);
}
}
else {
for(x = 0; x < width; x++, from+=4, to+=4) {
srgb_to_linearrgb_v4(tmp, from);
float_to_byte_v4(to, tmp);
}
}
}
}
}
}
/* byte to float pixels, input and output 4-channel RGBA */
void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from,
int profile_to, int profile_from, int predivide,
int width, int height, int stride_to, int stride_from)
{
float tmp[4];
int x, y;
/* we need valid profiles */
BLI_assert(profile_to != IB_PROFILE_NONE);
BLI_assert(profile_from != IB_PROFILE_NONE);
/* RGBA input */
for(y = 0; y < height; y++) {
const uchar *from = rect_from + stride_from*y*4;
float *to = rect_to + stride_to*y*4;
if(profile_to == profile_from) {
/* no color space conversion */
for(x = 0; x < width; x++, from+=4, to+=4)
byte_to_float_v4(to, from);
}
else if(profile_to == IB_PROFILE_LINEAR_RGB) {
/* convert sRGB to linear */
if(predivide) {
for(x = 0; x < width; x++, from+=4, to+=4) {
byte_to_float_v4(tmp, from);
srgb_to_linearrgb_predivide_v4(to, tmp);
}
}
else {
for(x = 0; x < width; x++, from+=4, to+=4) {
byte_to_float_v4(tmp, from);
srgb_to_linearrgb_v4(to, tmp);
}
}
}
else if(profile_to == IB_PROFILE_SRGB) {
/* convert linear to sRGB */
if(predivide) {
for(x = 0; x < width; x++, from+=4, to+=4) {
byte_to_float_v4(tmp, from);
linearrgb_to_srgb_predivide_v4(to, tmp);
}
}
else {
for(x = 0; x < width; x++, from+=4, to+=4) {
byte_to_float_v4(tmp, from);
linearrgb_to_srgb_v4(to, tmp);
}
}
}
}
}
/* float to float pixels, output 4-channel RGBA */
void IMB_buffer_float_from_float(float *rect_to, const float *rect_from,
int channels_from, int profile_to, int profile_from, int predivide,
int width, int height, int stride_to, int stride_from)
{
int x, y;
/* we need valid profiles */
BLI_assert(profile_to != IB_PROFILE_NONE);
BLI_assert(profile_from != IB_PROFILE_NONE);
if(channels_from==1) {
/* single channel input */
for(y = 0; y < height; y++) {
const float *from = rect_from + stride_from*y;
float *to = rect_to + stride_to*y*4;
for(x = 0; x < width; x++, from++, to+=4)
to[0] = to[1] = to[2] = to[3] = from[0];
}
}
else if(channels_from == 3) {
/* RGB input */
for(y = 0; y < height; y++) {
const float *from = rect_from + stride_from*y*3;
float *to = rect_to + stride_to*y*4;
if(profile_to == profile_from) {
/* no color space conversion */
for(x = 0; x < width; x++, from+=3, to+=4) {
copy_v3_v3(to, from);
to[3] = 1.0f;
}
}
else if(profile_to == IB_PROFILE_LINEAR_RGB) {
/* convert from sRGB to linear */
for(x = 0; x < width; x++, from+=3, to+=4) {
srgb_to_linearrgb_v3_v3(to, from);
to[3] = 1.0f;
}
}
else if(profile_to == IB_PROFILE_SRGB) {
/* convert from linear to sRGB */
for(x = 0; x < width; x++, from+=3, to+=4) {
linearrgb_to_srgb_v3_v3(to, from);
to[3] = 1.0f;
}
}
}
}
else if(channels_from == 4) {
/* RGBA input */
for(y = 0; y < height; y++) {
const float *from = rect_from + stride_from*y*4;
float *to = rect_to + stride_to*y*4;
if(profile_to == profile_from) {
/* same profile, copy */
memcpy(to, from, sizeof(float)*4*width);
}
else if(profile_to == IB_PROFILE_LINEAR_RGB) {
/* convert to sRGB to linear */
if(predivide) {
for(x = 0; x < width; x++, from+=4, to+=4)
srgb_to_linearrgb_predivide_v4(to, from);
}
else {
for(x = 0; x < width; x++, from+=4, to+=4)
srgb_to_linearrgb_v4(to, from);
}
}
else if(profile_to == IB_PROFILE_SRGB) {
/* convert from linear to sRGB */
if(predivide) {
for(x = 0; x < width; x++, from+=4, to+=4)
linearrgb_to_srgb_predivide_v4(to, from);
}
else {
for(x = 0; x < width; x++, from+=4, to+=4)
linearrgb_to_srgb_v4(to, from);
}
}
}
}
}
/* byte to byte pixels, input and output 4-channel RGBA */
void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from,
int profile_to, int profile_from, int predivide,
int width, int height, int stride_to, int stride_from)
{
float tmp[4];
int x, y;
/* we need valid profiles */
BLI_assert(profile_to != IB_PROFILE_NONE);
BLI_assert(profile_from != IB_PROFILE_NONE);
/* always RGBA input */
for(y = 0; y < height; y++) {
const uchar *from = rect_from + stride_from*y*4;
uchar *to = rect_to + stride_to*y*4;
if(profile_to == profile_from) {
/* same profile, copy */
memcpy(to, from, sizeof(uchar)*4*width);
}
else if(profile_to == IB_PROFILE_LINEAR_RGB) {
/* convert to sRGB to linear */
if(predivide) {
for(x = 0; x < width; x++, from+=4, to+=4) {
byte_to_float_v4(tmp, from);
srgb_to_linearrgb_predivide_v4(tmp, tmp);
float_to_byte_v4(to, tmp);
}
}
else {
for(x = 0; x < width; x++, from+=4, to+=4) {
byte_to_float_v4(tmp, from);
srgb_to_linearrgb_v4(tmp, tmp);
float_to_byte_v4(to, tmp);
}
}
}
else if(profile_to == IB_PROFILE_SRGB) {
/* convert from linear to sRGB */
if(predivide) {
for(x = 0; x < width; x++, from+=4, to+=4) {
byte_to_float_v4(tmp, from);
linearrgb_to_srgb_predivide_v4(tmp, tmp);
float_to_byte_v4(to, tmp);
}
}
else {
for(x = 0; x < width; x++, from+=4, to+=4) {
byte_to_float_v4(tmp, from);
linearrgb_to_srgb_v4(tmp, tmp);
float_to_byte_v4(to, tmp);
}
}
}
}
}
/****************************** ImBuf Conversion *****************************/
/* assume converting from linear float to sRGB byte */
void IMB_rect_from_float(struct ImBuf *ibuf)
{
/* quick method to convert floatbuf to byte */
float *tof = (float *)ibuf->rect_float;
// int do_dither = ibuf->dither != 0.f;
float dither= ibuf->dither / 255.0f;
float srgb[4];
int i, channels= ibuf->channels;
short profile= ibuf->profile;
unsigned char *to = (unsigned char *) ibuf->rect;
if(tof==NULL) return;
if(to==NULL) {
int predivide= 0, profile_from;
/* verify we have a float buffer */
if(ibuf->rect_float==NULL)
return;
/* create byte rect if it didn't exist yet */
if(ibuf->rect==NULL)
imb_addrectImBuf(ibuf);
to = (unsigned char *) ibuf->rect;
}
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]);
}
else if (profile == IB_PROFILE_LINEAR_RGB) {
if(channels == 3) {
for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) {
srgb[0]= linearrgb_to_srgb(tof[0]);
srgb[1]= linearrgb_to_srgb(tof[1]);
srgb[2]= linearrgb_to_srgb(tof[2]);
to[0] = FTOCHAR(srgb[0]);
to[1] = FTOCHAR(srgb[1]);
to[2] = FTOCHAR(srgb[2]);
to[3] = 255;
}
}
else if (channels == 4) {
if (dither != 0.f) {
for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
const float d = (BLI_frand()-0.5f)*dither;
srgb[0]= d + linearrgb_to_srgb(tof[0]);
srgb[1]= d + linearrgb_to_srgb(tof[1]);
srgb[2]= d + linearrgb_to_srgb(tof[2]);
srgb[3]= d + tof[3];
to[0] = FTOCHAR(srgb[0]);
to[1] = FTOCHAR(srgb[1]);
to[2] = FTOCHAR(srgb[2]);
to[3] = FTOCHAR(srgb[3]);
}
} else {
floatbuf_to_srgb_byte(tof, to, 0, ibuf->x, 0, ibuf->y, ibuf->x);
}
}
}
else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) {
if(channels==3) {
for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) {
to[0] = FTOCHAR(tof[0]);
to[1] = FTOCHAR(tof[1]);
to[2] = FTOCHAR(tof[2]);
to[3] = 255;
}
}
else {
if (dither != 0.f) {
for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
const float d = (BLI_frand()-0.5f)*dither;
float col[4];
/* determine profiles */
if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
profile_from = IB_PROFILE_LINEAR_RGB;
else if(ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE))
profile_from = IB_PROFILE_SRGB;
else
BLI_assert(0);
col[0]= d + tof[0];
col[1]= d + tof[1];
col[2]= d + tof[2];
col[3]= d + tof[3];
/* do conversion */
IMB_buffer_byte_from_float((uchar*)ibuf->rect, ibuf->rect_float,
ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
to[0] = FTOCHAR(col[0]);
to[1] = FTOCHAR(col[1]);
to[2] = FTOCHAR(col[2]);
to[3] = FTOCHAR(col[3]);
}
} else {
for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
to[0] = FTOCHAR(tof[0]);
to[1] = FTOCHAR(tof[1]);
to[2] = FTOCHAR(tof[2]);
to[3] = FTOCHAR(tof[3]);
}
}
}
}
/* ensure user flag is reset */
ibuf->userflags &= ~IB_RECT_INVALID;
}
/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
void IMB_partial_rect_from_float(struct ImBuf *ibuf,float *buffer, int x, int y, int w, int h)
void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h)
{
/* indices to source and destination image pixels */
float *srcFloatPxl;
unsigned char *dstBytePxl;
/* buffer index will fill buffer */
float *bufferIndex;
float *rect_float;
uchar *rect_byte;
int predivide= 0, profile_from;
/* convenience pointers to start of image buffers */
float *init_srcFloatPxl = (float *)ibuf->rect_float;
unsigned char *init_dstBytePxl = (unsigned char *) ibuf->rect;
/* Dithering factor */
float dither= ibuf->dither / 255.0f;
/* respective attributes of image */
short profile= ibuf->profile;
int channels= ibuf->channels;
int i, j;
/*
if called -only- from GPU_paint_update_image this test will never fail
but leaving it here for better or worse
*/
if(init_srcFloatPxl==NULL || (buffer == NULL)){
/* verify we have a float buffer */
if(ibuf->rect_float==NULL || buffer==NULL)
return;
}
if(init_dstBytePxl==NULL) {
/* create byte rect if it didn't exist yet */
if(ibuf->rect==NULL)
imb_addrectImBuf(ibuf);
init_dstBytePxl = (unsigned char *) ibuf->rect;
}
if(channels==1) {
for (j = 0; j < h; j++){
bufferIndex = buffer + w*j*4;
dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x);
for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl++, bufferIndex+=4) {
dstBytePxl[1]= dstBytePxl[2]= dstBytePxl[3]= dstBytePxl[0] = FTOCHAR(srcFloatPxl[0]);
bufferIndex[0] = bufferIndex[1] = bufferIndex[2] = bufferIndex[3] = srcFloatPxl[0];
}
}
}
else if (profile == IB_PROFILE_LINEAR_RGB) {
if(channels == 3) {
for (j = 0; j < h; j++){
bufferIndex = buffer + w*j*4;
dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3;
for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex += 4) {
linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
F3TOCHAR4(bufferIndex, dstBytePxl);
bufferIndex[3]= 1.0;
}
}
}
else if (channels == 4) {
if (dither != 0.f) {
for (j = 0; j < h; j++){
bufferIndex = buffer + w*j*4;
dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
const float d = (BLI_frand()-0.5f)*dither;
linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
bufferIndex[3] = srcFloatPxl[3];
add_v4_fl(bufferIndex, d);
F4TOCHAR4(bufferIndex, dstBytePxl);
}
}
} else {
for (j = 0; j < h; j++){
bufferIndex = buffer + w*j*4;
dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
bufferIndex[3]= srcFloatPxl[3];
F4TOCHAR4(bufferIndex, dstBytePxl);
}
}
}
}
}
else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) {
if(channels==3) {
for (j = 0; j < h; j++){
bufferIndex = buffer + w*j*4;
dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3;
for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex+=4) {
copy_v3_v3(bufferIndex, srcFloatPxl);
F3TOCHAR4(bufferIndex, dstBytePxl);
bufferIndex[3] = 1.0;
}
}
}
else {
if (dither != 0.f) {
for (j = 0; j < h; j++){
bufferIndex = buffer + w*j*4;
dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
const float d = (BLI_frand()-0.5f)*dither;
copy_v4_v4(bufferIndex, srcFloatPxl);
add_v4_fl(bufferIndex,d);
F4TOCHAR4(bufferIndex, dstBytePxl);
}
}
} else {
for (j = 0; j < h; j++){
bufferIndex = buffer + w*j*4;
dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
copy_v4_v4(bufferIndex, srcFloatPxl);
F4TOCHAR4(bufferIndex, dstBytePxl);
}
}
}
}
}
/* determine profiles */
if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
profile_from = IB_PROFILE_LINEAR_RGB;
else if(ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE))
profile_from = IB_PROFILE_SRGB;
else
BLI_assert(0);
/* do conversion */
rect_float= ibuf->rect_float + (x + y*ibuf->x)*ibuf->channels;
rect_byte= (uchar*)ibuf->rect + (x + y*ibuf->x)*4;
IMB_buffer_float_from_float(buffer, rect_float,
ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide,
w, h, w, ibuf->x);
IMB_buffer_byte_from_float(rect_byte, buffer,
4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0,
w, h, ibuf->x, w);
/* ensure user flag is reset */
ibuf->userflags &= ~IB_RECT_INVALID;
}
static void imb_float_from_rect_nonlinear(struct ImBuf *ibuf, float *fbuf)
{
float *tof = fbuf;
int i;
unsigned char *to = (unsigned char *) ibuf->rect;
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;
}
}
static void imb_float_from_rect_linear(struct ImBuf *ibuf, float *fbuf)
{
float *tof = fbuf;
int i;
unsigned char *to = (unsigned char *) ibuf->rect;
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;
}
}
void IMB_float_from_rect(struct ImBuf *ibuf)
{
/* quick method to convert byte to floatbuf */
if(ibuf->rect==NULL) return;
if(ibuf->rect_float==NULL) {
if (imb_addrectfloatImBuf(ibuf) == 0) return;
}
/* Float bufs should be stored linear */
int predivide= 0, profile_from;
if (ibuf->profile != IB_PROFILE_NONE) {
/* if the image has been given a profile then we're working
* with color management in mind, so convert it to linear space */
imb_float_from_rect_linear(ibuf, ibuf->rect_float);
} else {
imb_float_from_rect_nonlinear(ibuf, ibuf->rect_float);
}
/* verify if we byte and float buffers */
if(ibuf->rect==NULL)
return;
if(ibuf->rect_float==NULL)
if(imb_addrectfloatImBuf(ibuf) == 0)
return;
/* determine profiles */
if(ibuf->profile == IB_PROFILE_NONE)
profile_from = IB_PROFILE_LINEAR_RGB;
else
profile_from = IB_PROFILE_SRGB;
/* do conversion */
IMB_buffer_float_from_byte(ibuf->rect_float, (uchar*)ibuf->rect,
IB_PROFILE_LINEAR_RGB, profile_from, predivide,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
/* no profile conversion */
void IMB_float_from_rect_simple(struct ImBuf *ibuf)
{
int predivide= 0;
if(ibuf->rect_float==NULL)
imb_addrectfloatImBuf(ibuf);
imb_float_from_rect_nonlinear(ibuf, ibuf->rect_float);
IMB_buffer_float_from_byte(ibuf->rect_float, (uchar*)ibuf->rect,
IB_PROFILE_SRGB, IB_PROFILE_SRGB, predivide,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
void IMB_convert_profile(struct ImBuf *ibuf, int profile)
{
int ok= FALSE;
int i;
unsigned char *rct= (unsigned char *)ibuf->rect;
float *rctf= ibuf->rect_float;
int predivide= 0, profile_from, profile_to;
if(ibuf->profile == profile)
return;
if(ELEM(ibuf->profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* from */
if(profile == IB_PROFILE_LINEAR_RGB) { /* to */
if(ibuf->rect_float) {
for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
rctf[0]= srgb_to_linearrgb(rctf[0]);
rctf[1]= srgb_to_linearrgb(rctf[1]);
rctf[2]= srgb_to_linearrgb(rctf[2]);
}
}
if(ibuf->rect) {
for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
rct[0]= (unsigned char)((srgb_to_linearrgb((float)rct[0]/255.0f) * 255.0f) + 0.5f);
rct[1]= (unsigned char)((srgb_to_linearrgb((float)rct[1]/255.0f) * 255.0f) + 0.5f);
rct[2]= (unsigned char)((srgb_to_linearrgb((float)rct[2]/255.0f) * 255.0f) + 0.5f);
}
}
ok= TRUE;
}
}
else if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { /* from */
if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* to */
if(ibuf->rect_float) {
for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
rctf[0]= linearrgb_to_srgb(rctf[0]);
rctf[1]= linearrgb_to_srgb(rctf[1]);
rctf[2]= linearrgb_to_srgb(rctf[2]);
}
}
if(ibuf->rect) {
for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
rct[0]= (unsigned char)((linearrgb_to_srgb((float)rct[0]/255.0f) * 255.0f) + 0.5f);
rct[1]= (unsigned char)((linearrgb_to_srgb((float)rct[1]/255.0f) * 255.0f) + 0.5f);
rct[2]= (unsigned char)((linearrgb_to_srgb((float)rct[2]/255.0f) * 255.0f) + 0.5f);
}
}
ok= TRUE;
}
/* determine profiles */
if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
profile_from = IB_PROFILE_LINEAR_RGB;
else if(ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE))
profile_from = IB_PROFILE_SRGB;
else
BLI_assert(0);
if(profile == IB_PROFILE_LINEAR_RGB)
profile_to = IB_PROFILE_LINEAR_RGB;
else if(ELEM(profile, IB_PROFILE_SRGB, IB_PROFILE_NONE))
profile_to = IB_PROFILE_SRGB;
else
BLI_assert(0);
/* do conversion */
if(ibuf->rect_float) {
IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float,
4, profile_to, profile_from, predivide,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
if(ok==FALSE){
printf("IMB_convert_profile: failed profile conversion %d -> %d\n", ibuf->profile, profile);
return;
if(ibuf->rect) {
IMB_buffer_byte_from_byte((uchar*)ibuf->rect, (uchar*)ibuf->rect,
profile_to, profile_from, predivide,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
/* set new profile */
ibuf->profile= profile;
}
@ -448,18 +599,25 @@ void IMB_convert_profile(struct ImBuf *ibuf, int profile)
* if the return */
float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc)
{
/* stupid but it works like this everywhere now */
const short is_lin_from= (ibuf->profile != IB_PROFILE_NONE);
const short is_lin_to= (profile != IB_PROFILE_NONE);
int predivide= 0, profile_from, profile_to;
/* determine profiles */
if(ibuf->profile == IB_PROFILE_NONE)
profile_from = IB_PROFILE_LINEAR_RGB;
else
profile_from = IB_PROFILE_SRGB;
if(profile == IB_PROFILE_NONE)
profile_to = IB_PROFILE_LINEAR_RGB;
else
profile_to = IB_PROFILE_SRGB;
if(is_lin_from == is_lin_to) {
if(profile_from == profile_to) {
/* simple case, just allocate the buffer and return */
*alloc= 0;
/* simple case, just allocate the buffer and return */
if(ibuf->rect_float == NULL) {
if(ibuf->rect_float == NULL)
IMB_float_from_rect(ibuf);
}
return ibuf->rect_float;
}
@ -469,42 +627,36 @@ float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc)
*alloc= 1;
if(ibuf->rect_float == NULL) {
if(is_lin_to) {
imb_float_from_rect_linear(ibuf, fbuf);
}
else {
imb_float_from_rect_nonlinear(ibuf, fbuf);
}
IMB_buffer_float_from_byte(fbuf, (uchar*)ibuf->rect,
profile_to, profile_from, predivide,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
else {
if(is_lin_to) { /* lin -> nonlin */
linearrgb_to_srgb_rgba_rgba_buf(fbuf, ibuf->rect_float, ibuf->x * ibuf->y);
}
else { /* nonlin -> lin */
srgb_to_linearrgb_rgba_rgba_buf(fbuf, ibuf->rect_float, ibuf->x * ibuf->y);
}
IMB_buffer_float_from_float(fbuf, ibuf->rect_float,
4, profile_to, profile_from, predivide,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
return fbuf;
}
}
/**************************** Color to Grayscale *****************************/
/* no profile conversion */
void IMB_color_to_bw(struct ImBuf *ibuf)
{
float *rctf= ibuf->rect_float;
unsigned char *rct= (unsigned char *)ibuf->rect;
uchar *rct= (uchar*)ibuf->rect;
int i;
if(rctf) {
for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
for(i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4)
rctf[0]= rctf[1]= rctf[2]= rgb_to_grayscale(rctf);
}
}
if(rct) {
for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
for(i = ibuf->x * ibuf->y; i > 0; i--, rct+=4)
rct[0]= rct[1]= rct[2]= rgb_to_grayscale_byte(rct);
}
}
}

View File

@ -606,7 +606,9 @@ void generate_preview(void *data, bNode *node, CompBuf *stackbuf)
RenderData *rd= data;
bNodePreview *preview= node->preview;
int xsize, ysize;
int color_manage= rd->color_mgt_flag & R_COLOR_MANAGEMENT;
int profile_from= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
int predivide= 0;
int dither= 0;
unsigned char *rect;
if(preview && stackbuf) {
@ -633,10 +635,9 @@ void generate_preview(void *data, bNode *node, CompBuf *stackbuf)
/* convert to byte for preview */
rect= MEM_callocN(sizeof(unsigned char)*4*xsize*ysize, "bNodePreview.rect");
if(color_manage)
floatbuf_to_srgb_byte(cbuf->rect, rect, 0, xsize, 0, ysize, xsize);
else
floatbuf_to_byte(cbuf->rect, rect, 0, xsize, 0, ysize, xsize);
IMB_buffer_byte_from_float(rect, cbuf->rect,
4, dither, IB_PROFILE_SRGB, profile_from, predivide,
xsize, ysize, xsize, xsize);
free_compbuf(cbuf);
if(stackbuf_use!=stackbuf)

View File

@ -62,6 +62,7 @@ static bNodeSocketTemplate cmp_node_rlayers_out[]= {
float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
{
float *rect;
int predivide= 0;
*alloc= FALSE;
@ -71,7 +72,11 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
}
else {
rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
srgb_to_linearrgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y);
IMB_buffer_float_from_float(rect, ibuf->rect_float,
4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
*alloc= TRUE;
}
}
@ -81,7 +86,11 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
}
else {
rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
linearrgb_to_srgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y);
IMB_buffer_float_from_float(rect, ibuf->rect_float,
4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
*alloc= TRUE;
}
}

View File

@ -1149,32 +1149,17 @@ void RE_ResultGet32(Render *re, unsigned int *rect)
RE_AcquireResultImage(re, &rres);
if(rres.rect32)
if(rres.rect32) {
memcpy(rect, rres.rect32, sizeof(int)*rres.rectx*rres.recty);
}
else if(rres.rectf) {
float *fp= rres.rectf;
int tot= rres.rectx*rres.recty;
char *cp= (char *)rect;
if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) {
/* Finally convert back to sRGB rendered image */
for(;tot>0; tot--, cp+=4, fp+=4) {
cp[0] = FTOCHAR(linearrgb_to_srgb(fp[0]));
cp[1] = FTOCHAR(linearrgb_to_srgb(fp[1]));
cp[2] = FTOCHAR(linearrgb_to_srgb(fp[2]));
cp[3] = FTOCHAR(fp[3]);
}
}
else {
/* Color management is off : no conversion necessary */
for(;tot>0; tot--, cp+=4, fp+=4) {
cp[0] = FTOCHAR(fp[0]);
cp[1] = FTOCHAR(fp[1]);
cp[2] = FTOCHAR(fp[2]);
cp[3] = FTOCHAR(fp[3]);
}
}
int profile_from= (re->r.color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
int predivide= 0;
int dither= 0;
IMB_buffer_byte_from_float((unsigned char*)rect, rres.rectf,
4, dither, IB_PROFILE_SRGB, profile_from, predivide,
rres.rectx, rres.recty, rres.rectx, rres.rectx);
}
else
/* else fill with black */
@ -2567,24 +2552,18 @@ static void do_render_seq(Render * re)
if(ibuf) {
if(ibuf->rect_float) {
/* color management: when off ensure rectf is non-lin, since thats what the internal
* render engine delivers */
int profile_to= (re->r.color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
int profile_from= (ibuf->profile == IB_PROFILE_LINEAR_RGB)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
int predivide= 0;
if (!rr->rectf)
rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf");
/* color management: when off ensure rectf is non-lin, since thats what the internal
* render engine delivers */
if(re->r.color_mgt_flag & R_COLOR_MANAGEMENT) {
if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty);
else
srgb_to_linearrgb_rgba_rgba_buf(rr->rectf, ibuf->rect_float, rr->rectx*rr->recty);
}
else {
if(ibuf->profile != IB_PROFILE_LINEAR_RGB)
memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty);
else
linearrgb_to_srgb_rgba_rgba_buf(rr->rectf, ibuf->rect_float, rr->rectx*rr->recty);
}
IMB_buffer_float_from_float(rr->rectf, ibuf->rect_float,
4, profile_to, profile_from, predivide,
rr->rectx, rr->recty, rr->rectx, rr->rectx);
/* TSK! Since sequence render doesn't free the *rr render result, the old rect32
can hang around when sequence render has rendered a 32 bits one before */