-
Notifications
You must be signed in to change notification settings - Fork 106
Pdf rendering of rM handwritten notes #41
Comments
Hi Loric!
Actually, the #38's title is a bit of a misnomer. What that PR adds is initial support to render PDF notes as a separate PDF (without the original PDF document). As you mention, the format is exactly the same as the handwritten notes, and in fact, I actually test this with
Not really. We may need to change the PDF library in the future if we want to render annotations on top of the original PDF document. However, in order to support handwriting notes in a better way, what we need to do next is add better support for the different pens, tilts and pressures. Right now, all the styles (pen, tilt, pressure) are rendered in the same way. See this image: On the left you can see a doc rendered by the original app, and on the right a doc rendered by What we would need to do is play around with the different styles in pdf/setStyle() which currently is as simple as: func (p PdfGenerator) setStyle(pdf *gofpdf.Fpdf, stroke Stroke) {
pdf.SetDrawColor(0, 0,0)
pdf.SetLineWidth(0)
pdf.SetLineCapStyle("round")
} and compare the rendering results. Of course, rm2svg and @ax3l's work will be super useful to get this right quicker. I'm not going to have much time to work on this during the next few weeks so I'd be super grateful if you wanted to give it go. I'm also cc'ing @peerdavid who might also be interested. Thank you! Edit: @lobre, just saw your https://github.com/lobre/rm repo Nice work! You've probably spent more time on rendering rM notes than me! |
Effectively, I tried a while ago to rewrite @ax3l's work in pure Go ! I started with the parsing of the I am just not super satisfied of the code itself. It seems too complicated to understand, too many levels of indentations and not super idiomatic. But I could try to work on it again and try to integrate a first version here following what you started with annotations. I can see that the Remarkable As this format might change again, the parsing part of the code should be rather obvious to easily adapt if necessary. I still think it is a good idea to have a clear separation between the parsing and the rendering phases. That would allow to have a clearly defined model representing a rM note and to easily render it using different libraries and effects in the future (PDF, PNG format, or even integrating rainbow backgrounds and colourful pencils...). I don't know much of |
Cool, great work! There is also my rust prototype, lines-are-rusty ;-) But admittedly lines-are-beautiful is the real deal, where I can develop quicker in. Did you look into the new svg exports already so we an re-build the original renderer? The PDFs were too broken and I did not invest too much time yet. Would love to build the original lines pixel-by-pixel (started a while ago on it, but no time currently).
I should investigate the format changes, will do! ax3l/lines-are-beautiful#15
Yes, that is also the idea I had with the file handler lib. Renderers in my case are "examples" using the file API.
I would even prefer this in most cases for annotations that I share with other people :) |
Hi @ax3l, Thanks for your comment and thanks for the great work of analysis on the
I am sure it was a great fun to have this Remarkable device for tweaking around with rust! I have thrown a glance at your rust project but I was less comfortable with this language unfortunately.
I have had a quick look into this format. Here are what I noticed so far. Here is the general SVG format.
The first HTML tag apart from the header is a base64 PNG encoded version of the background template of the note. This means this template stays static. Then, there is a combination of graphic containers with each a single path. As no specific CSS class are used, it seems the styling is only using the default browser's "user agent stylesheet". A path element represents shapes with the same styling instructions. The style is defined through the SVG default stroke properties:
As far as I can see, the number of I did not go further than this quick analysis so far. I did not try multiple layers but I guess they don't impact the rendering. As well, I did not try to export an annotated PDF to SVG but I suppose the format would be the same. I think SVG would need way more analysis to correctly understand how it is implemented. But effectively, that could be more interesting than trying to generate a PDF version that would barely represent the original note. If we are able to generate the same SVG file, we would have exactly the same rendering which would be dope! Maybe we can even think of generating other rendering formats by converting an initial rendered SVG. I don't really estimate the difficulty for this. Do you also think SVG could be a "starting point" for the rendering?
Thanks a lot. Really impressed by your ability to decode binary formats! I have seen you talk and slides, it was of great interest. I will try to integrate a better version of the parser into |
Hi @lobre, thank you for the kind words! The rust project is just me learning rust, not really useful yet, the C++ implementation is the best reference.
Haha thanks, I was surprised as well. That was a lot of fun, never thought that it would lead somewhere as I never did this before and expected there be dragons.
Just wonderful. Base64-encoded templates are very good, I had to export the PNGs from the binary for my local testing which was less enjoyable and of course had no labels (and contained even some hidden ones that did not make it into pencils ;-) ).
Absolutely, the influence of tilt, pressure and tangent direction of two connected points in a line per pencil style would otherwise be very hard to analyze from any other of the formats (PDF is a cumbersome bloat-format and PNG is already combined and pixelated). What I did so far: take the Not that not all pencils styles (and their algorithms) will depend on e.g. tilt. Depends e.g. if you emulate a ballpoint pen (no tilt dependence), a paint brush (definitely tilt dependent), or a fountain pen with fancy flat fount (nibs for calligraphy, they should have added such as well <3). We already documented that by now from the official bog entries of reMarkable, thanks @matteodelabre for that. As an orientation, take a look how the gimp |
This methodology of analysis seems good to me! And the documentation table you are linking from your
If I remember well, the png background templates were stored externally on the remarkable device and only referenced by their name in the note's
Not sure to understand which process you are referring to. I don't recall seeing any png contained in the binary. Did I miss something?
I will have a look, if you are right, that would be a really convenient way for speeding the analysis. And for sure, I'll do my best to decode your german spoken video, I didn't realize you had this second one recorded! |
No, that was shortly before the SVG update was released and I did not go much further since then due to limited time, unfortunately. That was my start to try to analyze the PDF and PNG renderer, but now we have a much better starting point with the SVG since we actually see the placements of each patch/dot along the line depending on
Didn't know that, looked to me as if they were just embedded in the main
What I would do to avoid issues, because you might be touching copyright territory here with the original pngs/templates, is the following: a) just create a small sample svg drawing that contains all pencil templates and share that and read from it. It will naturally contain all the basic png/base64 patches you need. Or b) when you have the original templates just roll your own that are very close in pixel structure and final impression, but created new from scratch. That said: I am not a lawyer.
I was trying to see if I can understand the renderer from the final composed image in PNG and analytical
Sorry again for that, it's the slides that count :) Any other questions in the session were mainly about my impression of the openness of the company, on which I can only speculate. Feel free to ask any further questions. |
Okay cool, so to sum up! 1. SVG analysis for understanding the exact rendering process This new SVG beta export introduced by the latest upgrade from Remarkable can truly be an opportunity to finally implement a renderer that would have the exact same shape as Remarkable's exports. We need to analyse using different examples and understand the impacts of each pencil style on the exported SVG. Thereafter, we should easily be able to implement a realistic renderer. 2. Parsing the .lines format in Go I think we need a solid encoder/decoder from the binary Gladly, @ax3l has already done a excellent job of documenting the binary format here. He also has an implemented version of the decoder in C++ here. @ax3l may find some time to get the grasp on the 3rd 3. Encoding a modeled version into a A reversed process to encode a Go model representing a note into a valid 4. Implementation of the SVG renderer from the Go model When we will have decrypted/understood entirely the SVG format from Remarkable, we will be able to create our own SVG renderer from a Go model representing a note. 5. Conversion of SVG into other formats The final SVG note may then converted to other formats such as PDF or PNG... (External Go packages/libraries?). I pretty much have the same thoughts as @juruen about the fact we need a full Go implementation for the cloud api, the parser and the renderer. Having said that, we need a full time team of developer to get going :-D. More seriously, (even if I am also quite busy these days) I will try to find some time to have a look at the step 2 as I started this task on a separate repo here. |
I just updated lines-are-beautiful (C++) and lines-are-rusty (Rust) for v3 |
Thanks for the message! I am not far from creating a pull request here as well. |
Hi. I've written a converter in go called rm2pdf for rm files overlaying PDFs or simply notes as a holiday test project. I'm using a reMarkable running v2.0.2.0 software creating line It includes an .rm parser based on rm2svg and strokes paths using fpdf. It creates multi-layer PDFs. You can grab my work at http://campbell-lange.net/media/files/rm2pdf.tgz (sha1sum Run the tests to get some example output, or read doc.go, or run If it is useful I'm happy to stick the source on github after cleaning it up a bit. I'll also have to sort out the package paths if I publish it. Here is a PDF from an example note made on a reMarkable, with the layer colour forced to blue: |
👋 @rorycl, support to render PDF annotations is something we are missing and I'd definitely like to see.
So, yeah +1000 to do ⬆️ |
Hi @juruen. I've put the project at https://github.com/rorycl/rm2pdf. |
👋 @rorycl Thank you so much for uploading the code. I spent some time playing with it and with the import library and as you know, there are some issues with some PDFs. Actually, I had issues with most of my PDFs :( That's why I decided to explore the path of using a different PDF library and the results have been great so far. You can see the current PR in #85 Thank you! |
Hi @juruen I'll contact the author of the import library ( By the way, did you try the rmparser component of rm2pdf? I updated the docs earlier. See rm2pdf seems to work fine for handwritten notes in notebooks, using the A4 template, in my testing. |
Meanwhile, @lobre, I believe In the case of creating PDFs from a source PDF with annotations, we have found a problem I haven't had any reports of issues with the rmparser component of |
Just a quick note, I just merged #85 which introduces PDF annotations using We can now generate overlayed annotations on top of existing PDF documents. There's still a bit of work to use different styles and pen sizes but we finally can render handwritten notes on top of PDF docs 🎉 |
@rorycl gofpdi v1.0.9 now supports xref streams |
In pull request #138 there's an attempt to improve the render of annotation.
|
@f3fora please check out https://github.com/rorycl/rm2pdf The rmparse component and rmpdf/stroke.go could be turned into a library for abstractly describing strokes which could be written to pdf, svg, png etc using a configuration file as you suggest. Apart from these needing to be separate modules, there are unfortunately a number of issues with the gofpdi library not reliably importing pdf pages. An abstract library could allow people to use the underlying pdf library they wish to use (open-source or otherwise). |
Hello,
Thanks for starting this golang utility around the rM tablet. The rM official ecosystem is quite closed while this tablet has a great potential!
I know the aim of this project was simply to interact with the rM api to get or put files from the device's cloud.
However, I have seen you have started an implementation of pdf rendering for annotations. I started something similar for rendering regular notes a while ago and I did not go farther due to lack of time.
But as the scope of rmapi is expanding a little, maybe it could be a good idea to render as well regular handwritten notes from the rM format to pdf? As far as I understand, the format is quite the same for notes as for annotated pdf.
Having all the downloading/rendering in golang with a single binary would be rather interesting. If you agree with this, I could try to find some time to contribute and adapt the annotations implementation toward a more general one including both annotations and regular notes.
Did you notice any technical issues / conception problems that would make this task difficult to implement?
Thanks,
Loric
The text was updated successfully, but these errors were encountered: