forked from bartvdbraak/blender
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).
This commit is contained in:
parent
fde101c50c
commit
f62fc79da0
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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},
|
||||
|
@ -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,10 +167,22 @@ 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;
|
||||
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];
|
||||
@ -170,22 +190,41 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
|
||||
to[3] = from[3];
|
||||
to += 4; from += 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
color_type = PNG_COLOR_TYPE_RGB;
|
||||
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;
|
||||
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);
|
||||
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);
|
||||
if (pixels)
|
||||
MEM_freeN(pixels);
|
||||
if (pixels16)
|
||||
MEM_freeN(pixels16);
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
@ -281,10 +330,18 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
|
||||
}
|
||||
|
||||
/* set the individual row-pointers to point at the correct offsets */
|
||||
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 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
|
||||
/* clean up */
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user