Example #1
0
MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linear[4])
{
	srgb[0] = to_srgb_table_lookup(linear[0]);
	srgb[1] = to_srgb_table_lookup(linear[1]);
	srgb[2] = to_srgb_table_lookup(linear[2]);
	srgb[3] = FTOUSHORT(linear[3]);
}
Example #2
0
MINLINE void linearrgb_to_srgb_ushort4_predivide(unsigned short srgb[4], const float linear[4])
{
	float alpha, inv_alpha, t;
	int i;

	if (linear[3] == 1.0f || linear[3] == 0.0f) {
		linearrgb_to_srgb_ushort4(srgb, linear);
		return;
	}

	alpha = linear[3];
	inv_alpha = 1.0f / alpha;

	for (i = 0; i < 3; ++i) {
		t = linear[i] * inv_alpha;
		srgb[i] = (t < 1.0f) ? (unsigned short) (to_srgb_table_lookup(t) * alpha) : FTOUSHORT(linearrgb_to_srgb(t) * alpha);
	}

	srgb[3] = FTOUSHORT(linear[3]);
}
Example #3
0
int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
{
	png_structp png_ptr;
	png_infop info_ptr;

	unsigned char *pixels = NULL;
	unsigned char *from, *to;
	unsigned short *pixels16 = NULL, *to16;
	float *from_float, from_straight[4];
	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));
	compression = compression < 0 ? 0 : (compression > 9 ? 9 : compression);

	/* for prints */
	if (flags & IB_mem)
		name = "<memory>";

	bytesperpixel = (ibuf->planes + 7) >> 3;
	if ((bytesperpixel > 4) || (bytesperpixel == 2)) {
		printf("imb_savepng: Cunsupported bytes per pixel: %d for file: '%s'\n", bytesperpixel, name);
		return (0);
	}

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
	                                  NULL, NULL, NULL);
	if (png_ptr == NULL) {
		printf("imb_savepng: Cannot png_create_write_struct for file: '%s'\n", name);
		return 0;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		printf("imb_savepng: Cannot png_create_info_struct for file: '%s'\n", name);
		return 0;
	}

	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		printf("imb_savepng: Cannot setjmp for file: '%s'\n", name);
		return 0;
	}

	/* copy image data */

	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;
	}

	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--) {
					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;
				}
			}
			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;
			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;
				}
			}
			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--) {
					premul_to_straight_v4(from_straight, from_float);
					to16[0] = FTOUSHORT(from_straight[0]);
					to16++; from_float += 4;
				}
			}
			else {
				for (i = ibuf->x * ibuf->y; i > 0; i--) {
					to[0] = from[0];
					to++; from += 4;
				}
			}
			break;
	}

	if (flags & IB_mem) {
		/* create image in memory */
		imb_addencodedbufferImBuf(ibuf);
		ibuf->encodedsize = 0;

		png_set_write_fn(png_ptr,
		                 (png_voidp) ibuf,
		                 WriteData,
		                 Flush);
	}
	else {
		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;
		}
		png_init_io(png_ptr, fp);
	}

#if 0
	png_set_filter(png_ptr, 0,
	               PNG_FILTER_NONE  | PNG_FILTER_VALUE_NONE  |
	               PNG_FILTER_SUB   | PNG_FILTER_VALUE_SUB   |
	               PNG_FILTER_UP    | PNG_FILTER_VALUE_UP    |
	               PNG_FILTER_AVG   | PNG_FILTER_VALUE_AVG   |
	               PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH |
	               PNG_ALL_FILTERS);
