Пример #1
0
static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags)
{
	ImBuf *ibuf;
	LogImageFile *image;
	int x, y;
	unsigned short *row, *upix;
	int width, height, depth;
	float *frow;

	logImageSetVerbose((G.f & G_DEBUG) ? 1:0);
	
	image = logImageOpenFromMem(mem, size, use_cineon);
	
	if (!image) {
		printf("no image!\n");
		return NULL;
	}
	
	logImageGetSize(image, &width, &height, &depth);
	
	if (depth != 3) { /*need to do greyscale loading eventually.*/
		logImageClose(image);
		return NULL;
	}
	
	if (width == 0 && height == 0) {
		logImageClose(image);
		return NULL;
	}
	
	ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags);

	row = MEM_mallocN(sizeof(unsigned short)*width*depth, "row in cineon_dpx.c");
	frow = ibuf->rect_float+width*height*4;
	
	for (y = 0; y < height; y++) {
		logImageGetRowBytes(image, row, y); /* checks image->params.doLogarithm and convert */
		upix = row;
		frow -= width*4;
		
		for (x=0; x<width; x++) {
			*(frow++) = ((float)*(upix++)) / 65535.0f;
			*(frow++) = ((float)*(upix++)) / 65535.0f;
			*(frow++) = ((float)*(upix++)) / 65535.0f;
			*(frow++) = 1.0f;
		}
		frow -= width*4;
	}

	MEM_freeN(row);
	logImageClose(image);
	
	if (flags & IB_rect) {
		IMB_rect_from_float(ibuf);
	}
	return ibuf;
}
Пример #2
0
static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int use_cineon, int flags,
                                         char colorspace[IM_MAX_SPACE])
{
	ImBuf *ibuf;
	LogImageFile *image;
	int width, height, depth;

	colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT);

	logImageSetVerbose((G.f & G_DEBUG) ? 1 : 0);

	image = logImageOpenFromMemory(mem, size);

	if (image == 0) {
		printf("DPX/Cineon: error opening image.\n");
		return 0;
	}

	logImageGetSize(image, &width, &height, &depth);

	if (width == 0 || height == 0) {
		logImageClose(image);
		return 0;
	}

	ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags);
	if (ibuf == 0) {
		logImageClose(image);
		return 0;
	}

	if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) {
		/* Conversion not possible (probably because the format is unsupported) */
		logImageClose(image);
		MEM_freeN(ibuf);
		return 0;
	}

	logImageClose(image);
	ibuf->ftype = use_cineon ? CINEON : DPX;
	IMB_flipy(ibuf);

	if (flags & IB_rect)
		IMB_rect_from_float(ibuf);

	if (flags & IB_alphamode_detect)
		ibuf->flags |= IB_alphamode_premul;

	return ibuf;
}
Пример #3
0
static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int use_cineon, int flags,
                                         char colorspace[IM_MAX_SPACE])
{
	ImBuf *ibuf;
	LogImageFile *image;
	int width, height, depth;

	colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT);

	logImageSetVerbose((G.f & G_DEBUG) ? 1 : 0);

	image = logImageOpenFromMemory(mem, size);

	if (image == NULL) {
		printf("DPX/Cineon: error opening image.\n");
		return NULL;
	}

	logImageGetSize(image, &width, &height, &depth);

	ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags);
	if (ibuf == NULL) {
		logImageClose(image);
		return NULL;
	}

	if (!(flags & IB_test)) {
		if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) {
			logImageClose(image);
			IMB_freeImBuf(ibuf);
			return NULL;
		}
		IMB_flipy(ibuf);
	}

	logImageClose(image);
	ibuf->ftype = use_cineon ? CINEON : DPX;

	if (flags & IB_alphamode_detect)
		ibuf->flags |= IB_alphamode_premul;

	return ibuf;
}
Пример #4
0
static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon, int flags)
{
	LogImageByteConversionParameters conversion;
	const int width= ibuf->x;
	const int height= ibuf->y;
	const int depth= 3;
	LogImageFile* logImage;
	unsigned short* line, *pixel;
	int i, j;
	float *fline;
	float *fbuf;
	int is_alloc= 0;
	
	(void)flags; /* unused */

	// cineon_conversion_parameters(&conversion);
	logImageGetByteConversionDefaults(&conversion);

	/*
	 * Get the drawable for the current image...
	 */

	fbuf= IMB_float_profile_ensure(ibuf, conversion.doLogarithm ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE, &is_alloc);

	if (fbuf == NULL) { /* in the unlikely event that converting to a float buffer fails */
		return 0;
	}
	
	logImageSetVerbose((G.f & G_DEBUG) ? 1:0);
	logImage = logImageCreate(filename, use_cineon, width, height, depth);

	if (!logImage) return 0;
	
	if(logImageSetByteConversion(logImage, &conversion)==0) {
		printf("error setting args\n");
	}

	line = MEM_mallocN(sizeof(unsigned short)*depth*width, "line");
	
	/*note that image is flipped when sent to logImageSetRowBytes (see last passed parameter).*/
	for (j = 0; j < height; ++j) {
		fline = &fbuf[width*j*4];
		for (i=0; i<width; i++) {
			float *fpix, fpix2[3];
			/*we have to convert to cinepaint's 16-bit-per-channel here*/
			pixel = &line[i*depth];
			fpix = &fline[i*4];
			memcpy(fpix2, fpix, sizeof(float)*3);
			
			if (fpix2[0]>=1.0f) fpix2[0] = 1.0f; else if (fpix2[0]<0.0f) fpix2[0]= 0.0f;
			if (fpix2[1]>=1.0f) fpix2[1] = 1.0f; else if (fpix2[1]<0.0f) fpix2[1]= 0.0f;
			if (fpix2[2]>=1.0f) fpix2[2] = 1.0f; else if (fpix2[2]<0.0f) fpix2[2]= 0.0f;
			
			pixel[0] = (unsigned short)(fpix2[0] * 65535.0f); /*float-float math is faster*/
			pixel[1] = (unsigned short)(fpix2[1] * 65535.0f);
			pixel[2] = (unsigned short)(fpix2[2] * 65535.0f);
		}
		logImageSetRowBytes(logImage, (const unsigned short*)line, height-1-j);
	}
	logImageClose(logImage);

	MEM_freeN(line);
	
	if(is_alloc) {
		MEM_freeN(fbuf);
	}
	
	return 1;
}
Пример #5
0
LogImageFile *cineonCreate(const char *filename, int width, int height, int bitsPerSample, const char *creator)
{
	CineonMainHeader header;
	const char *shortFilename = NULL;
	/* unsigned char pad[6044]; */

	LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
	if (cineon == NULL) {
		if (verbose) printf("cineon: Failed to malloc cineon file structure.\n");
		return NULL;
	}

	/* Only 10 bits Cineon are supported */
	if (bitsPerSample != 10) {
		if (verbose) printf("cineon: Only 10 bits Cineon are supported.\n");
		logImageClose(cineon);
		return NULL;
	}

	cineon->width = width;
	cineon->height = height;
	cineon->element[0].bitsPerSample = 10;
	cineon->element[0].dataOffset = sizeof(CineonMainHeader);
	cineon->element[0].maxValue = 1023;
	cineon->isMSB = 1;
	cineon->numElements = 1;
	cineon->element[0].packing = 1;
	cineon->depth = 3;
	cineon->element[0].depth = 3;
	cineon->element[0].descriptor = descriptor_RGB;
	cineon->element[0].transfer = transfer_PrintingDensity;
	cineon->element[0].refHighQuantity = 2.048f;
	cineon->element[0].refLowQuantity = 0;
	cineon->element[0].refLowData = 0;
	cineon->element[0].refHighData = cineon->element[0].maxValue;
	cineon->referenceWhite = 685.0f;
	cineon->referenceBlack = 95.0f;
	cineon->gamma = 1.7f;

	shortFilename = strrchr(filename, '/');
	if (shortFilename == NULL)
		shortFilename = filename;
	else
		shortFilename++;

	cineon->file = BLI_fopen(filename, "wb");
	if (cineon->file == NULL) {
		if (verbose) printf("cineon: Couldn't open file %s\n", filename);
		logImageClose(cineon);
		return NULL;
	}

	fillCineonMainHeader(cineon, &header, shortFilename, creator);

	if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) {
		if (verbose) printf("cineon: Couldn't write image header\n");
		logImageClose(cineon);
		return NULL;
	}

	return cineon;
}
Пример #6
0
LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize)
{
	CineonMainHeader header;
	LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
	const char *filename = (const char *)byteStuff;
	int i;
	unsigned int dataOffset;

	if (cineon == NULL) {
		if (verbose) printf("Cineon: Failed to malloc cineon file structure.\n");
		return NULL;
	}

	/* zero the header */
	memset(&header, 0, sizeof(CineonMainHeader));

	/* for close routine */
	cineon->file = NULL;

	if (fromMemory == 0) {
		/* byteStuff is then the filename */
		cineon->file = BLI_fopen(filename, "rb");
		if (cineon->file == NULL) {
			if (verbose) printf("Cineon: Failed to open file \"%s\".\n", filename);
			logImageClose(cineon);
			return NULL;
		}
		/* not used in this case */
		cineon->memBuffer = NULL;
		cineon->memCursor = NULL;
		cineon->memBufferSize = 0;
	}
	else {
		cineon->memBuffer = (unsigned char *)byteStuff;
		cineon->memCursor = (unsigned char *)byteStuff;
		cineon->memBufferSize = bufferSize;
	}

	if (logimage_fread(&header, sizeof(header), 1, cineon) == 0) {
		if (verbose) printf("Cineon: Not enough data for header in \"%s\".\n", byteStuff);
		logImageClose(cineon);
		return NULL;
	}

	/* endianness determination */
	if (header.fileHeader.magic_num == swap_uint(CINEON_FILE_MAGIC, 1)) {
		cineon->isMSB = 1;
		if (verbose) printf("Cineon: File is MSB.\n");
	}
	else if (header.fileHeader.magic_num == CINEON_FILE_MAGIC) {
		cineon->isMSB = 0;
		if (verbose) printf("Cineon: File is LSB.\n");
	}
	else {
		if (verbose) printf("Cineon: Bad magic number %lu in \"%s\".\n",
			                (unsigned long)header.fileHeader.magic_num, byteStuff);
		logImageClose(cineon);
		return NULL;
	}

	cineon->width = swap_uint(header.imageHeader.element[0].pixels_per_line, cineon->isMSB);
	cineon->height = swap_uint(header.imageHeader.element[0].lines_per_image, cineon->isMSB);

	if (cineon->width == 0 || cineon->height == 0) {
		if (verbose) printf("Cineon: Wrong image dimension: %dx%d\n", cineon->width, cineon->height);
		logImageClose(cineon);
		return NULL;
	}

	cineon->depth = header.imageHeader.elements_per_image;
	cineon->srcFormat = format_Cineon;

	if (header.imageHeader.interleave == 0)
		cineon->numElements = 1;
	else if (header.imageHeader.interleave == 2)
		cineon->numElements = header.imageHeader.elements_per_image;
	else {
		if (verbose) printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave);
		logImageClose(cineon);
		return NULL;
	}

	if (cineon->depth == 1) {
		/* Grayscale image */
		cineon->element[0].descriptor = descriptor_Luminance;
		cineon->element[0].transfer = transfer_Linear;
		cineon->element[0].depth = 1;
	}
	else if (cineon->depth == 3) {
		/* RGB image */
		if (cineon->numElements == 1) {
			cineon->element[0].descriptor = descriptor_RGB;
			cineon->element[0].transfer = transfer_PrintingDensity;
			cineon->element[0].depth = 3;
		}
		else if (cineon->numElements == 3) {
			cineon->element[0].descriptor = descriptor_Red;
			cineon->element[0].transfer = transfer_PrintingDensity;
			cineon->element[0].depth = 1;
			cineon->element[1].descriptor = descriptor_Green;
			cineon->element[1].transfer = transfer_PrintingDensity;
			cineon->element[1].depth = 1;
			cineon->element[2].descriptor = descriptor_Blue;
			cineon->element[2].transfer = transfer_PrintingDensity;
			cineon->element[2].depth = 1;
		}
	}
	else {
		if (verbose) printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth);
		logImageClose(cineon);
		return NULL;
	}

	dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB);

	for (i = 0; i < cineon->numElements; i++) {
		cineon->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample;
		cineon->element[i].maxValue = powf(2, cineon->element[i].bitsPerSample) - 1.0f;
		cineon->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, cineon->isMSB);
		cineon->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity, cineon->isMSB);
		cineon->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data, cineon->isMSB);
		cineon->element[i].refHighQuantity = swap_float(header.imageHeader.element[i].ref_high_quantity, cineon->isMSB);

		switch (header.imageHeader.packing) {
			case 0:
				cineon->element[i].packing = 0;
				break;

			case 5:
				cineon->element[i].packing = 1;
				break;

			case 6:
				cineon->element[i].packing = 2;
				break;

			default:
				/* Not supported */
				if (verbose) printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing);
				logImageClose(cineon);
				return NULL;
		}

		if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32)
			cineon->element[i].refLowData = 0;

		if (cineon->element[i].refHighData == CINEON_UNDEFINED_U32)
			cineon->element[i].refHighData = (unsigned int)cineon->element[i].maxValue;

		if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refLowQuantity))
			cineon->element[i].refLowQuantity = 0.0f;

		if (cineon->element[i].refHighQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refHighQuantity)) {
			if (cineon->element[i].transfer == transfer_PrintingDensity)
				cineon->element[i].refHighQuantity = 2.048f;
			else
				cineon->element[i].refHighQuantity = cineon->element[i].maxValue;
		}

		cineon->element[i].dataOffset = dataOffset;
		dataOffset += cineon->height * getRowLength(cineon->width, cineon->element[i]);
	}

	cineon->referenceBlack = 95.0f / 1023.0f * cineon->element[0].maxValue;
	cineon->referenceWhite = 685.0f / 1023.0f * cineon->element[0].maxValue;
	cineon->gamma = 1.7f;

	if (verbose) {
		printf("size %d x %d x %d elements\n", cineon->width, cineon->height, cineon->numElements);
		for (i = 0; i < cineon->numElements; i++) {
			printf(" Element %d:\n", i);
			printf("  Bits per sample: %d\n", cineon->element[i].bitsPerSample);
			printf("  Depth: %d\n", cineon->element[i].depth);
			printf("  Transfer characteristics: %d\n", cineon->element[i].transfer);
			printf("  Packing: %d\n", cineon->element[i].packing);
			printf("  Descriptor: %d\n", cineon->element[i].descriptor);
			printf("  Data offset: %u\n", cineon->element[i].dataOffset);
			printf("  Reference low data: %u\n", cineon->element[i].refLowData);
			printf("  Reference low quantity: %f\n", cineon->element[i].refLowQuantity);
			printf("  Reference high data: %u\n", cineon->element[i].refHighData);
			printf("  Reference high quantity: %f\n", cineon->element[i].refHighQuantity);
			printf("\n");
		}

		printf("Gamma: %f\n", cineon->gamma);
		printf("Reference black: %f\n", cineon->referenceBlack);
		printf("Reference white: %f\n", cineon->referenceWhite);
		printf("----------------------------\n");
	}
	return cineon;
}
Пример #7
0
static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon, int flags)
{
	LogImageFile *logImage;
	float *fbuf;
	float *fbuf_ptr;
	unsigned char *rect_ptr;
	int x, y, depth, bitspersample, rvalue;

	if (flags & IB_mem) {
		printf("DPX/Cineon: saving in memory is not supported.\n");
		return 0;
	}
	
	logImageSetVerbose((G.f & G_DEBUG) ? 1 : 0);

	depth = (ibuf->planes + 7) >> 3;
	if (depth > 4 || depth < 3) {
		printf("DPX/Cineon: unsupported depth: %d for file: '%s'\n", depth, filename);
		return 0;
	}

	if (ibuf->ftype & CINEON_10BIT)
		bitspersample = 10;
	else if (ibuf->ftype & CINEON_12BIT)
		bitspersample = 12;
	else if (ibuf->ftype & CINEON_16BIT)
		bitspersample = 16;
	else
		bitspersample = 8;

	logImage = logImageCreate(filename, use_cineon, ibuf->x, ibuf->y, bitspersample, (depth == 4),
	                          (ibuf->ftype & CINEON_LOG), -1, -1, -1, "Blender");

	if (logImage == NULL) {
		printf("DPX/Cineon: error creating file.\n");
		return 0;
	}

	if (ibuf->rect_float != NULL && bitspersample != 8) {
		/* don't use the float buffer to save 8 bpp picture to prevent color banding
		 * (there's no dithering algorithm behing the logImageSetDataRGBA function) */

		fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon");

		for (y = 0; y < ibuf->y; y++) {
			float *dst_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x);
			float *src_ptr = ibuf->rect_float + 4 * (y * ibuf->x);

			memcpy(dst_ptr, src_ptr, 4 * ibuf->x * sizeof(float));
		}

		rvalue = (logImageSetDataRGBA(logImage, fbuf, 1) == 0);

		MEM_freeN(fbuf);
	}
	else {
		if (ibuf->rect == NULL)
			IMB_rect_from_float(ibuf);

		fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon");
		if (fbuf == NULL) {
			printf("DPX/Cineon: error allocating memory.\n");
			logImageClose(logImage);
			return 0;
		}
		for (y = 0; y < ibuf->y; y++) {
			for (x = 0; x < ibuf->x; x++) {
				fbuf_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x + x);
				rect_ptr = (unsigned char *)ibuf->rect + 4 * (y * ibuf->x + x);
				fbuf_ptr[0] = (float)rect_ptr[0] / 255.0f;
				fbuf_ptr[1] = (float)rect_ptr[1] / 255.0f;
				fbuf_ptr[2] = (float)rect_ptr[2] / 255.0f;
				fbuf_ptr[3] = (depth == 4) ? ((float)rect_ptr[3] / 255.0f) : 1.0f;
			}
		}
		rvalue = (logImageSetDataRGBA(logImage, fbuf, 0) == 0);
		MEM_freeN(fbuf);
	}

	logImageClose(logImage);
	return rvalue;
}
Пример #8
0
LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPerSample, int hasAlpha,
                        int isLogarithmic, int referenceWhite, int referenceBlack, float gamma,
                        const char *creator)
{
	DpxMainHeader header;
	const char *shortFilename = NULL;
	unsigned char pad[6044];

	LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
	if (dpx == NULL) {
		if (verbose) printf("DPX: Failed to malloc dpx file structure.\n");
		return NULL;
	}

	dpx->width = width;
	dpx->height = height;
	dpx->element[0].bitsPerSample = bitsPerSample;
	dpx->element[0].dataOffset = 8092;
	dpx->element[0].maxValue = powf(2, dpx->element[0].bitsPerSample) - 1.0f;
	dpx->isMSB = 1;
	dpx->numElements = 1;

	switch (bitsPerSample) {
		case 8:
		case 16:
			dpx->element[0].packing = 0;
			break;

		case 10:
		case 12:
			/* Packed Type A padding is the most common 10/12 bits format */
			dpx->element[0].packing = 1;
			break;

		default:
			if (verbose) printf("DPX: bitsPerSample not supported: %d\n", bitsPerSample);
			logImageClose(dpx);
			return NULL;
	}

	if (hasAlpha == 0) {
		dpx->depth = 3;
		dpx->element[0].depth = 3;
		dpx->element[0].descriptor = descriptor_RGB;
	}
	else {
		dpx->depth = 4;
		dpx->element[0].depth = 4;
		dpx->element[0].descriptor = descriptor_RGBA;
	}

	if (isLogarithmic == 0) {
		dpx->element[0].transfer = transfer_Linear;
		dpx->element[0].refHighQuantity = dpx->element[0].maxValue;
	}
	else {
		dpx->element[0].transfer = transfer_PrintingDensity;
		dpx->element[0].refHighQuantity = 2.048f;

	}

	dpx->element[0].refLowQuantity = 0;
	dpx->element[0].refLowData = 0;
	dpx->element[0].refHighData = dpx->element[0].maxValue;

	if (referenceWhite > 0)
		dpx->referenceWhite = referenceWhite;
	else
		dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue;

	if (referenceBlack > 0)
		dpx->referenceBlack = referenceBlack;
	else
		dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue;

	if (gamma > 0.0f)
		dpx->gamma = gamma;
	else
		dpx->gamma = 1.7f;


	shortFilename = strrchr(filename, '/');
	if (shortFilename == NULL)
		shortFilename = filename;
	else
		shortFilename++;

	dpx->file = BLI_fopen(filename, "wb");

	if (dpx->file == NULL) {
		if (verbose) printf("DPX: Couldn't open file %s\n", filename);
		logImageClose(dpx);
		return NULL;
	}

	fillDpxMainHeader(dpx, &header, shortFilename, creator);

	if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) {
		if (verbose) printf("DPX: Couldn't write image header\n");
		logImageClose(dpx);
		return NULL;
	}

	/* Header should be rounded to next 8k block
	 * 6044 = 8092 - sizeof(DpxMainHeader) */
	memset(&pad, 0, 6044);
	if (fwrite(&pad, 6044, 1, dpx->file) == 0) {
		if (verbose) printf("DPX: Couldn't write image header\n");
		logImageClose(dpx);
		return NULL;
	}

	return dpx;
}
Пример #9
0
LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize)
{
	DpxMainHeader header;
	LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
	const char *filename = (const char *)byteStuff;
	int i;

	if (dpx == NULL) {
		if (verbose) printf("DPX: Failed to malloc dpx file structure.\n");
		return NULL;
	}

	/* zero the header */
	memset(&header, 0, sizeof(DpxMainHeader));

	/* for close routine */
	dpx->file = NULL;

	if (fromMemory == 0) {
		/* byteStuff is then the filename */
		dpx->file = BLI_fopen(filename, "rb");
		if (dpx->file == NULL) {
			if (verbose) printf("DPX: Failed to open file \"%s\".\n", filename);
			logImageClose(dpx);
			return NULL;
		}
		/* not used in this case */
		dpx->memBuffer = NULL;
		dpx->memCursor = NULL;
		dpx->memBufferSize = 0;
	}
	else {
		dpx->memBuffer = (unsigned char *)byteStuff;
		dpx->memCursor = (unsigned char *)byteStuff;
		dpx->memBufferSize = bufferSize;
	}

	if (logimage_fread(&header, sizeof(header), 1, dpx) == 0) {
		if (verbose) printf("DPX: Not enough data for header in \"%s\".\n", byteStuff);
		logImageClose(dpx);
		return NULL;
	}

	/* endianness determination */
	if (header.fileHeader.magic_num == swap_uint(DPX_FILE_MAGIC, 1)) {
		dpx->isMSB = 1;
		if (verbose) printf("DPX: File is MSB.\n");
	}
	else if (header.fileHeader.magic_num == DPX_FILE_MAGIC) {
		dpx->isMSB = 0;
		if (verbose) printf("DPX: File is LSB.\n");
	}
	else {
		if (verbose)  {
			printf("DPX: Bad magic number %u in \"%s\".\n",
			       header.fileHeader.magic_num, byteStuff);
		}
		logImageClose(dpx);
		return NULL;
	}

	dpx->srcFormat = format_DPX;
	dpx->numElements = swap_ushort(header.imageHeader.elements_per_image, dpx->isMSB);
	if (dpx->numElements == 0) {
		if (verbose) printf("DPX: Wrong number of elements: %d\n", dpx->numElements);
		logImageClose(dpx);
		return NULL;
	}

	dpx->width = swap_uint(header.imageHeader.pixels_per_line, dpx->isMSB);
	dpx->height = swap_uint(header.imageHeader.lines_per_element, dpx->isMSB);

	if (dpx->width == 0 || dpx->height == 0) {
		if (verbose) printf("DPX: Wrong image dimension: %dx%d\n", dpx->width, dpx->height);
		logImageClose(dpx);
		return NULL;
	}

	dpx->depth = 0;

	for (i = 0; i < dpx->numElements; i++) {
		dpx->element[i].descriptor = header.imageHeader.element[i].descriptor;

		switch (dpx->element[i].descriptor) {
			case descriptor_Red:
			case descriptor_Green:
			case descriptor_Blue:
			case descriptor_Alpha:
			case descriptor_Luminance:
			case descriptor_Chrominance:
				dpx->depth++;
				dpx->element[i].depth = 1;
				break;

			case descriptor_CbYCrY:
				dpx->depth += 2;
				dpx->element[i].depth = 2;
				break;

			case descriptor_RGB:
			case descriptor_CbYCr:
			case descriptor_CbYACrYA:
				dpx->depth += 3;
				dpx->element[i].depth = 3;
				break;

			case descriptor_RGBA:
			case descriptor_ABGR:
			case descriptor_CbYCrA:
				dpx->depth += 4;
				dpx->element[i].depth = 4;
				break;

			case descriptor_Depth:
			case descriptor_Composite:
				/* unsupported */
				break;
		}

		if (dpx->depth == 0 || dpx->depth > 4) {
			if (verbose) printf("DPX: Unsupported image depth: %d\n", dpx->depth);
			logImageClose(dpx);
			return NULL;
		}

		dpx->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample;
		if (dpx->element[i].bitsPerSample != 1 && dpx->element[i].bitsPerSample != 8 &&
		    dpx->element[i].bitsPerSample != 10 && dpx->element[i].bitsPerSample != 12 &&
		    dpx->element[i].bitsPerSample != 16)
		{
			if (verbose) printf("DPX: Unsupported bitsPerSample for elements %d: %d\n", i, dpx->element[i].bitsPerSample);
			logImageClose(dpx);
			return NULL;
		}

		dpx->element[i].maxValue = powf(2, dpx->element[i].bitsPerSample) - 1.0f;

		dpx->element[i].packing = swap_ushort(header.imageHeader.element[i].packing, dpx->isMSB);
		if (dpx->element[i].packing > 2) {
			if (verbose) printf("DPX: Unsupported packing for element %d: %d\n", i, dpx->element[i].packing);
			logImageClose(dpx);
			return NULL;
		}

		/* Sometimes, the offset is not set correctly in the header */
		dpx->element[i].dataOffset = swap_uint(header.imageHeader.element[i].data_offset, dpx->isMSB);
		if (dpx->element[i].dataOffset == 0 && dpx->numElements == 1)
			dpx->element[i].dataOffset = swap_uint(header.fileHeader.offset, dpx->isMSB);

		if (dpx->element[i].dataOffset == 0) {
			if (verbose) printf("DPX: Image header is corrupted.\n");
			logImageClose(dpx);
			return NULL;
		}

		dpx->element[i].transfer = header.imageHeader.element[i].transfer;

		/* if undefined, assign default */
		dpx->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, dpx->isMSB);
		dpx->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity, dpx->isMSB);
		dpx->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data, dpx->isMSB);
		dpx->element[i].refHighQuantity = swap_float(header.imageHeader.element[i].ref_high_quantity, dpx->isMSB);

		switch (dpx->element[i].descriptor) {
			case descriptor_Red:
			case descriptor_Green:
			case descriptor_Blue:
			case descriptor_Alpha:
			case descriptor_RGB:
			case descriptor_RGBA:
			case descriptor_ABGR:
				if (dpx->element[i].refLowData == DPX_UNDEFINED_U32)
					dpx->element[i].refLowData = 0;

				if (dpx->element[i].refHighData == DPX_UNDEFINED_U32)
					dpx->element[i].refHighData = (unsigned int)dpx->element[i].maxValue;

				if (dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refLowQuantity))
					dpx->element[i].refLowQuantity = 0.0f;

				if (dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refHighQuantity)) {
					if (dpx->element[i].transfer == transfer_PrintingDensity || dpx->element[i].transfer == transfer_Logarithmic)
						dpx->element[i].refHighQuantity = 2.048f;
					else
						dpx->element[i].refHighQuantity = dpx->element[i].maxValue;
				}

				break;

			case descriptor_Luminance:
			case descriptor_Chrominance:
			case descriptor_CbYCrY:
			case descriptor_CbYCr:
			case descriptor_CbYACrYA:
			case descriptor_CbYCrA:
				if (dpx->element[i].refLowData == DPX_UNDEFINED_U32)
					dpx->element[i].refLowData = 16.0f / 255.0f * dpx->element[i].maxValue;

				if (dpx->element[i].refHighData == DPX_UNDEFINED_U32)
					dpx->element[i].refHighData = 235.0f / 255.0f * dpx->element[i].maxValue;

				if (dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refLowQuantity))
					dpx->element[i].refLowQuantity = 0.0f;

				if (dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refHighQuantity))
					dpx->element[i].refHighQuantity = 0.7f;

				break;

			default:
				break;
		}
	}

	dpx->referenceBlack = swap_float(header.televisionHeader.black_level, dpx->isMSB);
	dpx->referenceWhite = swap_float(header.televisionHeader.white_level, dpx->isMSB);
	dpx->gamma = swap_float(header.televisionHeader.gamma, dpx->isMSB);

	if ((dpx->referenceBlack == DPX_UNDEFINED_R32 || isnan(dpx->referenceBlack)) ||
	    (dpx->referenceWhite == DPX_UNDEFINED_R32 || dpx->referenceWhite <= dpx->referenceBlack || isnan(dpx->referenceWhite)) ||
	    (dpx->gamma == DPX_UNDEFINED_R32 || dpx->gamma <= 0 || isnan(dpx->gamma)))
	{
		dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue;
		dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue;
		dpx->gamma = 1.7f;
	}

	if (verbose) {
		printf("size %d x %d x %d elements\n", dpx->width, dpx->height, dpx->numElements);
		for (i = 0; i < dpx->numElements; i++) {
			printf(" Element %d:\n", i);
			printf("  Bits per sample: %d\n", dpx->element[i].bitsPerSample);
			printf("  Depth: %d\n", dpx->element[i].depth);
			printf("  Transfer characteristics: %d\n", dpx->element[i].transfer);
			printf("  Packing: %d\n", dpx->element[i].packing);
			printf("  Descriptor: %d\n", dpx->element[i].descriptor);
			printf("  Data offset: %d\n", dpx->element[i].dataOffset);
			printf("  Reference low data: %u\n", dpx->element[i].refLowData);
			printf("  Reference low quantity: %f\n", dpx->element[i].refLowQuantity);
			printf("  Reference high data: %u\n", dpx->element[i].refHighData);
			printf("  Reference high quantity: %f\n", dpx->element[i].refHighQuantity);
			printf("\n");
		}

		printf("Gamma: %f\n", dpx->gamma);
		printf("Reference black: %f\n", dpx->referenceBlack);
		printf("Reference white: %f\n", dpx->referenceWhite);
		printf("----------------------------\n");
	}
	return dpx;
}