[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [53425] trunk/blender/source/blender: 16 bit PNG write support

Sergey Sharybin sergey.vfx at gmail.com
Sun Dec 30 14:01:53 CET 2012


Revision: 53425
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=53425
Author:   nazgul
Date:     2012-12-30 13:01:47 +0000 (Sun, 30 Dec 2012)
Log Message:
-----------
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).

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/intern/image.c
    trunk/blender/source/blender/imbuf/IMB_imbuf_types.h
    trunk/blender/source/blender/imbuf/intern/filetype.c
    trunk/blender/source/blender/imbuf/intern/png.c

Modified: trunk/blender/source/blender/blenkernel/intern/image.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/image.c	2012-12-30 10:38:56 UTC (rev 53424)
+++ trunk/blender/source/blender/blenkernel/intern/image.c	2012-12-30 13:01:47 UTC (rev 53425)
@@ -1119,6 +1119,8 @@
 			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 @@
 		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 @@
 	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

Modified: trunk/blender/source/blender/imbuf/IMB_imbuf_types.h
===================================================================
--- trunk/blender/source/blender/imbuf/IMB_imbuf_types.h	2012-12-30 10:38:56 UTC (rev 53424)
+++ trunk/blender/source/blender/imbuf/IMB_imbuf_types.h	2012-12-30 13:01:47 UTC (rev 53425)
@@ -172,9 +172,9 @@
 
 /*
  * 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 @@
 #define JP2_J2K	(1 << 11)
 #endif
 
+#define PNG_16BIT			(1 << 10)
+
 #define RAWTGA	        (TGA | 1)
 
 #define JPG_STD	        (JPG | (0 << 8))

Modified: trunk/blender/source/blender/imbuf/intern/filetype.c
===================================================================
--- trunk/blender/source/blender/imbuf/intern/filetype.c	2012-12-30 10:38:56 UTC (rev 53424)
+++ trunk/blender/source/blender/imbuf/intern/filetype.c	2012-12-30 13:01:47 UTC (rev 53425)
@@ -69,7 +69,7 @@
 
 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},

Modified: trunk/blender/source/blender/imbuf/intern/png.c
===================================================================
--- trunk/blender/source/blender/imbuf/intern/png.c	2012-12-30 10:38:56 UTC (rev 53424)
+++ trunk/blender/source/blender/imbuf/intern/png.c	2012-12-30 13:01:47 UTC (rev 53425)
@@ -109,10 +109,14 @@
 
 	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 @@
 
 	/* 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,33 +167,64 @@
 
 	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 @@
 		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 @@
 	             info_ptr,
 	             ibuf->x,
 	             ibuf->y,
-	             8,
+	             is_16bit ? 16 : 8,
 	             color_type,
 	             PNG_INTERLACE_NONE,
 	             PNG_COMPRESSION_TYPE_DEFAULT,
@@ -268,12 +310,19 @@
 	/* 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,10 +330,18 @@
 	}
 
 	/* 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 */
 	png_write_image(png_ptr, row_pointers);
@@ -293,7 +350,10 @@
 	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 @@
 
 	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;




More information about the Bf-blender-cvs mailing list