mirror of
				https://github.com/quelsolaar/MergeSource
				synced 2025-10-31 01:16:12 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			835 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			835 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #define _CRT_SECURE_NO_WARNINGS
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| #include <stdio.h>
 | |
| #include "hxa.h"
 | |
| #include "hxa_utils.h"
 | |
| 
 | |
| #define FALSE 0
 | |
| #define TRUE !FALSE
 | |
| 
 | |
| char *hxa_aces_type_names[] = {"box2i",
 | |
| 							"chlist",
 | |
| 							"chromaticities",
 | |
| 							"compression",
 | |
| 							"double",
 | |
| 							"float",
 | |
| 							"half",
 | |
| 							"int",
 | |
| 							"lineOrder",
 | |
| 							"keycode",
 | |
| 							"rational",
 | |
| 							"short",
 | |
| 							"string",
 | |
| 							"stringVector",
 | |
| 							"timecode",
 | |
| 							"unsignedChar",
 | |
| 							"unsignedInt",
 | |
| 							"unsignedLong",
 | |
| 							"unsignedShort",
 | |
| 							"v2f",
 | |
| 							"v3f"};
 | |
| unsigned int hxa_aces_type_min_size[] = {16, /* HXA_ACES_ATTRIBUTE_TYPE_BOX2I */
 | |
| 									18, /* HXA_ACES_ATTRIBUTE_TYPE_CHLIST */
 | |
| 									4 * 8, /* HXA_ACES_ATTRIBUTE_TYPE_CHROMATICITIES */
 | |
| 									1, /* HXA_ACES_ATTRIBUTE_TYPE_COMPRESSION */
 | |
| 									8, /* HXA_ACES_ATTRIBUTE_TYPE_DOUBLE */
 | |
| 									4, /* HXA_ACES_ATTRIBUTE_TYPE_FLOAT */
 | |
| 									2, /* HXA_ACES_ATTRIBUTE_TYPE_HALF */
 | |
| 									4, /* HXA_ACES_ATTRIBUTE_TYPE_INT */
 | |
| 									1, /* HXA_ACES_ATTRIBUTE_TYPE_LINEORDER */
 | |
| 									4 * 7, /* HXA_ACES_ATTRIBUTE_TYPE_KEYCODE */
 | |
| 									4 * 2, /* HXA_ACES_ATTRIBUTE_TYPE_RATIONAL */
 | |
| 									2, /* HXA_ACES_ATTRIBUTE_TYPE_SHORT */
 | |
| 									2, /* HXA_ACES_ATTRIBUTE_TYPE_STRING */
 | |
| 									2, /* HXA_ACES_ATTRIBUTE_TYPE_STRINGVECTOR */
 | |
| 									4 * 4, /* HXA_ACES_ATTRIBUTE_TYPE_TIMECODE */
 | |
| 									1, /* HXA_ACES_ATTRIBUTE_TYPE_UNSIGNEDCHAR */
 | |
| 									4, /* HXA_ACES_ATTRIBUTE_TYPE_UNSIGNEDINT */
 | |
| 									8, /* HXA_ACES_ATTRIBUTE_TYPE_UNSIGNEDLONG */
 | |
| 									2, /* HXA_ACES_ATTRIBUTE_TYPE_UNSIGNEDSHORT */
 | |
| 									4 * 2, /* HXA_ACES_ATTRIBUTE_TYPE_V2F */
 | |
| 									4 * 3, /* HXA_ACES_ATTRIBUTE_TYPE_V3F */
 | |
| 									0}; /* HXA_ACES_ATTRIBUTE_TYPE_UNKNOWN */
 | |
| 
 | |
| 
 | |
| 
 | |
| typedef enum{
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_BOX2I,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_CHLIST,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_CHROMATICITIES,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_COMPRESSION,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_DOUBLE,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_HALF,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_INT,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_LINEORDER,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_KEYCODE,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_RATIONAL,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_SHORT,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_STRINGVECTOR,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_TIMECODE,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_UNSIGNEDCHAR,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_UNSIGNEDINT,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_UNSIGNEDLONG,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_UNSIGNEDSHORT,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_V2F,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_V3F,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_COUNT,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_UNKNOWN = HXA_ACES_ATTRIBUTE_TYPE_COUNT,
 | |
| 	HXA_ACES_ATTRIBUTE_TYPE_UNUSED
 | |
| }HxAACESAttributeTypes;
 | |
| 
 | |
| typedef enum{
 | |
|     HXA_ACES_ACPT_UINT32 = 0,
 | |
|     HXA_ACES_ACPT_HALF16 = 1,
 | |
|     HXA_ACES_ACPT_FLOAT32 = 2,
 | |
| }HxAACESAttributeClistPixelType;
 | |
| 
 | |
| typedef struct{
 | |
| 	char name[256];
 | |
| 	HxAACESAttributeClistPixelType pixelType;
 | |
| 	unsigned int pLinear;
 | |
| 	int xSampling;
 | |
| 	int ySampling;
 | |
| }HxAACESAttributeClist;
 | |
| 
 | |
