# Introduction to dash-canvas

> Note: dash-canvas is a legacy package. The recommended way to annotate images is to use the drawing tools of plotly figures.

`dash-canvas` is a module for image annotation and image processing using Dash. It provides both the `DashCanvas` object for drawing and annotations on images, and a set of utility functions to process images using the annotations.

`dash-canvas` can be used in various fields in which user interaction with images is required, such as quality control in industry, identification and segmentation of cells or organs in life and medical sciences, quantification of phases in materials and geosciences, construction of training sets for machine learning, etc.

Install `dash-canvas` with

    remotes::install_github('plotly/dash-canvas')

The source is on GitHub at plotly/dash-canvas.

### DashCanvas: a canvas object for annotations

Let's get started with a simple canvas object.

    library(dash)
    library(dashHtmlComponents)
    library(dashCanvas)

    app <- Dash$new()

    app$layout(htmlDiv(list(
      htmlH5("Press down the left mouse button and draw inside the canvas"),
      dashCanvas(id = 'canvas_101')
    )))

    app$run_server()

##### Press down the left mouse button and draw inside the canvas

You can draw inside the object with the freehand tool, and use the tool buttons to draw lines, zoom in and out, pan, select objects and move them inside the canvas.

`DashCanvas` comes with a set of properties which can be adjusted to control the geometry of the canvas, the default tool and its properties. You can pass a background image either as a filename (`filename` property) or as a data string (`image_content` property); more examples below.

    library(dash)
    library(dashHtmlComponents)
    library(dashCanvas)

    app <- Dash$new()

    filename <- 'https://upload.wikimedia.org/wikipedia/commons/e/e4/Mitochondria%2C_mammalian_lung_-_TEM_%282%29.jpg'
    canvas_width <- 500

    app$layout(htmlDiv(list(
      dashCanvas(
        id = 'canvaas_image',
        tool = 'line',
        lineWidth = 5,
        lineColor = 'red',
        filename = filename,
        width = canvas_width
      )
    )))

    app$run_server()

The height of the canvas is adjusted automatically by keeping the aspect ratio of the background image.

### Basic callbacks to modify DashCanvas properties

Like any Dash component, the properties of a `DashCanvas` can be modified by other components, via callbacks. Please be sure to have read about Basic Callbacks in the Dash Fundamentals.

    library(dash)
    library(dashHtmlComponents)
    library(dashCoreComponents)
    library(plotly)
    library(dashDaq)
    library(dashCanvas)

    filename <- 'https://www.publicdomainpictures.net/pictures/60000/nahled/flower-outline-coloring-page.jpg'
    canvas_width <- 300

    app <- Dash$new()

    app$layout(htmlDiv(list(
      htmlDiv(
        dashCanvas(
          id = 'canvaas-color',
          width = canvas_width,
          filename = filename,
          hide_buttons = list('line', 'zoom', 'pan')
        ),
        className = 'six columns'
      ),
      htmlDiv(
        list(
          htmlH6(children = 'Brush width'),
          dccSlider(
            id = 'bg-width-slider',
            min = 2,
            max = 40,
            step = 1,
            value = 5
          ),
          daqColorPicker(id = 'color-picker', label = 'Brush color', value = '#119DFF')
        ), className = 'three columns')
    )), className = "row")

    app$callback(
      output=list(id='canvaas-color', property='lineColor'),
      params=list(input(id='color-picker', property='value')),
      function(value){
        if(class(value)=='list'){
          return(value[['hex']])
        } else{
          return(value)
        }
      }
    )

    app$callback(
      output=list(id='canvaas-color', property='lineWidth'),
      params=list(input(id='bg-width-slider', property='value')),
      function(value){
        return(value)
      }
    )

    app$run_server()

###### Brush width

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
Brush color
hex

In the example above, a slider `dccSlider` and a color picker `daqColorPicker` are used to adjust the width and color of the drawing brush. We just created an image coloring tool in a few lines of code! You can learn more about available components in the component libraries section of the Dash documentation. Also note that the set of available buttons has been restricted through the`hide_buttons` properties, in order to keep the app design simple.

### Retrieving the geometry of annotations and using utility functions

The geometry of annotations can be retrieved by pressing the bottom-right button of the `DashCanvas`. This button is called "Save" by default; the name can be customized through the `goButtonTitle` property. This button updates the `json_data` property of `DashCanvas`, which is a JSON string with information about the background image and the geometry of annotations.

    library(dash)
    library(dashHtmlComponents)
    library(dashCanvas)
    library(dashTable)
    library(jsonlite)
    library(magrittr)

    filename <- 'https://upload.wikimedia.org/wikipedia/commons/e/e4/Mitochondria%2C_mammalian_lung_-_TEM_%282%29.jpg'
    canvas_width <- 500
    columns <- c("type", "width", "height", "scaleX", "strokeWidth", "path")

    app <- Dash$new()

    app$layout(htmlDiv(list(
      htmlH6('Draw on image and press Save to show annotations geometry'),
      htmlDiv(list(
        dashCanvas(
          id = 'annot-canvas',
          lineWidth = 5,
          filename = filename,
          width = canvas_width
        )
      )),
      htmlDiv(
        dashDataTable(
          id = 'canvaas-table',
          style_table = list('overflowX' = 'scroll'),
          style_cell = list(textAlign = 'left'),
          columns = lapply(columns, function(col) {
            return(list(name = col, id = col))
          })
        )
      )
    )))

    app$callback(
      output = list(id='canvaas-table', property='data'),
      params = list(input(id='annot-canvas',property='json_data')),

      function(json) {
        if (is.null(json[[1]]) || is.na(json[[1]])) {
          return(list(0, 0, 0, 0, 0, 0))
        } else {
          data <- fromJSON(json)
          df <- data[['objects']]
          df_filtered <- df[2:length(df)]
          return(df_filtered)
        }
      }
    )

    app$run_server()

###### Draw on image and press Save to show annotations geometry

type | width | height | scaleX | strokeWidth | path
--- | --- | --- | --- | --- | ---

More Examples utilizing geometry of annotations to create images is currently work in progress and will be added to the documentation soon...

### Updating the background image

The background image can be updated thanks to the `image_content` property (a `character` vector), for example using the `contents` property of `dccUpload` (an "open file" dialog). Updating `image_content` triggers the update of the `json_data` property containing the annotations.

### More examples

A gallery of examples using `DashCanvas` is available at plotly/canvas-portal.