diff --git a/.eslintrc b/.eslintrc
index f3fe6398314c69b792d21eb4d7c8973e3bc0cc24..5690374c9b41a9efc6237332f9581e77fa8a522b 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -2,7 +2,7 @@
   "env": {
     "jest/globals": true
   },
-  "extends": ["airbnb","react-app"],
+  "extends": ["airbnb"],
   "globals": {
     "page": true,
     "document": true
diff --git a/__tests__/WebAnnotation.test.js b/__tests__/WebAnnotation.test.js
index 0e4baa8c3885e1ae568647cebf3f8bf72632f680..ee08252a386eac1bf4d26c2fb1f9b8462b0ad3c9 100644
--- a/__tests__/WebAnnotation.test.js
+++ b/__tests__/WebAnnotation.test.js
@@ -3,7 +3,9 @@ import WebAnnotation from '../src/WebAnnotation';
 /** */
 function createSubject(args = {}) {
   return new WebAnnotation({
-    body: 'body',
+    body: {
+      value: 'body',
+    },
     canvasId: 'canvasId',
     fragsel: { t: '5,10', xywh: 'xywh' },
     id: 'id',
@@ -17,11 +19,16 @@ describe('WebAnnotation', () => {
   let subject = createSubject();
   describe('constructor', () => {
     it('sets instance accessors', () => {
-      ['body', 'canvasId', 'id', 'svg'].forEach((prop) => {
+      ['canvasId', 'id', 'svg'].forEach((prop) => {
         expect(subject[prop]).toBe(prop);
       });
       expect(subject.fragsel).toStrictEqual({ t: '5,10', xywh: 'xywh' });
     });
+    it('sets instance accessors for body', () => {
+      ['body'].forEach((prop) => {
+        expect(subject[prop].value).toBe(prop);
+      });
+    });
   });
   describe('target', () => {
     it('with svg and xywh', () => {
@@ -109,20 +116,34 @@ describe('WebAnnotation', () => {
       ]);
     });
     it('with text only', () => {
-      subject = createSubject({ tags: null });
+      subject = createSubject({ image: null, tags: null });
       expect(subject.createBody()).toEqual({
         type: 'TextualBody',
         value: 'body',
       });
     });
     it('with tags only', () => {
-      subject = createSubject({ body: null });
+      subject = createSubject({ body: null, image: null });
       expect(subject.createBody()).toEqual({
         purpose: 'tagging',
         type: 'TextualBody',
         value: 'tags',
       });
     });
+    it('with image and text', () => {
+      subject = createSubject({ body: {value: 'hello'}, image: {url: 'http://example.photo/pic.jpg' }, tags: null });
+      expect(subject.createBody()).toEqual([
+        {
+          type: 'TextualBody',
+          value: 'hello',
+        },
+        {
+          type: 'Image',
+          format: 'image/jpg',
+          id: 'http://example.photo/pic.jpg',
+        },
+      ]);
+    });
   });
   describe('toJson', () => {
     it('generates a WebAnnotation', () => {
diff --git a/package-lock.json b/package-lock.json
index 9285c519542db25119becf7b9a4df2eb8c1b7932..8eeaafc622102e476b6dcc7a189e7cbb100b0ebc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5878,6 +5878,16 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/bindings": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+      "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "file-uri-to-path": "1.0.0"
+      }
+    },
     "node_modules/blob": {
       "version": "0.0.5",
       "dev": true,
@@ -6500,6 +6510,25 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/chokidar/node_modules/fsevents": {
+      "version": "1.2.13",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+      "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+      "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.",
+      "dev": true,
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "dependencies": {
+        "bindings": "^1.5.0",
+        "nan": "^2.12.1"
+      },
+      "engines": {
+        "node": ">= 4.0"
+      }
+    },
     "node_modules/chokidar/node_modules/glob-parent": {
       "version": "3.1.0",
       "dev": true,
@@ -10265,6 +10294,13 @@
         "webpack": "^4.0.0"
       }
     },
+    "node_modules/file-uri-to-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+      "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+      "dev": true,
+      "optional": true
+    },
     "node_modules/filesize": {
       "version": "6.1.0",
       "dev": true,
@@ -10698,6 +10734,20 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/fsevents": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+      "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+      "dev": true,
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
     "node_modules/function-bind": {
       "version": "1.1.1",
       "dev": true,
@@ -15782,6 +15832,21 @@
         "node": ">=6"
       }
     },
+    "node_modules/mocha/node_modules/fsevents": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+      "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+      "deprecated": "\"Please update to latest v2.3 or v2.2\"",
+      "dev": true,
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
     "node_modules/mocha/node_modules/glob": {
       "version": "7.1.3",
       "dev": true,
@@ -28341,6 +28406,16 @@
       "version": "1.13.1",
       "dev": true
     },
+    "bindings": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+      "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "file-uri-to-path": "1.0.0"
+      }
+    },
     "blob": {
       "version": "0.0.5",
       "dev": true
@@ -28805,6 +28880,17 @@
             "to-regex-range": "^2.1.0"
           }
         },
+        "fsevents": {
+          "version": "1.2.13",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+          "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "bindings": "^1.5.0",
+            "nan": "^2.12.1"
+          }
+        },
         "glob-parent": {
           "version": "3.1.0",
           "dev": true,
@@ -31465,6 +31551,13 @@
         "schema-utils": "^2.5.0"
       }
     },
+    "file-uri-to-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+      "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+      "dev": true,
+      "optional": true
+    },
     "filesize": {
       "version": "6.1.0",
       "dev": true
@@ -31779,6 +31872,13 @@
       "version": "1.2.0",
       "dev": true
     },
+    "fsevents": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+      "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+      "dev": true,
+      "optional": true
+    },
     "function-bind": {
       "version": "1.1.1",
       "dev": true
@@ -35188,6 +35288,13 @@
             "locate-path": "^3.0.0"
           }
         },