| typedef struct{
 | |
| 	HxAACESAttributeTypes type;
 | |
| 	char name[256];
 | |
| 	union{
 | |
| 		struct{
 | |
| 			int x_min;
 | |
| 			int y_min;
 | |
| 			int x_max;
 | |
| 			int y_max;
 | |
| 		}box2i;
 | |
| 		struct{
 | |
| 			unsigned int length;
 | |
| 			HxAACESAttributeClist *list;
 | |
| 		}chlist;
 | |
| 		struct{
 | |
| 			float redX;
 | |
| 			float redY;
 | |
| 			float greenX;
 | |
| 			float greenY;
 | |
| 			float blueX;
 | |
| 			float blueY;
 | |
| 			float whiteX;
 | |
| 			float whiteY;
 | |
| 		}chromaticities;
 | |
| 		unsigned char compression;
 | |
| 		double type_double;
 | |
| 		float type_float;
 | |
| 		unsigned short type_half;
 | |
| 		unsigned int type_int;
 | |
| 		unsigned char lineOrder;
 | |
| 		struct{
 | |
| 			int filmMfCCode;
 | |
| 			int filmType;
 | |
| 			int prefix;
 | |
| 			int count;
 | |
| 			int perfOffset;
 | |
| 			int perfsPerFrame;
 | |
| 			int perfsPerCount;
 | |
| 		}keycode;
 | |
| 		struct{
 | |
| 			int n;
 | |
| 			unsigned int b;
 | |
| 		}rational;
 | |
| 		short type_short;
 | |
| 		struct{
 | |
| 			char *string;
 | |
| 			unsigned int length;
 | |
| 		}string;
 | |
| 		struct{
 | |
| 			char *string;
 | |
| 			unsigned int length;
 | |
| 		}stringVector;
 | |
| 		struct{
 | |
| 			unsigned int timeAndFlags;
 | |
| 			unsigned int userData;
 | |
| 		}timecode;
 | |
| 		unsigned char unsignedChar;
 | |
| 		unsigned int unsignedInt;
 | |
| 		unsigned long unsignedLong;
 | |
| 		unsigned short unsignedShort;
 | |
| 		float v2f[2];
 | |
| 		float v3f[3];
 | |
| 		struct{
 | |
| 			char *type_name;
 | |
| 			unsigned int length;
 | |
| 			void *data;
 | |
| 		}unknown;
 | |
| 	}data;
 | |
| }HxAACESAttributeType;
 | |
| 
 | |
| 
 | |
| typedef struct{
 | |
| 	char name[256];
 | |
| 	unsigned int channel_count;
 | |
| 	union{
 | |
| 		unsigned short *half_buffer;
 | |
| 		float *float_buffer;
 | |
| 	}pixels;
 | |
| }HxAACESLayer;
 | |
| 
 | |
| typedef struct{
 | |
| 	HxAACESAttributeType *attributes;
 | |
| 	unsigned int attribute_count;
 | |
| 	unsigned int attribute_allocate;
 | |
| 	HxAACESLayer *layers;
 | |
| 	unsigned int layer_count;
 | |
| }HxAACESImage;
 | |
| 
 | |
| typedef struct{
 | |
| 	char *name;
 | |
| 	HxAACESAttributeTypes type;
 | |
| }HxAACESAttributePredefined;
 | |
| 
 | |
| typedef struct{
 | |
| 	unsigned int layer;
 | |
| 	unsigned int channel;
 | |
| 	HxAACESAttributeClistPixelType type;
 | |
| }HxAChannelRead;
 | |
| 
 | |
| //"endOfHeaderOffset", HXA_ACES_ATTRIBUTE_TYPE_UNSIGNED_LONG
 | |
| //"free", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| //"headerChecksum", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| //"imageChecksum", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 
 | |
| #define HXA_ACES_ATTRIBUTES_PREDEFINED 54
 | |
| #define HXA_ACES_ATTRIBUTES_REQUIRED_OPENEXR 8
 | |
| #define HXA_ACES_ATTRIBUTES_REQUIRED_ACES 11
 | |
| #define HXA_ACES_ATTRIBUTES_IGNORE 4
 | |
| 
 | |
