summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2014-02-10 16:54:24 +0000
committerRobin Watts <robin.watts@artifex.com>2014-02-10 17:04:03 +0000
commita4a50269b2c62fddf34445140036e3f61b500d9e (patch)
treee5ab2bf4e75d0b96f0cced8f8e42dde3e564dc54
parent9b9438fa4210b29023f85bb98c73f8f58a7760d5 (diff)
downloadmupdf-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--Makefile7
-rw-r--r--include/mupdf/fitz/document.h1
-rw-r--r--include/mupdf/tiff.h51
-rw-r--r--platform/android/jni/Core.mk4
-rw-r--r--platform/win32/libmupdf.vcproj8
-rw-r--r--source/fitz/document-all.c1
-rw-r--r--source/fitz/document-no-run.c1
-rw-r--r--source/img/muimage.c7
-rw-r--r--source/tiff/mutiff.c207
9 files changed, 280 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index d94d6b69..be650cc3 100644
--- a/Makefile
+++ b/Makefile
@@ -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
+};