#endif

	png_set_compression_level(png_ptr, compression);

	/* png image settings */
	png_set_IHDR(png_ptr,
	             info_ptr,
	             ibuf->x,
	             ibuf->y,
	             is_16bit ? 16 : 8,
	             color_type,
	             PNG_INTERLACE_NONE,
	             PNG_COMPRESSION_TYPE_DEFAULT,
	             PNG_FILTER_TYPE_DEFAULT);

	/* image text info */
	if (ibuf->metadata) {
		png_text *metadata;
		ImMetaData *iptr;
		int num_text = 0;
		iptr = ibuf->metadata;
		while (iptr) {
			num_text++;
			iptr = iptr->next;
		}
		
		metadata = MEM_callocN(num_text * sizeof(png_text), "png_metadata");
		iptr = ibuf->metadata;
		num_text = 0;
		while (iptr) {
			
			metadata[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
			metadata[num_text].key = iptr->key;
			metadata[num_text].text = iptr->value;
			num_text++;
			iptr = iptr->next;
		}
		
		png_set_text(png_ptr, info_ptr, metadata, num_text);
		MEM_freeN(metadata);

	}

	if (ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) {
		png_set_pHYs(png_ptr, info_ptr, (unsigned int)(ibuf->ppm[0] + 0.5), (unsigned int)(ibuf->ppm[1] + 0.5), PNG_RESOLUTION_METER);
	}

	/* 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);
		}
		return 0;
	}

	/* 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);

	/* write the additional chunks to the PNG file (not really needed) */
	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);

	if (fp) {
		fflush(fp);
		fclose(fp);
	}

	return(1);
}
Example #4
0
/* wrap to avoid macro calling functions multiple times */
BLI_INLINE unsigned short ftoshort(float val)
{
	return FTOUSHORT(val);
}
Example #5
0
int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
{
	TIFF *image = NULL;
	uint16 samplesperpixel, bitspersample;
	size_t npixels;
	unsigned char *pixels = NULL;
	unsigned char *from = NULL, *to = NULL;
	unsigned short *pixels16 = NULL, *to16 = NULL;
	float *fromf = NULL;
	float xres, yres;
	int x, y, from_i, to_i, i;

	/* check for a valid number of bytes per pixel.  Like the PNG writer,
	 * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding
	 * to gray, RGB, RGBA respectively. */
	samplesperpixel = (uint16)((ibuf->planes + 7) >> 3);
	if ((samplesperpixel > 4) || (samplesperpixel == 2)) {
		fprintf(stderr,
		        "imb_savetiff: unsupported number of bytes per "
		        "pixel: %d\n", samplesperpixel);
		return (0);
	}

	if ((ibuf->ftype & TIF_16BIT) && ibuf->rect_float)
		bitspersample = 16;
	else
		bitspersample = 8;

	/* open TIFF file for writing */
	if (flags & IB_mem) {
		/* bork at the creation of a TIFF in memory */
		fprintf(stderr,
		        "imb_savetiff: creation of in-memory TIFF files is "
		        "not yet supported.\n");
		return (0);
	}
	else {
		/* create image as a file */
#ifdef WIN32
		wchar_t *wname = alloc_utf16_from_8(name, 0);
		image = TIFFOpenW(wname, "w");
		free(wname);
#else
		image = TIFFOpen(name, "w");
#endif
	}
	if (image == NULL) {
		fprintf(stderr,
		        "imb_savetiff: could not open TIFF for writing.\n");
		return (0);
	}

	/* allocate array for pixel data */
	npixels = ibuf->x * ibuf->y;
	if (bitspersample == 16)
		pixels16 = (unsigned short *)_TIFFmalloc(npixels *
		                                         samplesperpixel * sizeof(unsigned short));
	else
		pixels = (unsigned char *)_TIFFmalloc(npixels *
		                                      samplesperpixel * sizeof(unsigned char));

	if (pixels == NULL && pixels16 == NULL) {
		fprintf(stderr,
		        "imb_savetiff: could not allocate pixels array.\n");
		TIFFClose(image);
		return (0);
	}

	/* setup pointers */
	if (bitspersample == 16) {
		fromf = ibuf->rect_float;
		to16   = pixels16;
	}
	else {
		from = (unsigned char *)ibuf->rect;
		to   = pixels;
	}

	/* setup samples per pixel */
	TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bitspersample);
	TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);

	if (samplesperpixel == 4) {
		unsigned short extraSampleTypes[1];

		if (bitspersample == 16)
			extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA;
		else
			extraSampleTypes[0] = EXTRASAMPLE_UNASSALPHA;

		/* RGBA images */
		TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1,
		             extraSampleTypes);
		TIFFSetField(image, TIFFTAG_PHOTOMETRIC, 
		             PHOTOMETRIC_RGB);
	}
	else if (samplesperpixel == 3) {
		/* RGB images */
		TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
		             PHOTOMETRIC_RGB);
	}
	else if (samplesperpixel == 1) {
		/* grayscale images, 1 channel */
		TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
		             PHOTOMETRIC_MINISBLACK);
	}

	/* copy pixel data.  While copying, we flip the image vertically. */
	for (x = 0; x < ibuf->x; x++) {
		for (y = 0; y < ibuf->y; y++) {
			from_i = 4 * (y * ibuf->x + x);
			to_i   = samplesperpixel * ((ibuf->y - y - 1) * ibuf->x + x);

			if (pixels16) {
				/* convert from float source */
				float rgb[4];
				
				if (ibuf->float_colorspace) {
					/* float buffer was managed already, no need in color space conversion */
					copy_v3_v3(rgb, &fromf[from_i]);
				}
				else {
					/* standard linear-to-srgb conversion if float buffer wasn't managed */
					linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]);
				}

				rgb[3] = fromf[from_i + 3];

				for (i = 0; i < samplesperpixel; i++, to_i++)
					to16[to_i] = FTOUSHORT(rgb[i]);
			}
			else {
				for (i = 0; i < samplesperpixel; i++, to_i++, from_i++)
					to[to_i] = from[from_i];
			}
		}
	}

	/* write the actual TIFF file */
	TIFFSetField(image, TIFFTAG_IMAGEWIDTH,      ibuf->x);
	TIFFSetField(image, TIFFTAG_IMAGELENGTH,     ibuf->y);
	TIFFSetField(image, TIFFTAG_ROWSPERSTRIP,    ibuf->y);
	TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
	TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
	TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);


	if (ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) {
		xres = (float)(ibuf->ppm[0] * 0.0254);
		yres = (float)(ibuf->ppm[1] * 0.0254);
	}
	else {
		xres = yres = IMB_DPI_DEFAULT;
	}

	TIFFSetField(image, TIFFTAG_XRESOLUTION,     xres);
	TIFFSetField(image, TIFFTAG_YRESOLUTION,     yres);
	TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT,  RESUNIT_INCH);
	if (TIFFWriteEncodedStrip(image, 0,
	                          (bitspersample == 16) ? (unsigned char *)pixels16 : pixels,
	                          ibuf->x * ibuf->y * samplesperpixel * bitspersample / 8) == -1)
	{
		fprintf(stderr,
		        "imb_savetiff: Could not write encoded TIFF.\n");
		TIFFClose(image);
		if (pixels) _TIFFfree(pixels);
		if (pixels16) _TIFFfree(pixels16);
		return (1);
	}

	/* close the TIFF file */
	TIFFClose(image);
	if (pixels) _TIFFfree(pixels);
	if (pixels16) _TIFFfree(pixels16);
	return (1);
}
Example #6
0
int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
{
	TIFF *image = NULL;
	uint16 samplesperpixel, bitspersample;
	size_t npixels;
	unsigned char *pixels = NULL;
	unsigned char *from = NULL, *to = NULL;
	unsigned short *pixels16 = NULL, *to16 = NULL;
	float *fromf = NULL;
	int x, y, from_i, to_i, i;
	int extraSampleTypes[1] = { EXTRASAMPLE_ASSOCALPHA };
	

	/* check for a valid number of bytes per pixel.  Like the PNG writer,
	 * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding
	 * to gray, RGB, RGBA respectively. */
	samplesperpixel = (uint16)((ibuf->depth + 7) >> 3);
	if((samplesperpixel > 4) || (samplesperpixel == 2)) {
		fprintf(stderr,
			"imb_savetiff: unsupported number of bytes per " 
			"pixel: %d\n", samplesperpixel);
		return (0);
	}

	if((ibuf->ftype & TIF_16BIT) && ibuf->rect_float)
		bitspersample = 16;
	else
		bitspersample = 8;

	/* open TIFF file for writing */
	if(flags & IB_mem) {
		/* bork at the creation of a TIFF in memory */
		fprintf(stderr,
			"imb_savetiff: creation of in-memory TIFF files is " 
			"not yet supported.\n");
		return (0);
	}
	else {
		/* create image as a file */
		image = TIFFOpen(name, "w");
	}
	if(image == NULL) {
		fprintf(stderr,
			"imb_savetiff: could not open TIFF for writing.\n");
		return (0);
	}

	/* allocate array for pixel data */
	npixels = ibuf->x * ibuf->y;
	if(bitspersample == 16)
		pixels16 = (unsigned short*)_TIFFmalloc(npixels *
			samplesperpixel * sizeof(unsigned short));
	else
		pixels = (unsigned char*)_TIFFmalloc(npixels *
			samplesperpixel * sizeof(unsigned char));

	if(pixels == NULL && pixels16 == NULL) {
		fprintf(stderr,
			"imb_savetiff: could not allocate pixels array.\n");
		TIFFClose(image);
		return (0);
	}

	/* setup pointers */
	if(bitspersample == 16) {
		fromf = ibuf->rect_float;
		to16   = pixels16;
	}
	else {
		from = (unsigned char*)ibuf->rect;
		to   = pixels;
	}

	/* setup samples per pixel */
	TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bitspersample);
	TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);

	if(samplesperpixel == 4) {
		/* RGBA images */
		TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1,
				extraSampleTypes);
		TIFFSetField(image, TIFFTAG_PHOTOMETRIC, 
				PHOTOMETRIC_RGB);
	}
	else if(samplesperpixel == 3) {
		/* RGB images */
		TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
				PHOTOMETRIC_RGB);
	}
	else if(samplesperpixel == 1) {
		/* greyscale images, 1 channel */
		TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
				PHOTOMETRIC_MINISBLACK);
	}

	/* copy pixel data.  While copying, we flip the image vertically. */
	for(x = 0; x < ibuf->x; x++) {
		for(y = 0; y < ibuf->y; y++) {
			from_i = 4*(y*ibuf->x+x);
			to_i   = samplesperpixel*((ibuf->y-y-1)*ibuf->x+x);

			if(pixels16) {
				/* convert from float source */
				float rgb[3];
				
				if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
					linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]);
				else
					copy_v3_v3(rgb, &fromf[from_i]);

				to16[to_i+0] = FTOUSHORT(rgb[0]);
				to16[to_i+1] = FTOUSHORT(rgb[1]);
				to16[to_i+2] = FTOUSHORT(rgb[2]);
				to_i += 3; from_i+=3;
				
				if (samplesperpixel == 4) {
					to16[to_i+3] = FTOUSHORT(fromf[from_i+3]);
					/*to_i++; from_i++;*/ /*unused, set on each loop */
				}
			}
			else {
				for(i = 0; i < samplesperpixel; i++, to_i++, from_i++)
					to[to_i] = from[from_i];
			}
		}
	}

	/* write the actual TIFF file */
	TIFFSetField(image, TIFFTAG_IMAGEWIDTH,      ibuf->x);
	TIFFSetField(image, TIFFTAG_IMAGELENGTH,     ibuf->y);
	TIFFSetField(image, TIFFTAG_ROWSPERSTRIP,    ibuf->y);
	TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
	TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
	TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
	TIFFSetField(image, TIFFTAG_XRESOLUTION,     150.0);
	TIFFSetField(image, TIFFTAG_YRESOLUTION,     150.0);
	TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT,  RESUNIT_INCH);
	if(TIFFWriteEncodedStrip(image, 0,
			(bitspersample == 16)? (unsigned char*)pixels16: pixels,
			ibuf->x*ibuf->y*samplesperpixel*bitspersample/8) == -1) {
		fprintf(stderr,
			"imb_savetiff: Could not write encoded TIFF.\n");
		TIFFClose(image);
		if(pixels) _TIFFfree(pixels);
		if(pixels16) _TIFFfree(pixels16);
		return (1);
	}

	/* close the TIFF file */
	TIFFClose(image);
	if(pixels) _TIFFfree(pixels);
	if(pixels16) _TIFFfree(pixels16);
	return (1);
}