| HxAACESAttributePredefined hxa_aces_attribute_predefined[] = {
 | |
| 	/* OpenEXR Required attributes.*/
 | |
| 	"channels", HXA_ACES_ATTRIBUTE_TYPE_CHLIST,
 | |
| 	"compression", HXA_ACES_ATTRIBUTE_TYPE_COMPRESSION,
 | |
| 	"dataWindow", HXA_ACES_ATTRIBUTE_TYPE_BOX2I,
 | |
| 	"displayWindow", HXA_ACES_ATTRIBUTE_TYPE_BOX2I,
 | |
| 	"lineOrder", HXA_ACES_ATTRIBUTE_TYPE_LINEORDER,
 | |
| 	"pixelAspectRatio", HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	"screenWindowCenter", HXA_ACES_ATTRIBUTE_TYPE_V2F,
 | |
| 	"screenWindowWidth", HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	/* ACES Required attributes.*/
 | |
| 	"acesImageContainerFlag", HXA_ACES_ATTRIBUTE_TYPE_INT,
 | |
| 	"adoptedNeutral", HXA_ACES_ATTRIBUTE_TYPE_V2F,
 | |
| 	"chromaticities", HXA_ACES_ATTRIBUTE_TYPE_CHROMATICITIES,
 | |
| 	/* ignore the following*/
 | |
| 	"endOfHeaderOffset", HXA_ACES_ATTRIBUTE_TYPE_UNSIGNEDLONG,
 | |
| 	"free", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"headerChecksum", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"imageChecksum", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	/* make sure the following has right name/type combo */
 | |
| 	"altitude", HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	"aperture", HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	"cameraFirmwareVersion", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"cameraIPAddress", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"cameraLabel", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"cameraMake", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"cameraModel", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"cameraOrientation", HXA_ACES_ATTRIBUTE_TYPE_V3F,
 | |
| 	"comments", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"convergenceDistance", HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	"creator", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"expTime", HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	"focalLength", HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	"focus", HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	"framesPerSecond", HXA_ACES_ATTRIBUTE_TYPE_RATIONAL,
 | |
| 	"imageCounter", HXA_ACES_ATTRIBUTE_TYPE_INT,
 | |
| 	"imageRotation", HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	"interocularDistance", HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	"isoSpeed", HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	"keyCode", HXA_ACES_ATTRIBUTE_TYPE_KEYCODE,
 | |
| 	"latitude", HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	"lensAttributes", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"lensMake", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"lensModel", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"lensSerialNumber", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"longitude", HXA_ACES_ATTRIBUTE_TYPE_FLOAT,
 | |
| 	"multiView", HXA_ACES_ATTRIBUTE_TYPE_STRINGVECTOR,
 | |
| 	"originalImageFlag", HXA_ACES_ATTRIBUTE_TYPE_INT, // Support
 | |
| 	"owner", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"recorderFirmwareVersion", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"recorderMake", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"recorderModel", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"recorderSerialNumber", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"reelName", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"storageMediaSerialNumber", HXA_ACES_ATTRIBUTE_TYPE_STRING,
 | |
| 	"timeCode", HXA_ACES_ATTRIBUTE_TYPE_TIMECODE,
 | |
| 	"timecodeRate", HXA_ACES_ATTRIBUTE_TYPE_INT, 
 | |
| 	"utcOffset", HXA_ACES_ATTRIBUTE_TYPE_FLOAT, 
 | |
| 	"uuid", HXA_ACES_ATTRIBUTE_TYPE_STRING};
 | |
| 
 | |
| #define hxa_aces_copy16(a, b) memcpy(a, b, 2)
 | |
| #define hxa_aces_copy32(a, b) memcpy(a, b, 4)
 | |
| #define hxa_aces_copy64(a, b) memcpy(a, b, 8)
 | |
| 
 | |
| void hxa_util_aces_header_attribute_free(HxAACESAttributeType *attrib_array, unsigned int attrib_count)
 | |
