#!/usr/bin/env python3 # # Script for converting a reMarkable tablet lines file to an SVG # image. Originally from # # https://github.com/lschwetlick/maxio/tree/master/tools # # but hacked to allow for specification of desired size of resulting # SVG image in terms of width and height. Log of changes at the end # of the file. # # Changed by Eric S Fraga; see log of changes at end. import sys import struct import os.path import argparse __prog_name__ = "rM2svg" __version__ = "0.0.1beta $Revision: 1.7 $" # Size default_x_width = 1404 default_y_width = 1872 # Mappings stroke_colour={ 0 : "black", 1 : "grey", 2 : "white", } '''stroke_width={ 0x3ff00000 : 2, 0x40000000 : 4, 0x40080000 : 8, }''' def main(): parser = argparse.ArgumentParser(prog=__prog_name__) parser.add_argument("-1", "--singlefile", help="Enable multipage svg file", action='store_true', ) parser.add_argument('--height', help='Desired height of image', type=float, default=default_y_width) parser.add_argument('--width', help='Desired width of image', type=float, default=default_x_width) parser.add_argument("-i", "--input", help=".lines input file", required=True, metavar="FILENAME", #type=argparse.FileType('r') ) parser.add_argument("-o", "--output", help="prefix for output files", required=True, metavar="NAME", #type=argparse.FileType('w') ) parser.add_argument("-c", "--coloured_annotations", help="Colour annotations for document markup.", action='store_true', ) parser.add_argument('--version', action='version', version='%(prog)s {version}'.format(version=__version__)) args = parser.parse_args() if not os.path.exists(args.input): parser.error('The file "{}" does not exist!'.format(args.input)) if args.coloured_annotations: global stroke_colour stroke_colour = { 0: "blue", 1: "red", 2: "white", 3: "yellow" } lines2svg(args.input, args.output, args.singlefile, args.coloured_annotations, args.width, args.height) def abort(msg): print(msg, file=sys.stderr) sys.exit(1) def lines2svg(input_file, output_name, singlefile, coloured_annotations=False, x_width=default_x_width, y_width=default_y_width): # Read the file in memory. Consider optimising by reading chunks. with open(input_file, 'rb') as f: data = f.read() offset = 0 if output_name.endswith(".svg") and not singlefile: output_name = output_name[:-4] # Is this a reMarkable .lines file? expected_header=b'reMarkable lines with selections and layers' if len(data) < len(expected_header) + 4: abort('File too short to be a valid file') fmt = '<{}sI'.format(len(expected_header)) header, npages = struct.unpack_from(fmt, data, offset); offset += struct.calcsize(fmt) if header != expected_header or npages < 1: abort('Not a valid reMarkable file: '.format(header, npages)) if singlefile: output = open(output_name, 'w') output.write(''.format(y_width, x_width)) # BEGIN Notebook output.write(''' ''') # Iterate through pages (There is at least one) for page in range(npages): if singlefile: output.write(''.format(page, 'none' if page != 0 else 'inline')) # Opening page group, visible only for the first page. else: output = open("{}_{:02}.svg".format(output_name, page+1), 'w') output.write('\n'.format(y_width, x_width)) # BEGIN page fmt = '\n') # END stroke if singlefile: # Overlay the page with a clickable rect to flip pages output.write(''.format(x_width, y_width, (page + 1) % npages)) output.write('') # Closing page group else: output.write('') # END page output.close() if singlefile: output.write('') # END notebook output.close() if __name__ == "__main__": main() # $Log: rM2svg,v $ # Revision 1.7 2018/09/26 11:08:52 ucecesf # Summary: allow for floating point numbers for geometry # # revision 1.6 # date: 2018/09/24 06:18:19; author: ucecesf; state: Exp; lines: +14 -9 # Summary: adjust for different page width/height ratios # # revision 1.5 # date: 2018/09/23 18:21:43; author: ucecesf; state: Exp; lines: +15 -5 # Summary: added height and width arguments # # revision 1.4 # date: 2018/09/23 18:08:05; author: ucecesf; state: Exp; lines: +1 -1 # Summary: added revision info # # revision 1.3 # date: 2018/09/20 17:39:21; author: ucecesf; state: Exp; lines: +2 -0 # Summary: adjusted pen stroke width for new transformation # # revision 1.2 # date: 2018/09/20 17:24:22; author: ucecesf; state: Exp; lines: +6 -4 # Summary: transformation aiming at standard A4 LaTeX PDF document # # Line widths etc. still need adjusting. # # revision 1.1 # date: 2018/09/14 08:56:07; author: ucecesf; state: Exp; # Initial revision