Nbconvert: attached image in ipynb not shown in html

Created on 1 Nov 2017  路  19Comments  路  Source: jupyter/nbconvert

image_test.ipynb.zip
I tried converting this simple notebook with
python -m nbconvert docs/notebooks/image_test.ipynb
running nbconvert 5.3.1 . The notebook contains one markdown cell with a single line
![image.png](attachment:image.png)
But the image does not show up in the resulting html, only a cell with text 'image.png' in it.
(attachment:image.png). The image works in the notebook so it seems correctly embedded. Is this not supported? It's an important feature for me so any help would be really useful.
Thanks in advance

Most helpful comment

Have wrapped it together so anybody can immediately use it:

Usage: ipy2html.py filename.ipynb [--slides]

ipy2html.py.gz

All 19 comments

I would also need this feature, as atm it is not possible to make any other output but browser's print to PDF.

For PDF export I would suggest images are exported under some temp dir, like .ipynb_tmp to be able to generate a PDF.

How to increase intention for this feature?

Image attachments is such a cool feature with easy drag and drop images, makes it really possible to work in hardware development test and measurement projects, but without a proper HTML or PDF creation its use is limited.

I needed this, so I wrote a pre-processor to extract attached images and put them in the outputs, which is used for images in the output part of a code cell.

It has been working well for me.

https://gist.github.com/sglyon/5687b8455a0107afc6f4c60b5f313670

Thank you @sglyon for response.

Sounds interesting, and if I understand it: it extracts all images in dict{} which you then save into files, and use the files when generating the pdf with pdflatex?

If you have a small (one figure) example of usage it would be really helpful to understand the whole procedure and how you run it.

No problem.

My usage was as follows

from traitlets.config import Config
import nbformat
import nbconvert


def to_pdf(ipynb_path)
    c = Config()
    my_preprocesors = [ExtractAttachmentsPreprocessor]
    c.PDFExporter.preprocessors = my_preprocesors
    c.LatexExporter.preprocessors = my_preprocesors

    exporter = nbconvert.PDFExporter(config=c, extra_loaders=[dl])
    writer = nbconvert.writers.FilesWriter()

    nb = nbformat.read(ipynb_path, as_version=4)

    (body, resources) = exporter.from_notebook_node(nb, resources=resources)
    writer.write(body, resources, "output.pdf")

For what it's worth, fixing up the HTML post-conversion manually is also pretty straightforward: Assuming that all attachment filenames are unique, you could do something like

import nbconvert
import nbformat

with open('my_notebook.ipynb') as nb_file:
    nb_contents = nb_file.read()

# Convert using the ordinary exporter
notebook = nbformat.reads(nb_contents, as_version=4)
exporter = nbconvert.HTMLExporter()
body, res = exporter.from_notebook_node(notebook)

# Create a dict mapping all image attachments to their base64 representations
images = {}
for cell in notebook['cells']:
    if 'attachments' in cell:
        attachments = cell['attachments']
        for filename, attachment in attachments.items():
            for mime, base64 in attachment.items():
                images[f'attachment:{filename}'] = f'data:{mime};base64,{base64}'

# Fix up the HTML and write it to disk
for src, base64 in images.items():
    body = body.replace(f'src="{src}"', f'src="{base64}"')
with open('my_notebook.html', 'w') as output_file:
    output_file.write(body)

Of course, this does nothing to actually fix the bug. Without being able to claim much of an overview of how rendering occurs, it seems like you would want to somehow take this into account in the filter nbconvert.html.HTMLExporter.markdown2html (which does not see the NotebookNode itself, but if you don't mind adding this as state, you could do so in from_notebook_node).

Thank you @fuglede it is a great work-around export lib for the HTML output!

Have wrapped it together so anybody can immediately use it:

Usage: ipy2html.py filename.ipynb [--slides]

ipy2html.py.gz

Hello guys. Thanks for your workaround code snippets.

I slightly changed @platise's code which can handle multiple non-unique attachments.

import nbformat
import nbconvert
import sys

if len(sys.argv) < 2:
    print("Usage:", sys.argv[0], 'filename.ipynb', '[--slides]')
    exit(-1)

with open(sys.argv[1]) as nb_file:
    nb_contents = nb_file.read()

# Convert using the ordinary exporter
notebook = nbformat.reads(nb_contents, as_version=4)
if len(sys.argv) == 3 and sys.argv[2] == '--slides':
    outname = sys.argv[1].split('.ipynb')[0] + '.slides.html'
    print("Converting to slides:", outname)    
    exporter = nbconvert.SlidesExporter()    
else:
    outname = sys.argv[1].split('.ipynb')[0] + '.html'
    print("Converting to HTML:", outname)
    exporter = nbconvert.HTMLExporter()

body, res = exporter.from_notebook_node(notebook)

# Create a list saving all image attachments to their base64 representations
images = []
for cell in notebook['cells']:
    if 'attachments' in cell:
        attachments = cell['attachments']
        for filename, attachment in attachments.items():
            for mime, base64 in attachment.items():
                images.append( [f'attachment:{filename}', f'data:{mime};base64,{base64}'] )

# Fix up the HTML and write it to disk
for itmes in images:
    src = itmes[0]
    base64 = itmes[1]
    body = body.replace(f'src="{src}"', f'src="{base64}"', 1)

with open(outname, 'w') as output_file:
    output_file.write(body)

The usage is same.

ipy2html.py

For what it's worth, I've had success with the Export HTML with Embedded Images extension. Not sure if there's a motivating use case that's not handled by it, but it works for me.

Thanks @imcomking for upgrade, works well! and also handles exports where Embedded HTML doesn't work, with ref to @tonycpsu

Status on this?

The proposed workarounds are fine but afaict nbviewer has no use for them and images embedded via MarkDown are rendered, e.g., with the string ![My beautiful washing machine](drawing.svg) displayed directly in the rendered notebook.

Thank you @imcomking and @platise for publishing your workarounds. They work fine.

Ultimately it would be nice, if nbconvert could implement this functionality as well.

We're always open to a nice PR :) I probably don't have time to move the work-around in and test it thoroughly for a while. But I'm trying to may attention to new PR contributions and not let them linger indefinitely.

I tried the example at the top of this page with master, and it worked as expected.

So I guess this is resolved?
I'm not sure if it's in a release yet, though.

For reference, this is partly solved in #780 indeed, but i'm working on a fix and possible improvement in #980

Nice to have.

This issue appears resolved by #980 (#1057 notwithstanding). However, this issue does appear to still occur for the PDFExporter, but I will open a separate issue for that.

Was this page helpful?
0 / 5 - 0 ratings