#include"png_cache.h" #include #include #include /* Read image and add to cache. */ ImageCache *LoadImage(const char *filename, ImageCache **cache) { ImageCache *node, **previous; int size; /* Return existing file if it has already been loaded. */ previous = cache; for(node = *cache; node != NULL; node = node->next) { if( strcmp(filename, node->filename) == 0 ) return node; previous = &(node->next); } /* Allocate new node. */ node = (ImageCache*)calloc(1, sizeof(ImageCache)); if( node == NULL ) { fputs("Out of memory.\n", stderr); return NULL; } /* Load image header. */ node->filename = filename; node->image.version = PNG_IMAGE_VERSION; if( strcmp(filename, "-") == 0 ) { if( !png_image_begin_read_from_stdio(&(node->image), stdin) ) { fputs("-: error reading from stdin.\n", stderr); free(node); return NULL; } } else { if( !png_image_begin_read_from_file(&(node->image), filename) ) { fprintf(stderr, "%s: error reading from file.\n", filename); free(node); return NULL; } } /* Drop images that are too small or too large. */ if( node->image.width < 1 || node->image.width >= 0x8000 || node->image.height < 1 || node->image.height >= 0x8000 ) { fprintf(stderr, "%s: unacceptable image size (%u,%u)\n", filename, node->image.width, node->image.height); free(node); return NULL; } /* Load pixel data. */ node->image.format = PNG_FORMAT_RGBA; size = PNG_IMAGE_SIZE(node->image); node->pixels = (png_bytep)malloc(size); if( node->pixels == NULL ) { fputs("Out of memory.\n", stderr); free(node); return NULL; } if( !png_image_finish_read(&(node->image), NULL, node->pixels, 0, NULL) ) { fprintf(stderr, "%s: error loading file.\n", filename); free(node->pixels); free(node); return NULL; } /* Add node to list. */ *previous = node; return node; } /* Release memory. */ void FreeImageCache(ImageCache **cache) { ImageCache *next; for(; *cache != NULL; *cache = next) { next = (*cache)->next; free((*cache)->pixels); free(*cache); } }