X-Git-Url: https://www.kengrimes.com/gitweb/?p=henge%2Fapc.git;a=blobdiff_plain;f=src%2Fbinaryout.c;fp=src%2Fbinaryout.c;h=ee82c6f99ad56a3c1e2b90db0ee8e5458f9a56ba;hp=0000000000000000000000000000000000000000;hb=db01318a8e246249ceea23255a6512ea8a5c00c2;hpb=2d355679ac2a1e225f158ab8064566174e9e1402 diff --git a/src/binaryout.c b/src/binaryout.c new file mode 100644 index 0000000..ee82c6f --- /dev/null +++ b/src/binaryout.c @@ -0,0 +1,833 @@ +/* Standard */ +#include //exit, malloc +#include //print +#include //va_args +#include //memset, str* +#include +/* Unicode */ +#include //u8_* functions +#include //uint8_t as a char +#include //u32_cpy +#include //ulc_fprintf +/* Local */ +#include "print.h" +#include "apc.h" +#include "ir.h" +#include "pagenode.h" +#undef do_error +#define do_error(...) exit(-1) +#define XXH_PRIVATE_API +#include "../xxHash/xxhash.h" +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + +/* Public */ +void ir_binout_init(struct ir_class_t*); + +/* Memory Allocation */ +#define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T))) +static +struct pagelist_t linkpages, datapages; + +enum model_type { SS }; +/* Binaryout out structure definitions */ +struct bin_img_info_t { + int height; + int width; + int fwidth; //map and frame width + int fheight; //map and frame height + int unaligned_width; + int unaligned_height; +}; +struct bin_ht_header_t { + long start; + int entries; +}; +struct bin_ht_entry_t { + uint32_t key; + long value; +}; +struct bin_class_header_t { + struct bin_ht_header_t child_ht; + struct bin_ht_header_t rootset_ht; + int namelen; +}; +struct bin_set_header_t { + struct bin_ht_header_t child_ht; + long sdat_start; //points to setdata_header + int namelen; +}; +struct bin_setdata_header_t { + struct bin_ht_header_t variant_ht; + long attach_pos; +}; +struct bin_model_header_t { //one for each framebox, currently + long facing_array_start; + enum model_type type; +}; +struct bin_frame_header_t { + int width; + int height; + int frames; + long op_start; +}; +struct bin_plink_t { + enum ltype type; + ir_set trg_set; + uint8_t* name; + long src_pos; +}; +struct bin_pixel_t { + int x, y, z; + uint32_t ref; +}; +struct bin_pixel_node_t { + struct bin_pixel_node_t* next; + struct bin_pixel_t data; +}; +struct bin_op_t { + int x; + int y; + int attach_idx; +}; +struct bin_attachment_header_t { + int num_attachment_lists; + int num_attachments; +}; +struct bin_attachment_t { + int idx; + ir_set set; +}; +/* Read out of the als, after first ir pass, resolves the + attach_pos of the src-set that created the attachment_list + to the header that describes the attachment_list */ +struct bin_attachment_list_t { + int num_attachments; + struct bin_attachment_t** attachments; + long filepos; +}; + +struct bin_attachment_list_t **attachment_stack, **asp; //attachment_stack, attachment_stack_pointer +FILE* binaryout; + + + +#define NAMEHASH(name, domain) (XXH32(name, u8_strlen(name), 0XCEED ) & domain) + +/* Given a position and a size, checks if the bytes are null and returns + the file position to where it started. 1 if not null, 0 if null*/ +/* TODO: Determine why fseeking file past end sets bytes to -1, and not 0 */ +static inline +int bytes_null( int len, int pos ) +{ while(len--) + { if(fgetc(binaryout) > 0) + { fseek(binaryout, pos, SEEK_SET); + return 1; + } + } + fseek(binaryout, pos, SEEK_SET); + return 0; +} +/* Checks if the key at entrypos is the same as the parameter key. Returns + 1 if so, 0 if not. */ +static inline +int bin_keys_identical +( long entry_pos, + uint32_t key +) +{ uint32_t curr_key; + fseek(binaryout, entry_pos, SEEK_SET); + fscanf(binaryout, "%u", &curr_key); + if( curr_key == key) + return 1; + return 0; +} + +long bin_traverse_class(ir_class); +/* Takes root class and begins processing */ +void +ir_binout_init(ir_class root_class) +{ binaryout = fopen("binaryout", "w+"); + asp = attachment_stack; + pagelist_init(datapages, (size_t) SYS_PAGESIZE); + pagelist_init(linkpages, (size_t) SYS_PAGESIZE); + bin_traverse_class(root_class); +} + +#define ENTRY_OCCUPIED() (bytes_null(sizeof(ht_entry->key), entry_pos)) +#define WRITE_ENTRY() do { \ + if(fseek(binaryout, entry_pos, SEEK_SET) == -1) wprintf("fseek failed with %s", strerror(errno)); \ + fwrite(&ht_entry, sizeof ht_entry, 1, binaryout); \ + } while (0) +#define LOOP_ENTRY(_HTSTART) (entry_pos = _HTSTART) +#define INC_ENTRY() do { \ + entry_pos += sizeof(ht_entry); \ + if(fseek(binaryout, entry_pos, SEEK_SET) == -1) eprintf("fseek failed with %s", strerror(errno)); \ + } while (0) +#define HT_END(_HTEND) (entry_pos >= _HTEND) //just in case at last entry +void +/* TODO: Should overwrite be a default? */ +bin_insert_ht_entry +( long ht_start, + long ht_size, + struct bin_ht_entry_t* ht_entry, + int overwrite +) +{ long entry_pos, ht_end; + + ht_end = ht_start + ht_size; + entry_pos = ht_start + sizeof(ht_entry) * ht_entry->key; + fseek(binaryout, entry_pos, SEEK_SET); + + if (!ENTRY_OCCUPIED()) + { uprintf("key not occupied\n"); + WRITE_ENTRY(); + } + while( ENTRY_OCCUPIED() ) + { if(overwrite) + { if(bin_keys_identical(entry_pos, ht_entry->key)) + break; + else + { eprintf("error in hashtable insertion, keys are identical"); + } + } + if (HT_END(ht_end)) + LOOP_ENTRY(ht_start); + else + INC_ENTRY(); + } + WRITE_ENTRY(); + +} + +/* | class header | + |--------------------| + | rootset ht | + |--------------------| + | rootsets data | + |--------------------| + | classchild ht | + |--------------------| + | classchild header | + | ... | +*/ + +long bin_traverse_set(ir_set); +long +#define HT_INIT(_START, _SIZE, _INIT_ENTRIES) do { \ + _SIZE = _INIT_ENTRIES ? (_INIT_ENTRIES * (sizeof(struct bin_ht_entry_t) << 1)): 0; \ + _START = ftell(binaryout); \ + fseek(binaryout, _SIZE, SEEK_CUR); \ +} while (0) +bin_traverse_class +( ir_class class) +{ ir_class citer; + ir_set siter; + struct bin_class_header_t class_header; + struct bin_ht_entry_t ht_entry; + long class_start, classht_start, classht_size, rootsetht_start, rootsetht_size; + int num_csibs, num_ssibs; + uint8_t* class_name; + + class_start = ftell(binaryout); + class_name = get_class_name(class); + + num_csibs = get_class_sibcount(class); + num_ssibs = get_set_sibcount(get_class_root_set(class)); + + /* alloc space (before hash tables) for class header */ + class_header.namelen = u8_strlen(class_name); + fseek(binaryout, class_start + sizeof(class_header) + class_header.namelen ,SEEK_SET); + + HT_INIT(classht_start, classht_size, num_csibs); + HT_INIT(rootsetht_start, rootsetht_size, num_ssibs); + + /* TODO: Figure out generic way to output headers */ + /* populate class header */ + class_header.child_ht.entries = num_csibs; + class_header.child_ht.start = classht_start; + class_header.rootset_ht.entries = num_ssibs; + class_header.rootset_ht.start = rootsetht_start; + fseek(binaryout, class_start, SEEK_SET); //seek back to where we allocated header + fwrite(&class_header, sizeof(class_header), 1, binaryout); + fwrite(class_name, class_header.namelen, 1, binaryout); + + /* Start populating root_set hash table */ + for ( siter = get_class_root_set(class); siter != NULL; siter = get_set_nextsib(siter)) + { fseek(binaryout, 0, SEEK_END); + ht_entry.key = NAMEHASH(get_set_name(siter), num_ssibs << 1); + ht_entry.value = bin_traverse_set(siter); + bin_insert_ht_entry(rootsetht_start, rootsetht_size, &ht_entry, 0); + } + + /* Start populating class child hash table */ + for ( citer = get_class_nextchild(class); citer != NULL; citer = get_class_nextsib(citer)) + { fseek(binaryout, 0, SEEK_END); + ht_entry.key = NAMEHASH(get_class_name(citer), num_csibs << 1); + ht_entry.value = bin_traverse_class(citer); + bin_insert_ht_entry(classht_start, classht_size, &ht_entry, 0); + } + + return class_start; +} + +long bin_process_sdat( ir_set); + +/* | set header |--| + |-----------------| | + | set data |<-| + |-----------------| | +---| setchild ht |<-- +| |-----------------| +|->| setchild header | +|->| ... | +*/ + +long +bin_traverse_set +( ir_set set ) +{ ir_set iter; + struct bin_set_header_t header; + struct bin_ht_entry_t ht_entry; + int num_child, setname_len; + long childht_start, childht_size, set_start; + uint8_t* set_name; + + set_start = ftell(binaryout); + set_name = get_set_name(set); + + /* alloc space for set header */ + setname_len = u8_strlen(set_name); + fseek(binaryout, sizeof(struct bin_set_header_t) + setname_len , SEEK_CUR); + + /* process the set data */ + header.sdat_start = bin_process_sdat(set); + + /* Setup child hash table for current sets children */ + num_child = get_set_sibcount(get_set_nextchild(set)); + HT_INIT(childht_start, childht_size, num_child); + + /* populate header, write to file */ + header.child_ht.entries = num_child; + header.child_ht.start = childht_start; + fseek(binaryout, set_start, SEEK_SET); + fwrite(&header, sizeof(struct bin_set_header_t), 1, binaryout); + fwrite(set_name, setname_len, 1, binaryout); + + for(iter = get_set_nextchild(set); iter != NULL; iter = get_set_nextsib(iter)) + { fseek(binaryout, 0, SEEK_END); + ht_entry.key = NAMEHASH(get_set_name(iter), num_child << 1); + ht_entry.value = bin_traverse_set(iter); + bin_insert_ht_entry(childht_start, childht_size, &ht_entry, 0); + } + + + set_set_filepos(set, set_start); + return set_start; + +} +/* | sdat header | + |------------------| + | variant ht | + |------------------| + | 1st variant data | -- variant == framebox + |------------------| + | 2nd variant data | + |------------------| + | etc. | + +*/ + +void bin_insert_links(int, struct bin_ht_header_t*, long); +struct bin_pixel_node_t* bin_find_default_pixel_list(ir_set); +void bin_process_frameboxes(ir_set, struct bin_ht_header_t*, struct bin_pixel_node_t*); +int bin_process_links(ir_set, ir_setdata); + +/* Init the variant hash table for the set, process the sets links and add them to link_stack + and variant hash table, and then output the actual framedata */ +long +bin_process_sdat +( ir_set set ) +{ struct bin_setdata_header_t header; + struct bin_attachment_list_t attachment_list; + struct bin_pixel_node_t *default_pixel_list; + struct bin_ht_header_t ht_header; + long varht_start, varht_size, sdat_start; + int num_entries, num_links; + ir_setdata olink_head; + + sdat_start = ftell(binaryout); + + /* Alloc position for sdat_header */ + fseek(binaryout, sizeof(struct bin_setdata_header_t), SEEK_CUR); + + num_links = bin_process_links(set, olink_head); + num_entries = get_set_variants(set) + num_links; + + HT_INIT(varht_start, varht_size, num_entries); + + /* Populate the sdat_header */ + fseek(binaryout, 0, sdat_start); + header.variant_ht.start = ht_header.start = varht_start; + header.variant_ht.entries = ht_header.entries = num_entries; + attachment_list.filepos = header.attach_pos = ftell(binaryout) + sizeof(varht_start) + sizeof(num_entries); + fwrite(&header, sizeof(header), 1, binaryout); + fseek(binaryout, 0, SEEK_END); + + /* insert the links that were processed into the variant hash table */ + bin_insert_links(num_links, &ht_header, attachment_list.filepos); + /* Determine the default pixel list for all of the frameboxes */ + default_pixel_list = bin_find_default_pixel_list(set); + /* Output each framebox, and insert it into the variant hash table */ + bin_process_frameboxes(set, &ht_header, default_pixel_list); + + /* TODO: Convert the default pixel list to an attachment_list and then push the */ + /* sdats attachment_list onto the attachment_stack so it can be procesed */ + + + return sdat_start; +} + + +/* Adds a vlink onto the stack_alloc to be popped during the processing of the + sets variant hash table. If the vlink has a name, its a vlink to a single + variant. if the vlink doesnt have a name, its the vlink to an entire variant + hash table, and each variant (framebox) needs to be added */ +int +bin_process_vlink +( ir_setdata vlink, + ir_set trg_set +) +{ struct bin_plink_t* plp; + ir_setdata fiter; + uint8_t* link_name; + int num_links; + + num_links = 0; + + /* TODO: Macroize? or not worth? */ + link_name = get_link_name(vlink); + + if (link_name) + { plp = struct_alloc(bin_plink_t); + plp->src_pos = 0; // TBD @ process_setdata + plp->name = link_name; + plp->trg_set = trg_set; + plp->type = VLINK; + num_links++; + } + else // linking a variant hash table + for (fiter = get_set_frameboxes(trg_set); fiter != NULL; fiter = get_framebox_nextsib(fiter)) + { plp = struct_alloc(bin_plink_t); + plp->src_pos = 0; // TBD @ process_setdata + plp->name = get_framebox_name(fiter); + plp->trg_set = trg_set; + plp->type = VLINK; + num_links++; + } + + return num_links; + +} + +/* Adds an mlink to the stack_alloc, to be processed later */ +int +bin_process_mlink +( ir_setdata mlink, + ir_set trg_set +) +{ struct bin_plink_t* plp; + uint8_t* mlink_name; + mlink_name = get_link_name(mlink); + plp = struct_alloc(bin_plink_t); + plp->src_pos = 0; //TBD after resolving the childlist | TODO: attach_pos? + if(mlink_name) plp->name = mlink_name; + plp->trg_set = trg_set; + plp->type = MLINK; + + return 1; +} + +/* TODO: implement this */ +/* Determine if olink is already part of the olink_list. + if it is, theres a cycle, return 1. Else return 0. */ +static inline +int olink_cycle +( ir_setdata olink, + ir_setdata olink_head ) +{ ir_setdata iter; + + + + return 0; + + +} + +/* Given a set, determine the number of links it has and process each link and + then add them to stack_alloc, where they will be popped off and further processed. */ +int +bin_process_links +( ir_set src_set, + ir_setdata olink_head +) +{ int num_links; + ir_setdata liter; //link iter + ir_set trg_set; + + num_links = 0; + + for(liter = get_set_links(src_set); liter != NULL; liter = get_link_nextsib(liter)) + { trg_set = get_set_from_ref(get_link_ref(liter)); + switch (get_link_type(liter)) { + case OLINK: + if (olink_cycle(liter, olink_head)) //TODO: stack of olinks to iterate and check for cycles? + return num_links; + num_links += bin_process_vlink(liter, trg_set); + num_links += bin_process_mlink(liter, trg_set); + num_links += bin_process_links(trg_set, liter); + break; + case VLINK: + num_links += bin_process_vlink(liter, trg_set); + break; + case MLINK: + num_links += bin_process_mlink(liter, trg_set); + break; + case ALINK: //TODO: ? + break; + } + } + return num_links; +} + +/* Insert both mlinks and vlinks into the link stack, after determining their src_pos. Vlinks + have an additional requirement of being added into the variant hash table */ +#define pop_linkp() (*(struct bin_plink_t**) pagelist_pop(&datapages, sizeof(struct bin_plink_t*))) +#define PUSH_PLINK(_LINK) (*(struct bin_plink_t**) stack_alloc(&linkpages, sizeof (_LINK)) = _LINK ) +void +bin_insert_links +( int num_links, + struct bin_ht_header_t* ht, + long attach_pos +) +{ struct bin_plink_t* plp; + struct bin_ht_entry_t ht_entry; + int i; + + /* Insert vlinks into hash table, put v/mlinks on link stack to be processed later */ + for ( i = 0; i < num_links; i++) + { plp = pop_linkp(); + switch (plp->type) { + case MLINK: + plp->trg_set = plp->trg_set; + plp->src_pos = attach_pos; + PUSH_PLINK(plp); + break; + case VLINK: + ht_entry.key = NAMEHASH(plp->name, ht->entries << 1); + ht_entry.value = 0; + bin_insert_ht_entry(ht->start, ht->entries * sizeof(ht_entry), &ht_entry, 0); + plp->src_pos = ht_entry.key + sizeof(ht_entry.key); + PUSH_PLINK(plp); + break; + case OLINK: + break; + //shouldnt exist + case ALINK: + break; + //TBD + } + } +} + +long bin_process_facing(ir_setdata, apc_facing, struct bin_pixel_node_t*); +/* |-------------------| + | framebox header | + |-------------------| + | SFACE framesheet | + |-------------------| + | SWFACE framesheet | + |-------------------| + | etc. | +*/ +long +bin_process_framebox +( ir_set set, + ir_setdata framebox, + struct bin_pixel_node_t* default_pixel_list +) +{ struct bin_model_header_t header; + long framebox_start, index_pos; + int i; + + framebox_start = ftell(binaryout); + + /* insert model header */ + header.type = SS; + header.facing_array_start = framebox_start + sizeof(header); + fwrite(&header, sizeof(header), 1, binaryout); + + /* Create the index array for framesheet of each direction */ + for ( i = SFACE; i < FACING_MAX; i++) + { fseek(binaryout, 0, SEEK_END); + index_pos = bin_process_facing(framebox, i, default_pixel_list); //TODO: finish process_direction + fseek(binaryout, header.facing_array_start + i * sizeof(long), SEEK_SET); + fwrite(&index_pos, sizeof(long), 1, binaryout); + } + + return framebox_start; +} +void +bin_process_frameboxes +( ir_set set, + struct bin_ht_header_t* ht, + struct bin_pixel_node_t* default_pixel_list +) +{ struct bin_ht_entry_t ht_entry; + ir_setdata fiter; + + /* Insert variants into hash table to overwrite olink insertions*/ + for ( fiter = get_set_frameboxes(set); fiter != NULL; fiter = get_framebox_nextsib(fiter)) + { fseek(binaryout, 0, SEEK_END); + ht_entry.key = NAMEHASH(get_framebox_name(fiter), ht->entries << 1); + ht_entry.value = bin_process_framebox(set, fiter, default_pixel_list); + bin_insert_ht_entry(ht->start, ht->entries * sizeof(ht_entry), &ht_entry, 1); + } + +} +/* Determine clipping based on image height/width and frame height/width */ +static inline +void bin_set_img_info +( struct bin_img_info_t* img_info, + ir_setdata framedata +) +{ img_info->fwidth = get_framedata_width(framedata); + img_info->fheight = get_framedata_height(framedata); + img_info->unaligned_height = img_info->height % img_info->fheight; + img_info->unaligned_width = img_info->width % img_info->fwidth; + +} + +/* TODO: Implement this */ +long +bin_process_frame + () +{} + + + +/* Combine the framesheet and mapsheet to create + the output sheet */ +/* |-------------------------| + | outputsheet header | + |-------------------------| + | pixel data for frame1 | + |-------------------------| + | op data for frame1 | + |-------------------------| + | etc. | */ +//TODO: processing direction sounds dumb, but cant call it process_framesheet because +// its actually the mapsheet and the framesheet. rename to output sheet? +/* THIS FUNCTION IS NOT DONE */ +long +bin_process_facing +( ir_setdata framebox, + apc_facing facing, + struct bin_pixel_node_t* default_pixel_list +) +{ struct bin_img_info_t mapsheet_info, framesheet_info; + int num_mapchannels, num_framechannels; + long facing_start; + unsigned char* mapdata, * framedata; + + facing_start = ftell(binaryout); + + + /* Set up data pointers to mapsheet and framesheet, as well as their image infos */ + mapdata = stbi_load(get_framedata_name(get_framebox_facing_mapdata(framebox,SFACE)), &mapsheet_info.width, &mapsheet_info.width, &num_framechannels , 0); + framedata = stbi_load(get_framedata_name(get_framebox_facing_framedata(framebox,SFACE)), &framesheet_info.width, &framesheet_info.height, &num_mapchannels, 0); + bin_set_img_info(&framesheet_info, get_framebox_facing_framedata(framebox, SFACE)); + bin_set_img_info(&mapsheet_info, get_framebox_facing_mapdata(framebox, SFACE)); + + /* TODO: output framesheet/direction header */ + + + /* For each frame and map i in framesheet + mapsheet */ + /* output frame data */ + /* output op space for frames */ + /* determine ops in map */ + /* check if ops are acceptable */ + /* output ops */ + + + return facing_start; + +} + + + + + +/* Insert pixel(s) into the list, z sorted */ +void +bin_insert_node_into_list +( struct bin_pixel_node_t* pixel_list_root, + struct bin_pixel_node_t* pixel_node +) +{ struct bin_pixel_node_t* head_node, *prev_node; + int node_z; + + head_node = pixel_list_root->next; + node_z = pixel_node->data.z; + + if(head_node == NULL) + { head_node = pixel_node; + } + prev_node = pixel_list_root; + while(head_node != NULL) + { if(node_z > head_node->data.z) + { prev_node = head_node; + head_node = head_node->next; + } + else if (node_z < head_node->data.z || node_z == head_node->data.z) + { prev_node->next = pixel_node; + pixel_node->next = head_node; + break; + } + } + + +} + +/* TODO: Finish this */ +struct bin_pixel_node_t* +bin_process_pixel +( unsigned char* data, + int x, + int y, + int init_height, + int init_width +) +{ struct bin_pixel_node_t* pixel_node; + + + pixel_node = struct_alloc(bin_pixel_node_t); + + if(data) + { /* get ref from 4 bytes of data */ + pixel_node->data.ref = (int) data; + /* bitshift by ? to get Z ordering */ + + /* set x and y */ + pixel_node->data.x = x + init_width ; + pixel_node->data.y = y + init_width; + data += 4; + } + else + { data += 4; //TODO: does this correctly increment past 0x00000000? + return NULL; + } + + + + return pixel_node; + +} + +/* Returns the non null pixels of a single frame */ +/* TODO: Finish this */ +struct bin_pixel_node_t* +bin_map_to_pixel_list +( struct bin_img_info_t* img_info, + int init_height, + int init_width, + unsigned char* data +) +{ int x, y; + struct bin_pixel_node_t* pixel_list, * pixel_node; + + pixel_list = NULL; + + /* Check if frame clips */ + if( img_info->unaligned_width ) + ; + if (img_info->unaligned_height ) + ; + + /* Process the map*/ + for (y = 0; y < img_info->fheight; y++) + { for ( x = 0; x < img_info->fwidth; x++ ) + { pixel_node = bin_process_pixel(data, x, y, init_height, init_width); + bin_insert_node_into_list(pixel_list, pixel_node); + } + } + + return pixel_node; +} + +static inline +int bin_pixel_list_len +( struct bin_pixel_node_t* pl ) +{ struct bin_pixel_node_t* plp; + int count; + count = 0; + plp = pl; + while(plp) + { count++; + plp = plp->next; + } + return count; +} + +struct bin_pixel_node_t* +bin_cmp_default_pixel_lists +( struct bin_pixel_node_t* pl1, + struct bin_pixel_node_t* pl2 +) +{ struct bin_pixel_node_t* pl1p, * pl2p; + int i, pl1_len, pl2_len; + + pl1p = pl1; + pl2p = pl2; + pl1_len = bin_pixel_list_len(pl1); + pl2_len = bin_pixel_list_len(pl2); + + if (pl1_len > pl2_len) + return pl1; + else if (pl1_len < pl2_len) + return pl2; + /* pl1 == pl2, make sure that all refs are the same */ + /* TODO: what type of warning/error handling should occur here? */ + for (i = 0; i < pl1_len; i++) + { if (pl1p->data.ref != pl2p->data.ref) + eprintf("Error in determining default pixel list\n"); + pl1p = pl1p->next; + pl2p = pl2p->next; + } + return pl1; //doesnt matter which one you return +} + +/* Find default framebox, based on the framebox with the most attachments*/ +/* Search through first frame of S of each framebox */ +struct bin_pixel_node_t* +bin_find_default_pixel_list +( ir_set set) +{ ir_setdata fiter; + struct bin_pixel_node_t* default_pixel_list, * curr_pixel_list; + unsigned char* data; + int num_channels; + struct bin_img_info_t img_info; + + for (fiter = get_set_frameboxes(set); fiter != NULL; fiter = get_framebox_nextsib(fiter)) + { /* TODO: Stringify the frame name with .png? */ + /* TODO: Add directory changing */ + data = stbi_load(get_framedata_name(get_framebox_facing_mapdata(fiter, SFACE)), &img_info.width, &img_info.width, &num_channels, 0); + bin_set_img_info(&img_info, get_framebox_facing_mapdata(fiter, SFACE)); + curr_pixel_list = bin_map_to_pixel_list(&img_info, 0, 0, data); + default_pixel_list = bin_cmp_default_pixel_lists(curr_pixel_list, default_pixel_list); + + free(data); + } + + return default_pixel_list; +}