Fix #34359: 2.66 crashes when using output node

16bit PNG and Jpeg2K exporters were not aware of the simple
fact that float buffer could have only 3 or 1 channels.
This commit is contained in:
Sergey Sharybin 2013-02-22 09:20:22 +00:00
parent 1cdaf1e329
commit 08d356a7e0
2 changed files with 250 additions and 63 deletions

@ -108,6 +108,13 @@ static void info_callback(const char *msg, void *client_data)
i++, _rect += 4) \
{ \
# define PIXEL_LOOPER_BEGIN_CHANNELS(_rect, _channels) \
for (y = h - 1; y != (unsigned int)(-1); y--) { \
for (i = y * w, i_next = (y + 1) * w; \
i < i_next; \
i++, _rect += _channels) \
{ \
# define PIXEL_LOOPER_END \
} \
} (void)0 \
@ -663,76 +670,198 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters)
}
if (rect_float) {
int channels_in_float = ibuf->channels ? ibuf->channels : 4;
switch (prec) {
case 8: /* Convert blenders float color channels to 8, 12 or 16bit ints */
if (numcomps == 4) {
PIXEL_LOOPER_BEGIN(rect_float)
{
premul_to_straight_v4_v4(from_straight, rect_float);
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2]));
a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(from_straight[3]);
if (channels_in_float == 4) {
PIXEL_LOOPER_BEGIN(rect_float)
{
premul_to_straight_v4_v4(from_straight, rect_float);
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2]));
a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(from_straight[3]);
}
PIXEL_LOOPER_END;
}
else if (channels_in_float == 3) {
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
{
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2]));
a[i] = 255;
}
PIXEL_LOOPER_END;
}
else {
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
{
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
g[i] = b[i] = r[i];
a[i] = 255;
}
PIXEL_LOOPER_END;
}
PIXEL_LOOPER_END;
}
else {
PIXEL_LOOPER_BEGIN(rect_float)
{
premul_to_straight_v4_v4(from_straight, rect_float);
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2]));
if (channels_in_float == 4) {
PIXEL_LOOPER_BEGIN(rect_float)
{
premul_to_straight_v4_v4(from_straight, rect_float);
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2]));
}
PIXEL_LOOPER_END;
}
else if (channels_in_float == 3) {
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
{
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2]));
}
PIXEL_LOOPER_END;
}
else {
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
{
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
g[i] = b[i] = r[i];
}
PIXEL_LOOPER_END;
}
PIXEL_LOOPER_END;
}
break;
case 12:
if (numcomps == 4) {
PIXEL_LOOPER_BEGIN(rect_float)
{
premul_to_straight_v4_v4(from_straight, rect_float);
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2]));
a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(from_straight[3]);
if (channels_in_float == 4) {
PIXEL_LOOPER_BEGIN(rect_float)
{
premul_to_straight_v4_v4(from_straight, rect_float);
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2]));
a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(from_straight[3]);
}
PIXEL_LOOPER_END;
}
else if (channels_in_float == 3) {
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
{
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2]));
a[i] = 4095;
}
PIXEL_LOOPER_END;
}
else {
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
{
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
g[i] = b[i] = r[i];
a[i] = 4095;
}
PIXEL_LOOPER_END;
}
PIXEL_LOOPER_END;
}
else {
PIXEL_LOOPER_BEGIN(rect_float)
{
premul_to_straight_v4_v4(from_straight, rect_float);
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2]));
if (channels_in_float == 4) {
PIXEL_LOOPER_BEGIN(rect_float)
{
premul_to_straight_v4_v4(from_straight, rect_float);
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2]));
}
PIXEL_LOOPER_END;
}
else if (channels_in_float == 3) {
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
{
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2]));
}
PIXEL_LOOPER_END;
}
else {
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
{
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
g[i] = b[i] = r[i];
}
PIXEL_LOOPER_END;
}
PIXEL_LOOPER_END;
}
break;
case 16:
if (numcomps == 4) {
PIXEL_LOOPER_BEGIN(rect_float)
{
premul_to_straight_v4_v4(from_straight, rect_float);
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2]));
a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(from_straight[3]);
if (channels_in_float == 4){
PIXEL_LOOPER_BEGIN(rect_float)
{
premul_to_straight_v4_v4(from_straight, rect_float);
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2]));
a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(from_straight[3]);
}
PIXEL_LOOPER_END;
}
else if (channels_in_float == 3) {
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
{
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2]));
a[i] = 65535;
}
PIXEL_LOOPER_END;
}
else {
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
{
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
g[i] = b[i] = r[i];
a[i] = 65535;
}
PIXEL_LOOPER_END;
}
PIXEL_LOOPER_END;
}
else {
PIXEL_LOOPER_BEGIN(rect_float)
{
premul_to_straight_v4_v4(from_straight, rect_float);
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2]));
if (channels_in_float == 4) {
PIXEL_LOOPER_BEGIN(rect_float)
{
premul_to_straight_v4_v4(from_straight, rect_float);
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2]));
}
PIXEL_LOOPER_END;
}
else if (channels_in_float == 3) {
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
{
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1]));
b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2]));
}
PIXEL_LOOPER_END;
}
else {
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
{
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
g[i] = b[i] = r[i];
}
PIXEL_LOOPER_END;
}
PIXEL_LOOPER_END;
}
break;
}

