bugfix [#23406] DPX Images load darker then saved, UI broken.

- a linear float buffer was being created and saved into a non-linear DPX/Cineon file.
- removed the UI since the settings are not used at the moment.

added a utility function IMB_float_profile_ensure(), which returns a float buffer in the requested profile, using the existing if needed or returning an allocated buffer if the profile is different to that of the ImBuf. - Useful this case where the save function has its own linear setting.
This commit is contained in:
Campbell Barton 2010-12-01 02:54:10 +00:00
parent ad0dd98f26
commit f801b2bcba
4 changed files with 114 additions and 46 deletions

@ -336,7 +336,10 @@ class RENDER_PT_output(RenderButtonsPanel, bpy.types.Panel):
col.prop(rd, "jpeg2k_ycc") col.prop(rd, "jpeg2k_ycc")
elif file_format in ('CINEON', 'DPX'): elif file_format in ('CINEON', 'DPX'):
split = layout.split() split = layout.split()
split.label("FIXME: hard coded Non-Linear, Gamma:1.0")
'''
col = split.column() col = split.column()
col.prop(rd, "use_cineon_log", text="Convert to Log") col.prop(rd, "use_cineon_log", text="Convert to Log")
@ -345,6 +348,7 @@ class RENDER_PT_output(RenderButtonsPanel, bpy.types.Panel):
col.prop(rd, "cineon_black", text="Black") col.prop(rd, "cineon_black", text="Black")
col.prop(rd, "cineon_white", text="White") col.prop(rd, "cineon_white", text="White")
col.prop(rd, "cineon_gamma", text="Gamma") col.prop(rd, "cineon_gamma", text="Gamma")
'''
elif file_format == 'TIFF': elif file_format == 'TIFF':
split = layout.split() split = layout.split()

@ -321,6 +321,7 @@ void IMB_float_from_rect(struct ImBuf *ibuf);
void IMB_float_from_rect_simple(struct ImBuf *ibuf); /* no profile conversion */ void IMB_float_from_rect_simple(struct ImBuf *ibuf); /* no profile conversion */
/* note, check that the conversion exists, only some are supported */ /* note, check that the conversion exists, only some are supported */
void IMB_convert_profile(struct ImBuf *ibuf, int profile); void IMB_convert_profile(struct ImBuf *ibuf, int profile);
float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc);
/** /**
* Change the ordering of the color bytes pointed to by rect from * Change the ordering of the color bytes pointed to by rect from

@ -44,6 +44,7 @@
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
#if 0
static void cineon_conversion_parameters(LogImageByteConversionParameters *params) static void cineon_conversion_parameters(LogImageByteConversionParameters *params)
{ {
// params->blackPoint = scene?scene->r.cineonblack:95; // params->blackPoint = scene?scene->r.cineonblack:95;
@ -55,8 +56,8 @@ static void cineon_conversion_parameters(LogImageByteConversionParameters *param
params->whitePoint = 685; params->whitePoint = 685;
params->gamma = 1.0f; params->gamma = 1.0f;
params->doLogarithm = 0; params->doLogarithm = 0;
} }
#endif
static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags) static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags)
{ {
@ -116,49 +117,50 @@ static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int
return ibuf; return ibuf;
} }
static int imb_save_dpx_cineon(ImBuf *buf, const char *filename, int use_cineon, int flags) static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon, int flags)
{ {
LogImageByteConversionParameters conversion; LogImageByteConversionParameters conversion;
int width, height, depth; const int width= ibuf->x;
const int height= ibuf->y;
const int depth= 3;
LogImageFile* logImage; LogImageFile* logImage;
unsigned short* line, *pixel; unsigned short* line, *pixel;
int i, j; int i, j;
int index; int index;
float *fline; float *fline;
float *fbuf;
int is_alloc= 0;
(void)flags; /* unused */ (void)flags; /* unused */
cineon_conversion_parameters(&conversion); // cineon_conversion_parameters(&conversion);
logImageGetByteConversionDefaults(&conversion);
/* /*
* Get the drawable for the current image... * Get the drawable for the current image...
*/ */
width = buf->x; fbuf= IMB_float_profile_ensure(ibuf, conversion.doLogarithm ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE, &is_alloc);
height = buf->y;
depth = 3;
if (fbuf == NULL) { /* in the unlikely event that converting to a float buffer fails */
if (!buf->rect_float) {
IMB_float_from_rect(buf);
if (!buf->rect_float) { /* in the unlikely event that converting to a float buffer fails */
return 0; return 0;
} }
}
logImageSetVerbose((G.f & G_DEBUG) ? 1:0); logImageSetVerbose((G.f & G_DEBUG) ? 1:0);
logImage = logImageCreate(filename, use_cineon, width, height, depth); logImage = logImageCreate(filename, use_cineon, width, height, depth);
if (!logImage) return 0; if (!logImage) return 0;
logImageSetByteConversion(logImage, &conversion); if(logImageSetByteConversion(logImage, &conversion)==0) {
printf("error setting args\n");
}
index = 0; index = 0;
line = MEM_mallocN(sizeof(unsigned short)*depth*width, "line"); line = MEM_mallocN(sizeof(unsigned short)*depth*width, "line");
/*note that image is flipped when sent to logImageSetRowBytes (see last passed parameter).*/ /*note that image is flipped when sent to logImageSetRowBytes (see last passed parameter).*/
for (j = 0; j < height; ++j) { for (j = 0; j < height; ++j) {
fline = &buf->rect_float[width*j*4]; fline = &fbuf[width*j*4];
for (i=0; i<width; i++) { for (i=0; i<width; i++) {
float *fpix, fpix2[3]; float *fpix, fpix2[3];
/*we have to convert to cinepaint's 16-bit-per-channel here*/ /*we have to convert to cinepaint's 16-bit-per-channel here*/
@ -179,6 +181,11 @@ static int imb_save_dpx_cineon(ImBuf *buf, const char *filename, int use_cineon,
logImageClose(logImage); logImageClose(logImage);
MEM_freeN(line); MEM_freeN(line);
if(is_alloc) {
MEM_freeN(fbuf);
}
return 1; return 1;
} }

@ -40,6 +40,8 @@
#include "BKE_utildefines.h" #include "BKE_utildefines.h"
#include "BKE_colortools.h" #include "BKE_colortools.h"
#include "MEM_guardedalloc.h"
void IMB_de_interlace(struct ImBuf *ibuf) void IMB_de_interlace(struct ImBuf *ibuf)
{ {
struct ImBuf * tbuf1, * tbuf2; struct ImBuf * tbuf1, * tbuf2;
@ -187,13 +189,47 @@ void IMB_rect_from_float(struct ImBuf *ibuf)
} }
} }
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) void IMB_float_from_rect(struct ImBuf *ibuf)
{ {
/* quick method to convert byte to floatbuf */ /* quick method to convert byte to floatbuf */
float *tof = ibuf->rect_float; float *tof = ibuf->rect_float;
int i;
unsigned char *to = (unsigned char *) ibuf->rect;
unsigned char *to = (unsigned char *) ibuf->rect;
if(to==NULL) return; if(to==NULL) return;
if(tof==NULL) { if(tof==NULL) {
if (imb_addrectfloatImBuf(ibuf) == 0) return; if (imb_addrectfloatImBuf(ibuf) == 0) return;
@ -205,41 +241,16 @@ void IMB_float_from_rect(struct ImBuf *ibuf)
if (ibuf->profile != IB_PROFILE_NONE) { if (ibuf->profile != IB_PROFILE_NONE) {
/* if the image has been given a profile then we're working /* if the image has been given a profile then we're working
* with color management in mind, so convert it to linear space */ * with color management in mind, so convert it to linear space */
imb_float_from_rect_linear(ibuf, ibuf->rect_float);
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 { } else {
for (i = ibuf->x * ibuf->y; i > 0; i--) imb_float_from_rect_nonlinear(ibuf, ibuf->rect_float);
{
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;
}
} }
} }
/* no profile conversion */ /* no profile conversion */
void IMB_float_from_rect_simple(struct ImBuf *ibuf) void IMB_float_from_rect_simple(struct ImBuf *ibuf)
{ {
int profile = IB_PROFILE_NONE; imb_float_from_rect_nonlinear(ibuf, ibuf->rect_float);
/* no color management:
* don't disturb the existing profiles */
SWAP(int, ibuf->profile, profile);
IMB_float_from_rect(ibuf);
SWAP(int, ibuf->profile, profile);
} }
void IMB_convert_profile(struct ImBuf *ibuf, int profile) void IMB_convert_profile(struct ImBuf *ibuf, int profile)
@ -299,3 +310,48 @@ void IMB_convert_profile(struct ImBuf *ibuf, int profile)
ibuf->profile= profile; ibuf->profile= profile;
} }
/* use when you need to get a buffer with a certain 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);
if(is_lin_from == is_lin_to) {
*alloc= 0;
/* simple case, just allocate the buffer and return */
if(ibuf->rect_float == NULL) {
IMB_float_from_rect(ibuf);
}
return ibuf->rect_float;
}
else {
/* conversion is needed, first check */
float *fbuf= MEM_mallocN(ibuf->x * ibuf->y * sizeof(float) * 4, "IMB_float_profile_ensure");
*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);
}
}
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);
}
}
return fbuf;
}
}