Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Adjust the view using native content transform #95

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions paper2remarkable/adjust.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-

"""Code for adjusting view

Author: G.J.J. van den Burg
License: See LICENSE file
Copyright: 2021, G.J.J. van den Burg

"""

from collections import namedtuple

from .crop import Cropper

# This is an experimental module that aims to use the reMarkable's own file
# format to adjust the view of a PDF, instead of setting the bounding box as is
# done in the "Cropper". At the moment this is work in progress.
#
# To the best of my knowledge the content file format of the reMarkable is not
# extensively documented outside what is available
# [here](https://remarkablewiki.com/tech/filesystem#content_file_format). This
# module will mainly rely on the "transform" attribute, which is largely
# undocumented.
#
# TODO:
# - Figure out what m31 and m32 do in the "transform".
# - Test if we can reliably do left/center/right crops using transforms.
# - Add a UI flag to use adjust instead of crop (as well as config option)
# - Figure out how to deliver a ZIP instead of a PDF using rmapi/rmapy


class Transform:
def __init__(self, transform=None):
self.transform = transform or self._default_transform()

def _default_transform(self):
keys = ["m%i%i" % (i, j) for i in range(3) for j in range(3)]
keys.sort()
transform = {k: 0 for k in keys}
transform["m11"] = transform["m22"] = transform["m33"] = 1
return transform


# (0, 0) bottom left: so xmin = left margin, xmax is margin + content
BBox = namedtuple("BBox", ["xmin", "xmax", "ymin", "ymax"])

PageDims = namedtuple("PageDims", ["width", "height"])


class Adjuster:
def __init__(self, input_file, pdftoppm_path="pdftoppm"):
self.cropper = Cropper(
input_file=input_file, pdftoppm_path=pdftoppm_path
)

def left(self, margins=1) -> Transform:
return self.process_file(kind="left", margins=margins)

def center(self, padding=15) -> Transform:
return self.process_file(kind="center", padding=padding)

def right(self, padding=15) -> Transform:
return self.process_file(kind="right", padding=padding)

def process_file(self, kind="left", **kwargs):
outerbbox = BBox(
xmin=float("inf"),
xmax=-float("inf"),
ymin=float("inf"),
ymax=-float("inf"),
)
outerpage = PageDims(-float("inf"), -float("inf"))

for page_idx in range(self.cropper.reader.getNumPages()):
tmpfname = self.cropper.export_page(page_idx)
raw_bbox = self.cropper.get_raw_bbox(tmpfname)
page_dims = PageDims(width=raw_bbox[4], height=raw_bbox[5])

if kind == "left":
bbox = self.cropper.get_bbox(tmpfname, **kwargs)
elif kind == "center":
bbox = self.cropper.get_center_bbox(tmpfname, **kwargs)
elif kind == "right":
bbox = self.cropper.get_right_bbox(tmpfname, **kwargs)
else:
raise ValueError(f"Unknown crop type: {kind}")

page_bbox = BBox(
xmin=bbox[0], xmax=bbox[2], ymin=bbox[1], ymax=bbox[3]
)

outerbbox.xmin = min(outerbbox.xmin, page_bbox.xmin)
outerbbox.ymin = min(outerbbox.ymin, page_bbox.ymin)
outerbbox.xmax = max(outerbbox.xmax, page_bbox.xmax)
outerbbox.ymax = max(outerbbox.ymax, page_bbox.ymax)

outerpage.width = max(outerpage.width, page_dims.width)
outerpage.height = max(outerpage.height, page_dims.height)

bbox_width = outerbbox.xmax - outerbbox.xmin
bbox_height = outerbbox.ymax - outerbbox.ymin

transform = Transform()
transform["m11"] = outerpage.height / bbox_height
transform["m22"] = outerpage.width / bbox_width
# TODO Figure out what m31 and m32 do, they're likely offsets
return transform