diff --git a/PKG-INFO b/PKG-INFO
index 28dca9496..9bd51e4a1 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: PyMuPDF
-Version: 1.14.7
+Version: 1.14.8
Author: Ruikai Liu
Author-email: lrk700@gmail.com
Maintainer: Ruikai Liu
@@ -10,7 +10,7 @@ Download-url: https://github.com/rk700/PyMuPDF
Summary: PyMuPDF is a Python binding for the PDF rendering library MuPDF
Description:
- Release date: January 15, 2019
+ Release date: January 31, 2019
Authors
=======
@@ -21,7 +21,7 @@ Description:
Introduction
============
- This is **version 1.14.7 of PyMuPDF**, a Python binding for `MuPDF `_ - "a lightweight PDF and XPS viewer".
+ This is **version 1.14.8 of PyMuPDF**, a Python binding for `MuPDF `_ - "a lightweight PDF and XPS viewer".
MuPDF can access files in PDF, XPS, OpenXPS, epub, comic and fiction book formats, and it is known for both, its top performance and high rendering quality.
diff --git a/README.md b/README.md
index 15efd2e4f..526b0e9c8 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# PyMuPDF 1.14.7
+# PyMuPDF 1.14.8
![logo](https://github.com/rk700/PyMuPDF/blob/master/demo/pymupdf.jpg)
@@ -14,7 +14,7 @@ On **[PyPI](https://pypi.org/project/PyMuPDF)** since August 2016: [![](https://
# Introduction
-This is **version 1.14.7 of PyMuPDF (formerly python-fitz)**, a Python binding with support for [MuPDF 1.14.x](http://mupdf.com/) - "a lightweight PDF, XPS, and E-book viewer".
+This is **version 1.14.8 of PyMuPDF (formerly python-fitz)**, a Python binding with support for [MuPDF 1.14.x](http://mupdf.com/) - "a lightweight PDF, XPS, and E-book viewer".
MuPDF can access files in PDF, XPS, OpenXPS, CBZ, EPUB and FB2 (e-books) formats, and it is known for its top performance and high rendering quality.
@@ -61,21 +61,23 @@ In addition to wheels, this platform offers [pre-generated binaries](https://git
If you are looking to make your own binary, consult this [Wiki page](https://github.com/rk700/PyMuPDF/wiki/Windows-Binaries-Generation). It explains how to use Visual Studio for generating MuPDF in quite some detail.
# Usage and Documentation
-For all document types you can render pages in raster (PNG) or vector (SVG) formats, extract text and access meta information, links, annotations and bookmarks, as well as decrypt the document. For PDF files, most of these objects can also be created, modified or deleted. Plus you can rotate, re-arrange, duplicate, create, or delete pages and join or split documents.
+For all document types you can render pages in raster (PNG) or vector (SVG) formats, extract text and images, and access meta information, links, annotations and bookmarks, as well as decrypt the document.
-Specifically for PDF files, PyMuPDF provides update access to low-level structure data, supports handling of embedded files and modification of page contents (like inserting images, fonts, text, annotations and drawings).
+For PDF files, most of these objects can also be created, modified or deleted. Plus you can rotate, re-arrange, duplicate, create, delete and split or join **pages** and you can **join or split PDF** documents.
+
+Specifically for **PDF files**, PyMuPDF also provides update access to **low-level structure** data, supports handling of embedded files and modification of **page contents** (like inserting images, fonts, text, annotations and drawings).
Other features include embedding vector images (SVG, PDF) such as logos or watermarks, "posterizing" a PDF or creating "booklet" and "4-up" versions.
-You can now also create and update Form PDFs and form fields with support for text, checkbox, listbox and combobox widgets.
+You can now also create and update **Form PDFs** and **form fields** with support for text, checkbox, listbox and combobox widgets.
-To some degree, PyMuPDF can also be used as an [image converter](https://github.com/rk700/PyMuPDF/wiki/How-to-Convert-Images): it can read a broad range of input formats and can produce **Portable Network Graphics (PNG)**, **Portable Anymaps** (PNM, etc.), **Portable Arbitrary Maps (PAM)**, **Targa Image Files (TGA)**, **Adobe Postscript** and **Adobe Photoshop** documents, making the use of other graphics packages obselete in many cases. Interfacing with PIL/Pillow is easy as well.
+To some degree, PyMuPDF can also be used as an [image converter](https://github.com/rk700/PyMuPDF/wiki/How-to-Convert-Images): it can read a broad range of input formats and can produce **Portable Network Graphics (PNG)**, **Portable Anymaps** (**PNM**, etc.), **Portable Arbitrary Maps (PAM)**, **Adobe Postscript** and **Adobe Photoshop** documents, making the use of other graphics packages obselete in many cases. But interfacing with e.g. PIL/Pillow for image input and output is easy as well.
Have a look at the basic [demos](https://github.com/rk700/PyMuPDF/tree/master/demo), the [examples](https://github.com/rk700/PyMuPDF/tree/master/examples) (which contain complete, working programs), and the **recipes** section of our [Wiki](https://github.com/rk700/PyMuPDF/wiki) sidebar, which contains more than a dozen of guides in How-To-style.
-Our **documentation**, written using Sphinx, is available in various formats from the following sources. It currently is a combination of a reference guide and a user manual. For a quick start to using PyMuPDF look at the [tutorial](https://pymupdf.readthedocs.io/en/latest/tutorial/) and the [recipes](https://pymupdf.readthedocs.io/en/latest/faq/) chapters.
+Our **documentation**, written using Sphinx, is available in various formats from the following sources. It currently is a combination of a reference guide and a user manual. For a **quick start** look at the [tutorial](https://pymupdf.readthedocs.io/en/latest/tutorial/) and the [recipes](https://pymupdf.readthedocs.io/en/latest/faq/) chapters.
-* You can view it online at [Read the Docs](https://pymupdf.readthedocs.io/). For **best quality downloads** use the following links.
+* You can view it online at [Read the Docs](https://pymupdf.readthedocs.io/). For **best quality downloads** you should however use the following links.
* zipped [HTML](https://github.com/rk700/PyMuPDF/tree/master/doc/html.zip)
* [Windows CHM](https://github.com/JorjMcKie/PyMuPDF-optional-material/tree/master/doc/PyMuPDF.chm)
* [PDF](https://github.com/rk700/PyMuPDF/blob/master/doc/PyMuPDF.pdf)
diff --git a/fitz/fitz.i b/fitz/fitz.i
index 4d37d4513..640b2d021 100644
--- a/fitz/fitz.i
+++ b/fitz/fitz.i
@@ -181,6 +181,7 @@ fitz_py2 = str is bytes # if true, this is Python 2
%include helper-other.i
%include helper-out-barray.i
%include helper-write-c.i
+%include helper-pixmap.i
%include helper-geo-py.i
%include helper-annot.i
%include helper-stext.i
@@ -1391,7 +1392,9 @@ if links:
cbuf = fz_compressed_image_buffer(gctx, image);
type = cbuf == NULL ? FZ_IMAGE_UNKNOWN : cbuf->params.type;
// ensure returning a PNG for unsupported images ----------
- if (type < FZ_IMAGE_BMP) type = FZ_IMAGE_UNKNOWN;
+ if (type < FZ_IMAGE_BMP ||
+ type == FZ_IMAGE_JBIG2)
+ type = FZ_IMAGE_UNKNOWN;
pdf_obj *o = pdf_dict_get(gctx, obj, PDF_NAME(SMask));
if (o) smask = pdf_to_num(gctx, o);
@@ -3768,7 +3771,7 @@ struct fz_pixmap_s
//----------------------------------------------------------------------
void clearWith(int value, PyObject *bbox)
{
- fz_clear_pixmap_rect_with_value(gctx, $self, value, JM_irect_from_py(bbox));
+ JM_clear_pixmap_rect_with_value(gctx, $self, value, JM_irect_from_py(bbox));
}
//----------------------------------------------------------------------
@@ -3964,10 +3967,11 @@ def writePNG(self, filename, savealpha = -1):
}
fz_irect r = JM_irect_from_py(irect);
- if (!fz_is_infinite_irect(r))
- fz_invert_pixmap_rect(gctx, $self, r);
- else
- fz_invert_pixmap(gctx, $self);
+ if (fz_is_infinite_irect(r))
+ r = fz_pixmap_bbox(gctx, $self);
+
+ JM_invert_pixmap_rect(gctx, $self, r);
+
}
//----------------------------------------------------------------------
@@ -3996,7 +4000,7 @@ def writePNG(self, filename, savealpha = -1):
}
//----------------------------------------------------------------------
- // Set one pixel given as a sequence
+ // Set one pixel to a given color tuple
//----------------------------------------------------------------------
FITZEXCEPTION(setPixel, !result)
%feature("autodoc","Set the pixel at (x,y) to the integers in sequence 'value'.") setPixel;
@@ -4032,6 +4036,36 @@ def writePNG(self, filename, savealpha = -1):
return NONE;
}
+ //----------------------------------------------------------------------
+ // Set a rect to a given color tuple
+ //----------------------------------------------------------------------
+ FITZEXCEPTION(setRect, !result)
+ %feature("autodoc","Set a rectangle to the integers in sequence 'value'.") setRect;
+ PyObject *setRect(PyObject *irect, PyObject *value)
+ {
+ fz_try(gctx)
+ {
+ int n = $self->n;
+ if (!PySequence_Check(value) || PySequence_Size(value) != n)
+ THROWMSG("bad pixel value");
+ int i, j;
+ unsigned char c[5];
+ for (j = 0; j < n; j++)
+ {
+ i = (int) PyInt_AsLong(PySequence_ITEM(value, j));
+ if (!INRANGE(i, 0, 255)) THROWMSG("bad pixel component");
+ c[j] = (unsigned char) i;
+ }
+ JM_fill_pixmap_rect_with_color(gctx, $self, c, JM_irect_from_py(irect));
+ }
+ fz_catch(gctx)
+ {
+ PyErr_Clear();
+ return NULL;
+ }
+ return NONE;
+ }
+
//----------------------------------------------------------------------
// get length of one image row
//----------------------------------------------------------------------
diff --git a/fitz/fitz.py b/fitz/fitz.py
index b22231d6d..4ecf6f0cb 100644
--- a/fitz/fitz.py
+++ b/fitz/fitz.py
@@ -105,9 +105,9 @@ class _object:
VersionFitz = "1.14.0"
-VersionBind = "1.14.7"
-VersionDate = "2019-01-17 16:53:54"
-version = (VersionBind, VersionFitz, "20190117165354")
+VersionBind = "1.14.8"
+VersionDate = "2019-01-30 16:03:25"
+version = (VersionBind, VersionFitz, "20190130160325")
class Matrix():
@@ -407,13 +407,16 @@ def abs_unit(self):
def distance_to(self, *args):
"""Return the distance to a rectangle or another point."""
- assert len(args) > 0, "at least one parameter must be given"
+ if not len(args) > 0:
+ raise ValueError("at least one parameter must be given")
+
x = args[0]
if len(args) > 1:
unit = args[1]
else:
unit = "px"
- u = {"px": (1.,1.), "in": (1.,72.), "cm": (2.54, 72.), "mm": (25.4, 72.)}
+ u = {"px": (1.,1.), "in": (1.,72.), "cm": (2.54, 72.),
+ "mm": (25.4, 72.)}
f = u[unit][0] / u[unit][1]
if type(x) is Point:
return abs(self - x) * f
@@ -3248,6 +3251,11 @@ def setPixel(self, x, y, value):
"""Set the pixel at (x,y) to the integers in sequence 'value'."""
return _fitz.Pixmap_setPixel(self, x, y, value)
+
+ def setRect(self, irect, value):
+ """Set a rectangle to the integers in sequence 'value'."""
+ return _fitz.Pixmap_setRect(self, irect, value)
+
@property
def stride(self):
diff --git a/fitz/fitz_wrap.c b/fitz/fitz_wrap.c
index 8e6ba28b3..9638e014c 100644
--- a/fitz/fitz_wrap.c
+++ b/fitz/fitz_wrap.c
@@ -7106,6 +7106,132 @@ void JM_save_document(fz_context *ctx, pdf_document *doc, const char *filename,
}
+//-----------------------------------------------------------------------------
+// pixmap helper functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Clear a pixmap rectangle - my version also supports non-alpha pixmaps
+//-----------------------------------------------------------------------------
+void
+JM_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *dest, int value, fz_irect b)
+{
+ unsigned char *destp;
+ int x, y, w, k, destspan;
+
+ b = fz_intersect_irect(b, fz_pixmap_bbox(ctx, dest));
+ w = b.x1 - b.x0;
+ y = b.y1 - b.y0;
+ if (w <= 0 || y <= 0)
+ return;
+
+ destspan = dest->stride;
+ destp = dest->samples + (unsigned int)(destspan * (b.y0 - dest->y) + dest->n * (b.x0 - dest->x));
+
+ /* CMYK needs special handling (and potentially any other subtractive colorspaces) */
+ if (fz_colorspace_n(ctx, dest->colorspace) == 4)
+ {
+ value = 255 - value;
+ do
+ {
+ unsigned char *s = destp;
+ for (x = 0; x < w; x++)
+ {
+ *s++ = 0;
+ *s++ = 0;
+ *s++ = 0;
+ *s++ = value;
+ if (dest->alpha) *s++ = 255;
+ }
+ destp += destspan;
+ }
+ while (--y);
+ return;
+ }
+
+ do
+ {
+ unsigned char *s = destp;
+ for (x = 0; x < w; x++)
+ {
+ for (k = 0; k < dest->n - 1; k++)
+ *s++ = value;
+ if (dest->alpha) *s++ = 255;
+ else *s++ = value;
+ }
+ destp += destspan;
+ }
+ while (--y);
+}
+
+//-----------------------------------------------------------------------------
+// fill a rect with a color tuple
+//-----------------------------------------------------------------------------
+void
+JM_fill_pixmap_rect_with_color(fz_context *ctx, fz_pixmap *dest, unsigned char col[5], fz_irect b)
+{
+ unsigned char *destp;
+ int x, y, w, i, destspan;
+
+ b = fz_intersect_irect(b, fz_pixmap_bbox(ctx, dest));
+ w = b.x1 - b.x0;
+ y = b.y1 - b.y0;
+ if (w <= 0 || y <= 0)
+ return;
+
+ destspan = dest->stride;
+ destp = dest->samples + (unsigned int)(destspan * (b.y0 - dest->y) + dest->n * (b.x0 - dest->x));
+
+ do
+ {
+ unsigned char *s = destp;
+ for (x = 0; x < w; x++)
+ {
+ for (i = 0; i < dest->n; i++)
+ *s++ = col[i];
+ }
+ destp += destspan;
+ }
+ while (--y);
+}
+
+//-----------------------------------------------------------------------------
+// invert a rectangle - also supports non-alpha pixmaps
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// fill a rect with a color tuple
+//-----------------------------------------------------------------------------
+void
+JM_invert_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_irect b)
+{
+ unsigned char *destp;
+ int x, y, w, i, destspan;
+
+ b = fz_intersect_irect(b, fz_pixmap_bbox(ctx, dest));
+ w = b.x1 - b.x0;
+ y = b.y1 - b.y0;
+ if (w <= 0 || y <= 0)
+ return;
+
+ destspan = dest->stride;
+ destp = dest->samples + (unsigned int)(destspan * (b.y0 - dest->y) + dest->n * (b.x0 - dest->x));
+ int n0 = dest->n - dest->alpha;
+ do
+ {
+ unsigned char *s = destp;
+ for (x = 0; x < w; x++)
+ {
+ for (i = 0; i < n0; i++)
+ *s++ = 255 - *s;
+ if (dest->alpha) *s++;
+ }
+ destp += destspan;
+ }
+ while (--y);
+}
+
+
+
//----------------------------------------------------------------------------
// annotation types
//----------------------------------------------------------------------------
@@ -7814,18 +7940,17 @@ JM_extract_stext_imageblock_as_dict(fz_context *ctx, fz_stext_block *block)
{
fz_image *image = block->u.i.image;
fz_buffer *buf = NULL, *freebuf = NULL;
+ fz_compressed_buffer *buffer = fz_compressed_image_buffer(ctx, image);
fz_var(buf);
fz_var(freebuf);
- fz_compressed_buffer *buffer = NULL;
int n = fz_colorspace_n(ctx, image->colorspace);
int w = image->w;
int h = image->h;
- int type = 0;
+ int type = FZ_IMAGE_UNKNOWN;
+ if (buffer) type = buffer->params.type;
unsigned char ext[5];
PyObject *bytes = JM_BinFromChar("");
fz_var(bytes);
- buffer = fz_compressed_image_buffer(ctx, image);
- if (buffer) type = buffer->params.type;
PyObject *dict = PyDict_New();
PyDict_SetItemString(dict, "type", PyInt_FromLong(FZ_STEXT_BLOCK_IMAGE));
PyDict_SetItemString(dict, "bbox", Py_BuildValue("[ffff]",
@@ -7835,12 +7960,14 @@ JM_extract_stext_imageblock_as_dict(fz_context *ctx, fz_stext_block *block)
PyDict_SetItemString(dict, "height", PyInt_FromLong((long) h));
fz_try(ctx)
{
- if (image->use_colorkey) type = FZ_IMAGE_UNKNOWN;
- if (image->use_decode) type = FZ_IMAGE_UNKNOWN;
- if (image->mask) type = FZ_IMAGE_UNKNOWN;
- if (type < FZ_IMAGE_BMP) type = FZ_IMAGE_UNKNOWN;
- if (n != 1 && n != 3 && type == FZ_IMAGE_JPEG)
+ if (image->use_colorkey ||
+ image->use_decode ||
+ image->mask ||
+ type < FZ_IMAGE_BMP ||
+ type == FZ_IMAGE_JBIG2 ||
+ n != 1 && n != 3 && type == FZ_IMAGE_JPEG)
type = FZ_IMAGE_UNKNOWN;
+
if (type != FZ_IMAGE_UNKNOWN)
{
buf = buffer->buffer;
@@ -10480,7 +10607,9 @@ SWIGINTERN PyObject *fz_document_s_extractImage(struct fz_document_s *self,int x
cbuf = fz_compressed_image_buffer(gctx, image);
type = cbuf == NULL ? FZ_IMAGE_UNKNOWN : cbuf->params.type;
// ensure returning a PNG for unsupported images ----------
- if (type < FZ_IMAGE_BMP) type = FZ_IMAGE_UNKNOWN;
+ if (type < FZ_IMAGE_BMP ||
+ type == FZ_IMAGE_JBIG2)
+ type = FZ_IMAGE_UNKNOWN;
pdf_obj *o = pdf_dict_get(gctx, obj, PDF_NAME(SMask));
if (o) smask = pdf_to_num(gctx, o);
@@ -12025,7 +12154,7 @@ SWIGINTERN void fz_pixmap_s_clearWith__SWIG_1(struct fz_pixmap_s *self,int value
fz_clear_pixmap_with_value(gctx, self, value);
}
SWIGINTERN void fz_pixmap_s_clearWith__SWIG_2(struct fz_pixmap_s *self,int value,PyObject *bbox){
- fz_clear_pixmap_rect_with_value(gctx, self, value, JM_irect_from_py(bbox));
+ JM_clear_pixmap_rect_with_value(gctx, self, value, JM_irect_from_py(bbox));
}
SWIGINTERN PyObject *fz_pixmap_s_copyPixmap(struct fz_pixmap_s *self,struct fz_pixmap_s *src,PyObject *bbox){
fz_try(gctx)
@@ -12152,10 +12281,11 @@ SWIGINTERN void fz_pixmap_s_invertIRect(struct fz_pixmap_s *self,PyObject *irect
}
fz_irect r = JM_irect_from_py(irect);
- if (!fz_is_infinite_irect(r))
- fz_invert_pixmap_rect(gctx, self, r);
- else
- fz_invert_pixmap(gctx, self);
+ if (fz_is_infinite_irect(r))
+ r = fz_pixmap_bbox(gctx, self);
+
+ JM_invert_pixmap_rect(gctx, self, r);
+
}
SWIGINTERN PyObject *fz_pixmap_s_pixel(struct fz_pixmap_s *self,int x,int y){
PyObject *p = NULL;
@@ -12205,6 +12335,29 @@ SWIGINTERN PyObject *fz_pixmap_s_setPixel(struct fz_pixmap_s *self,int x,int y,P
}
return NONE;
}
+SWIGINTERN PyObject *fz_pixmap_s_setRect(struct fz_pixmap_s *self,PyObject *irect,PyObject *value){
+ fz_try(gctx)
+ {
+ int n = self->n;
+ if (!PySequence_Check(value) || PySequence_Size(value) != n)
+ THROWMSG("bad pixel value");
+ int i, j;
+ unsigned char c[5];
+ for (j = 0; j < n; j++)
+ {
+ i = (int) PyInt_AsLong(PySequence_ITEM(value, j));
+ if (!INRANGE(i, 0, 255)) THROWMSG("bad pixel component");
+ c[j] = (unsigned char) i;
+ }
+ JM_fill_pixmap_rect_with_color(gctx, self, c, JM_irect_from_py(irect));
+ }
+ fz_catch(gctx)
+ {
+ PyErr_Clear();
+ return NULL;
+ }
+ return NONE;
+ }
SWIGINTERN int fz_pixmap_s_stride(struct fz_pixmap_s *self){
return fz_pixmap_stride(gctx, self);
}
@@ -18807,6 +18960,41 @@ SWIGINTERN PyObject *_wrap_Pixmap_setPixel(PyObject *SWIGUNUSEDPARM(self), PyObj
}
+SWIGINTERN PyObject *_wrap_Pixmap_setRect(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+ PyObject *resultobj = 0;
+ struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ;
+ PyObject *arg2 = (PyObject *) 0 ;
+ PyObject *arg3 = (PyObject *) 0 ;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ PyObject * obj0 = 0 ;
+ PyObject * obj1 = 0 ;
+ PyObject * obj2 = 0 ;
+ PyObject *result = 0 ;
+
+ if (!PyArg_ParseTuple(args,(char *)"OOO:Pixmap_setRect",&obj0,&obj1,&obj2)) SWIG_fail;
+ res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_pixmap_s, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_setRect" "', argument " "1"" of type '" "struct fz_pixmap_s *""'");
+ }
+ arg1 = (struct fz_pixmap_s *)(argp1);
+ arg2 = obj1;
+ arg3 = obj2;
+ {
+ result = (PyObject *)fz_pixmap_s_setRect(arg1,arg2,arg3);
+ if(!result)
+ {
+ PyErr_SetString(PyExc_RuntimeError, fz_caught_message(gctx));
+ return NULL;
+ }
+ }
+ resultobj = result;
+ return resultobj;
+fail:
+ return NULL;
+}
+
+
SWIGINTERN PyObject *_wrap_Pixmap_stride(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ;
@@ -21885,6 +22073,7 @@ static PyMethodDef SwigMethods[] = {
{ (char *)"Pixmap_invertIRect", _wrap_Pixmap_invertIRect, METH_VARARGS, (char *)"Pixmap_invertIRect(self, irect=None)"},
{ (char *)"Pixmap_pixel", _wrap_Pixmap_pixel, METH_VARARGS, (char *)"Return the pixel at (x,y) as a list. Last item is the alpha if Pixmap.alpha is true."},
{ (char *)"Pixmap_setPixel", _wrap_Pixmap_setPixel, METH_VARARGS, (char *)"Set the pixel at (x,y) to the integers in sequence 'value'."},
+ { (char *)"Pixmap_setRect", _wrap_Pixmap_setRect, METH_VARARGS, (char *)"Set a rectangle to the integers in sequence 'value'."},
{ (char *)"Pixmap_stride", _wrap_Pixmap_stride, METH_VARARGS, (char *)"Pixmap_stride(self) -> int"},
{ (char *)"Pixmap_alpha", _wrap_Pixmap_alpha, METH_VARARGS, (char *)"Pixmap_alpha(self) -> int"},
{ (char *)"Pixmap_colorspace", _wrap_Pixmap_colorspace, METH_VARARGS, (char *)"Pixmap_colorspace(self) -> Colorspace"},
diff --git a/fitz/helper-geo-py.i b/fitz/helper-geo-py.i
index 3b6e2c29a..05d83381d 100644
--- a/fitz/helper-geo-py.i
+++ b/fitz/helper-geo-py.i
@@ -296,13 +296,16 @@ class Point():
def distance_to(self, *args):
"""Return the distance to a rectangle or another point."""
- assert len(args) > 0, "at least one parameter must be given"
+ if not len(args) > 0:
+ raise ValueError("at least one parameter must be given")
+
x = args[0]
if len(args) > 1:
unit = args[1]
else:
unit = "px"
- u = {"px": (1.,1.), "in": (1.,72.), "cm": (2.54, 72.), "mm": (25.4, 72.)}
+ u = {"px": (1.,1.), "in": (1.,72.), "cm": (2.54, 72.),
+ "mm": (25.4, 72.)}
f = u[unit][0] / u[unit][1]
if type(x) is Point:
return abs(self - x) * f
diff --git a/fitz/helper-pixmap.i b/fitz/helper-pixmap.i
new file mode 100644
index 000000000..b7dae34a7
--- /dev/null
+++ b/fitz/helper-pixmap.i
@@ -0,0 +1,126 @@
+%{
+//-----------------------------------------------------------------------------
+// pixmap helper functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Clear a pixmap rectangle - my version also supports non-alpha pixmaps
+//-----------------------------------------------------------------------------
+void
+JM_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *dest, int value, fz_irect b)
+{
+ unsigned char *destp;
+ int x, y, w, k, destspan;
+
+ b = fz_intersect_irect(b, fz_pixmap_bbox(ctx, dest));
+ w = b.x1 - b.x0;
+ y = b.y1 - b.y0;
+ if (w <= 0 || y <= 0)
+ return;
+
+ destspan = dest->stride;
+ destp = dest->samples + (unsigned int)(destspan * (b.y0 - dest->y) + dest->n * (b.x0 - dest->x));
+
+ /* CMYK needs special handling (and potentially any other subtractive colorspaces) */
+ if (fz_colorspace_n(ctx, dest->colorspace) == 4)
+ {
+ value = 255 - value;
+ do
+ {
+ unsigned char *s = destp;
+ for (x = 0; x < w; x++)
+ {
+ *s++ = 0;
+ *s++ = 0;
+ *s++ = 0;
+ *s++ = value;
+ if (dest->alpha) *s++ = 255;
+ }
+ destp += destspan;
+ }
+ while (--y);
+ return;
+ }
+
+ do
+ {
+ unsigned char *s = destp;
+ for (x = 0; x < w; x++)
+ {
+ for (k = 0; k < dest->n - 1; k++)
+ *s++ = value;
+ if (dest->alpha) *s++ = 255;
+ else *s++ = value;
+ }
+ destp += destspan;
+ }
+ while (--y);
+}
+
+//-----------------------------------------------------------------------------
+// fill a rect with a color tuple
+//-----------------------------------------------------------------------------
+void
+JM_fill_pixmap_rect_with_color(fz_context *ctx, fz_pixmap *dest, unsigned char col[5], fz_irect b)
+{
+ unsigned char *destp;
+ int x, y, w, i, destspan;
+
+ b = fz_intersect_irect(b, fz_pixmap_bbox(ctx, dest));
+ w = b.x1 - b.x0;
+ y = b.y1 - b.y0;
+ if (w <= 0 || y <= 0)
+ return;
+
+ destspan = dest->stride;
+ destp = dest->samples + (unsigned int)(destspan * (b.y0 - dest->y) + dest->n * (b.x0 - dest->x));
+
+ do
+ {
+ unsigned char *s = destp;
+ for (x = 0; x < w; x++)
+ {
+ for (i = 0; i < dest->n; i++)
+ *s++ = col[i];
+ }
+ destp += destspan;
+ }
+ while (--y);
+}
+
+//-----------------------------------------------------------------------------
+// invert a rectangle - also supports non-alpha pixmaps
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// fill a rect with a color tuple
+//-----------------------------------------------------------------------------
+void
+JM_invert_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_irect b)
+{
+ unsigned char *destp;
+ int x, y, w, i, destspan;
+
+ b = fz_intersect_irect(b, fz_pixmap_bbox(ctx, dest));
+ w = b.x1 - b.x0;
+ y = b.y1 - b.y0;
+ if (w <= 0 || y <= 0)
+ return;
+
+ destspan = dest->stride;
+ destp = dest->samples + (unsigned int)(destspan * (b.y0 - dest->y) + dest->n * (b.x0 - dest->x));
+ int n0 = dest->n - dest->alpha;
+ do
+ {
+ unsigned char *s = destp;
+ for (x = 0; x < w; x++)
+ {
+ for (i = 0; i < n0; i++)
+ *s++ = 255 - *s;
+ if (dest->alpha) *s++;
+ }
+ destp += destspan;
+ }
+ while (--y);
+}
+
+%}
\ No newline at end of file
diff --git a/fitz/helper-stext.i b/fitz/helper-stext.i
index 088b01697..ae5e8048b 100644
--- a/fitz/helper-stext.i
+++ b/fitz/helper-stext.i
@@ -242,18 +242,17 @@ JM_extract_stext_imageblock_as_dict(fz_context *ctx, fz_stext_block *block)
{
fz_image *image = block->u.i.image;
fz_buffer *buf = NULL, *freebuf = NULL;
+ fz_compressed_buffer *buffer = fz_compressed_image_buffer(ctx, image);
fz_var(buf);
fz_var(freebuf);
- fz_compressed_buffer *buffer = NULL;
int n = fz_colorspace_n(ctx, image->colorspace);
int w = image->w;
int h = image->h;
- int type = 0;
+ int type = FZ_IMAGE_UNKNOWN;
+ if (buffer) type = buffer->params.type;
unsigned char ext[5];
PyObject *bytes = JM_BinFromChar("");
fz_var(bytes);
- buffer = fz_compressed_image_buffer(ctx, image);
- if (buffer) type = buffer->params.type;
PyObject *dict = PyDict_New();
PyDict_SetItemString(dict, "type", PyInt_FromLong(FZ_STEXT_BLOCK_IMAGE));
PyDict_SetItemString(dict, "bbox", Py_BuildValue("[ffff]",
@@ -263,12 +262,14 @@ JM_extract_stext_imageblock_as_dict(fz_context *ctx, fz_stext_block *block)
PyDict_SetItemString(dict, "height", PyInt_FromLong((long) h));
fz_try(ctx)
{
- if (image->use_colorkey) type = FZ_IMAGE_UNKNOWN;
- if (image->use_decode) type = FZ_IMAGE_UNKNOWN;
- if (image->mask) type = FZ_IMAGE_UNKNOWN;
- if (type < FZ_IMAGE_BMP) type = FZ_IMAGE_UNKNOWN;
- if (n != 1 && n != 3 && type == FZ_IMAGE_JPEG)
+ if (image->use_colorkey ||
+ image->use_decode ||
+ image->mask ||
+ type < FZ_IMAGE_BMP ||
+ type == FZ_IMAGE_JBIG2 ||
+ n != 1 && n != 3 && type == FZ_IMAGE_JPEG)
type = FZ_IMAGE_UNKNOWN;
+
if (type != FZ_IMAGE_UNKNOWN)
{
buf = buffer->buffer;
diff --git a/fitz/utils.py b/fitz/utils.py
index 3b7c6114e..73699cf8c 100644
--- a/fitz/utils.py
+++ b/fitz/utils.py
@@ -167,7 +167,8 @@ def getPixmap(page, matrix = None, colorspace = csRGB, clip = None,
cs = csCMYK
else:
cs = csRGB
- assert cs.n in (1,3,4), "unsupported colorspace"
+ if cs.n not in (1,3,4):
+ raise ValueError("unsupported colorspace")
dl = page.getDisplayList() # create DisplayList
if clip:
@@ -731,7 +732,9 @@ def updateLink(page, lnk):
""" Update a link on the current page. """
CheckParent(page)
annot = getLinkText(page, lnk)
- assert annot != "", "link kind not supported"
+ if annot == "":
+ raise ValueError("link kind not supported")
+
page.parent._updateObject(lnk["xref"], annot, page = page)
return
@@ -739,7 +742,9 @@ def insertLink(page, lnk, mark = True):
""" Insert a new link for the current page. """
CheckParent(page)
annot = getLinkText(page, lnk)
- assert annot != "", "link kind not supported"
+ if annot == "":
+ raise ValueError("link kind not supported")
+
page._addAnnot_FromString([annot])
return
@@ -2069,7 +2074,9 @@ def insertText(self, point, buffer,
CheckColor(color)
morphing = CheckMorph(morph)
rot = rotate
- assert rot % 90 == 0, "rotate not multiple of 90"
+ if rot % 90 != 0:
+ raise ValueError("rotate not multiple of 90")
+
while rot < 0: rot += 360
rot = rot % 360 # text rotate = 0, 90, 270, 180
red, green, blue = color if color else (0,0,0)
@@ -2175,7 +2182,9 @@ def insertTextbox(self, rect, buffer,
if rect.isEmpty or rect.isInfinite:
raise ValueError("text box must be finite and not empty")
CheckColor(color)
- assert rotate % 90 == 0, "rotate must be multiple of 90"
+ if rotate % 90 != 0:
+ raise ValueError("rotate must be multiple of 90")
+
rot = rotate
while rot < 0: rot += 360
rot = rot % 360
diff --git a/fitz/version.i b/fitz/version.i
index b5e1bcf0c..296b67f43 100644
--- a/fitz/version.i
+++ b/fitz/version.i
@@ -1,6 +1,6 @@
%pythoncode %{
VersionFitz = "1.14.0"
-VersionBind = "1.14.7"
-VersionDate = "2019-01-17 16:53:54"
-version = (VersionBind, VersionFitz, "20190117165354")
+VersionBind = "1.14.8"
+VersionDate = "2019-01-30 16:03:25"
+version = (VersionBind, VersionFitz, "20190130160325")
%}
\ No newline at end of file
diff --git a/nano_setup.py b/nano_setup.py
index 98edfbab3..5cfb27357 100644
--- a/nano_setup.py
+++ b/nano_setup.py
@@ -52,7 +52,7 @@
sources=['./fitz/fitz_wrap.c',])
setup(name = 'PyMuPDF',
- version = "1.14.7",
+ version = "1.14.8",
description = 'Python bindings for the PDF rendering library MuPDF',
classifiers = ['Development Status :: 5 - Production/Stable',
'Environment :: Console',
diff --git a/setup.py b/setup.py
index 86b9e5c88..0c7c0b821 100644
--- a/setup.py
+++ b/setup.py
@@ -67,7 +67,7 @@
long_desc = "\n".join(long_dtab)
setup(name = 'PyMuPDF',
- version = "1.14.7",
+ version = "1.14.8",
description = 'Python bindings for the PDF rendering library MuPDF',
long_description = long_desc,
classifiers = classifier,