diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c index ff0aeb068e2..3d04b8ee184 100644 --- a/source/blender/imbuf/intern/jp2.c +++ b/source/blender/imbuf/intern/jp2.c @@ -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; } diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index cc73f688e70..68385f22a7a 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -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 {