diff options
-rw-r--r-- | source/blender/blenkernel/intern/image.c | 14 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_imbuf_types.h | 6 | ||||
-rw-r--r-- | source/blender/imbuf/intern/filetype.c | 2 | ||||
-rw-r--r-- | source/blender/imbuf/intern/png.c | 108 |
4 files changed, 102 insertions, 28 deletions
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 22995e5a7ee..8630ace4edf 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1119,6 +1119,8 @@ char BKE_imtype_valid_depths(const char imtype) return R_IMF_CHAN_DEPTH_10; case R_IMF_IMTYPE_JP2: return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16; + case R_IMF_IMTYPE_PNG: + return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_16; /* most formats are 8bit only */ default: return R_IMF_CHAN_DEPTH_8; @@ -1313,9 +1315,13 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i im_format->imtype = R_IMF_IMTYPE_RADHDR; #endif - else if (ftype == PNG) + else if (ftype == PNG) { im_format->imtype = R_IMF_IMTYPE_PNG; + if (custom_flags & PNG_16BIT) + im_format->depth = R_IMF_CHAN_DEPTH_16; + } + #ifdef WITH_DDS else if (ftype == DDS) im_format->imtype = R_IMF_IMTYPE_DDS; @@ -1847,8 +1853,12 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf) else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) { ibuf->ftype = PNG; - if (imtype == R_IMF_IMTYPE_PNG) + if (imtype == R_IMF_IMTYPE_PNG) { + if (imf->depth == R_IMF_CHAN_DEPTH_16) + ibuf->ftype |= PNG_16BIT; + ibuf->ftype |= compress; + } } #ifdef WITH_DDS diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 433123914ce..9fe66b562d1 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -172,9 +172,9 @@ typedef struct ImBuf { /* * The bit flag is stored in the ImBuf.ftype variable. - * Note that the lower 10 bits is used for storing custom flags + * Note that the lower 11 bits is used for storing custom flags */ -#define IB_CUSTOM_FLAGS_MASK 0x3ff +#define IB_CUSTOM_FLAGS_MASK 0x400 #define PNG (1 << 30) #define TGA (1 << 28) @@ -221,6 +221,8 @@ typedef struct ImBuf { #define JP2_J2K (1 << 11) #endif +#define PNG_16BIT (1 << 10) + #define RAWTGA (TGA | 1) #define JPG_STD (JPG | (0 << 8)) diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c index 5c2dc0c7df9..6d1f2abab0b 100644 --- a/source/blender/imbuf/intern/filetype.c +++ b/source/blender/imbuf/intern/filetype.c @@ -69,7 +69,7 @@ void quicktime_exit(void); ImFileType IMB_FILE_TYPES[] = { {NULL, NULL, imb_is_a_jpeg, imb_ftype_default, imb_load_jpeg, imb_savejpeg, NULL, 0, JPG, COLOR_ROLE_DEFAULT_BYTE}, - {NULL, NULL, imb_is_a_png, imb_ftype_default, imb_loadpng, imb_savepng, NULL, 0, PNG, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_png, imb_ftype_default, imb_loadpng, imb_savepng, NULL, IM_FTYPE_FLOAT, PNG, COLOR_ROLE_DEFAULT_BYTE}, {NULL, NULL, imb_is_a_bmp, imb_ftype_default, imb_bmp_decode, imb_savebmp, NULL, 0, BMP, COLOR_ROLE_DEFAULT_BYTE}, {NULL, NULL, imb_is_a_targa, imb_ftype_default, imb_loadtarga, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE}, {NULL, NULL, imb_is_a_iris, imb_ftype_iris, imb_loadiris, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE}, diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index dcfebb95b87..c0737fadffa 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -109,10 +109,14 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) unsigned char *pixels = NULL; unsigned char *from, *to; + unsigned short *pixels16 = NULL, *to16; + float *from_float; png_bytepp row_pointers = NULL; int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY; FILE *fp = NULL; + int is_16bit = (ibuf->ftype & PNG_16BIT) && ibuf->rect_float; + /* use the jpeg quality setting for compression */ int compression; compression = (int)(((float)(ibuf->ftype & 0xff) / 11.1111f)); @@ -150,8 +154,12 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) /* copy image data */ - pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels"); - if (pixels == NULL) { + if (is_16bit) + pixels16 = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned short), "png 16bit pixels"); + else + pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "png 8bit pixels"); + + if (pixels == NULL && pixels16 == NULL) { png_destroy_write_struct(&png_ptr, &info_ptr); printf("imb_savepng: Cannot allocate pixels array of %dx%d, %d bytes per pixel for file: '%s'\n", ibuf->x, ibuf->y, bytesperpixel, name); return 0; @@ -159,32 +167,63 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) from = (unsigned char *) ibuf->rect; to = pixels; + from_float = ibuf->rect_float; + to16 = pixels16; switch (bytesperpixel) { case 4: color_type = PNG_COLOR_TYPE_RGBA; - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to[0] = from[0]; - to[1] = from[1]; - to[2] = from[2]; - to[3] = from[3]; - to += 4; from += 4; + if (is_16bit) { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = FTOUSHORT(from_float[0]); + to16[1] = FTOUSHORT(from_float[1]); + to16[2] = FTOUSHORT(from_float[2]); + to16[3] = FTOUSHORT(from_float[3]); + to16 += 4; from_float += 4; + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; + to += 4; from += 4; + } } break; case 3: color_type = PNG_COLOR_TYPE_RGB; - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to[0] = from[0]; - to[1] = from[1]; - to[2] = from[2]; - to += 3; from += 4; + if (is_16bit) { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = FTOUSHORT(from_float[0]); + to16[1] = FTOUSHORT(from_float[1]); + to16[2] = FTOUSHORT(from_float[2]); + to16 += 3; from_float += 4; + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to += 3; from += 4; + } } break; case 1: color_type = PNG_COLOR_TYPE_GRAY; - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to[0] = from[0]; - to++; from += 4; + if (is_16bit) { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = FTOUSHORT(from_float[0]); + to16++; from_float += 4; + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to[0] = from[0]; + to++; from += 4; + } } break; } @@ -203,7 +242,10 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) fp = BLI_fopen(name, "wb"); if (!fp) { png_destroy_write_struct(&png_ptr, &info_ptr); - MEM_freeN(pixels); + if (pixels) + MEM_freeN(pixels); + if (pixels16) + MEM_freeN(pixels16); printf("imb_savepng: Cannot open file for writing: '%s'\n", name); return 0; } @@ -227,7 +269,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) info_ptr, ibuf->x, ibuf->y, - 8, + is_16bit ? 16 : 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, @@ -268,12 +310,19 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) /* write the file header information */ png_write_info(png_ptr, info_ptr); +#ifdef __LITTLE_ENDIAN__ + png_set_swap(png_ptr); +#endif + /* allocate memory for an array of row-pointers */ row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers"); if (row_pointers == NULL) { printf("imb_savepng: Cannot allocate row-pointers array for file '%s'\n", name); png_destroy_write_struct(&png_ptr, &info_ptr); - MEM_freeN(pixels); + if (pixels) + MEM_freeN(pixels); + if (pixels16) + MEM_freeN(pixels16); if (fp) { fclose(fp); } @@ -281,9 +330,17 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) } /* set the individual row-pointers to point at the correct offsets */ - for (i = 0; i < ibuf->y; i++) { - row_pointers[ibuf->y - 1 - i] = (png_bytep) - ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char)); + if (is_16bit) { + for (i = 0; i < ibuf->y; i++) { + row_pointers[ibuf->y - 1 - i] = (png_bytep) + ((unsigned short *)pixels16 + (i * ibuf->x) * bytesperpixel); + } + } + else { + for (i = 0; i < ibuf->y; i++) { + row_pointers[ibuf->y - 1 - i] = (png_bytep) + ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char)); + } } /* write out the entire image data in one call */ @@ -293,7 +350,10 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) png_write_end(png_ptr, info_ptr); /* clean up */ - MEM_freeN(pixels); + if (pixels) + MEM_freeN(pixels); + if (pixels16) + MEM_freeN(pixels16); MEM_freeN(row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); @@ -394,6 +454,8 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[I if (ibuf) { ibuf->ftype = PNG; + if (bit_depth == 16) + ibuf->ftype |= PNG_16BIT; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) { int unit_type; |