@ -133,6 +133,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
bool is_16bit = (ibuf->ftype & PNG_16BIT);
bool has_float = (ibuf->rect_float != NULL);
int channels_in_float = ibuf->channels ? ibuf->channels : 4;
float (*chanel_colormanage_cb)(float);
@ -156,7 +157,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
bytesperpixel = (ibuf->planes + 7) >> 3;
if ((bytesperpixel > 4) || (bytesperpixel == 2)) {
printf("imb_savepng: Cunsupported bytes per pixel: %d for file: '%s'\n", bytesperpixel, name);
printf("imb_savepng: Unsupported bytes per pixel: %d for file: '%s'\n", bytesperpixel, name);
return (0);
}
@ -203,13 +204,32 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
color_type = PNG_COLOR_TYPE_RGBA;
if (is_16bit) {
if (has_float) {
for (i = ibuf->x * ibuf->y; i > 0; i--) {
premul_to_straight_v4_v4(from_straight, from_float);
to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0]));
to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1]));
to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2]));
to16[3] = ftoshort(chanel_colormanage_cb(from_straight[3]));
to16 += 4; from_float += 4;
if (channels_in_float == 4) {
for (i = ibuf->x * ibuf->y; i > 0; i--) {
premul_to_straight_v4_v4(from_straight, from_float);
to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0]));
to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1]));
to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2]));
to16[3] = ftoshort(chanel_colormanage_cb(from_straight[3]));
to16 += 4; from_float += 4;
}
}
else if (channels_in_float == 3) {
for (i = ibuf->x * ibuf->y; i > 0; i--) {
to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
to16[1] = ftoshort(chanel_colormanage_cb(from_float[1]));
to16[2] = ftoshort(chanel_colormanage_cb(from_float[2]));
to16[3] = 65535;
to16 += 4; from_float += 3;
}
}
else {
for (i = ibuf->x * ibuf->y; i > 0; i--) {
to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
to16[2] = to16[1] = to16[0];
to16[3] = 65535;
to16 += 4; from_float++;
}
}
}
else {
@ -236,12 +256,29 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
color_type = PNG_COLOR_TYPE_RGB;
if (is_16bit) {
if (has_float) {
for (i = ibuf->x * ibuf->y; i > 0; i--) {
premul_to_straight_v4_v4(from_straight, from_float);
to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0]));
to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1]));
to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2]));
to16 += 3; from_float += 4;
if (channels_in_float == 4) {
for (i = ibuf->x * ibuf->y; i > 0; i--) {
premul_to_straight_v4_v4(from_straight, from_float);
to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0]));
to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1]));
to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2]));
to16 += 3; from_float += 4;
}
}
else if (channels_in_float == 3) {
for (i = ibuf->x * ibuf->y; i > 0; i--) {
to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
to16[1] = ftoshort(chanel_colormanage_cb(from_float[1]));
to16[2] = ftoshort(chanel_colormanage_cb(from_float[2]));
to16 += 3; from_float += 3;
}
}
else {
for (i = ibuf->x * ibuf->y; i > 0; i--) {
to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
to16[2] = to16[1] = to16[0];
to16 += 3; from_float++;
}
}
}
else {
@ -266,10 +303,31 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
color_type = PNG_COLOR_TYPE_GRAY;
if (is_16bit) {
if (has_float) {
for (i = ibuf->x * ibuf->y; i > 0; i--) {
premul_to_straight_v4_v4(from_straight, from_float);
to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0]));
to16++; from_float += 4;
float rgb[3];
if (channels_in_float == 4) {
for (i = ibuf->x * ibuf->y; i > 0; i--) {
premul_to_straight_v4_v4(from_straight, from_float);
rgb[0] = chanel_colormanage_cb(from_straight[0]);
rgb[1] = chanel_colormanage_cb(from_straight[1]);
rgb[2] = chanel_colormanage_cb(from_straight[2]);
to16[0] = ftoshort(rgb_to_bw(rgb));
to16++; from_float += 4;
}
}
else if (channels_in_float == 3) {
for (i = ibuf->x * ibuf->y; i > 0; i--) {
rgb[0] = chanel_colormanage_cb(from_float[0]);
rgb[1] = chanel_colormanage_cb(from_float[1]);
rgb[2] = chanel_colormanage_cb(from_float[2]);
to16[0] = ftoshort(rgb_to_bw(rgb));
to16++; from_float += 3;
}
}
else {
for (i = ibuf->x * ibuf->y; i > 0; i--) {
to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
to16++; from_float++;
}
}
}
else {