Render reMarkable documents to PDF

Overview

rmrl: reMarkable Rendering Library

rmrl is a Python library for rendering reMarkable documents to PDF files. It takes the original PDF document and the files describing your annotations, combining them to produce a document close to what reMarkable itself would output.

Demo

The same notebook was rendered to a PDF via the reMarkable app and rmrl. The resultant PDF files were converted to PNGs with ImageMagick at 300 dpi.

reMarkable output rmrl output
reMarkable rmrl

The biggest differences are the lack of texture in the pencils and paintbrush, which we hope to address in the future. Two differences are intentional:

  • The highlight color is more saturated, since we feel the default color is too subtle.
  • The grid lines from the template are less saturated, to better reflect the appearance on the device. This is configurable.

Installation

rmrl requires Python 3.7 or later. If that's installed, the easiest installation is to do a

pip install rmrl

Alternatively, you may clone this repository. Poetry is used for development, so once that is installed you can run

poetry install

to get a virtual environment all set up.

Usage

The main interface to rmrl is through a single function:

from rmrl import render

output = render(source)

source may be:

  • The filename of a zip file containing the document.
  • The filename of any (root-level) file from an unpacked document.
  • Any object that provides open() and exists() methods. See rmrl/sources.py for more details on this API.

The output is a filestream with the contents of the PDF file.

The render function takes the following keyword arguments:

  • progress_cb: A callback function to be called periodically during the rendering process. It will be called with a single argument, a number from 0 to 100 indicating the progress. This function can abort the process by raising an exception.

Command-line Usage

rmrl may be called as a command-line tool. Once it has been installed, run

python -m rmrl filename

to convert filename to an annotated PDF. The default output is to stdout. Use

python -m rmrl -h

to see all of the options.

Templates

rmrl can use the reMarkable templates as a background when rendering notebooks. We cannot ship copies of these templates. You may be allowed to copy them from your own reMarkable device on to your computer for personal use. If this is legal in your jurisdiction, you may connect your device to your computer by the USB cable and run

python -m rmrl.load_templates

This will copy these templates to ~/.local/share/rmrl/templates (assuming default XDG settings).

History

rmrl derives from the reMarkable Connection Utility, by Davis Remmel. RCU is a full-featured GUI for managing all aspects of a reMarkable device. Do check it out if you are looking for a stand-alone solution for getting documents on and off of your device.

RCU was chosen as a base for rmrl due to its high-quality rendering. The following are the major changes:

  • rmrl is designed as a library, for incorporation into other programs. RCU is designed as a stand-alone program.
  • rmrl uses the pure-Python ReportLab Toolkit for rendering PDF files. RCU uses the Qt framework, which is a significantly heavier installation.
  • rmrl only supports vector output, while RCU offers both raster and vector rendering.
  • RCU supports PDF layers (Optional Content Groups). At this point, rmrl does not.
  • RCU can add PDF annotations corresponding to highlights. At this point, rmrl does not.

Trademarks

reMarkable(R) is a registered trademark of reMarkable AS. rmrl is not affiliated with, or endorsed by, reMarkable AS. The use of “reMarkable” in this work refers to the company’s e-paper tablet product(s).

Copyright

Copyright (C) 2020 Davis Remmel

Copyright 2021 Robert Schroll

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

