def goto_page(self, page_number=None, zoom=None): ''' Updates display to show specified page number and zoom level, defaulting to current values if None. Updates self.page_number and self.zoom if we are successful. ''' # Recreate the bitmap that we are displaying. We should probably use a # mupdf.DisplayList to avoid processing the page each time we need to # change zoom etc. # # We can run out of memory for large zoom values; should probably only # create bitmap for the visible region (or maybe slightly larger than # the visible region to allow for some limited scrolling?). # if page_number is None: page_number = self.page_number if zoom is None: zoom = self.zoom if page_number is None or page_number < 0 or page_number >= self.document.count_pages( ): return self.page = mupdf.Page(self.document, page_number) page_rect = self.page.bound_page() z = 2**(zoom / self.zoom_multiple) # For now we always use 'fit width' view semantics. # # Using -2 here avoids always-present horizontal scrollbar; not sure # why... z *= (self.centralWidget().size().width() - 2) / (page_rect.x1 - page_rect.x0) # Need to preserve the pixmap after we return because the Qt image will # refer to it, so we use self.pixmap. try: self.pixmap = self.page.new_pixmap_from_page_contents( ctm=mupdf.Matrix(z, 0, 0, z, 0, 0), cs=mupdf.Colorspace(mupdf.Colorspace.Fixed_RGB), alpha=0, ) except Exception as e: print(f'self.page.new_pixmap_from_page_contents() failed: {e}') return image = PyQt5.QtGui.QImage( int(self.pixmap.pixmap_samples()), self.pixmap.pixmap_width(), self.pixmap.pixmap_height(), self.pixmap.pixmap_stride(), PyQt5.QtGui.QImage.Format_RGB888, ) qpixmap = PyQt5.QtGui.QPixmap.fromImage(image) self.central_widget.setPixmap(qpixmap) self.page_number = page_number self.zoom = zoom
def trace_runpage( use_display_list, doc, number): page = mupdf.Page( doc, number-1) mediabox = page.bound_page() print( f'<page number="{number}" mediabox="{mediabox.x0} {mediabox.y0} {mediabox.x1} {mediabox.y1}">') output = mupdf.Output( mupdf.Output.Fixed_STDOUT) dev = mupdf.Device( output) if use_display_list: list_ = mupdf.DisplayList( page) list_.run_display_list( dev, mupdf.Matrix(mupdf.fz_identity), mupdf.Rect(mupdf.fz_infinite_rect), mupdf.Cookie()) else: page.run( dev, mupdf.Matrix(mupdf.fz_identity), mupdf.Cookie()) output.close_output() print( '</page>')
def convert_runpage( doc, number, out): page = mupdf.Page( doc, number - 1) mediabox = page.bound_page() dev = out.begin_page(mediabox) page.run( dev, mupdf.Matrix(mupdf.fz_identity), mupdf.Cookie()) out.end_page()
def test(path): ''' Runs various mupdf operations on <path>, which is assumed to be a file that mupdf can open. ''' log(f'testing path={path}') assert os.path.isfile(path) global g_test_n g_test_n += 1 # See notes in mupdfwrap.py:build_swig() about buffer_extract() and # buffer_storage(). # assert getattr(mupdf.Buffer, 'buffer_storage_raw') assert getattr(mupdf.Buffer, 'buffer_storage', None) is None assert getattr(mupdf.Buffer, 'buffer_extract_raw') assert getattr(mupdf.Buffer, 'buffer_extract') # Test operations using functions: # log('Testing functions.') log(f' Opening: %s' % path) document = mupdf.open_document(path) log(f' mupdf.needs_password(document)={mupdf.needs_password(document)}') log(f' mupdf.count_pages(document)={mupdf.count_pages(document)}') log(f' mupdf.document_output_intent(document)={mupdf.document_output_intent(document)}' ) # Test operations using classes: # log(f'Testing classes') document = mupdf.Document(path) log(f'Have created mupdf.Document for {path}') log(f'document.needs_password()={document.needs_password()}') log(f'document.count_pages()={document.count_pages()}') if 0: log(f'stext info:') show_stext(document) for k in ( 'format', 'encryption', 'info:Author', 'info:Title', 'info:Creator', 'info:Producer', 'qwerty', ): v = document.lookup_metadata(k) log(f'document.lookup_metadata() k={k} returned v={v!r}') if k == 'qwerty': assert v is None, f'v={v!r}' else: pass zoom = 10 scale = mupdf.Matrix.scale(zoom / 100., zoom / 100.) page_number = 0 log(f'Have created scale: a={scale.a} b={scale.b} c={scale.c} d={scale.d} e={scale.e} f={scale.f}' ) colorspace = mupdf.Colorspace(mupdf.Colorspace.Fixed_RGB) log(f'{colorspace.m_internal.key_storable.storable.refs}') if 0: c = colorspace.clamp_color([3.14]) log('colorspace.clamp_color returned c={c}') pixmap = mupdf.Pixmap(document, page_number, scale, colorspace, 0) log(f'Have created pixmap: {pixmap.m_internal.w} {pixmap.m_internal.h} {pixmap.m_internal.stride} {pixmap.m_internal.n}' ) filename = f'mupdf_test-out1-{g_test_n}.png' pixmap.save_pixmap_as_png(filename) log(f'Have created {filename} using pixmap.save_pixmap_as_png().') # Print image data in ascii PPM format. Copied from # mupdf/docs/examples/example.c. # samples = pixmap.samples() stride = pixmap.stride() n = pixmap.n() filename = f'mupdf_test-out2-{g_test_n}.ppm' with open(filename, 'w') as f: f.write('P3\n') f.write('%s %s\n' % (pixmap.m_internal.w, pixmap.m_internal.h)) f.write('255\n') for y in range(0, pixmap.m_internal.h): for x in range(pixmap.m_internal.w): if x: f.write(' ') offset = y * stride + x * n if hasattr(mupdf, 'bytes_getitem'): # swig f.write('%3d %3d %3d' % ( mupdf.bytes_getitem(samples, offset + 0), mupdf.bytes_getitem(samples, offset + 1), mupdf.bytes_getitem(samples, offset + 2), )) else: # cppyy f.write('%3d %3d %3d' % ( samples[offset + 0], samples[offset + 1], samples[offset + 2], )) f.write('\n') log(f'Have created {filename} by scanning pixmap.') # Generate .png and but create Pixmap from Page instead of from Document. # page = mupdf.Page(document, 0) separations = page.page_separations() log(f'page_separations() returned {"true" if separations else "false"}') pixmap = mupdf.Pixmap(page, scale, colorspace, 0) filename = f'mupdf_test-out3-{g_test_n}.png' pixmap.save_pixmap_as_png(filename) log(f'Have created {filename} using pixmap.save_pixmap_as_png()') # Show links log(f'Links.') page = mupdf.Page(document, 0) link = mupdf.load_links(page.m_internal) log(f'{link}') if link: for i in link: log(f'{i}') # Check we can iterate over Link's, by creating one manually. # link = mupdf.Link(mupdf.Rect(0, 0, 1, 1), "hello") log(f'items in <link> are:') for i in link: log(f' {i.m_internal.refs} {i.m_internal.uri}') # Check iteration over Outlines. # log(f'Outlines.') outline = mupdf.Outline(document) log(f'outline.m_internal={outline.m_internal}') if outline.m_internal: log(f'{outline.uri()} {outline.page()} {outline.x()} {outline.y()} {outline.is_open()} {outline.title()}' ) log(f'items in outline tree are:') for o in outline: log(f' {o.uri()} {o.page()} {o.x()} {o.y()} {o.is_open()} {o.title()}' ) # Check iteration over StextPage. # log(f'StextPage.') stext_options = mupdf.StextOptions(0) page_num = 40 try: stext_page = mupdf.StextPage(document, page_num, stext_options) except Exception: log(f'no page_num={page_num}') else: device_stext = mupdf.Device(stext_page, stext_options) matrix = mupdf.Matrix() page = mupdf.Page(document, 0) cookie = mupdf.Cookie() page.run_page(device_stext, matrix, cookie) log(f' stext_page is:') for block in stext_page: log(f' block:') for line in block: line_text = '' for char in line: line_text += chr(char.m_internal.c) log(f' {line_text}') device_stext.close_device() # Check copy-constructor. log(f'Checking copy-constructor') document2 = mupdf.Document(document) del document page = mupdf.Page(document2, 0) scale = mupdf.Matrix() pixmap = mupdf.Pixmap(page, scale, colorspace, 0) pixmap.save_pixmap_as_png('mupdf_test-out3.png') stdout = mupdf.Output(mupdf.Output.Fixed_STDOUT) log(f'{type(stdout)} {stdout.m_internal.state}') mediabox = page.bound_page() out = mupdf.DocumentWriter(filename, 'png', '', mupdf.DocumentWriter.FormatPathType_DOCUMENT) dev = out.begin_page(mediabox) page.run_page(dev, mupdf.Matrix(mupdf.fz_identity), mupdf.Cookie()) out.end_page() # Check out-params are converted into python return value. bitmap = mupdf.Bitmap(10, 20, 8, 72, 72) bitmap_details = bitmap.bitmap_details() log(f'{bitmap_details}') assert list(bitmap_details) == [10, 20, 8, 12], f'bitmap_details={bitmap_details!r}' log(f'finished test of %s' % path)
def drawpage(doc, pagenum): list_ = None cookie = mupdf.Cookie() seps = None features = "" start = gettime() if state.showtime else 0 page = mupdf.Page(doc, pagenum - 1) if state.spots != SPOTS_NONE: seps = page.page_separations() if seps.m_internal: n = seps.count_separations() if state.spots == SPOTS_FULL: for i in range(n): seps.set_separation_behavior(i, mupdf.FZ_SEPARATION_SPOT) else: for i in range(n): seps.set_separation_behavior(i, mupdf.FZ_SEPARATION_COMPOSITE) elif page.page_uses_overprint(): # This page uses overprint, so we need an empty # sep object to force the overprint simulation on. seps = mupdf.Separations(0) elif state.oi and state.oi.m_internal and state.oi.colorspace_n( ) != state.colorspace.colorspace_n(): # We have an output intent, and it's incompatible # with the colorspace our device needs. Force the # overprint simulation on, because this ensures that # we 'simulate' the output intent too. */ seps = mupdf.Separations(0) if state.uselist: list_ = mupdf.DisplayList(page.bound_page()) dev = mupdf.Device(list_) if state.lowmemory: dev.enable_device_hints(FZ_NO_CACHE) page.run(dev, mupdf.Matrix(), cookie) dev.close_device() if bgprint.active and state.showtime: end = gettime() start = end - start if state.showfeatures: # SWIG doesn't appear to handle the out-param is_color in # mupdf.Device() constructor that wraps fz_new_test_device(), so we use # the underlying mupdf function() instead. # dev, iscolor = mupdf.new_test_device(0.02, 0, None) dev = mupdf.Device(dev) if state.lowmemory: dev.enable_device_hints(mupdf.FZ_NO_CACHE) if list_: list_.run_display_list(dev, mupdf.Matrix(mupdf.fz_identity), mupdf.Rect(mupdf.fz_infinite_rect), mupdf.Cookie()) else: page.run(dev, fz_identity, cookie) dev.close_device() features = " color" if iscolor else " grayscale" if state.output_file_per_page: bgprint_flush() if state.out: state.out.close_output() text_buffer = mupdf.format_output_path(state.output, pagenum) state.out = mupdf.Output(text_buffer, 0) if bgprint.active: bgprint_flush() if bgprint.active: if not state.quiet or state.showfeatures or state.showtime or state.showmd5: sys.stderr.write("page %s %d%s" % (state.filename, pagenum, features)) bgprint.started = 1 bgprint.page = page bgprint.list = list_ bgprint.seps = seps bgprint.filename = state.filename bgprint.pagenum = pagenum bgprint.interptime = start else: if not state.quiet or state.showfeatures or state.showtime or state.showmd5: sys.stderr.write("page %s %d%s" % (state.filename, pagenum, features)) dodrawpage(page, list_, pagenum, cookie, start, 0, state.filename, 0, seps)