Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2012-12-30 17:01:47 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2012-12-30 17:01:47 +0400
commitf62fc79da05b1b3568871adaff8b246eb6b30793 (patch)
treee69c8dbea350b3b8f4a37b0a1b064afa3daa4429
parentfde101c50c3d7ad6bb43a578d7622cea084001a3 (diff)
16 bit PNG write support
This commit adds a support of saving 16bit PNG files. Alpha for such files would be premultiplied, would be corrected with an upcoming alpha premul cleanup (it's not the only format which will output 16bit image with premul alpha).
-rw-r--r--source/blender/blenkernel/intern/image.c14
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h6
-rw-r--r--source/blender/imbuf/intern/filetype.c2
-rw-r--r--source/blender/imbuf/intern/png.c108
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;