Comments
  • Render only annotated PDF pages

    Render only annotated PDF pages

    Remarkable cannot add white pages or delete useless pages from a PDF.
    As workaround, I usually add a white page after each document page and then upload this document on the tablet, so I can read and annotate the document and add comment on white pages. However several pages aren't use and I do not really care about them.

    Exporting only the annotated pages will be a great feature. This features is already present, for example, in rmapi, but there's no great open source PDF tool in go, so the render is bad.

    opened by f3fora 2
  • Get Annotations working

    Get Annotations working

    Added functionality to support annotations properly. OCG not addressed here. Tested, working on:

    Edition Windows 10 Home Version 20H2 Installed on ‎2/‎10/‎2021 OS build 19042.867 Experience Windows Feature Experience Pack 120.2212.551.0

    opened by brush701 1
  • Render crash with annotated PDF

    Render crash with annotated PDF

    Related to rschroll/rmfuse#17

    Run python -m rmrl Test.zip Test,pdf

    File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main
        return _run_code(code, main_globals, None,
      File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
        exec(code, run_globals)
      File "/usr/lib/python3.9/site-packages/rmrl/__main__.py", line 53, in <module>
        sys.exit(main())
      File "/usr/lib/python3.9/site-packages/rmrl/__main__.py", line 44, in main
        stream = render(source,
      File "/usr/lib/python3.9/site-packages/rmrl/render.py", line 149, in render
        merge_pages(basepage, rmpage, i in changed_pages, expand_pages)
      File "/usr/lib/python3.9/site-packages/rmrl/render.py", line 478, in merge_pages
        effective_rotation = int(basepage.Rotate)
    TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'
    

    where Test.zip is an annotated PDF.

    opened by f3fora 1
  • Use of templates causes unexpected slowdown

    Use of templates causes unexpected slowdown

    When using templates, rendering a document with 140 pages of handwritten notes takes over half an hour on my raspberry pi. The same file renders in ~1min without templates. It would be nice if the template rendering could be optimized, since the aforementioned slowdown makes them somewhat unusable right now.

    opened by malte-v 0
  • Index out of bounds errror?

    Index out of bounds errror?

    Hi - getting the following error:

    Traceback (most recent call last): File "/usr/local/Cellar/[email protected]/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py", line 197, in _run_module_as_main return _run_code(code, main_globals, None, File "/usr/local/Cellar/[email protected]/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py", line 87, in _run_code exec(code, run_globals) File "/usr/local/lib/python3.9/site-packages/rmrl/__main__.py", line 53, in <module> sys.exit(main()) File "/usr/local/lib/python3.9/site-packages/rmrl/__main__.py", line 44, in main stream = render(source, File "/usr/local/lib/python3.9/site-packages/rmrl/render.py", line 130, in render rmpage = rmpdfr.pages[i] IndexError: list index out of range

    Looks like the code is operating on a range using the length of the basepdfr.pages array and then also using that on the rmpdfr.pages array that apparently isn't always the same length. Don't know how to fix. Anyone else experiencing this?

    opened by amrmjd 1
  • Add support for red and blue pens

    Add support for red and blue pens

    v2.11 added support for two more pen colors (red and blue): https://support.remarkable.com/hc/en-us/articles/4413620362897-Software-release-2-11#article-heading-1

    (The fork @naturale0 mentions in https://github.com/rschroll/rmrl/issues/12#issuecomment-996850116 includes support for these.)

    As-is, I get the following error when I try to use 89b5cc38ef45251b96bd3d1c3618429b6b46db92 on a document where I've drawn in red or blue:

    $ python -m rmrl 'Quick reference.zip' 'Quick reference.pdf'
    Traceback (most recent call last):
      File "/Users/jmyers/.pyenv/versions/3.9.6/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py", line 197, in _run_module_as_main
        return _run_code(code, main_globals, None,
      File "/Users/jmyers/.pyenv/versions/3.9.6/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py", line 87, in _run_code
        exec(code, run_globals)
      File "/Users/jmyers/wtf/rm-todos/rmrl/src/rmrl/rmrl/__main__.py", line 53, in <module>
        sys.exit(main())
      File "/Users/jmyers/wtf/rm-todos/rmrl/src/rmrl/rmrl/__main__.py", line 44, in main
        stream = render(source,
      File "/Users/jmyers/wtf/rm-todos/rmrl/src/rmrl/rmrl/render.py", line 95, in render
        page.render_to_painter(pdf_canvas, vector, template_alpha)
      File "/Users/jmyers/wtf/rm-todos/rmrl/src/rmrl/rmrl/document.py", line 148, in render_to_painter
        layer.render_to_painter(canvas, vector)
      File "/Users/jmyers/wtf/rm-todos/rmrl/src/rmrl/rmrl/document.py", line 245, in render_to_painter
        self.paint_strokes(painter, vector=vector)
      File "/Users/jmyers/wtf/rm-todos/rmrl/src/rmrl/rmrl/document.py", line 238, in paint_strokes
        color=self.colors[color])
    IndexError: list index out of range
    
    opened by myersjustinc 1
  • Running this on the reMarkable itself?

    Running this on the reMarkable itself?

    I want to be able to run this on the device itself to export PDFs to a directory.

    I've tried installing python 3 and other items via toltec. I've done the following:

    opkg install python-3 python3-pip python3-dev libxml2 libxml2-dev libxslt python3-lxml
    

    Then when I try:

    pip install rmrl
    

    I get a bunch of errors below.

    Is it because there no Entware package for libxslt-dev? I've tried this:

    opkg install libxslt-devel
    Unknown package 'libxslt-devel'.
    

    Errors I get on pip install rmrl:

    Collecting rmrl
      Using cached rmrl-0.2.1-py3-none-any.whl (519 kB)
    Collecting pdfrw<0.5,>=0.4
      Using cached pdfrw-0.4-py2.py3-none-any.whl (69 kB)
    Collecting svglib<2.0.0,>=1.0.1
      Using cached svglib-1.2.1.tar.gz (896 kB)
    Collecting xdg<6.0.0,>=5.0.1
      Using cached xdg-5.1.1-py3-none-any.whl (5.0 kB)
    Collecting reportlab<4.0.0,>=3.5.59
      Using cached reportlab-3.6.8.tar.gz (4.5 MB)
    Collecting pillow>=4.0.0
      Using cached Pillow-9.0.1.tar.gz (49.5 MB)
    Collecting lxml
      Using cached lxml-4.8.0.tar.gz (3.2 MB)
        ERROR: Command errored out with exit status 1:
         command: /opt/bin/python3 -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-gpdmkj2i/lxml_be3a8c5a26a64a79b1597aadcc844957/setup.py'"'"'; __file__='"'"'/tmp/pip-install-gpdmkj2i/lxml_be3a8c5a26a64a79b1597aadcc844957/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-uumkos1o
             cwd: /tmp/pip-install-gpdmkj2i/lxml_be3a8c5a26a64a79b1597aadcc844957/
        Complete output (3 lines):
        Building lxml version 4.8.0.
        Building without Cython.
        Error: Please make sure the libxml2 and libxslt development packages are installed.
        ----------------------------------------
    WARNING: Discarding https://files.pythonhosted.org/packages/3b/94/e2b1b3bad91d15526c7e38918795883cee18b93f6785ea8ecf13f8ffa01e/lxml-4.8.0.tar.gz#sha256=f63f62fc60e6228a4ca9abae28228f35e1bd3ce675013d1dfb828688d50c6e23 (from https://pypi.org/simple/lxml/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*). Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
      Using cached lxml-4.7.1.tar.gz (3.2 MB)
        ERROR: Command errored out with exit status 1:
         command: /opt/bin/python3 -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-gpdmkj2i/lxml_9897fc1680fc4fe7bf94e67fd3453bc3/setup.py'"'"'; __file__='"'"'/tmp/pip-install-gpdmkj2i/lxml_9897fc1680fc4fe7bf94e67fd3453bc3/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-4qqd7cvf
             cwd: /tmp/pip-install-gpdmkj2i/lxml_9897fc1680fc4fe7bf94e67fd3453bc3/
        Complete output (3 lines):
        Building lxml version 4.7.1.
        Building without Cython.
        Error: Please make sure the libxml2 and libxslt development packages are installed.
        ----------------------------------------
    WARNING: Discarding https://files.pythonhosted.org/packages/84/74/4a97db45381316cd6e7d4b1eb707d7f60d38cb2985b5dfd7251a340404da/lxml-4.7.1.tar.gz#sha256=a1613838aa6b89af4ba10a0f3a972836128801ed008078f8c1244e65958f1b24 (from https://pypi.org/simple/lxml/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*). Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
      Using cached lxml-4.6.5.tar.gz (3.2 MB)
        ERROR: Command errored out with exit status 1:
         command: /opt/bin/python3 -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-gpdmkj2i/lxml_25b1ad733309462c9b1acde05cb640a6/setup.py'"'"'; __file__='"'"'/tmp/pip-install-gpdmkj2i/lxml_25b1ad733309462c9b1acde05cb640a6/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-t67f5uvh
             cwd: /tmp/pip-install-gpdmkj2i/lxml_25b1ad733309462c9b1acde05cb640a6/
        Complete output (3 lines):
        Building lxml version 4.6.5.
        Building without Cython.
        Error: Please make sure the libxml2 and libxslt development packages are installed.
        ----------------------------------------
    WARNING: Discarding https://files.pythonhosted.org/packages/e6/e1/34b3ab08553fe9a30e15b2bb9d1803a49d7d907dd9f245638839190042f0/lxml-4.6.5.tar.gz#sha256=6e84edecc3a82f90d44ddee2ee2a2630d4994b8471816e226d2b771cda7ac4ca (from https://pypi.org/simple/lxml/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*). Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
      Using cached lxml-4.6.4.tar.gz (3.2 MB)
        ERROR: Command errored out with exit status 1:
         command: /opt/bin/python3 -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-gpdmkj2i/lxml_e3bc24bf52d54b969d8debee5b7a4e18/setup.py'"'"'; __file__='"'"'/tmp/pip-install-gpdmkj2i/lxml_e3bc24bf52d54b969d8debee5b7a4e18/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-ten5m3nq
             cwd: /tmp/pip-install-gpdmkj2i/lxml_e3bc24bf52d54b969d8debee5b7a4e18/
        Complete output (3 lines):
        Building lxml version 4.6.4.
        Building without Cython.
        Error: Please make sure the libxml2 and libxslt development packages are installed.
        ----------------------------------------
    WARNING: Discarding https://files.pythonhosted.org/packages/fe/4c/a4dbb4e389f75e69dbfb623462dfe0d0e652107a95481d40084830d29b37/lxml-4.6.4.tar.gz#sha256=daf9bd1fee31f1c7a5928b3e1059e09a8d683ea58fb3ffc773b6c88cb8d1399c (from https://pypi.org/simple/lxml/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*). Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
      Using cached lxml-4.6.3.tar.gz (3.2 MB)
        ERROR: Command errored out with exit status 1:
         command: /opt/bin/python3 -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-gpdmkj2i/lxml_63004563a68546a698c1583822c0341f/setup.py'"'"'; __file__='"'"'/tmp/pip-install-gpdmkj2i/lxml_63004563a68546a698c1583822c0341f/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-puy8pbiv
             cwd: /tmp/pip-install-gpdmkj2i/lxml_63004563a68546a698c1583822c0341f/
        Complete output (3 lines):
        Building lxml version 4.6.3.
        Building without Cython.
        Error: Please make sure the libxml2 and libxslt development packages are installed.
        ----------------------------------------
    WARNING: Discarding https://files.pythonhosted.org/packages/e5/21/a2e4517e3d216f0051687eea3d3317557bde68736f038a3b105ac3809247/lxml-4.6.3.tar.gz#sha256=39b78571b3b30645ac77b95f7c69d1bffc4cf8c3b157c435a34da72e78c82468 (from https://pypi.org/simple/lxml/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*). Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
      Using cached lxml-4.6.2.tar.gz (3.2 MB)
        ERROR: Command errored out with exit status 1:
         command: /opt/bin/python3 -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-gpdmkj2i/lxml_04c27419a28c4b08923a74df446ad40b/setup.py'"'"'; __file__='"'"'/tmp/pip-install-gpdmkj2i/lxml_04c27419a28c4b08923a74df446ad40b/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-bvlxwq6f
             cwd: /tmp/pip-install-gpdmkj2i/lxml_04c27419a28c4b08923a74df446ad40b/
        Complete output (3 lines):
        Building lxml version 4.6.2.
        Building without Cython.
        Error: Please make sure the libxml2 and libxslt development packages are installed.
        ----------------------------------------
    WARNING: Discarding https://files.pythonhosted.org/packages/db/f7/43fecb94d66959c1e23aa53d6161231dca0e93ec500224cf31b3c4073e37/lxml-4.6.2.tar.gz#sha256=cd11c7e8d21af997ee8079037fff88f16fda188a9776eb4b81c7e4c9c0a7d7fc (from https://pypi.org/simple/lxml/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*). Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
      Using cached lxml-4.6.1.tar.gz (3.2 MB)
        ERROR: Command errored out with exit status 1:
         command: /opt/bin/python3 -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-gpdmkj2i/lxml_498dbd20f35f47ada88bbcd0ddb96ba8/setup.py'"'"'; __file__='"'"'/tmp/pip-install-gpdmkj2i/lxml_498dbd20f35f47ada88bbcd0ddb96ba8/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-4kxza0d7
             cwd: /tmp/pip-install-gpdmkj2i/lxml_498dbd20f35f47ada88bbcd0ddb96ba8/
        Complete output (3 lines):
        Building lxml version 4.6.1.
        Building without Cython.
        Error: Please make sure the libxml2 and libxslt development packages are installed.
        ----------------------------------------
    WARNING: Discarding https://files.pythonhosted.org/packages/c5/2f/a0d8aa3eee6d53d5723d89e1fc32eee11e76801b424e30b55c7aa6302b01/lxml-4.6.1.tar.gz#sha256=c152b2e93b639d1f36ec5a8ca24cde4a8eefb2b6b83668fcd8e83a67badcb367 (from https://pypi.org/simple/lxml/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*). Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
      Using cached lxml-4.6.0.tar.gz (3.2 MB)
        ERROR: Command errored out with exit status 1:
         command: /opt/bin/python3 -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-gpdmkj2i/lxml_50b0dfd6c92641aebd64ea7ed392a312/setup.py'"'"'; __file__='"'"'/tmp/pip-install-gpdmkj2i/lxml_50b0dfd6c92641aebd64ea7ed392a312/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-703vabft
             cwd: /tmp/pip-install-gpdmkj2i/lxml_50b0dfd6c92641aebd64ea7ed392a312/
        Complete output (3 lines):
        Building lxml version 4.6.0.
        Building without Cython.
        Error: Please make sure the libxml2 and libxslt development packages are installed.
        ----------------------------------------
    WARNING: Discarding https://files.pythonhosted.org/packages/3c/5a/81446fb5a4706bb07a98427634ab93219dc7fa393841d81f5da5c7e151b7/lxml-4.6.0.tar.gz#sha256=8319abacbbe9fd9791c2e3c23deb9b6a16abc0fcbdfcc26722035e865b3d207f (from https://pypi.org/simple/lxml/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*). Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
    reMarkable: ~/convert/ pip install rmrl
    Collecting rmrl
      Using cached rmrl-0.2.1-py3-none-any.whl (519 kB)
    Collecting xdg<6.0.0,>=5.0.1
      Using cached xdg-5.1.1-py3-none-any.whl (5.0 kB)
    Collecting svglib<2.0.0,>=1.0.1
      Using cached svglib-1.2.1.tar.gz (896 kB)
    Collecting reportlab<4.0.0,>=3.5.59
      Using cached reportlab-3.6.8.tar.gz (4.5 MB)
    Collecting pdfrw<0.5,>=0.4
      Using cached pdfrw-0.4-py2.py3-none-any.whl (69 kB)
    Collecting pillow>=4.0.0
      Using cached Pillow-9.0.1.tar.gz (49.5 MB)
    Requirement already satisfied: lxml in /opt/lib/python3.10/site-packages (from svglib<2.0.0,>=1.0.1->rmrl) (4.6.4)
    Collecting tinycss2>=0.6.0
      Downloading tinycss2-1.1.1-py3-none-any.whl (21 kB)
    Collecting cssselect2>=0.2.0
      Downloading cssselect2-0.5.0-py3-none-any.whl (15 kB)
    Collecting webencodings
      Downloading webencodings-0.5.1-py2.py3-none-any.whl (11 kB)
    Using legacy 'setup.py install' for reportlab, since package 'wheel' is not installed.
    Using legacy 'setup.py install' for pillow, since package 'wheel' is not installed.
    Using legacy 'setup.py install' for svglib, since package 'wheel' is not installed.
    Installing collected packages: webencodings, tinycss2, pillow, reportlab, cssselect2, xdg, svglib, pdfrw, rmrl
        Running setup.py install for pillow ... error
        ERROR: Command errored out with exit status 1:
         command: /opt/bin/python3 -u -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-vzrk0rdx/pillow_63dcc110421046ebab7061d959a6be4b/setup.py'"'"'; __file__='"'"'/tmp/pip-install-vzrk0rdx/pillow_63dcc110421046ebab7061d959a6be4b/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-zrig3tko/install-record.txt --single-version-externally-managed --compile --install-headers /opt/include/python3.10/pillow
             cwd: /tmp/pip-install-vzrk0rdx/pillow_63dcc110421046ebab7061d959a6be4b/
        Complete output (163 lines):
        running install
        running build
        running build_py
        creating build
        creating build/lib.linux-armv7l-3.10
        creating build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/features.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/_version.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/_util.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/_tkinter_finder.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/_binary.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/__main__.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/__init__.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/XpmImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/XbmImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/XVThumbImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/WmfImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/WebPImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/WalImageFile.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/TiffTags.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/TiffImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/TgaImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/TarIO.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/SunImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/SpiderImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/SgiImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/PyAccess.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/PsdImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/PpmImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/PngImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/PixarImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/PdfParser.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/PdfImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/PcxImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/PcfFontFile.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/PcdImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/PalmImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/PaletteFile.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/PSDraw.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/MspImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/MpoImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/MpegImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/MicImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/McIdasImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/JpegPresets.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/JpegImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/Jpeg2KImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/IptcImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImtImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageWin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageTransform.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageTk.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageStat.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageShow.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageSequence.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageQt.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImagePath.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImagePalette.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageOps.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageMorph.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageMode.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageMath.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageGrab.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageFont.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageFilter.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageFile.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageEnhance.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageDraw2.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageDraw.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageColor.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageCms.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImageChops.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/Image.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ImImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/IcoImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/IcnsImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/Hdf5StubImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/GribStubImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/GimpPaletteFile.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/GimpGradientFile.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/GifImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/GdImageFile.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/GbrImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/FtexImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/FpxImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/FontFile.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/FliImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/FitsStubImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ExifTags.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/EpsImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/DdsImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/DcxImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/CurImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/ContainerIO.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/BufrStubImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/BmpImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/BlpImagePlugin.py -> build/lib.linux-armv7l-3.10/PIL
        copying src/PIL/BdfFontFile.py -> build/lib.linux-armv7l-3.10/PIL
        running egg_info
        writing src/Pillow.egg-info/PKG-INFO
        writing dependency_links to src/Pillow.egg-info/dependency_links.txt
        writing top-level names to src/Pillow.egg-info/top_level.txt
        reading manifest file 'src/Pillow.egg-info/SOURCES.txt'
        reading manifest template 'MANIFEST.in'
        warning: no files found matching '*.c'
        warning: no files found matching '*.h'
        warning: no files found matching '*.sh'
        warning: no previously-included files found matching '.appveyor.yml'
        warning: no previously-included files found matching '.clang-format'
        warning: no previously-included files found matching '.coveragerc'
        warning: no previously-included files found matching '.editorconfig'
        warning: no previously-included files found matching '.readthedocs.yml'
        warning: no previously-included files found matching 'codecov.yml'
        warning: no previously-included files matching '.git*' found anywhere in distribution
        warning: no previously-included files matching '*.pyc' found anywhere in distribution
        warning: no previously-included files matching '*.so' found anywhere in distribution
        no previously-included directories found matching '.ci'
        adding license file 'LICENSE'
        writing manifest file 'src/Pillow.egg-info/SOURCES.txt'
        running build_ext
    
    
        The headers or library files could not be found for zlib,
        a required dependency when compiling Pillow from source.
    
        Please see the install instructions at:
           https://pillow.readthedocs.io/en/latest/installation.html
    
        Traceback (most recent call last):
          File "/tmp/pip-install-vzrk0rdx/pillow_63dcc110421046ebab7061d959a6be4b/setup.py", line 989, in <module>
            setup(
          File "/opt/lib/python3.10/site-packages/setuptools/__init__.py", line 153, in setup
          File "/opt/lib/python3.10/distutils/core.py", line 148, in setup
          File "/opt/lib/python3.10/distutils/dist.py", line 966, in run_commands
          File "/opt/lib/python3.10/distutils/dist.py", line 985, in run_command
          File "/opt/lib/python3.10/site-packages/setuptools/command/install.py", line 61, in run
          File "/opt/lib/python3.10/distutils/command/install.py", line 568, in run
          File "/opt/lib/python3.10/distutils/cmd.py", line 313, in run_command
          File "/opt/lib/python3.10/distutils/dist.py", line 985, in run_command
          File "/opt/lib/python3.10/distutils/command/build.py", line 135, in run
          File "/opt/lib/python3.10/distutils/cmd.py", line 313, in run_command
          File "/opt/lib/python3.10/distutils/dist.py", line 985, in run_command
          File "/opt/lib/python3.10/site-packages/setuptools/command/build_ext.py", line 79, in run
          File "/opt/lib/python3.10/distutils/command/build_ext.py", line 343, in run
          File "/tmp/pip-install-vzrk0rdx/pillow_63dcc110421046ebab7061d959a6be4b/setup.py", line 804, in build_extensions
            raise RequiredDependencyException(f)
        __main__.RequiredDependencyException: zlib
    
        During handling of the above exception, another exception occurred:
    
        Traceback (most recent call last):
          File "<string>", line 1, in <module>
          File "/tmp/pip-install-vzrk0rdx/pillow_63dcc110421046ebab7061d959a6be4b/setup.py", line 1009, in <module>
            raise RequiredDependencyException(msg)
        __main__.RequiredDependencyException:
    
        The headers or library files could not be found for zlib,
        a required dependency when compiling Pillow from source.
    
        Please see the install instructions at:
           https://pillow.readthedocs.io/en/latest/installation.html
    
    
        ----------------------------------------
    ERROR: Command errored out with exit status 1: /opt/bin/python3 -u -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-vzrk0rdx/pillow_63dcc110421046ebab7061d959a6be4b/setup.py'"'"'; __file__='"'"'/tmp/pip-install-vzrk0rdx/pillow_63dcc110421046ebab7061d959a6be4b/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-zrig3tko/install-record.txt --single-version-externally-managed --compile --install-headers /opt/include/python3.10/pillow Check the logs for full command output.
    WARNING: You are using pip version 21.2.3; however, version 22.0.3 is available.
    You should consider upgrading via the '/opt/bin/python3 -m pip install --upgrade pip' command.
    
    opened by nickian 0
  • Bugfix template selection

    Bugfix template selection

    During initialization of DocumentPage instances, a bug caused rmrl to always render the template of the notebook's last page. The bugfix is trivial since this was only a mix-up (max instead of min).

    For more context (if needed) - consider the inline documentation prior to the culprit line: https://github.com/rschroll/rmrl/blob/89b5cc38ef45251b96bd3d1c3618429b6b46db92/rmrl/document.py#L60-L64

    In such cases, len(template_names) would be less than self.num. Access with max would then raise an IndexError.
    For all other exports (where self.num is always less than len(template_names)), this line will always select the last entry within template_names.

    opened by snototter 0
  • merge_pages() recursively searches for page size (fixes #11)

    merge_pages() recursively searches for page size (fixes #11)

    Spent a bit looking into this on my own before realizing someone had already figured it out in #11.

    Using the following recursive dict search mostly from here on a PDF of a random textbook I have:

    def _finditem(obj, key, path=None):
        if path is None:
            path = []
        if key in obj:
            print(f"key {key} found at path {path}")
            return obj[key]
        for k, v in obj.items():
            if isinstance(v,dict):
                item = _finditem(v, key, path + [k])
                if item is not None:
                    return item
    print(_finditem(basepage, '/MediaBox')
    

    The output looks like:

    key /MediaBox found at path ['/Parent', '/Parent', '/Parent', '/Parent', '/Parent']
    ['0', '0', '612', '792']
    

    The output matches what pdfinfo finds:

    (rmrl-WvqN329U-py3.8) rmrl-WvqN329U-py3 λ › pdfinfo -box /mnt/d/remarkable_sync/5cf892dc-6471-430c-9c75-7e83867f5eab.pdf                                                             git_WSL/rmrl fix_pagesize
    Title:          Mastering STM32
    Author:         Carmine Noviello
    Creator:        LaTeX with hyperref package
    Producer:       XeTeX 0.99999
    CreationDate:   Fri Aug 17 06:35:42 2018 PDT
    ModDate:        Tue Jun 11 03:03:22 2019 PDT
    Tagged:         no
    UserProperties: no
    Suspects:       no
    Form:           AcroForm
    JavaScript:     no
    Pages:          852
    Encrypted:      no
    Page size:      612 x 792 pts (letter)
    Page rot:       0
    MediaBox:           0.00     0.00   612.00   792.00
    CropBox:            0.00     0.00   612.00   792.00
    BleedBox:           0.00     0.00   612.00   792.00
    TrimBox:            0.00     0.00   612.00   792.00
    ArtBox:             0.00     0.00   612.00   792.00
    File size:      38994922 bytes
    Optimized:      no
    PDF version:    1.5
    
    opened by Gigahawk 0
Owner
Robert Schroll
Robert Schroll
Render to print for blender 2.9+

render_to_print_blender_addon ** render2print: Blender AddOn for Blender 2.90.0+ ** Calculates camera parameters to allow printing a rendered image to

null 5 Nov 19, 2021
Blender Add-on That Provides Quick Access to Render Controls

Blender Render Buttons Blender Add-on That Provides Quick Access to Render Controls A Blender 3.0 compatablity update of Blender2.8x-RenderButton v0.0

Don Schnitzius 3 Oct 18, 2022
An After Effects render queue for ShotGrid Toolkit.

AEQueue An After Effects render queue for ShotGrid Toolkit. Features Render multiple comps to locations defined by templates in your Toolkit config. C

Brand New School 5 Nov 20, 2022
A refresher for PowerBI Desktop documents

PowerBI_Refresher-NPP Informació Per executar el programa s'ha de tenir instalat el python versio 3 o mes. Requeriments a requirements.txt. El fitxer

Nil Pujol 1 May 2, 2022
Plugin to manage site, circuit and device diagrams and documents in Netbox

Netbox Documents Plugin A plugin designed to faciliate the storage of site, circuit and device specific documents within NetBox Note: Netbox v3.2+ is

Jason Yates 38 Dec 24, 2022
This app converts an pdf file into the audio file.

PDF-to-Audio This app takes an pdf as an input and convert it into audio, and the library text-to-speech starts speaking the preffered page given in t

Ojas Barawal 3 Aug 4, 2021
A python script that fetches the grades of a student from a WAEC result in pdf format.

About waec-result-analyzer A python script that fetches the grades of a student from a WAEC result in pdf format. Built for federal government college

Oshodi Kolapo 2 Dec 4, 2021
Software that extracts spreadsheets from various .pdf files to .csv

Extração de planilhas de diversos arquivos .pdf para .csv O código inteiro foi desenvolvido em Python. Foi utilizado o pacote "tabula" e a biblioteca

Marcos Silva 2 Jan 9, 2022
RMfuse provides access to your reMarkable Cloud files in the form of a FUSE filesystem

RMfuse provides access to your reMarkable Cloud files in the form of a FUSE filesystem. These files are exposed either in their original format, or as PDF files that contain your annotations. This lets you manage files in the reMarkable Cloud using the same tools you use on your local system.

Robert Schroll 82 Nov 24, 2022
Remarkable Markdown Debian Package Fix

Remarkable debian package fix For some reason the Debian package for remarkable markdown editor has not been made to install properly on Ubuntu 20.04

Eric Seifert 37 Jan 2, 2023
Unoffical reMarkable AddOn for Firefox.

reMarkable for Firefox (Download) This repo converts the offical reMarkable Chrome Extension into a Firefox AddOn published here under the name "Unoff

Jelle Schutter 45 Nov 28, 2022
A simple toolchain for moving Remarkable highlights to Readwise

A simple toolchain for moving Remarkable highlights to Readwise

zach wick 20 Dec 20, 2022
WeasyPrint is a smart solution helping web developers to create PDF documents.

WeasyPrint is a smart solution helping web developers to create PDF documents. It turns simple HTML pages into gorgeous statistical reports, invoices, tickets…

Kozea 5.4k Jan 8, 2023
x-ray is a Python library for finding bad redactions in PDF documents.

A tool to detect whether a PDF has a bad redaction

Free Law Project 73 Dec 19, 2022
Small python-gtk application, which helps the user to merge or split pdf documents and rotate, crop and rearrange their pages using an interactive and intuitive graphical interface

Small python-gtk application, which helps the user to merge or split pdf documents and rotate, crop and rearrange their pages using an interactive and intuitive graphical interface

null 1.8k Dec 29, 2022
This tool crawls a list of websites and download all PDF and office documents

This tool crawls a list of websites and download all PDF and office documents. Then it analyses the PDF documents and tries to detect accessibility issues.

AccessibilityLU 7 Sep 30, 2022
minipdf is a package for creating simple, single-page PDF documents.

minipdf minipdf is a package for creating simple, single-page PDF documents. Installation You can install the development version from GitHub with: #

mikefc 41 Dec 19, 2022
Python utility library for compositing PDF documents with reportlab.

pdfdoc-py Python utility library for compositing PDF documents with reportlab. Installation The pdfdoc-py package can be installed directly from the s

Michael Gale 1 Jan 6, 2022
The official implementation of NeMo: Neural Mesh Models of Contrastive Features for Robust 3D Pose Estimation [ICLR-2021]. https://arxiv.org/pdf/2101.12378.pdf

NeMo: Neural Mesh Models of Contrastive Features for Robust 3D Pose Estimation [ICLR-2021] Release Notes The offical PyTorch implementation of NeMo, p

Angtian Wang 76 Nov 23, 2022
This repo provides the official code for TransBTS: Multimodal Brain Tumor Segmentation Using Transformer (https://arxiv.org/pdf/2103.04430.pdf).

TransBTS: Multimodal Brain Tumor Segmentation Using Transformer This repo is the official implementation for TransBTS: Multimodal Brain Tumor Segmenta

Raymond 247 Dec 28, 2022