terom@0: #include "image.h" terom@0: terom@0: static int pt_image_new (struct pt_image **img_ptr, struct pt_ctx *ctx, const char *png_path) terom@0: { terom@0: struct pt_image *img; terom@0: terom@0: // alloc terom@0: if ((img = calloc(1, sizeof(*img))) == NULL) terom@0: return -1; terom@0: terom@0: if ((img->png_path = strdup(png_path)) == NULL) terom@0: goto error; terom@0: terom@0: // init terom@0: img->ctx = ctx; terom@0: terom@0: // ok terom@0: *img_ptr = img; terom@0: terom@0: return 0; terom@0: terom@0: error: terom@0: pt_image_destroy(img); terom@0: terom@0: return -1; terom@0: } terom@0: terom@0: /** terom@0: * Open the image's FILE terom@0: */ terom@0: static int pt_image_open_file (struct pt_image *img, FILE **file_ptr) terom@0: { terom@0: FILE *fp; terom@0: terom@0: // open terom@0: if (fopen(img->png_path, "rb") < 0) terom@0: return -1; terom@0: terom@0: // ok terom@0: *file_ptr = fp; terom@0: terom@0: return 0; terom@0: } terom@0: terom@0: /** terom@0: * Open the PNG image, setting up the I/O and returning the png_structp and png_infop terom@0: */ terom@0: static int pt_image_open_png (struct pt_image *img, png_structp *png_ptr, png_infop *info_ptr) terom@0: { terom@0: FILE *fp = NULL; terom@0: png_structp png = NULL; terom@0: png_infop info = NULL; terom@0: terom@0: // open I/O terom@0: if (pt_image_open_file(img, &fp)) terom@0: goto error; terom@0: terom@0: // create the struct terom@0: if ((png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) terom@0: goto error; terom@0: terom@0: // create the info terom@0: if ((info = png_create_info_struct(png)) == NULL) terom@0: goto error; terom@0: terom@0: // setup error trap for the I/O terom@0: if (setjmp(png_jmpbuf(png))) terom@0: goto error; terom@0: terom@0: // setup I/O to FILE terom@0: png_init_io(png, fp); terom@0: terom@0: // ok terom@0: *png_ptr = png; terom@0: *info_ptr = info; terom@0: terom@0: return 0; terom@0: terom@0: error: terom@0: // cleanup file terom@0: if (fp) fclose(fp); terom@0: terom@0: // cleanup PNG state terom@0: png_destroy_read_struct(&png, &info, NULL); terom@0: terom@0: return -1; terom@0: } terom@0: terom@0: /** terom@0: * Open the PNG image, and write out to the cache terom@0: */ terom@0: static int pt_image_update_cache (struct pt_image *img) terom@0: { terom@0: png_structp png; terom@0: png_infop info; terom@0: terom@0: // open .png terom@0: if (pt_image_open_png(img, &png, &info)) terom@0: return -1; terom@0: terom@0: // setup error trap terom@0: if (setjmp(png_jmpbuf(png))) terom@0: goto error; terom@0: terom@0: // read meta-info terom@0: png_read_info(png, info); terom@0: terom@0: // pass to cache object terom@0: if (pt_cache_update_png(img->cache, png, info)) terom@0: goto error; terom@0: terom@0: // finish off, ignore trailing data terom@0: png_read_end(png, NULL); terom@0: terom@0: // clean up terom@0: png_destroy_read_struct(&png, &info); terom@0: terom@0: return 0; terom@0: terom@0: error: terom@0: // clean up terom@0: png_destroy_read_struct(&png, &info); terom@0: terom@0: return -1; terom@0: } terom@0: terom@0: int pt_image_open (struct pt_image **img_ptr, struct pt_ctx *ctx, const char *png_path, int cache_mode) terom@0: { terom@0: struct pt_image *img; terom@0: terom@0: // XXX: verify that the png_path exists and looks like a PNG file terom@0: terom@0: // alloc terom@0: if (pt_image_new(&img, ctx, png_path)) terom@0: return -1; terom@0: terom@0: // open the cache object for this image terom@0: if (pt_cache_open(&img->cache, img, mode)) terom@0: goto error; terom@0: terom@0: // update if not fresh terom@0: if (!pt_cache_fresh(img->cache)) terom@0: pt_image_update_cache(img); terom@0: terom@0: // ok, ready for access terom@0: *img_ptr = img; terom@0: terom@0: return 0; terom@0: terom@0: error: terom@0: pt_image_destroy(img); terom@0: }