6

Images can be easily displayed inline in an Org-mode file.

#+STARTUP: inlineimages

* headline 1

** headline 2

[[./dog-o.jpg]]

This text should be displayed to the 
right of the image above. 

Ideally, this would work for multiple lines, 
but if it's just one long wrapped line, that 
would be find too.

After the image, text should again take the 
full width of the line...

produces

enter image description here

Instead of how it is displayed above, I would like the text to be shown to the right of the image, effectively wrapping the text around the image. (This does not concern HTML or LaTeX exports, I'm specifically asking for a way to display text and image side by side in Org-mode).

Here an example of the desired result:

enter image description here

Is it possible? How could this be achieved?

3 Answers 3

4

It is possible if you can use embedded LaTeX fragments:

Code:

* headline 1

** headline 2
#+LATEX_HEADER: \usepackage{dejavu}\renewcommand*\familydefault{\ttdefault}

 [[file:2019-05-21/dog-o.jpg]] $\parbox{5cm}{\normalfont
This text should be displayed to the 
right of the image above.\\
Ideally, this would work for multiple lines, 
but if it's just one long wrapped line, that 
would be find too.}$

After the image, text should again take the 
full width of the line...

Display after translating the LaTeX fragment with C-c C-x C-l:

Image and text side-by-side.

Note that the black bar beside the text is just the cursor. It goes away if you press <down>.

You can open the text by typing C-c C-x C-l again.

4

This answer presents a method that does not need LaTeX but it needs SVG support.

The following Elisp snippet defines a new major mode txtimg that behaves just like text-mode.
A babel execution method for txtimg-mode makes that mode special.
If you type C-c C-c on an imgtxt source code block and the newline before it the block are covered with an svg image displaying the text.

You can copy the code to your init file if you like it.

;; -*- lexical-binding: t -*-

(defun text-to-img (txt &optional scale-width)
  "Create a svg image containing TXT.
The internally calculated text width is only an approximation.
If the image does not have the right width use the float number
SCALE-WIDTH which defaults to 1.0."
  (require 'svg)
  (unless scale-width (setq scale-width 1.0))
  (let* ((line 0)
     (font-family (last (split-string (aref (x-decompose-font-name (frame-parameter (selected-frame) 'font)) 0) "-")))
     (char-height (frame-char-height))
     (char-width (frame-char-width))
     (lines (split-string txt "\n"))
     (line-height (* 1.2 char-height))
     (width (ceiling (* scale-width char-width (apply #'max (mapcar #'length lines)))))
     (height (* line-height (length lines)))
     (svg (svg-create (ceiling width) (ceiling height))))
    (mapc
     (lambda (txt) (svg-text svg txt
                 :font-family font-family
                 :font-size (number-to-string char-height)
                 :y (number-to-string (floor (* line-height (incf line))))))
     lines)
    (svg-image svg)))

(define-derived-mode txtimg-mode text-mode "txtimg"
  "Helper mode for org-babel.
Just ordinary `text-mode' with another name.")

(define-key txtimg-mode-map (kbd "C-c C-c") #'org-babel-execute:txtimg)

(defun org-babel-execute:txtimg (&optional body params)
  "Put an txtimg overlay on the source block with BODY and PARAMS.
If there is already a txtimg overlay remove it.
The txtimg overlay displays the image containing the text."
  (interactive)
  (let ((ol (cl-loop for ol being the overlays from (point) to (1+ (point))
              if (overlay-get ol 'txtimg)
              return ol)))
    (if ol
    (delete-overlay ol)
      (when (and body params)
    (let* ((scale-width (plist-get params :scale-width))
           (el (org-element-context))
           (b (max 1 (1- (save-excursion
                   (goto-char (org-element-property :begin el))
                   (line-beginning-position)))))
           (e (save-excursion
            (goto-char (org-element-property :end el))
            (skip-chars-backward "[:space:]\n")
            (point)))
           (ol (make-overlay b e)))
      (overlay-put ol 'txtimg t)
      (overlay-put ol 'keymap txtimg-mode-map)
      (overlay-put ol 'display
               (text-to-img body scale-width)))))))

The the following example org source code is displayed as the image below it after pressing C-c C-c on the txtimg block.

[[file:2019-05-21/dog-o.jpg]] 
#+BEGIN_SRC txtimg :results none
This text should be displayed to the
right of the image above.
Ideally, this would work for multiple lines,
but if it's just one long wrapped line,
that would be find too.
#+END_SRC
After the image, text should again take the 
full width of the line...

image and text side-by-side

You can transform all txtimg source blocks to images at opening an Orgmode file with the following org-mode-hook:

(defun org-imgtxt-hook-fun ()
  "Process all imgtxt blocks of an orgmode buffer.
You can put this in `org-mode-hook' if you like."
  (org-save-outline-visibility t
    (org-babel-map-executables nil
      (when (eq (org-element-type (org-element-context)) 'src-block)
        (org-babel-execute-src-block)))))

(add-hook 'org-mode-hook #'org-imgtxt-hook-fun)
3

Can't be done. The image is an overlay over a single character (a "["), so as far as emacs is concerned, it's just a (big) character. If you put the cursor on the image (probably the easiest way is to put it on the line above and arrow down), then do C-u C-x = (or equivalently C-u M-x what-cursor-postion) you'll see what's going on.

The best you can do is put the text next to the link: when the image is displayed, the text is at the horizontal midpoint of the image. You can add as much text as you want to that line, but if you reformat it (e.g. with M-q), whateved does not fit ends up on the next line, i.e.underneath the image.

The moral of the story is that Emacs is not a typesetting engine.

Of course, you can accomplish what you want by exporting to LaTeX and fiddling with the appropriate LaTeX packages (e.g. wrapfig). The resulting PDF can be made exactly what you want, but doing the same thing in the emacs buffer is a lost cause I'm afraid.

1
  • Thanks for the reply, what you say makes sense. Maybe the image could be cut horizontally and displayed as a vertical stack – according to your explanation, this would give a number of lines to the right of the image? May 21, 2019 at 9:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.