diff options
author | Robin Watts <robin.watts@artifex.com> | 2014-02-10 16:54:24 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2014-02-10 17:04:03 +0000 |
commit | a4a50269b2c62fddf34445140036e3f61b500d9e (patch) | |
tree | e5ab2bf4e75d0b96f0cced8f8e42dde3e564dc54 | |
parent | 9b9438fa4210b29023f85bb98c73f8f58a7760d5 (diff) | |
download | mupdf-a4a50269b2c62fddf34445140036e3f61b500d9e.tar.xz |
Bug 695022: Add TIFF format handler
Patch from Thomas Fach-Pedersen. Many thanks!
Add a new format handler that copes with TIFF files. This replaces
the TIFF functionality within the image format handler, and is
better because this copes with multiple images (as one image per
page).
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | include/mupdf/fitz/document.h | 1 | ||||
-rw-r--r-- | include/mupdf/tiff.h | 51 | ||||
-rw-r--r-- | platform/android/jni/Core.mk | 4 | ||||
-rw-r--r-- | platform/win32/libmupdf.vcproj | 8 | ||||
-rw-r--r-- | source/fitz/document-all.c | 1 | ||||
-rw-r--r-- | source/fitz/document-no-run.c | 1 | ||||
-rw-r--r-- | source/img/muimage.c | 7 | ||||
-rw-r--r-- | source/tiff/mutiff.c | 207 |
9 files changed, 280 insertions, 7 deletions
@@ -65,6 +65,7 @@ ALL_DIR += $(OUT)/pdf $(OUT)/pdf/js ALL_DIR += $(OUT)/xps ALL_DIR += $(OUT)/cbz ALL_DIR += $(OUT)/img +ALL_DIR += $(OUT)/tiff ALL_DIR += $(OUT)/tools ALL_DIR += $(OUT)/platform/x11 ALL_DIR += $(OUT)/platform/x11/curl @@ -80,18 +81,21 @@ PDF_SRC := $(wildcard source/pdf/*.c) XPS_SRC := $(wildcard source/xps/*.c) CBZ_SRC := $(wildcard source/cbz/*.c) IMG_SRC := $(wildcard source/img/*.c) +TIFF_SRC := $(wildcard source/tiff/*.c) FITZ_SRC_HDR := $(wildcard source/fitz/*.h) PDF_SRC_HDR := $(wildcard source/pdf/*.h) XPS_SRC_HDR := $(wildcard source/xps/*.h) CBZ_SRC_HDR := $(wildcard source/cbz/*.h) IMG_SRC_HDR := $(wildcard source/img/*.h) +TIFF_SRC_HDR := $(wildcard source/tiff/*.h) FITZ_OBJ := $(subst source/, $(OUT)/, $(addsuffix .o, $(basename $(FITZ_SRC)))) PDF_OBJ := $(subst source/, $(OUT)/, $(addsuffix .o, $(basename $(PDF_SRC)))) XPS_OBJ := $(subst source/, $(OUT)/, $(addsuffix .o, $(basename $(XPS_SRC)))) CBZ_OBJ := $(subst source/, $(OUT)/, $(addsuffix .o, $(basename $(CBZ_SRC)))) IMG_OBJ := $(subst source/, $(OUT)/, $(addsuffix .o, $(basename $(IMG_SRC)))) +TIFF_OBJ := $(subst source/, $(OUT)/, $(addsuffix .o, $(basename $(TIFF_SRC)))) PDF_JS_JSCORE_OBJ := $(OUT)/pdf/js/pdf-js.o $(OUT)/pdf/js/pdf-jsimp-jscore.o PDF_JS_V8_OBJ := $(OUT)/pdf/js/pdf-js.o $(OUT)/pdf/js/pdf-jsimp-cpp.o $(OUT)/pdf/js/pdf-jsimp-v8.o @@ -102,6 +106,7 @@ $(PDF_OBJ) : $(FITZ_HDR) $(PDF_HDR) $(PDF_SRC_HDR) $(XPS_OBJ) : $(FITZ_HDR) $(XPS_HDR) $(XPS_SRC_HDR) $(CBZ_OBJ) : $(FITZ_HDR) $(CBZ_HDR) $(CBZ_SRC_HDR) $(IMG_OBJ) : $(FITZ_HDR) $(IMG_HDR) $(IMG_SRC_HDR) +$(TIFF_OBJ) : $(FITZ_HDR) $(IMG_HDR) $(TIFF_SRC_HDR) $(PDF_JS_JSCORE_OBJ) : $(FITZ_HDR) $(PDF_HDR) $(PDF_SRC_HDR) $(PDF_JS_V8_OBJ) : $(FITZ_HDR) $(PDF_HDR) $(PDF_SRC_HDR) @@ -112,7 +117,7 @@ $(PDF_JS_NONE_OBJ) := $(FITZ_HDR) $(PDF_HDR) $(PDF_SRC_HDR) MUPDF_LIB := $(OUT)/libmupdf.a MUPDF_JS_NONE_LIB := $(OUT)/libmupdf-js-none.a -$(MUPDF_LIB) : $(FITZ_OBJ) $(PDF_OBJ) $(XPS_OBJ) $(CBZ_OBJ) $(IMG_OBJ) +$(MUPDF_LIB) : $(FITZ_OBJ) $(PDF_OBJ) $(XPS_OBJ) $(CBZ_OBJ) $(IMG_OBJ) $(TIFF_OBJ) $(MUPDF_JS_NONE_LIB) : $(PDF_JS_NONE_OBJ) ifeq "$(V8_PRESENT)" "yes" diff --git a/include/mupdf/fitz/document.h b/include/mupdf/fitz/document.h index cda8870a..a3d0b244 100644 --- a/include/mupdf/fitz/document.h +++ b/include/mupdf/fitz/document.h @@ -77,6 +77,7 @@ extern fz_document_handler pdf_no_run_document_handler; extern fz_document_handler xps_document_handler; extern fz_document_handler cbz_document_handler; extern fz_document_handler img_document_handler; +extern fz_document_handler tiff_document_handler; void fz_register_document_handler(fz_context *ctx, const fz_document_handler *handler); diff --git a/include/mupdf/tiff.h b/include/mupdf/tiff.h new file mode 100644 index 00000000..1304e4b2 --- /dev/null +++ b/include/mupdf/tiff.h @@ -0,0 +1,51 @@ +#ifndef MUPDF_TIFF_H +#define MUPDF_TIFF_H + +#include "mupdf/fitz.h" + +typedef struct tiff_document_s tiff_document; +typedef struct tiff_page_s tiff_page; + +/* + tiff_open_document: Open a document. + + Open a document for reading so the library is able to locate + objects and pages inside the file. + + The returned tiff_document should be used when calling most + other functions. Note that it wraps the context, so those + functions implicitly get access to the global state in + context. + + filename: a path to a file as it would be given to open(2). +*/ +tiff_document *tiff_open_document(fz_context *ctx, const char *filename); + +/* + tiff_open_document_with_stream: Opens a document. + + Same as tiff_open_document, but takes a stream instead of a + filename to locate the document to open. Increments the + reference count of the stream. See fz_open_file, + fz_open_file_w or fz_open_fd for opening a stream, and + fz_close for closing an open stream. +*/ +tiff_document *tiff_open_document_with_stream(fz_context *ctx, fz_stream *file); + +/* + tiff_close_document: Closes and frees an opened document. + + The resource store in the context associated with tiff_document + is emptied. + + Does not throw exceptions. +*/ +void tiff_close_document(tiff_document *doc); + +int tiff_count_pages(tiff_document *doc); +tiff_page *tiff_load_page(tiff_document *doc, int number); +fz_rect *tiff_bound_page(tiff_document *doc, tiff_page *page, fz_rect *rect); +void tiff_free_page(tiff_document *doc, tiff_page *page); +void tiff_run_page(tiff_document *doc, tiff_page *page, fz_device *dev, const fz_matrix *ctm, fz_cookie *cookie); + +#endif diff --git a/platform/android/jni/Core.mk b/platform/android/jni/Core.mk index 336d82d9..58ac8477 100644 --- a/platform/android/jni/Core.mk +++ b/platform/android/jni/Core.mk @@ -31,6 +31,7 @@ LOCAL_C_INCLUDES := \ ../../source/xps \ ../../source/cbz \ ../../source/img \ + ../../source/tiff \ ../../scripts/freetype \ ../../scripts/jpeg \ ../../scripts/openjpeg \ @@ -51,7 +52,8 @@ LOCAL_SRC_FILES := \ $(wildcard $(MY_ROOT)/source/pdf/*.c) \ $(wildcard $(MY_ROOT)/source/xps/*.c) \ $(wildcard $(MY_ROOT)/source/cbz/*.c) \ - $(wildcard $(MY_ROOT)/source/img/*.c) + $(wildcard $(MY_ROOT)/source/img/*.c) \ + $(wildcard $(MY_ROOT)/source/tiff/*.c) ifdef MEMENTO LOCAL_SRC_FILES += $(MY_ROOT)/fitz/memento.c endif diff --git a/platform/win32/libmupdf.vcproj b/platform/win32/libmupdf.vcproj index e8dc6fc6..2c80d712 100644 --- a/platform/win32/libmupdf.vcproj +++ b/platform/win32/libmupdf.vcproj @@ -1122,6 +1122,14 @@ </File> </Filter> </Filter> + <Filter + Name="tiff" + > + <File + RelativePath="..\..\source\tiff\mutiff.c" + > + </File> + </Filter> </Files> <Globals> </Globals> diff --git a/source/fitz/document-all.c b/source/fitz/document-all.c index 92b1c037..e1eb4a58 100644 --- a/source/fitz/document-all.c +++ b/source/fitz/document-all.c @@ -6,4 +6,5 @@ void fz_register_document_handlers(fz_context *ctx) fz_register_document_handler(ctx, &xps_document_handler); fz_register_document_handler(ctx, &cbz_document_handler); fz_register_document_handler(ctx, &img_document_handler); + fz_register_document_handler(ctx, &tiff_document_handler); } diff --git a/source/fitz/document-no-run.c b/source/fitz/document-no-run.c index b0defe91..2fd608ee 100644 --- a/source/fitz/document-no-run.c +++ b/source/fitz/document-no-run.c @@ -6,4 +6,5 @@ void fz_register_no_run_document_handlers(fz_context *ctx) fz_register_document_handler(ctx, &xps_document_handler); fz_register_document_handler(ctx, &cbz_document_handler); fz_register_document_handler(ctx, &img_document_handler); + fz_register_document_handler(ctx, &tiff_document_handler); } diff --git a/source/img/muimage.c b/source/img/muimage.c index 300d6603..d545068f 100644 --- a/source/img/muimage.c +++ b/source/img/muimage.c @@ -164,16 +164,13 @@ image_recognize(fz_context *doc, const char *magic) { if (!fz_strcasecmp(ext, ".png") || !fz_strcasecmp(ext, ".jpg") || !fz_strcasecmp(ext, ".jpeg") || !fz_strcasecmp(ext, ".jfif") || - !fz_strcasecmp(ext, ".jfif-tbnl") || !fz_strcasecmp(ext, ".jpe") || - !fz_strcasecmp(ext, ".tif") || !fz_strcasecmp(ext, ".tiff")) + !fz_strcasecmp(ext, ".jfif-tbnl") || !fz_strcasecmp(ext, ".jpe")) return 100; } if (!strcmp(magic, "png") || !strcmp(magic, "image/png") || !strcmp(magic, "jpg") || !strcmp(magic, "image/jpeg") || !strcmp(magic, "jpeg") || !strcmp(magic, "image/pjpeg") || - !strcmp(magic, "jpe") || !strcmp(magic, "jfif") || - !strcmp(magic, "tif") || !strcmp(magic, "image/tiff") || - !strcmp(magic, "tiff") || !strcmp(magic, "image/x-tiff")) + !strcmp(magic, "jpe") || !strcmp(magic, "jfif")) return 100; return 0; 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 +}; |