/** * Load entire image into memory using fileaccess load method. * Faster than open+read+close. */ static pixmap_t * fa_imageloader2(const char *url, const char **vpaths, char *errbuf, size_t errlen) { uint8_t *p; size_t size; meminfo_t mi; pixmap_type_t fmt; int width = -1, height = -1, orientation = 0; if((p = fa_load(url, &size, vpaths, errbuf, errlen, NULL)) == NULL) return NULL; mi.data = p; mi.size = size; /* Probe format */ if((p[6] == 'J' && p[7] == 'F' && p[8] == 'I' && p[9] == 'F') || (p[6] == 'E' && p[7] == 'x' && p[8] == 'i' && p[9] == 'f')) { jpeginfo_t ji; if(jpeg_info(&ji, jpeginfo_mem_reader, &mi, JPEG_INFO_DIMENSIONS | JPEG_INFO_ORIENTATION, p, size, errbuf, errlen)) { free(p); return NULL; } fmt = PIXMAP_JPEG; width = ji.ji_width; height = ji.ji_height; orientation = ji.ji_orientation; jpeg_info_clear(&ji); } else if(!memcmp(pngsig, p, 8)) { fmt = PIXMAP_PNG; } else if(!memcmp(gif87sig, p, sizeof(gif87sig)) || !memcmp(gif89sig, p, sizeof(gif89sig))) { fmt = PIXMAP_GIF; } else { snprintf(errbuf, errlen, "%s: unknown format", url); free(p); return NULL; } pixmap_t *pm = pixmap_alloc_coded(p, size, fmt); pm->pm_width = width; pm->pm_height = height; pm->pm_orientation = orientation; free(p); return pm; }
static void fa_probe_exif(metadata_t *md, const char *url, uint8_t *pb, fa_handle_t *fh) { jpeginfo_t ji; if(jpeg_info(&ji, jpeginfo_reader, fh, JPEG_INFO_DIMENSIONS | JPEG_INFO_ORIENTATION | JPEG_INFO_METADATA, pb, 256, NULL, 0)) return; md->md_time = ji.ji_time; md->md_manufacturer = rstr_dup(ji.ji_manufacturer); md->md_equipment = rstr_dup(ji.ji_equipment); jpeg_info_clear(&ji); }
/** * Load entire image into memory using fileaccess load method. * Faster than open+read+close. */ static pixmap_t * fa_imageloader2(const char *url, const char **vpaths, char *errbuf, size_t errlen, int *cache_control, cancellable_t *c) { buf_t *buf; jpeg_meminfo_t mi; pixmap_type_t fmt; int width = -1, height = -1, orientation = 0; buf = fa_load(url, FA_LOAD_VPATHS(vpaths), FA_LOAD_ERRBUF(errbuf, errlen), FA_LOAD_CACHE_CONTROL(cache_control), FA_LOAD_CANCELLABLE(c), NULL); if(buf == NULL || buf == NOT_MODIFIED) return (pixmap_t *)buf; const uint8_t *p = buf_c8(buf); mi.data = p; mi.size = buf->b_size; if(buf->b_size < 16) goto bad; /* Probe format */ if((p[6] == 'J' && p[7] == 'F' && p[8] == 'I' && p[9] == 'F') || (p[6] == 'E' && p[7] == 'x' && p[8] == 'i' && p[9] == 'f')) { jpeginfo_t ji; if(jpeg_info(&ji, jpeginfo_mem_reader, &mi, JPEG_INFO_DIMENSIONS | JPEG_INFO_ORIENTATION, p, buf->b_size, errbuf, errlen)) { buf_release(buf); return NULL; } fmt = PIXMAP_JPEG; width = ji.ji_width; height = ji.ji_height; orientation = ji.ji_orientation; jpeg_info_clear(&ji); } else if(!memcmp(pngsig, p, 8)) { fmt = PIXMAP_PNG; } else if(!memcmp(gif87sig, p, sizeof(gif87sig)) || !memcmp(gif89sig, p, sizeof(gif89sig))) { fmt = PIXMAP_GIF; } else if(!memcmp(svgsig1, p, sizeof(svgsig1)) || !memcmp(svgsig2, p, sizeof(svgsig2))) { fmt = PIXMAP_SVG; } else { bad: snprintf(errbuf, errlen, "Unknown format"); buf_release(buf); return NULL; } pixmap_t *pm = pixmap_alloc_coded(p, buf->b_size, fmt); if(pm != NULL) { pm->pm_width = width; pm->pm_height = height; pm->pm_orientation = orientation; } else { snprintf(errbuf, errlen, "Out of memory"); } buf_release(buf); return pm; }
pixmap_t * fa_imageloader(const char *url, const struct image_meta *im, const char **vpaths, char *errbuf, size_t errlen, int *cache_control, cancellable_t *c) { uint8_t p[16]; int r; int width = -1, height = -1, orientation = 0; fa_handle_t *fh; pixmap_t *pm; pixmap_type_t fmt; #if ENABLE_LIBAV if(strchr(url, '#')) return fa_image_from_video(url, im, errbuf, errlen, cache_control, c); #endif if(!im->im_want_thumb) return fa_imageloader2(url, vpaths, errbuf, errlen, cache_control, c); fa_open_extra_t foe = { .foe_c = c }; if((fh = fa_open_vpaths(url, vpaths, errbuf, errlen, FA_BUFFERED_SMALL, &foe)) == NULL) return NULL; if(ONLY_CACHED(cache_control)) { snprintf(errbuf, errlen, "Not cached"); return NULL; } if(fa_read(fh, p, sizeof(p)) != sizeof(p)) { snprintf(errbuf, errlen, "File too short"); fa_close(fh); return NULL; } /* Probe format */ if((p[6] == 'J' && p[7] == 'F' && p[8] == 'I' && p[9] == 'F') || (p[6] == 'E' && p[7] == 'x' && p[8] == 'i' && p[9] == 'f')) { jpeginfo_t ji; if(jpeg_info(&ji, jpeginfo_reader, fh, JPEG_INFO_DIMENSIONS | JPEG_INFO_ORIENTATION | (im->im_want_thumb ? JPEG_INFO_THUMBNAIL : 0), p, sizeof(p), errbuf, errlen)) { fa_close(fh); return NULL; } if(im->im_want_thumb && ji.ji_thumbnail) { pixmap_t *pm = pixmap_dup(ji.ji_thumbnail); fa_close(fh); jpeg_info_clear(&ji); return pm; } fmt = PIXMAP_JPEG; width = ji.ji_width; height = ji.ji_height; orientation = ji.ji_orientation; jpeg_info_clear(&ji); } else if(!memcmp(pngsig, p, 8)) { fmt = PIXMAP_PNG; } else if(!memcmp(gif87sig, p, sizeof(gif87sig)) || !memcmp(gif89sig, p, sizeof(gif89sig))) { fmt = PIXMAP_GIF; } else if(!memcmp(svgsig1, p, sizeof(svgsig1)) || !memcmp(svgsig2, p, sizeof(svgsig2))) { fmt = PIXMAP_SVG; } else { snprintf(errbuf, errlen, "Unknown format"); fa_close(fh); return NULL; } int64_t s = fa_fsize(fh); if(s < 0) { snprintf(errbuf, errlen, "Can't read from non-seekable file"); fa_close(fh); return NULL; } pm = pixmap_alloc_coded(NULL, s, fmt); if(pm == NULL) { snprintf(errbuf, errlen, "Out of memory"); fa_close(fh); return NULL; } pm->pm_width = width; pm->pm_height = height; pm->pm_orientation = orientation; fa_seek(fh, SEEK_SET, 0); r = fa_read(fh, pm->pm_data, pm->pm_size); fa_close(fh); if(r != pm->pm_size) { pixmap_release(pm); snprintf(errbuf, errlen, "Read error"); return NULL; } return pm; }
static image_t * fa_imageloader_buf(buf_t *buf, char *errbuf, size_t errlen) { jpeg_meminfo_t mi; image_coded_type_t fmt; int width = -1, height = -1, orientation = 0, progressive = 0, planes = 0; const uint8_t *p = buf_c8(buf); mi.data = p; mi.size = buf->b_size; if(buf->b_size < 16) goto bad; /* Probe format */ if(p[0] == 0xff && p[1] == 0xd8 && p[2] == 0xff) { jpeginfo_t ji; if(jpeg_info(&ji, jpeginfo_mem_reader, &mi, JPEG_INFO_DIMENSIONS | JPEG_INFO_ORIENTATION, p, buf->b_size, errbuf, errlen)) { return NULL; } fmt = IMAGE_JPEG; width = ji.ji_width; height = ji.ji_height; orientation = ji.ji_orientation; progressive = ji.ji_progressive; planes = ji.ji_components; jpeg_info_clear(&ji); } else if(!memcmp(pngsig, p, 8)) { fmt = IMAGE_PNG; } else if(!memcmp(gif87sig, p, sizeof(gif87sig)) || !memcmp(gif89sig, p, sizeof(gif89sig))) { fmt = IMAGE_GIF; } else if(p[0] == 'B' && p[1] == 'M') { fmt = IMAGE_BMP; } else if(!memcmp(svgsig1, p, sizeof(svgsig1)) || !memcmp(svgsig2, p, sizeof(svgsig2))) { fmt = IMAGE_SVG; } else { bad: snprintf(errbuf, errlen, "Unknown format"); return NULL; } image_t *img = image_coded_create_from_buf(buf, fmt); if(img != NULL) { img->im_width = width; img->im_height = height; img->im_orientation = orientation; img->im_color_planes = planes; if(progressive) img->im_flags |= IMAGE_PROGRESSIVE; } else { snprintf(errbuf, errlen, "Out of memory"); } return img; }
image_t * fa_imageloader(const char *url, const struct image_meta *im, const char **vpaths, char *errbuf, size_t errlen, int *cache_control, cancellable_t *c) { uint8_t p[16]; int r; int width = -1, height = -1, orientation = 0; fa_handle_t *fh; image_t *img; image_coded_type_t fmt; #if ENABLE_LIBAV if(strchr(url, '#')) return fa_image_from_video(url, im, errbuf, errlen, cache_control, c); #endif if(!im->im_want_thumb) return fa_imageloader2(url, vpaths, errbuf, errlen, cache_control, c); fa_open_extra_t foe = { .foe_cancellable = c }; if((fh = fa_open_vpaths(url, vpaths, errbuf, errlen, FA_BUFFERED_SMALL, &foe)) == NULL) return NULL; if(ONLY_CACHED(cache_control)) { snprintf(errbuf, errlen, "Not cached"); return NULL; } if(fa_read(fh, p, sizeof(p)) != sizeof(p)) { snprintf(errbuf, errlen, "File too short"); fa_close(fh); return NULL; } /* Probe format */ if(p[0] == 0xff && p[1] == 0xd8 && p[2] == 0xff) { jpeginfo_t ji; if(jpeg_info(&ji, jpeginfo_reader, fh, JPEG_INFO_DIMENSIONS | JPEG_INFO_ORIENTATION | (im->im_want_thumb ? JPEG_INFO_THUMBNAIL : 0), p, sizeof(p), errbuf, errlen)) { fa_close(fh); return NULL; } if(im->im_want_thumb && ji.ji_thumbnail) { image_t *im = image_retain(ji.ji_thumbnail); fa_close(fh); jpeg_info_clear(&ji); im->im_flags |= IMAGE_ADAPTED; return im; } fmt = IMAGE_JPEG; width = ji.ji_width; height = ji.ji_height; orientation = ji.ji_orientation; jpeg_info_clear(&ji); } else if(!memcmp(pngsig, p, 8)) { fmt = IMAGE_PNG; } else if(!memcmp(gif87sig, p, sizeof(gif87sig)) || !memcmp(gif89sig, p, sizeof(gif89sig))) { fmt = IMAGE_GIF; } else if(p[0] == 'B' && p[1] == 'M') { fmt = IMAGE_BMP; } else if(!memcmp(svgsig1, p, sizeof(svgsig1)) || !memcmp(svgsig2, p, sizeof(svgsig2))) { fmt = IMAGE_SVG; } else { snprintf(errbuf, errlen, "Unknown format"); fa_close(fh); return NULL; } int64_t s = fa_fsize(fh); if(s < 0) { snprintf(errbuf, errlen, "Can't read from non-seekable file"); fa_close(fh); return NULL; } void *ptr; img = image_coded_alloc(&ptr, s, fmt); if(img == NULL) { snprintf(errbuf, errlen, "Out of memory"); fa_close(fh); return NULL; } img->im_width = width; img->im_height = height; img->im_orientation = orientation; fa_seek(fh, SEEK_SET, 0); r = fa_read(fh, ptr, s); fa_close(fh); if(r != s) { image_release(img); snprintf(errbuf, errlen, "Read error"); return NULL; } return img; }
/** * Load entire image into memory using fileaccess load method. * Faster than open+read+close. */ static pixmap_t * fa_imageloader2(const char *url, const char **vpaths, char *errbuf, size_t errlen, int *cache_control, fa_load_cb_t *cb, void *opaque) { uint8_t *p; size_t size; jpeg_meminfo_t mi; pixmap_type_t fmt; int width = -1, height = -1, orientation = 0; p = fa_load(url, &size, vpaths, errbuf, errlen, cache_control, 0, cb, opaque); if(p == NULL || p == NOT_MODIFIED) return (pixmap_t *)p; mi.data = p; mi.size = size; if(size < 16) goto bad; /* Probe format */ if((p[6] == 'J' && p[7] == 'F' && p[8] == 'I' && p[9] == 'F') || (p[6] == 'E' && p[7] == 'x' && p[8] == 'i' && p[9] == 'f')) { jpeginfo_t ji; if(jpeg_info(&ji, jpeginfo_mem_reader, &mi, JPEG_INFO_DIMENSIONS | JPEG_INFO_ORIENTATION, p, size, errbuf, errlen)) { free(p); return NULL; } fmt = PIXMAP_JPEG; width = ji.ji_width; height = ji.ji_height; orientation = ji.ji_orientation; jpeg_info_clear(&ji); } else if(!memcmp(pngsig, p, 8)) { fmt = PIXMAP_PNG; } else if(!memcmp(gif87sig, p, sizeof(gif87sig)) || !memcmp(gif89sig, p, sizeof(gif89sig))) { fmt = PIXMAP_GIF; } else if(!memcmp(svgsig1, p, sizeof(svgsig1)) || !memcmp(svgsig2, p, sizeof(svgsig2))) { fmt = PIXMAP_SVG; } else { bad: snprintf(errbuf, errlen, "Unknown format"); free(p); return NULL; } pixmap_t *pm = pixmap_alloc_coded(p, size, fmt); if(pm != NULL) { pm->pm_width = width; pm->pm_height = height; pm->pm_orientation = orientation; } else { snprintf(errbuf, errlen, "Out of memory"); } free(p); return pm; }
pixmap_t * fa_imageloader(const char *url, const struct image_meta *im, const char **vpaths, char *errbuf, size_t errlen) { uint8_t p[16]; int r; enum CodecID codec; int width = -1, height = -1, orientation = 0; AVIOContext *avio; pixmap_t *pm; if(strchr(url, '#')) { pm = fa_image_from_video(url, im); if(pm == NULL) snprintf(errbuf, errlen, "%s: Unable to extract image", url); return pm; } if(!im->want_thumb) return fa_imageloader2(url, vpaths, errbuf, errlen); if((avio = fa_libav_open_vpaths(url, 32768, vpaths)) == NULL) { snprintf(errbuf, errlen, "%s: Unable to open file", url); return NULL; } if(avio_read(avio, p, sizeof(p)) != sizeof(p)) { snprintf(errbuf, errlen, "%s: file too short", url); fa_libav_close(avio); return NULL; } /* Probe format */ if((p[6] == 'J' && p[7] == 'F' && p[8] == 'I' && p[9] == 'F') || (p[6] == 'E' && p[7] == 'x' && p[8] == 'i' && p[9] == 'f')) { jpeginfo_t ji; if(jpeg_info(&ji, jpeginfo_reader, avio, JPEG_INFO_DIMENSIONS | JPEG_INFO_ORIENTATION | (im->want_thumb ? JPEG_INFO_THUMBNAIL : 0), p, sizeof(p), errbuf, errlen)) { fa_libav_close(avio); return NULL; } if(im->want_thumb && ji.ji_thumbnail) { pixmap_t *pm = pixmap_dup(ji.ji_thumbnail); fa_libav_close(avio); jpeg_info_clear(&ji); return pm; } codec = CODEC_ID_MJPEG; width = ji.ji_width; height = ji.ji_height; orientation = ji.ji_orientation; jpeg_info_clear(&ji); } else if(!memcmp(pngsig, p, 8)) { codec = CODEC_ID_PNG; } else if(!memcmp(gif87sig, p, sizeof(gif87sig)) || !memcmp(gif89sig, p, sizeof(gif89sig))) { codec = CODEC_ID_GIF; } else { snprintf(errbuf, errlen, "%s: unknown format", url); fa_libav_close(avio); return NULL; } size_t s = avio_size(avio); if(s < 0) { snprintf(errbuf, errlen, "%s: Can't read from non-seekable file", url); fa_libav_close(avio); return NULL; } pm = pixmap_alloc_coded(NULL, s, codec); if(pm == NULL) { snprintf(errbuf, errlen, "%s: no memory", url); fa_libav_close(avio); return NULL; } pm->pm_width = width; pm->pm_height = height; pm->pm_orientation = orientation; avio_seek(avio, SEEK_SET, 0); r = avio_read(avio, pm->pm_data, pm->pm_size); fa_libav_close(avio); if(r != pm->pm_size) { pixmap_release(pm); snprintf(errbuf, errlen, "%s: read error", url); return NULL; } return pm; }