diff mupdf-source/source/cbz/muimg.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mupdf-source/source/cbz/muimg.c	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,326 @@
+// Copyright (C) 2004-2024 Artifex Software, Inc.
+//
+// This file is part of MuPDF.
+//
+// MuPDF is free software: you can redistribute it and/or modify it under the
+// terms of the GNU Affero General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or (at your option)
+// any later version.
+//
+// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
+//
+// Alternative licensing terms are available from the licensor.
+// For commercial licensing, see <https://www.artifex.com/> or contact
+// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
+// CA 94129, USA, for further information.
+
+#include "mupdf/fitz.h"
+
+#include <string.h>
+
+#define DPI 72.0f
+
+typedef struct
+{
+	fz_page super;
+	fz_image *image;
+} img_page;
+
+typedef struct
+{
+	fz_document super;
+	fz_buffer *buffer;
+	const char *format;
+	int page_count;
+	fz_pixmap *(*load_subimage)(fz_context *ctx, const unsigned char *p, size_t total, int subimage);
+} img_document;
+
+static void
+img_drop_document(fz_context *ctx, fz_document *doc_)
+{
+	img_document *doc = (img_document*)doc_;
+	fz_drop_buffer(ctx, doc->buffer);
+}
+
+static int
+img_count_pages(fz_context *ctx, fz_document *doc_, int chapter)
+{
+	img_document *doc = (img_document*)doc_;
+	return doc->page_count;
+}
+
+static fz_rect
+img_bound_page(fz_context *ctx, fz_page *page_, fz_box_type box)
+{
+	img_page *page = (img_page*)page_;
+	fz_image *image = page->image;
+	int xres, yres;
+	fz_rect bbox;
+	uint8_t orientation = fz_image_orientation(ctx, page->image);
+
+	fz_image_resolution(image, &xres, &yres);
+	bbox.x0 = bbox.y0 = 0;
+	if (orientation == 0 || (orientation & 1) == 1)
+	{
+		bbox.x1 = image->w * DPI / xres;
+		bbox.y1 = image->h * DPI / yres;
+	}
+	else
+	{
+		bbox.y1 = image->w * DPI / xres;
+		bbox.x1 = image->h * DPI / yres;
+	}
+	return bbox;
+}
+
+static void
+img_run_page(fz_context *ctx, fz_page *page_, fz_device *dev, fz_matrix ctm, fz_cookie *cookie)
+{
+	img_page *page = (img_page*)page_;
+	fz_image *image = page->image;
+	int xres, yres;
+	float w, h;
+	uint8_t orientation = fz_image_orientation(ctx, page->image);
+	fz_matrix immat = fz_image_orientation_matrix(ctx, page->image);
+
+	fz_image_resolution(image, &xres, &yres);
+	if (orientation == 0 || (orientation & 1) == 1)
+	{
+		w = image->w * DPI / xres;
+		h = image->h * DPI / yres;
+	}
+	else
+	{
+		h = image->w * DPI / xres;
+		w = image->h * DPI / yres;
+	}
+	immat = fz_post_scale(immat, w, h);
+	ctm = fz_concat(immat, ctm);
+	fz_fill_image(ctx, dev, image, ctm, 1, fz_default_color_params);
+}
+
+static void
+img_drop_page(fz_context *ctx, fz_page *page_)
+{
+	img_page *page = (img_page*)page_;
+	fz_drop_image(ctx, page->image);
+}
+
+static fz_page *
+img_load_page(fz_context *ctx, fz_document *doc_, int chapter, int number)
+{
+	img_document *doc = (img_document*)doc_;
+	fz_pixmap *pixmap = NULL;
+	fz_image *image = NULL;
+	img_page *page = NULL;
+
+	if (number < 0 || number >= doc->page_count)
+		fz_throw(ctx, FZ_ERROR_ARGUMENT, "invalid page number %d", number);
+
+	fz_var(pixmap);
+	fz_var(image);
+	fz_var(page);
+
+	fz_try(ctx)
+	{
+		if (doc->load_subimage)
+		{
+			size_t len;
+			unsigned char *data;
+			len = fz_buffer_storage(ctx, doc->buffer, &data);
+			pixmap = doc->load_subimage(ctx, data, len, number);
+			image = fz_new_image_from_pixmap(ctx, pixmap, NULL);
+		}
+		else
+		{
+			image = fz_new_image_from_buffer(ctx, doc->buffer);
+		}
+
+		page = fz_new_derived_page(ctx, img_page, doc_);
+		page->super.bound_page = img_bound_page;
+		page->super.run_page_contents = img_run_page;
+		page->super.drop_page = img_drop_page;
+		page->image = fz_keep_image(ctx, image);
+	}
+	fz_always(ctx)
+	{
+		fz_drop_image(ctx, image);
+		fz_drop_pixmap(ctx, pixmap);
+	}
+	fz_catch(ctx)
+	{
+		fz_free(ctx, page);
+		fz_rethrow(ctx);
+	}
+
+	return (fz_page*)page;
+}
+
+static int
+img_lookup_metadata(fz_context *ctx, fz_document *doc_, const char *key, char *buf, size_t size)
+{
+	img_document *doc = (img_document*)doc_;
+	if (!strcmp(key, FZ_META_FORMAT))
+		return 1 + (int)fz_strlcpy(buf, doc->format, size);
+	return -1;
+}
+
+static fz_document *
+img_open_document(fz_context *ctx, const fz_document_handler *handler, fz_stream *file, fz_stream *accel, fz_archive *dir, void *state)
+{
+	img_document *doc = fz_new_derived_document(ctx, img_document);
+
+	doc->super.drop_document = img_drop_document;
+	doc->super.count_pages = img_count_pages;
+	doc->super.load_page = img_load_page;
+	doc->super.lookup_metadata = img_lookup_metadata;
+
+	fz_try(ctx)
+	{
+		int fmt;
+		size_t len;
+		unsigned char *data;
+
+		doc->buffer = fz_read_all(ctx, file, 0);
+		len = fz_buffer_storage(ctx, doc->buffer, &data);
+
+		fmt = FZ_IMAGE_UNKNOWN;
+		if (len >= 8)
+			fmt = fz_recognize_image_format(ctx, data);
+		if (fmt == FZ_IMAGE_TIFF)
+		{
+			doc->page_count = fz_load_tiff_subimage_count(ctx, data, len);
+			doc->load_subimage = fz_load_tiff_subimage;
+			doc->format = "TIFF";
+		}
+		else if (fmt == FZ_IMAGE_PNM)
+		{
+			doc->page_count = fz_load_pnm_subimage_count(ctx, data, len);
+			doc->load_subimage = fz_load_pnm_subimage;
+			doc->format = "PNM";
+		}
+		else if (fmt == FZ_IMAGE_JBIG2)
+		{
+			doc->page_count = fz_load_jbig2_subimage_count(ctx, data, len);
+			if (doc->page_count > 1)
+				doc->load_subimage = fz_load_jbig2_subimage;
+			doc->format = "JBIG2";
+		}
+		else if (fmt == FZ_IMAGE_BMP)
+		{
+			doc->page_count = fz_load_bmp_subimage_count(ctx, data, len);
+			doc->load_subimage = fz_load_bmp_subimage;
+			doc->format = "BMP";
+		}
+		else
+		{
+			doc->page_count = 1;
+			doc->format = "Image";
+		}
+	}
+	fz_catch(ctx)
+	{
+		fz_drop_document(ctx, (fz_document*)doc);
+		fz_rethrow(ctx);
+	}
+
+	return (fz_document*)doc;
+}
+
+static int
+img_recognize_content(fz_context *ctx, const fz_document_handler *handler, fz_stream *stream, fz_archive *dir, void **state, fz_document_recognize_state_free_fn **free_state)
+{
+	unsigned char data[8];
+	size_t n;
+	int fmt;
+
+	if (stream == NULL)
+		return 0;
+
+	if (state)
+		*state = NULL;
+	if (free_state)
+		*free_state = NULL;
+
+	n = fz_read(ctx, stream, data, 8);
+
+	if (n != 8)
+		return 0;
+
+	fmt = fz_recognize_image_format(ctx, data);
+	if (fmt != FZ_IMAGE_UNKNOWN)
+		return 100;
+
+	return 0;
+}
+
+static const char *img_extensions[] =
+{
+	"bmp",
+	"gif",
+	"hdp",
+	"j2k",
+	"jb2",
+	"jbig2",
+	"jfif",
+	"jfif-tbnl",
+	"jp2",
+	"jpe",
+	"jpeg",
+	"jpg",
+	"jpx",
+	"jxr",
+	"pam",
+	"pbm",
+	"pfm",
+	"pgm",
+	"pkm",
+	"png",
+	"pnm",
+	"ppm",
+	"psd",
+	"tif",
+	"tiff",
+	"wdp",
+	NULL
+};
+
+static const char *img_mimetypes[] =
+{
+	"image/bmp",
+	"image/gif",
+	"image/jp2",
+	"image/jpeg",
+	"image/jpx",
+	"image/jxr",
+	"image/pjpeg",
+	"image/png",
+	"image/tiff",
+	"image/vnd.ms-photo",
+	"image/vnd.adobe.photoshop",
+	"image/x-jb2",
+	"image/x-jbig2",
+	"image/x-portable-anymap",
+	"image/x-portable-arbitrarymap",
+	"image/x-portable-bitmap",
+	"image/x-portable-greymap",
+	"image/x-portable-pixmap",
+	"image/x-portable-floatmap",
+	"image/x-tiff",
+	NULL
+};
+
+fz_document_handler img_document_handler =
+{
+	NULL,
+	img_open_document,
+	img_extensions,
+	img_mimetypes,
+	img_recognize_content
+};