| {
 | |
| 	unsigned int i;
 | |
| 	for(i = 0; i < attrib_count; i++)
 | |
| 	{
 | |
| 		switch(attrib_array[i].type)
 | |
| 		{
 | |
| 			case HXA_ACES_ATTRIBUTE_TYPE_CHLIST :
 | |
| 				free(attrib_array[i].data.chlist.list);
 | |
| 			break;
 | |
| 			case HXA_ACES_ATTRIBUTE_TYPE_STRING :
 | |
| 				free(attrib_array[i].data.string.string);
 | |
| 			break;
 | |
| 			case HXA_ACES_ATTRIBUTE_TYPE_STRINGVECTOR :
 | |
| 				free(attrib_array[i].data.stringVector.string);
 | |
| 			break;
 | |
| 			case HXA_ACES_ATTRIBUTE_TYPE_UNKNOWN :
 | |
| 				free(attrib_array[i].data.unknown.type_name);
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 	free(attrib_array);
 | |
| }
 | |
| 
 | |
| int hxa_util_aces_header_parse(HxAACESAttributeType **attrib_array, unsigned int *attrib_count, unsigned int *attrib_allocated, char *type, char *name, int length, unsigned char *data, int silent)
 | |
| {
 | |
| 	HxAACESAttributeTypes aces_type;
 | |
| 	unsigned int i, pos = 0, pre_define;
 | |
| 	HxAACESAttributeType *attribute;
 | |
| 	for(aces_type = 0; aces_type < HXA_ACES_ATTRIBUTE_TYPE_COUNT; aces_type++)
 | |
| 	{
 | |
| 		for(i = 0; hxa_aces_type_names[aces_type][i] == type[i] && type[i] != 0; i++);
 | |
| 		if(hxa_aces_type_names[aces_type][i] == type[i])
 | |
| 			break;
 | |
| 	}
 | |
| 	for(pre_define = 0; pre_define < HXA_ACES_ATTRIBUTES_PREDEFINED; pre_define++)
 | |
| 	{
 | |
| 		for(i = 0; hxa_aces_attribute_predefined[pre_define].name[i] == name[i] && name[i] != 0; i++);
 | |
| 		if(hxa_aces_attribute_predefined[pre_define].name[i] == name[i])
 | |
| 		{
 | |
| 			if(hxa_aces_attribute_predefined[pre_define].type != aces_type)
 | |
| 			{
 | |
| 				if(!silent)
 | |
| 					printf("HxA Error: Predefined attibute %s found to have wrong type: %s. Standard requires attribute %s to be of type %s\n", name, hxa_aces_type_names[aces_type], name, hxa_aces_type_names[hxa_aces_attribute_predefined[pre_define].type]);
 | |
| 				return FALSE;
 | |
| 			}
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 	if(pre_define >= HXA_ACES_ATTRIBUTES_REQUIRED_OPENEXR && pre_define < HXA_ACES_ATTRIBUTES_REQUIRED_OPENEXR + HXA_ACES_ATTRIBUTES_IGNORE)
 | |
| 		return TRUE;
 | |
| 
 | |
| 	if(hxa_aces_type_min_size[aces_type] > length)
 | |
| 	{
 | |
| 		if(!silent)
 | |
| 			printf("HxA Error: Attibute %s of type %s only has %u bytes of storage but require at least %u bytes.\n", name, type, length, hxa_aces_type_min_size[aces_type]);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 	if(pre_define < HXA_ACES_ATTRIBUTES_REQUIRED_OPENEXR)
 | |
| 		attribute = &(*attrib_array)[pre_define];
 | |
| 	else if(*attrib_count < *attrib_allocated)
 | |
| 		attribute = &(*attrib_array)[(*attrib_count)++];
 | |
| 	else
 | |
| 	{
 | |
| 		*attrib_allocated += 16;
 | |
| 		*attrib_array = realloc(*attrib_array, (sizeof *attribute) * *attrib_allocated);			
 | |
| 		attribute = &(*attrib_array)[(*attrib_count)++];
 | |
| 	}
 | |
| 
 | |
| 	for(i = 0; name[i] != 0; i++)
 | |
| 		attribute->name[i] = name[i];
 | |
| 	attribute->name[i] = 0;
 | |
| 	attribute->type = aces_type;
 | |
| 	switch(aces_type)
 | |
| 	{
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_BOX2I :
 | |
| 			hxa_aces_copy32(&attribute->data.box2i.x_min, &data[0]);
 | |
| 			hxa_aces_copy32(&attribute->data.box2i.y_min, &data[4]);
 | |
| 			hxa_aces_copy32(&attribute->data.box2i.x_max, &data[8]);
 | |
| 			hxa_aces_copy32(&attribute->data.box2i.y_max, &data[12]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_CHLIST :
 | |
| 			attribute->data.chlist.length = 0;
 | |
| 			attribute->data.chlist.list = malloc((sizeof *attribute->data.chlist.list) * (length / (2 + 4 + 4 + 4 + 4)));
 | |
| 			while(data[pos] != 0)
 | |
| 			{
 | |
| 				for(i = 0; i < 255 && pos + 16 < length && data[pos] != 0; i++)
 | |
| 					attribute->data.chlist.list[attribute->data.chlist.length].name[i] = data[pos++];
 | |
| 				if(i >= 255 || pos + 16 + 1 > length)
 | |
| 				{
 | |
| 					if(!silent)
 | |
| 						printf("HxA Error: Attibute %s of type clist is not correctly null terminated\n", name);
 | |
| 					return FALSE;
 | |
| 				}
 | |
| 				pos++;
 | |
| 				attribute->data.chlist.list[attribute->data.chlist.length].name[i] = 0;
 | |
| 				hxa_aces_copy32(&attribute->data.chlist.list[attribute->data.chlist.length].pixelType, &data[pos]);
 | |
| 				hxa_aces_copy32(&attribute->data.chlist.list[attribute->data.chlist.length].pLinear, &data[pos + 4]);
 | |
| 				hxa_aces_copy32(&attribute->data.chlist.list[attribute->data.chlist.length].xSampling, &data[pos + 8]);
 | |
| 				hxa_aces_copy32(&attribute->data.chlist.list[attribute->data.chlist.length].ySampling, &data[pos + 12]);
 | |
| 				pos += 16;
 | |
| 				attribute->data.chlist.length++;
 | |
| 			}
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_CHROMATICITIES :
 | |
| 			hxa_aces_copy32(&attribute->data.chromaticities.redX, &data[0]);
 | |
| 			hxa_aces_copy32(&attribute->data.chromaticities.redY, &data[4]);
 | |
| 			hxa_aces_copy32(&attribute->data.chromaticities.greenX, &data[8]);
 | |
| 			hxa_aces_copy32(&attribute->data.chromaticities.greenY, &data[12]);
 | |
| 			hxa_aces_copy32(&attribute->data.chromaticities.blueX, &data[16]);
 | |
| 			hxa_aces_copy32(&attribute->data.chromaticities.blueY, &data[20]);
 | |
| 			hxa_aces_copy32(&attribute->data.chromaticities.whiteX, &data[24]);
 | |
| 			hxa_aces_copy32(&attribute->data.chromaticities.whiteY, &data[28]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_COMPRESSION :
 | |
| 			attribute->data.compression = data[0];
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_DOUBLE :
 | |
| 			hxa_aces_copy64(&attribute->data.type_double, &data[0]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_FLOAT :
 | |
| 			hxa_aces_copy32(&attribute->data.type_float, &data[0]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_HALF :
 | |
| 			hxa_aces_copy16(&attribute->data.box2i.x_min, &data[0]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_INT :
 | |
| 			hxa_aces_copy32(&attribute->data.type_int, &data[0]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_LINEORDER :
 | |
| 			attribute->data.lineOrder = data[0];
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_KEYCODE :
 | |
| 			hxa_aces_copy32(&attribute->data.keycode.filmMfCCode, &data[0]);
 | |
| 			hxa_aces_copy32(&attribute->data.keycode.filmType, &data[4]);
 | |
| 			hxa_aces_copy32(&attribute->data.keycode.prefix, &data[8]);
 | |
| 			hxa_aces_copy32(&attribute->data.keycode.count, &data[12]);
 | |
| 			hxa_aces_copy32(&attribute->data.keycode.perfOffset, &data[16]);
 | |
| 			hxa_aces_copy32(&attribute->data.keycode.perfsPerFrame, &data[20]);
 | |
| 			hxa_aces_copy32(&attribute->data.keycode.perfsPerCount, &data[24]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_RATIONAL :
 | |
| 			hxa_aces_copy32(&attribute->data.rational.n, &data[0]);
 | |
| 			hxa_aces_copy32(&attribute->data.rational.b, &data[4]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_SHORT :
 | |
| 			hxa_aces_copy16(&attribute->data.type_short, &data[0]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_STRING :
 | |
| 			attribute->data.string.length = length;
 | |
| 			attribute->data.string.string = malloc(length + 1);
 | |
| 			memcpy(attribute->data.string.string, data, length);
 | |
| 			attribute->data.string.string[length] = 0;
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_STRINGVECTOR :
 | |
| 			attribute->data.string.length = length;
 | |
| 			attribute->data.string.string = malloc(length + 1);
 | |
| 			memcpy(attribute->data.string.string, data, length);
 | |
| 			attribute->data.string.string[length] = 0;
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_TIMECODE :
 | |
| 			hxa_aces_copy32(&attribute->data.timecode.timeAndFlags, &data[0]);
 | |
| 			hxa_aces_copy32(&attribute->data.timecode.userData, &data[4]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_UNSIGNEDCHAR :
 | |
| 			attribute->data.unsignedChar = data[0];
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_UNSIGNEDINT :
 | |
| 			hxa_aces_copy32(&attribute->data.unsignedInt, &data[0]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_UNSIGNEDLONG :
 | |
| 			hxa_aces_copy64(&attribute->data.unsignedLong, &data[0]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_UNSIGNEDSHORT :
 | |
| 			hxa_aces_copy16(&attribute->data.unsignedShort, &data[0]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_V2F :
 | |
| 			hxa_aces_copy32(&attribute->data.v2f[0], &data[0]);
 | |
| 			hxa_aces_copy32(&attribute->data.v2f[1], &data[4]);
 | |
| 		return TRUE;
 | |
| 		case HXA_ACES_ATTRIBUTE_TYPE_V3F :
 | |
| 			hxa_aces_copy32(&attribute->data.v3f[0], &data[0]);
 | |
| 			hxa_aces_copy32(&attribute->data.v3f[1], &data[4]);
 | |
| 			hxa_aces_copy32(&attribute->data.v3f[2], &data[8]);
 | |
| 		return TRUE;
 | |
| 		case  HXA_ACES_ATTRIBUTE_TYPE_UNKNOWN :
 | |
| 			for(i = 0; type[i] != 0; i++);
 | |
| 			attribute->data.unknown.type_name = malloc(++i + length);
 | |
| 			memcpy(attribute->data.unknown.type_name, type, i);
 | |
| 			attribute->data.unknown.data = &attribute->data.unknown.type_name[i];
 | |
| 			attribute->data.unknown.length = length;
 | |
| 			memcpy(attribute->data.unknown.data, data, length);
 | |
| 		return TRUE;
 | |
| 	}
 | |
| 	return FALSE;
 | |
| }
 | |
| 
 | |
| char *hxa_util_aces_file_load(char *file_name, size_t *size)
 | |
| {
 | |
| 	char *buffer;
 | |
| 	unsigned int allocation, i;
 | |
| 	FILE *f;
 | |
| 	f = fopen(file_name, "rb");
 | |
| 	if(f == NULL)
 | |
| 	{
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	fseek(f, 0, SEEK_END);
 | |
| 	allocation = ftell(f);
 | |
| 	rewind(f);
 | |
| 	buffer = malloc(allocation + 1);
 | |
| 	memset(buffer, 0, allocation + 1);
 | |
| 	fread(buffer, 1, allocation, f);
 | |
| 	i = ftell(f);
 | |
| 	fclose(f);
 | |
| 	buffer[allocation] = 0;
 | |
| 	if(size != NULL)
 | |
| 		*size = allocation;
 | |
| 	return buffer;
 | |
| }
 | |
| 
 | |
| 
 | |
| float hxa_util_aces_float16_to_float32(unsigned short value)
 | |
| {
 | |
| 	union { int integer; float real; }convert;
 | |
| 	int sign, exponent, sig;
 | |
| 	sign = (value >> 15) & 0x00000001;
 | |
| 	exponent = (value >> 10) & 0x0000001f;
 | |
| 	sig = value & 0x000003ff;
 | |
| 
 | |
| 	if (exponent == 0)
 | |
| 	{
 | |
| 		if (sig == 0)
 | |
| 		{
 | |
| 			convert.integer = sign << 31;
 | |
| 			return convert.real;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			while (!(sig & 0x00000400))
 | |
| 			{
 | |
| 				sig <<= 1;
 | |
| 				exponent -= 1;
 | |
| 			}
 | |
| 			exponent += 1;
 | |
| 			sig &= ~0x00000400;
 | |
| 		}
 | |
| 	}
 | |
| 	else if (exponent == 31)
 | |
| 	{
 | |
| 		if (sig == 0)
 | |
| 		{
 | |
| 			convert.integer = (sign << 31) | 0x7f800000;
 | |
| 			return convert.real;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			convert.integer = (sign << 31) | 0x7f800000 | (sig << 13);
 | |
| 			return convert.real;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	exponent = exponent + (127 - 15);
 | |
| 	sig = sig << 13;
 | |
| 
 | |
| 	convert.integer = (sign << 31) | (exponent << 23) | sig;
 | |
| 	return convert.real;
 | |
| }
 | |
| 
 | |
| int hxa_util_aces_scanline(HxAACESImage *image, unsigned char *data, size_t size, unsigned int x, unsigned int y, HxAChannelRead *channel_reads, int silent, int convert)
 | |
| {
 | |
| 	unsigned int i, j, pos = 0, line, line_size, stride;
 | |
| 	unsigned short *uint16_read, *uint16_write;
 | |
| 	float *float32_read, *float32_write;
 | |
| 	if(size < 8)
 | |
| 	{
 | |
| 		if(!silent)
 | |
| 			printf("HxA Error: .\n");
 | |
| 		return FALSE;			
 | |
| 	}
 | |
| 	hxa_aces_copy32(&line, &data[pos]);
 | |
| 	hxa_aces_copy32(&line_size, &data[pos + 4]);
 | |
| 	pos += 8;
 | |
| 	for(i = 0; i < image->attributes[0].data.chlist.length; i++)
 | |
| 	{
 | |
| 	/*	channel_reads[i].layer;
 | |
| 		channel_reads[i].channel;
 | |
| 		channel_reads[i].type;*/
 | |
| 		stride = image->layers[channel_reads[i].layer].channel_count;
 | |
| 		float32_write = &image->layers[channel_reads[i].layer].pixels.float_buffer[stride * line * x + channel_reads[i].channel];
 | |
| 		uint16_read = &data[pos];
 | |
| 		for(j = 0; j < x; j++)
 | |
| 		{
 | |
| 			*float32_write = hxa_util_aces_float16_to_float32(*uint16_read++);
 | |
| 			float32_write += stride;
 | |
| 		}
 | |
| 		pos += x * sizeof(short);
 | |
| 	}	
 | |
| 	return TRUE;		
 | |
| }
 | |
| 
 | |
| void hxa_util_aces_free(HxAACESImage *image)
 | |
| {
 | |
| 	unsigned int i;
 | |
| 	hxa_util_aces_header_attribute_free(image->attributes, image->attribute_count);
 | |
| 	for(i = 0; i < image->layer_count; i++)
 | |
| 		if(image->layers[i].pixels.float_buffer != NULL)
 | |
| 			free(image->layers[i].pixels.float_buffer);
 | |
| 	free(image->layers);
 | |
| 	free(image);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| void hxa_util_aces_channel_list(HxAACESImage *file, HxAACESAttributeClist *list, unsigned int list_length, HxAChannelRead *reads, unsigned int silent)
 | |
| {
 | |
| 	char channel_names[] = {'R', 'G', 'B', 'A', 'X', 'Y', 'Z'};
 | |
| 	int period;
 | |
| 	unsigned int i, j, k, channel;
 | |
| 	file->layers = malloc((sizeof *file->layers) * list_length);
 | |
| 	file->layer_count = 0;	 
 | |
| 	for(i = 0; i < list_length; i++)
 | |
| 	{
 | |
| 		period = FALSE;
 | |
| 		channel = 0;
 | |
| 		for(j = 0; list[i].name[j] != 0; j++)	
 | |
| 			if(list[i].name[j] == '.')
 | |
| 				period = TRUE;
 | |
| 		if(j == 1 || period)
 | |
| 		{
 | |
| 			for(k = 0; k < 7; k++)
 | |
| 			{
 | |
| 				if(list[i].name[j - 1] == channel_names[k])
 | |
| 				{
 | |
| 					period = TRUE;
 | |
| 					list[i].name[j - 1] = 0;
 | |
| 					channel = k % 4;
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		if(period)
 | |
| 		{
 | |
| 			for(j = 0; j < file->layer_count; j++)
 | |
| 			{
 | |
| 				for(k = 0; list[i].name[k] != 0 && list[i].name[k] == file->layers[j].name[k]; k++);
 | |
| 				if(list[i].name[k] == file->layers[j].name[k])
 | |
| 					break;
 | |
| 			}
 | |
| 		}else
 | |
| 			j = file->layer_count;
 | |
| 		if(j == file->layer_count)
 | |
| 		{
 | |
| 			file->layer_count++;
 | |
| 			for(k = 0; k < list[i].name[k]; k++)
 | |
| 				file->layers[j].name[k] = list[i].name[k];
 | |
| 			file->layers[j].name[k] = 0;
 | |
| 			file->layers[j].channel_count = channel + 1;
 | |
| 		}
 | |
| 		else
 | |
| 			if(channel + 1 > file->layers[j].channel_count) 
 | |
| 				file->layers[j].channel_count = channel + 1;
 | |
| 
 | |
| 		reads[i].layer = j;
 | |
| 		reads[i].channel = channel;
 | |
| 		reads[i].type = list[i].pixelType;
 | |
| 	}
 | |
| 	for(i = 0; i < file->layer_count; i++)
 | |
| 	{
 | |
| 		file->layers[i].pixels.float_buffer = malloc(sizeof(float) * file->layers[j].channel_count * (unsigned int)(file->attributes[2].data.box2i.x_max + 1 - file->attributes[2].data.box2i.x_min) * (unsigned int)(file->attributes[2].data.box2i.y_max + 1 - file->attributes[2].data.box2i.y_min));
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| HxAACESImage *hxa_util_aces_load(char *file_path, int silent)
 | |
| {
 | |
| 	unsigned char *data;
 | |
| 	size_t size, pos;
 | |
| 	unsigned long long offset;
 | |
| 	unsigned int i, magic_number = 0, version = 0, x, y;
 | |
| 	HxAChannelRead *channel_reads, channel_reads_buffer[64];
 | |
| 	HxAACESAttributeType *attrib_array;
 | |
| 	HxAACESImage *image;
 | |
| 	unsigned int attribute_count, attrib_allocated = HXA_ACES_ATTRIBUTES_PREDEFINED;
 | |
| 	attribute_count = HXA_ACES_ATTRIBUTES_REQUIRED_ACES;
 | |
| 	data = hxa_util_aces_file_load(file_path, &size);
 | |
| 	if(data == NULL)
 | |
| 	{
 | |
| 		if(!silent)
 | |
| 			printf("HxA Error: File %s not found.\n", file_path);
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 	if(size < 4)
 | |
| 	{
 | |
| 		if(!silent)
 | |
| 			printf("HxA Error: Unexpected end of file found.\n");
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 	hxa_aces_copy32(&magic_number, data);
 | |
| 	if(magic_number != 20000630)
 | |
| 	{
 | |
| 		if(!silent)
 | |
| 			printf("HxA Error: Filw is not a valid OpenEXR/ACES file (wrong magic number).\n");
 | |
| 		return FALSE;
 | |
| 	}
 | |
| 	pos = 4;
 | |
| 	hxa_aces_copy32(&version, &data[pos]);
 | |
| 
 | |
| /*	if(magic_number != 20000630)
 | |
| 	{
 | |
| 		if(!silent)
 | |
| 			printf("HxA Error: Filw is not a valid OpenEXR/ACES file (wrong magic number).\n");
 | |
| 		return FALSE;
 | |
| 	}*/
 | |
| 	pos += 4;
 | |
| 	attrib_array = malloc((sizeof *attrib_array) * attrib_allocated);
 | |
| 	for(i = 0; i < HXA_ACES_ATTRIBUTES_REQUIRED_ACES; i++)
 | |
| 		attrib_array[i].type = HXA_ACES_ATTRIBUTE_TYPE_UNUSED;
 | |
| 	while(data[pos] != 0)
 | |
| 	{
 | |
| 		char name[256], type[256];
 | |
| 		int length;
 | |
| 		for(i = 0; data[pos] != 0; i++)
 | |
| 		{
 | |
| 			if(i == 255)
 | |
| 			{
 | |
| 				name[255] = 0; 
 | |
| 				if(!silent)
 | |
| 					printf("HxA Error: File attribute <%s> is not termnated\n", name);
 | |
| 				hxa_util_aces_header_attribute_free(attrib_array, attribute_count);
 | |
| 				return NULL;
 | |
| 			}
 | |
| 			name[i] = data[pos++];
 | |
| 		}
 | |
| 		name[i] = 0;
 | |
| 		pos++;
 | |
| 		for(i = 0; data[pos] != 0; i++)
 | |
| 		{
 | |
| 			if(i == 255)
 | |
| 			{
 | |
| 				type[255] = 0; 
 | |
| 				if(!silent)
 | |
| 					printf("HxA Error: File attribute %s has a non termnated type <%s>\n", name, type);
 | |
| 				hxa_util_aces_header_attribute_free(attrib_array, attribute_count);
 | |
| 				return NULL;
 | |
| 			}
 | |
| 			type[i] = data[pos++];
 | |
| 		}
 | |
| 		type[i] = 0;
 | |
| 		pos++;
 | |
| 		memcpy(&length, &data[pos], 4);
 | |
| 		if(length < 0 || length > 1024 * 1024 + 4 - pos)
 | |
| 		{
 | |
| 			if(!silent)
 | |
| 				printf("HxA Error: Unexpected end of file at attribute %s with length <%u>\n", name, length);
 | |
| 			hxa_util_aces_header_attribute_free(attrib_array, attribute_count);
 | |
| 			return NULL;
 | |
| 		}
 | |
| 		pos += 4;
 | |
| 		if(!hxa_util_aces_header_parse(&attrib_array, &attribute_count, &attrib_allocated, type, name, length, &data[pos], silent))
 | |
| 		{
 | |
| 			hxa_util_aces_header_attribute_free(attrib_array, attribute_count);
 | |
| 			return NULL;
 | |
| 		}	
 | |
| 		printf("name %s type %s\n", name, type);
 | |
| 		pos += length;
 | |
| 	}
 | |
| 	pos++;
 | |
| 	if(attrib_array[0].type != HXA_ACES_ATTRIBUTE_TYPE_CHLIST)
 | |
| 	{
 | |
| 		if(!silent)
 | |
| 			printf("HxA Error: no chanel list found in file.\n");
 | |
| 		hxa_util_aces_header_attribute_free(attrib_array, attribute_count);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	if(attrib_array[1].type != HXA_ACES_ATTRIBUTE_TYPE_COMPRESSION)
 | |
| 	{
 | |
| 		if(!silent)
 | |
| 			printf("HxA Error: no compression attribute found in file.\n");
 | |
| 		hxa_util_aces_header_attribute_free(attrib_array, attribute_count);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	if(attrib_array[1].data.compression != 0)
 | |
| 	{
 | |
| 		if(!silent)
 | |
| 			printf("HxA Error: The compression (%u) in this file is not supported by ACES. ACES Only supports uncompressed files (0).\n", (unsigned int)attrib_array[1].data.compression);
 | |
| 		hxa_util_aces_header_attribute_free(attrib_array, attribute_count);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	if(attrib_array[2].type != HXA_ACES_ATTRIBUTE_TYPE_BOX2I)
 | |
| 	{
 | |
| 		if(!silent)
 | |
| 			printf("HxA Error: no data window found in file.\n");
 | |
| 		hxa_util_aces_header_attribute_free(attrib_array, attribute_count);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	if(attrib_array[2].data.box2i.x_max < attrib_array[2].data.box2i.x_min || attrib_array[2].data.box2i.y_max < attrib_array[2].data.box2i.y_min)
 | |
| 	{
 | |
| 		if(!silent)
 | |
| 			printf("HxA Error: File has negative image size.\n");
 | |
| 		hxa_util_aces_header_attribute_free(attrib_array, attribute_count);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	image = malloc(sizeof *image);
 | |
| 	image->attributes = attrib_array;
 | |
| 	image->attribute_allocate = attrib_allocated;
 | |
| 	image->attribute_count = attribute_count;
 | |
| 	x = (unsigned int)(attrib_array[2].data.box2i.x_max + 1 - attrib_array[2].data.box2i.x_min);
 | |
| 	y = (unsigned int)(attrib_array[2].data.box2i.y_max + 1 - attrib_array[2].data.box2i.y_min);
 | |
| 	if(attrib_array[0].data.chlist.length <= 64)
 | |
| 		channel_reads = channel_reads_buffer;
 | |
| 	else
 | |
| 		channel_reads = malloc((sizeof *channel_reads) * attrib_array[0].data.chlist.length);
 | |
| 	hxa_util_aces_channel_list(image, attrib_array[0].data.chlist.list, attrib_array[0].data.chlist.length, channel_reads, silent);
 | |
| 
 | |
| 	if(pos + y * 8 > size)
 | |
| 	{
 | |
| 		if(!silent)
 | |
| 			printf("HxA Error: Unexpected end of file in scanline table.\n");
 | |
| 		hxa_util_aces_free(image);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 
 | |
| 	for(i = 0; i < y; i++)
 | |
| 	{
 | |
| 		{
 | |
| 			unsigned char values[8];
 | |
| 			int j;
 | |
| 			hxa_aces_copy64(&values, &data[pos + i * 8]);
 | |
| 			printf("offset %u [%u + %u * 8]", pos + i * 8, pos, i);
 | |
| 			for(j = 0; j < 8; j++)
 | |
| 				printf(" %u", (unsigned int)values[j]);
 | |
| 			printf("\n");
 | |
| 		}
 | |
| 
 | |
| 		hxa_aces_copy64(&offset, &data[pos + i * 8]);
 | |
| 		if(size < offset)
 | |
| 		{
 | |
| 			if(!silent)
 | |
| 				printf("HxA Error: Scanline table points to a position outside file\n");
 | |
| 			hxa_util_aces_free(image);
 | |
| 			return NULL;
 | |
| 		}
 | |
| 		if(!hxa_util_aces_scanline(image, &data[offset], size - offset, x, y, channel_reads, silent, FALSE))
 | |
| 		{
 | |
| 			if(!silent)
 | |
| 				printf("HxA Error: File has negative image size.\n");
 | |
| 			hxa_util_aces_free(image);
 | |
| 			return NULL;
 | |
| 		}
 | |
| 	}
 | |
| 	if(channel_reads != channel_reads_buffer)
 | |
| 		free(channel_reads);
 | |
| 	return image;
 | |
| }
 | |
| 
 | |
| 
 | |
| void *hxa_util_aces_load_test(char *file_path, int silent, unsigned int *x, unsigned int *y)
 | |
| {
 | |
| 	HxAACESImage *image;
 | |
| 	image = hxa_util_aces_load(file_path, TRUE);	
 | |
| 	*x = (unsigned int)(image->attributes[2].data.box2i.x_max + 1 - image->attributes[2].data.box2i.x_min);
 | |
| 	*y = (unsigned int)(image->attributes[2].data.box2i.y_max + 1 - image->attributes[2].data.box2i.y_min);
 | |
| 	return image->layers[0].pixels.float_buffer;
 | |
| } |