+        "fsevents": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+          "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+          "dev": true,
+          "optional": true
+        },
         "glob": {
           "version": "7.1.3",
           "dev": true,
diff --git a/src/AnnotationCreation.js b/src/AnnotationCreation.js
index 49a04ec29b9b024d8f7a8d0f39ff45c0c8e00d2a..52042c62999a8e394004d4396526eea47bfcc22f 100644
--- a/src/AnnotationCreation.js
+++ b/src/AnnotationCreation.js
@@ -1,7 +1,7 @@
 import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import {
-  IconButton, Button, Paper, Grid, Popover, Divider,
+  Button, Paper, Grid, Popover, Divider,
   MenuList, MenuItem, ClickAwayListener,
 } from '@material-ui/core';
 import { Alarm, LastPage } from '@material-ui/icons';
@@ -19,6 +19,14 @@ import StrokeColorIcon from '@material-ui/icons/BorderColor';
 import LineWeightIcon from '@material-ui/icons/LineWeight';
 import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
 import FormatShapesIcon from '@material-ui/icons/FormatShapes';
+import InsertPhotoIcon from '@material-ui/icons/InsertPhoto';
+import Dialog from '@material-ui/core/Dialog';
+import DialogTitle from '@material-ui/core/DialogTitle';
+import DialogContent from '@material-ui/core/DialogContent';
+import DialogActions from '@material-ui/core/DialogActions';
+import TextField from '@material-ui/core/TextField';
+import Checkbox from '@material-ui/core/Checkbox';
+import FormControlLabel from '@material-ui/core/FormControlLabel';
 import { SketchPicker } from 'react-color';
 import { v4 as uuid } from 'uuid';
 import { withStyles } from '@material-ui/core/styles';
@@ -55,25 +63,52 @@ function geomFromAnnoTarget(annotarget) {
 
 /** */
 class AnnotationCreation extends Component {
+  /** */
+  static checkURL(url) {
+    const expression = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/;
+    const regex = new RegExp(expression);
+
+    return url.match(regex);
+  }
+
+  /** */
+  static loadImg(url) {
+    return new Promise((resolve, reject) => {
+      const img = new Image();
+      img.src = url;
+
+      img.onload = () => resolve({ height: img.height, width: img.width });
+      img.onerror = reject;
+    });
+  }
+
   /** */
   constructor(props) {
     super(props);
 
     const annoState = {};
+    annoState.image = false;
+
     if (props.annotation) {
       //
       // annotation body
       if (Array.isArray(props.annotation.body)) {
         annoState.tags = [];
         props.annotation.body.forEach((body) => {
-          if (body.purpose === 'tagging') {
+          if (body.purpose === 'tagging' && body.type === 'TextualBody') {
             annoState.tags.push(body.value);
-          } else {
-            annoState.annoBody = body.value;
+          } else if (body.type === 'TextualBody') {
+            annoState.textBody = body.value;
+          } else if (body.type === 'Image') {
+            // annoState.textBody = body.value; // why text body here ???
+            annoState.image = body;
           }
         });
-      } else {
-        annoState.annoBody = props.annotation.body.value;
+      } else if (props.annotation.body.type === 'TextualBody') {
+        annoState.textBody = props.annotation.body.value;
+      } else if (props.annotation.body.type === 'Image') {
+        // annoState.textBody = props.annotation.body.value; // why text body here ???
+        annoState.image = props.annotation.body;
       }
       //
       // drawing position
@@ -102,29 +137,55 @@ class AnnotationCreation extends Component {
       activeTool: 'cursor',
       closedMode: 'closed',
       currentColorType: false,
+      colorPopoverOpen: false,
       fillColor: null,
       strokeColor: '#00BFFF',
       strokeWidth: 3,
       ...(props.config.annotation.defaults || {}),
     };
-
     this.state = {
       ...toolState,
-      annoBody: '',
-      colorPopoverOpen: false,
+      textBody: '',
+      activeTool: 'cursor',
+      closedMode: 'closed',
+      currentColorType: false,
+      fillColor: null,
       lineWeightPopoverOpen: false,
+      openAddImgDialog: false,
       popoverAnchorEl: null,
       popoverLineWeightAnchorEl: null,
       svg: null,
       tend: Math.floor(props.currentTime) + 10,
       textEditorStateBustingKey: 0,
       tstart: Math.floor(props.currentTime),
+      imgConstrain: false,
+      imgHeight: {
+        lastSubmittedValue: '',
+        srcValue: '',
+        validity: 0,
+        value: '',
+      },
+      imgUrl: {
+        lastSubmittedValue: '',
+        validity: 0,
+        value: '',
+      },
+      imgWidth: {
+        lastSubmittedValue: '',
+        srcValue: '',
+        validity: 0,
+        value: '',
+      },
       xywh: null,
       ...annoState,
     };
 
     this.submitForm = this.submitForm.bind(this);
-    this.updateBody = this.updateBody.bind(this);
+    // this.updateBody = this.updateBody.bind(this);
+    this.updateTextBody = this.updateTextBody.bind(this);
+    this.getImgDimensions = this.getImgDimensions.bind(this);
+    this.setImgWidth = this.setImgWidth.bind(this);
+    this.setImgHeight = this.setImgHeight.bind(this);
     this.updateTstart = this.updateTstart.bind(this);
     this.updateTend = this.updateTend.bind(this);
     this.setTstartNow = this.setTstartNow.bind(this);
@@ -140,6 +201,79 @@ class AnnotationCreation extends Component {
     this.handleCloseLineWeight = this.handleCloseLineWeight.bind(this);
     this.closeChooseColor = this.closeChooseColor.bind(this);
     this.updateStrokeColor = this.updateStrokeColor.bind(this);
+    this.isConstrained = this.isConstrained.bind(this);
+    this.handleConstrainCheck = this.handleConstrainCheck.bind(this);
+    this.handleImgDialogChange = this.handleImgDialogChange.bind(this);
+    this.handleImgDialogSubmit = this.handleImgDialogSubmit.bind(this);
+  }
+
+  /** */
+  handleImgDialogChange(open) {
+    const { imgHeight, imgWidth, imgUrl } = this.state;
+
+    this.setState({
+      imgHeight: {
+        ...imgHeight,
+        validity: 1,
+        value: imgHeight.lastSubmittedValue,
+      },
+      imgUrl: {
+        ...imgUrl,
+        validity: 1,
+        value: imgUrl.lastSubmittedValue,
+      },
+      imgWidth: {
+        ...imgWidth,
+        validity: 1,
+        value: imgWidth.lastSubmittedValue,
+      },
+      openAddImgDialog: open,
+    });
+  }
+
+  /** */
+  handleConstrainCheck(event) {
+    const value = event.target.checked;
+
+    this.setState({
+      imgConstrain: value,
+    });
+  }
+
+  /** */
+  handleImgDialogSubmit() {
+    let open = true;
+    const { imgUrl, imgHeight, imgWidth } = this.state;
+
+    const urlValidity = AnnotationCreation.checkURL(imgUrl.value) ? 1 : 2;
+    const widthValidity = imgWidth.value > 0 ? 1 : 2;
+    const heightValidity = imgHeight.value > 0 ? 1 : 2;
+    if (urlValidity === 1 && widthValidity === 1 && heightValidity === 1) {
+      open = false;
+    }
+
+    this.setState({
+      image: { id: imgUrl.value },
+      imgHeight: {
+        ...imgHeight,
+        lastSubmittedValue: heightValidity === 1 ? imgHeight.value : imgHeight.lastSubmittedValue,
+        validity: heightValidity,
+        value: imgHeight.value,
+      },
+      imgUrl: {
+        ...imgUrl,
+        lastSubmittedValue: urlValidity === 1 ? imgUrl.value : imgUrl.lastSubmittedValue,
+        validity: urlValidity,
+        value: imgUrl.value,
+      },
+      imgWidth: {
+        ...imgWidth,
+        lastSubmittedValue: widthValidity === 1 ? imgWidth.value : imgWidth.lastSubmittedValue,
+        validity: widthValidity,
+        value: imgWidth.value,
+      },
+      openAddImgDialog: open,
+    });
   }
 
   /** */
@@ -199,6 +333,106 @@ class AnnotationCreation extends Component {
     }
   }
 
+  /** */
+  async getImgDimensions(url) {
+    const { imgHeight, imgWidth, imgUrl } = this.state;
+    const urlValidity = AnnotationCreation.checkURL(url) ? 1 : 2;
+
+    try {
+      const dimensions = await AnnotationCreation.loadImg(url);
+
+      this.setState({
+        imgHeight: {
+          ...imgHeight,
+          srcValue: dimensions.height || '',
+          value: dimensions.height || '',
+        },
+        imgUrl: {
+          ...imgUrl,
+          validity: 1,
+          value: url,
+        },
+        imgWidth: {
+          ...imgWidth,
+          srcValue: dimensions.width || '',
+          value: dimensions.width || '',
+        },
+      });
+    } catch (e) {
+      this.setState({
+        imgUrl: {
+          ...imgUrl,
+          validity: urlValidity,
+          value: url,
+        },
+      });
+    }
+  }
+
+  /** */
+  setImgWidth(value) {
+    const { imgWidth } = this.state;
+    this.setState({
+      imgWidth: {
+        ...imgWidth,
+        value,
+      },
+    });
+  }
+
+  /** */
+  setImgUrl(value) {
+    const { imgUrl } = this.state;
+    this.setState({
+      imgUrl: {
+        ...imgUrl,
+        value,
+      },
+    });
+  }
+
+  /** */
+  setImgHeight(value) {
+    const { imgHeight } = this.state;
+    this.setState({
+      imgHeight: {
+        ...imgHeight,
+        value,
+      },
+    });
+  }
+
+  /** */
+  isConstrained(event) { // adjust other dimension in proportion to inputted dimension
+    const { imgConstrain, imgWidth, imgHeight } = this.state;
+    const ratio = imgWidth.srcValue / imgHeight.srcValue;
+
+    if (imgConstrain) {
+      if (event.target.id === 'width' && imgWidth.srcValue !== '') {
+        // set height to be the same as width if width is less than 0
+        const height = imgWidth.value > 0 ? imgWidth.value * (1 / ratio) : imgWidth.value;
+        this.setState({
+          imgHeight: {
+            ...imgHeight,
+            validity: 1,
+            value: height,
+          },
+        });
+      } else if (event.target.id === 'height' && imgHeight.srcValue !== '') {
+        // set width to be the same as height if height is less than 0
+        const width = imgHeight.value > 0 ? imgHeight.value * ratio : imgHeight.value;
+
+        this.setState({
+          imgWidth: {
+            ...imgWidth,
+            validity: 1,
+            value: width,
+          },
+        });
+      }
+    }
+  }
+
   /** */
   openChooseColor(e) {
     this.setState({
@@ -240,19 +474,37 @@ class AnnotationCreation extends Component {
       annotation, canvases, receiveAnnotation, config,
     } = this.props;
     const {
-      annoBody, tags, xywh, svg, tstart, tend, textEditorStateBustingKey,
+      textBody, image, imgWidth, imgHeight, imgUrl, tags, xywh, svg,
+      imgConstrain, tstart, tend, textEditorStateBustingKey,
     } = this.state;
+    const annoBody = { value: !textBody.length ? `${secondsToHMS(tstart)} -> ${secondsToHMS(tend)}` : textBody };
+
+    let imgBody;
+    if (imgWidth.validity === 1 && imgHeight.validity === 1 && imgUrl.validity === 1) {
+      imgBody = {
+        constrain: imgConstrain,
+        h: imgHeight.value,
+        url: imgUrl.value,
+        w: imgWidth.value,
+      };
+    } else {
+      imgBody = image;
+    }
+
     canvases.forEach((canvas) => {
       const storageAdapter = config.annotation.adapter(canvas.id);
+
       const anno = new WebAnnotation({
-        body: !annoBody.length ? `${secondsToHMS(tstart)} -> ${secondsToHMS(tend)}` : annoBody,
+        body: annoBody,
         canvasId: canvas.id,
         fragsel: { t: `${tstart},${tend}`, xywh },
         id: (annotation && annotation.id) || `${uuid()}`,
+        image: imgBody,
         manifestId: canvas.options.resource.id,
         svg,
         tags,
       }).toJson();
+
       if (annotation) {
         storageAdapter.update(anno).then((annoPage) => {
           receiveAnnotation(canvas.id, storageAdapter.annotationPageId, annoPage);
@@ -265,9 +517,10 @@ class AnnotationCreation extends Component {
     });
 
     this.setState({
-      annoBody: '',
+      image: false,
       svg: null,
       tend: 0,
+      textBody: '',
       textEditorStateBustingKey: textEditorStateBustingKey + 1,
       tstart: 0,
       xywh: null,
@@ -289,8 +542,8 @@ class AnnotationCreation extends Component {
   }
 
   /** */
-  updateBody(annoBody) {
-    this.setState({ annoBody });
+  updateTextBody(textBody) {
+    this.setState({ textBody });
   }
 
   /** */
@@ -307,9 +560,10 @@ class AnnotationCreation extends Component {
     } = this.props;
 
     const {
-      activeTool, colorPopoverOpen, currentColorType, fillColor, popoverAnchorEl, strokeColor,
-      popoverLineWeightAnchorEl, lineWeightPopoverOpen, strokeWidth, closedMode, annoBody, svg,
-      tstart, tend, textEditorStateBustingKey,
+      activeTool, colorPopoverOpen, currentColorType, fillColor, openAddImgDialog, popoverAnchorEl,
+      strokeColor, popoverLineWeightAnchorEl, lineWeightPopoverOpen, strokeWidth, closedMode,
+      textBody, imgUrl, imgWidth, imgHeight, imgConstrain, svg, tstart, tend,
+      textEditorStateBustingKey, image,
     } = this.state;
 
     const mediaIsVideo = typeof VideosReferences.get(windowId) !== 'undefined';
@@ -322,6 +576,7 @@ class AnnotationCreation extends Component {
       >
         <AnnotationDrawing
           activeTool={activeTool}
+          annotation={annotation}
           fillColor={fillColor}
           strokeColor={strokeColor}
           strokeWidth={strokeWidth}
@@ -436,47 +691,133 @@ class AnnotationCreation extends Component {
                   )
                   : null
               }
-
             </Grid>
           </Grid>
           <Grid container>
             { mediaIsVideo && (
             <>
-              <Grid item xs={12} onClick={this.seekToTstart}>
-                <IconButton size="small"><LastPage /></IconButton>
+              <Grid item xs={12}>
+                <ToggleButton value="true" title="Go to start time" size="small" onClick={this.seekToTstart} className={classes.timecontrolsbutton}>
+                  <LastPage />
+                </ToggleButton>
                 <Typography variant="overline">
                   Start
                 </Typography>
               </Grid>
 
               <Grid item xs={12} className={classes.paper}>
-                <IconButton onClick={this.setTstartNow}><Alarm /></IconButton>
+                <ToggleButton value="true" title="Set current time" size="small" onClick={this.setTstartNow} className={classes.timecontrolsbutton}>
+                  <Alarm />
+                </ToggleButton>
                 <HMSInput seconds={tstart} onChange={this.updateTstart} />
               </Grid>
 
-              <Grid item xs={12} onClick={this.seekToTend}>
+              <Grid item xs={12}>
                 <Typography variant="overline">
-                  <IconButton size="small"><LastPage /></IconButton>
+                  <ToggleButton value="true" title="Go to end time" size="small" onClick={this.seekToTend} className={classes.timecontrolsbutton}>
+                    <LastPage />
+                  </ToggleButton>
                   End
                 </Typography>
               </Grid>
 
               <Grid item xs={12} className={classes.paper}>
-                <IconButton onClick={this.setTendNow}><Alarm /></IconButton>
+                <ToggleButton value="true" title="Set current time" size="small" onClick={this.setTendNow} className={classes.timecontrolsbutton}>
+                  <Alarm />
+                </ToggleButton>
                 <HMSInput seconds={tend} onChange={this.updateTend} />
               </Grid>
             </>
             )}
             <Grid item xs={12}>
               <Typography variant="overline">
-                Content
+                Image Content
+              </Typography>
+            </Grid>
+            <Grid item xs={12} style={{ marginBottom: 10 }}>
+              <ToggleButton value="image-icon" aria-label="insert an image" onClick={() => this.handleImgDialogChange(true)}>
+                { image === false && <InsertPhotoIcon /> }
+                { image !== false && <img src={image.id} width="100" height="auto" alt="no trad" /> }
+              </ToggleButton>
+            </Grid>
+            <Dialog open={openAddImgDialog} fullWidth onClose={() => this.handleImgDialogChange(false)} aria-labelledby="form-dialog-title">
+              <DialogTitle id="form-dialog-title" disableTypography>
+                <Typography variant="h2">Insert image</Typography>
+              </DialogTitle>
+              <DialogContent>
+                <DialogTitle id="form-dialog-subtitle-1" style={{ paddingLeft: 0 }} disableTypography>
+                  <Typography variant="h5">Image source</Typography>
+                </DialogTitle>
+                <TextField
+                  value={imgUrl.value}
+                  onChange={(e) => this.setImgUrl(e.target.value)}
+                  onBlur={(e) => this.getImgDimensions(e.target.value)}
+                  error={imgUrl.validity === 2}
+                  helperText={imgUrl.validity === 2 ? 'Invalid URL' : ''}
+                  margin="dense"
+                  id="source"
+                  label="Image URL"
+                  type="url"
+                  fullWidth
+                />
+              </DialogContent>
+              <DialogContent>
+                <DialogTitle id="form-dialog-subtitle-2" style={{ paddingLeft: 0 }} disableTypography>
+                  <Typography variant="h5">Image dimensions</Typography>
+                </DialogTitle>
+                <TextField
+                  value={imgWidth.value}
+                  style={{ marginRight: 10, width: 100 }}
+                  onChange={(e) => this.setImgWidth(e.target.value)}
+                  onBlur={(e) => this.isConstrained(e)}
+                  error={imgWidth.validity === 2}
+                  helperText={imgWidth.validity === 2 ? 'Invalid width' : ''}
+                  margin="dense"
+                  id="width"
+                  label="Width"
+                  type="number"
+                  variant="outlined"
+                />
+                <TextField
+                  value={imgHeight.value}
+                  style={{ marginLeft: 10, width: 100 }}
+                  onChange={(e) => this.setImgHeight(e.target.value)}
+                  onBlur={(e) => this.isConstrained(e)}
+                  error={imgHeight.validity === 2}
+                  helperText={imgHeight.validity === 2 ? 'Invalid height' : ''}
+                  margin="dense"
+                  id="height"
+                  label="Height"
+                  type="number"
+                  variant="outlined"
+                />
+                <FormControlLabel
+                  control={(
+                    <Checkbox
+                      checked={imgConstrain}
+                      onChange={(e) => this.handleConstrainCheck(e)}
+                      inputProps={{ 'aria-label': 'primary checkbox' }}
+                      style={{ marginLeft: 30 }}
+                    />
+                  )}
+                  label="Constrain proportions"
+                />
+              </DialogContent>
+              <DialogActions>
+                <Button onClick={() => this.handleImgDialogChange(false)}>Cancel</Button>
+                <Button variant="contained" onClick={this.handleImgDialogSubmit} color="primary">Add</Button>
+              </DialogActions>
+            </Dialog>
+            <Grid item xs={12}>
+              <Typography variant="overline">
+                Text Content
               </Typography>
             </Grid>
             <Grid item xs={12}>
               <TextEditor
                 key={textEditorStateBustingKey}
-                annoHtml={annoBody}
-                updateAnnotationBody={this.updateBody}
+                annoHtml={textBody}
+                updateAnnotationBody={this.updateTextBody}
               />
             </Grid>
           </Grid>
@@ -551,6 +892,13 @@ const styles = (theme) => ({
     paddingRight: theme.spacing(1),
     paddingTop: theme.spacing(2),
   },
+  timecontrolsbutton: {
+    height: '30px',
+    margin: 'auto',
+    marginLeft: '0',
+    marginRight: '5px',
+    width: '30px',
+  },
 });
 
 AnnotationCreation.propTypes = {
diff --git a/src/WebAnnotation.js b/src/WebAnnotation.js
index 281055edee98da07573e80af4880cd842cfbe389..84371660aba5e694e40c52b988b0d05b69e01e96 100644
--- a/src/WebAnnotation.js
+++ b/src/WebAnnotation.js
@@ -2,7 +2,7 @@
 export default class WebAnnotation {
   /** */
   constructor({
-    canvasId, id, fragsel, body, tags, svg, manifestId,
+    canvasId, id, image, fragsel, body, tags, svg, manifestId,
   }) {
     this.id = id;
     this.canvasId = canvasId;
@@ -10,6 +10,7 @@ export default class WebAnnotation {
     this.body = body;
     this.tags = tags;
     this.svg = svg;
+    this.image = image;
     this.manifestId = manifestId;
   }
 
@@ -27,12 +28,25 @@ export default class WebAnnotation {
   /** */
   createBody() {
     let bodies = [];
-    if (this.body) {
-      bodies.push({
+
+    if (this.body && this.body.value !== '') {
+      const textBody = {
         type: 'TextualBody',
-        value: this.body,
-      });
+        value: this.body.value,
+      };
+      bodies.push(textBody);
     }
+
+    if (this.image) {
+      const imgBody = {
+        // TODO format detection
+        format: 'image/jpg',
+        id: this.image.url,
+        type: 'Image',
+      };
+      bodies.push(imgBody);
+    }
+
     if (this.tags) {
       bodies = bodies.concat(this.tags.map((tag) => ({
         purpose: 'tagging',
diff --git a/src/plugins/annotationCreationCompanionWindow.js b/src/plugins/annotationCreationCompanionWindow.js
index 5a1d537d60b399c09ad2e69d97b1c374118a2550..afe5bed4c5d67df92ac81225c52159f05344665d 100644
--- a/src/plugins/annotationCreationCompanionWindow.js
+++ b/src/plugins/annotationCreationCompanionWindow.js
@@ -2,6 +2,7 @@ import * as actions from 'mirador/dist/es/src/state/actions';
 import { getCompanionWindow } from 'mirador/dist/es/src/state/selectors/companionWindows';
 import { getWindowCurrentTime, getWindowPausedStatus } from 'mirador/dist/es/src/state/selectors/window';
 import { getVisibleCanvases } from 'mirador/dist/es/src/state/selectors/canvases';
+import { getPresentAnnotationsOnSelectedCanvases } from 'mirador/dist/es/src/state/selectors/annotations';
 import AnnotationCreation from '../AnnotationCreation';
 
 /** */
@@ -23,16 +24,9 @@ function mapStateToProps(state, { id: companionWindowId, windowId }) {
   const { annotationid } = cw;
   const canvases = getVisibleCanvases(state, { windowId });
 
-  let annotation = null;
-  canvases.forEach((canvas) => {
-    const annotationsOnCanvas = state.annotations[canvas.id];
-    Object.values(annotationsOnCanvas || {}).forEach((value, i) => {
-      if (value.json && value.json.items) {
-        const maybeAnnot = value.json.items.find((anno) => anno.id === annotationid);
-        if (maybeAnnot !== undefined) annotation = maybeAnnot;
-      }
-    });
-  });
+  const annotation = getPresentAnnotationsOnSelectedCanvases(state, { windowId })
+    .flatMap((annoPage) => annoPage.json.items)
+    .find((annot) => annot.id === annotationid);
 
   return {
     annotation,