diff options
Diffstat (limited to 'source/blender/imbuf/intern/png.c')
-rw-r--r-- | source/blender/imbuf/intern/png.c | 93 |
1 files changed, 75 insertions, 18 deletions
diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index bbe43132051..cc73f688e70 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -60,6 +60,11 @@ static void ReadData(png_structp png_ptr, png_bytep data, png_size_t length); static void WriteData(png_structp png_ptr, png_bytep data, png_size_t length); static void Flush(png_structp png_ptr); +BLI_INLINE unsigned short UPSAMPLE_8_TO_16(const unsigned char _val) +{ + return (_val << 8) + _val; +} + int imb_is_a_png(unsigned char *mem) { int ret_val = 0; @@ -102,6 +107,17 @@ static void ReadData(png_structp png_ptr, png_bytep data, png_size_t length) longjmp(png_jmpbuf(png_ptr), 1); } +static float channel_colormanage_noop(float value) +{ + return value; +} + +/* wrap to avoid macro calling functions multiple times */ +BLI_INLINE unsigned short ftoshort(float val) +{ + return FTOUSHORT(val); +} + int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) { png_structp png_ptr; @@ -115,13 +131,25 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY; FILE *fp = NULL; - int is_16bit = (ibuf->ftype & PNG_16BIT) && ibuf->rect_float; + bool is_16bit = (ibuf->ftype & PNG_16BIT); + bool has_float = (ibuf->rect_float != NULL); + + float (*chanel_colormanage_cb)(float); /* use the jpeg quality setting for compression */ int compression; compression = (int)(((float)(ibuf->ftype & 0xff) / 11.1111f)); compression = compression < 0 ? 0 : (compression > 9 ? 9 : compression); + if (ibuf->float_colorspace) { + /* float buffer was managed already, no need in color space conversion */ + chanel_colormanage_cb = channel_colormanage_noop; + } + else { + /* standard linear-to-srgb conversion if float buffer wasn't managed */ + chanel_colormanage_cb = linearrgb_to_srgb; + } + /* for prints */ if (flags & IB_mem) name = "<memory>"; @@ -174,13 +202,24 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) case 4: color_type = PNG_COLOR_TYPE_RGBA; if (is_16bit) { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - premul_to_straight_v4(from_straight, from_float); - to16[0] = FTOUSHORT(from_straight[0]); - to16[1] = FTOUSHORT(from_straight[1]); - to16[2] = FTOUSHORT(from_straight[2]); - to16[3] = FTOUSHORT(from_straight[3]); - to16 += 4; from_float += 4; + 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; + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = UPSAMPLE_8_TO_16(from[0]); + to16[1] = UPSAMPLE_8_TO_16(from[1]); + to16[2] = UPSAMPLE_8_TO_16(from[2]); + to16[3] = UPSAMPLE_8_TO_16(from[3]); + to16 += 4; from += 4; + } } } else { @@ -196,12 +235,22 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) case 3: color_type = PNG_COLOR_TYPE_RGB; if (is_16bit) { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - premul_to_straight_v4(from_straight, from_float); - to16[0] = FTOUSHORT(from_straight[0]); - to16[1] = FTOUSHORT(from_straight[1]); - to16[2] = FTOUSHORT(from_straight[2]); - to16 += 3; from_float += 4; + 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; + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = UPSAMPLE_8_TO_16(from[0]); + to16[1] = UPSAMPLE_8_TO_16(from[1]); + to16[2] = UPSAMPLE_8_TO_16(from[2]); + to16 += 3; from += 4; + } } } else { @@ -216,10 +265,18 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) case 1: color_type = PNG_COLOR_TYPE_GRAY; if (is_16bit) { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - premul_to_straight_v4(from_straight, from_float); - to16[0] = FTOUSHORT(from_straight[0]); - to16++; from_float += 4; + 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; + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = UPSAMPLE_8_TO_16(from[0]); + to16++; from += 4; + } } } else { |