diff options
Diffstat (limited to 'source/tiff')
-rw-r--r-- | source/tiff/mutiff.c | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/source/tiff/mutiff.c b/source/tiff/mutiff.c new file mode 100644 index 00000000..e2772f11 --- /dev/null +++ b/source/tiff/mutiff.c @@ -0,0 +1,207 @@ +#include "mupdf/tiff.h" + +static void tiff_init_document(tiff_document *doc); + +#define DPI 72.0f + +struct tiff_page_s +{ + fz_image *image; +}; + +struct tiff_document_s +{ + fz_document super; + + fz_context *ctx; + fz_stream *file; + fz_buffer *buffer; + int page_count; +}; + +tiff_document * +tiff_open_document_with_stream(fz_context *ctx, fz_stream *file) +{ + tiff_document *doc; + int len; + unsigned char *buf; + + doc = fz_malloc_struct(ctx, tiff_document); + tiff_init_document(doc); + doc->ctx = ctx; + doc->file = fz_keep_stream(file); + doc->page_count = 0; + + fz_try(ctx) + { + doc->buffer = fz_read_all(doc->file, 1024); + len = doc->buffer->len; + buf = doc->buffer->data; + + doc->page_count = fz_load_tiff_subimage_count(ctx, buf, len); + } + fz_catch(ctx) + { + tiff_close_document(doc); + fz_rethrow(ctx); + } + + return doc; +} + +tiff_document * +tiff_open_document(fz_context *ctx, const char *filename) +{ + fz_stream *file; + tiff_document *doc; + + file = fz_open_file(ctx, filename); + if (!file) + fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", filename, strerror(errno)); + + fz_try(ctx) + { + doc = tiff_open_document_with_stream(ctx, file); + } + fz_always(ctx) + { + fz_close(file); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } + + return doc; +} + +void +tiff_close_document(tiff_document *doc) +{ + fz_context *ctx = doc->ctx; + fz_drop_buffer(ctx, doc->buffer); + fz_close(doc->file); + fz_free(ctx, doc); +} + +int +tiff_count_pages(tiff_document *doc) +{ + return doc->page_count; +} + +tiff_page * +tiff_load_page(tiff_document *doc, int number) +{ + fz_context *ctx = doc->ctx; + fz_image *mask = NULL; + fz_pixmap *pixmap = NULL; + tiff_page *page = NULL; + + if (number < 0 || number >= doc->page_count) + return NULL; + + fz_var(pixmap); + fz_var(page); + fz_try(ctx) + { + pixmap = fz_load_tiff_subimage(ctx, doc->buffer->data, doc->buffer->len, number); + + page = fz_malloc_struct(ctx, tiff_page); + page->image = fz_new_image_from_pixmap(ctx, pixmap, mask); + } + fz_catch(ctx) + { + tiff_free_page(doc, page); + fz_rethrow(ctx); + } + + return page; +} + +void +tiff_free_page(tiff_document *doc, tiff_page *page) +{ + if (!page) + return; + fz_drop_image(doc->ctx, page->image); + fz_free(doc->ctx, page); +} + +fz_rect * +tiff_bound_page(tiff_document *doc, tiff_page *page, fz_rect *bbox) +{ + fz_image *image = page->image; + bbox->x0 = bbox->y0 = 0; + bbox->x1 = image->w * DPI / image->xres; + bbox->y1 = image->h * DPI / image->yres; + return bbox; +} + +void +tiff_run_page(tiff_document *doc, tiff_page *page, fz_device *dev, const fz_matrix *ctm, fz_cookie *cookie) +{ + fz_matrix local_ctm = *ctm; + fz_image *image = page->image; + float w = image->w * DPI / image->xres; + float h = image->h * DPI / image->yres; + fz_pre_scale(&local_ctm, w, h); + fz_fill_image(dev, image, &local_ctm, 1); +} + +static int +tiff_meta(tiff_document *doc, int key, void *ptr, int size) +{ + switch (key) + { + case FZ_META_FORMAT_INFO: + sprintf((char *)ptr, "TIFF"); + return FZ_META_OK; + default: + return FZ_META_UNKNOWN_KEY; + } +} + +static void +tiff_rebind(tiff_document *doc, fz_context *ctx) +{ + doc->ctx = ctx; + fz_rebind_stream(doc->file, ctx); +} + +static void +tiff_init_document(tiff_document *doc) +{ + doc->super.close = (fz_document_close_fn *)tiff_close_document; + doc->super.count_pages = (fz_document_count_pages_fn *)tiff_count_pages; + doc->super.load_page = (fz_document_load_page_fn *)tiff_load_page; + doc->super.bound_page = (fz_document_bound_page_fn *)tiff_bound_page; + doc->super.run_page_contents = (fz_document_run_page_contents_fn *)tiff_run_page; + doc->super.free_page = (fz_document_free_page_fn *)tiff_free_page; + doc->super.meta = (fz_document_meta_fn *)tiff_meta; + doc->super.rebind = (fz_document_rebind_fn *)tiff_rebind; +} + +static int +tiff_recognize(fz_context *doc, const char *magic) +{ + char *ext = strrchr(magic, '.'); + + if (ext) + { + if (!fz_strcasecmp(ext, ".tiff") || !fz_strcasecmp(ext, ".tif")) + return 100; + } + if (!strcmp(magic, "tif") || !strcmp(magic, "image/tiff") || + !strcmp(magic, "tiff") || !strcmp(magic, "image/x-tiff")) + return 100; + + return 0; +} + +fz_document_handler tiff_document_handler = +{ + (fz_document_recognize_fn *)&tiff_recognize, + (fz_document_open_fn *)&tiff_open_document, + (fz_document_open_with_stream_fn *)&tiff_open_document_with_stream +}; |