├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ └── pkgdown.yaml ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── NEWS ├── NEWS.md ├── R ├── color.R ├── helpers.R ├── legend.R ├── plainView.R ├── plainview-package.R └── raster.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── data └── poppendorf.rda ├── inst └── htmlwidgets │ ├── plainView.js │ ├── plainView.yaml │ └── slideView_style │ └── style.css ├── man ├── figures │ ├── README-layer.png │ ├── README-stack_false.png │ └── README-stack_true.png ├── plainView.Rd ├── plainViewOutput.Rd ├── plainview-package.Rd └── poppendorf.Rd └── plainview.Rproj /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^cran-comments\.md$ 2 | ^\.travis\.yml$ 3 | ^CODE_OF_CONDUCT\.md$ 4 | ^README\.Rmd$ 5 | ^plainview\.Rproj$ 6 | ^\.Rproj\.user$ 7 | ^\.github$ 8 | ^_pkgdown\.yml$ 9 | ^docs$ 10 | ^pkgdown$ 11 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/master/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: macOS-latest, r: 'release'} 22 | - {os: windows-latest, r: 'release'} 23 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 24 | - {os: ubuntu-latest, r: 'release'} 25 | - {os: ubuntu-latest, r: 'oldrel-1'} 26 | 27 | env: 28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 29 | R_KEEP_PKG_SOURCE: yes 30 | 31 | steps: 32 | - uses: actions/checkout@v2 33 | 34 | - uses: r-lib/actions/setup-pandoc@v1 35 | 36 | - uses: r-lib/actions/setup-r@v1 37 | with: 38 | r-version: ${{ matrix.config.r }} 39 | http-user-agent: ${{ matrix.config.http-user-agent }} 40 | use-public-rspm: true 41 | 42 | - uses: r-lib/actions/setup-r-dependencies@v1 43 | with: 44 | extra-packages: rcmdcheck 45 | 46 | - uses: r-lib/actions/check-r-package@v1 47 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/master/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | release: 7 | types: [published] 8 | workflow_dispatch: 9 | 10 | name: pkgdown 11 | 12 | jobs: 13 | pkgdown: 14 | runs-on: ubuntu-latest 15 | env: 16 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - uses: r-lib/actions/setup-pandoc@v1 21 | 22 | - uses: r-lib/actions/setup-r@v1 23 | with: 24 | use-public-rspm: true 25 | 26 | - uses: r-lib/actions/setup-r-dependencies@v1 27 | with: 28 | extra-packages: pkgdown 29 | needs: website 30 | 31 | - name: Deploy package 32 | run: | 33 | git config --local user.name "$GITHUB_ACTOR" 34 | git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" 35 | Rscript -e 'pkgdown::deploy_to_branch(new_process = FALSE)' 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | docs 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: r 2 | sudo: required 3 | dist: xenial 4 | cache: packages 5 | latex: true 6 | 7 | # we cannot install lwgeom via apt as it requires v2.4.0 but only v2.1.2 is in the repos 8 | addons: 9 | apt: 10 | sources: 11 | - sourceline: 'ppa:ubuntugis/ubuntugis-unstable' 12 | packages: 13 | - libproj-dev 14 | - libgeos-dev 15 | - libgdal-dev 16 | - libudunits2-dev 17 | 18 | r: 19 | - release 20 | - devel 21 | - oldrel 22 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who 4 | contribute through reporting issues, posting feature requests, updating documentation, 5 | submitting pull requests or patches, and other activities. 6 | 7 | We are committed to making participation in this project a harassment-free experience for 8 | everyone, regardless of level of experience, gender, gender identity and expression, 9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 10 | 11 | Examples of unacceptable behavior by participants include the use of sexual language or 12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment, 13 | insults, or other unprofessional conduct. 14 | 15 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 18 | from the project team. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 21 | opening an issue or contacting one or more of the project maintainers. 22 | 23 | This Code of Conduct is adapted from the Contributor Covenant 24 | (http://contributor-covenant.org), version 1.0.0, available at 25 | http://contributor-covenant.org/version/1/0/0/ 26 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: plainview 2 | Title: Plot Raster Images Interactively on a Plain HTML Canvas 3 | Version: 0.2.1 4 | Authors@R: 5 | c(person(given = "Tim", 6 | family = "Appelhans", 7 | role = c("cre", "aut"), 8 | email = "tim.appelhans@gmail.com"), 9 | person(given = "Stefan", 10 | family = "Woellauer", 11 | role = "aut", 12 | email = "stephan.woellauer@geo.uni-marburg.de")) 13 | Maintainer: Tim Appelhans 14 | Description: Provides methods for plotting potentially large (raster) images 15 | interactively on a plain HTML canvas. In contrast to package 'mapview' 16 | data are plotted without background map, but data can be projected to 17 | any spatial coordinate reference system. 18 | Supports plotting of classes 'RasterLayer', 'RasterStack', 'RasterBrick' 19 | (from package 'raster') as well as 'png' files located on disk. 20 | Interactivity includes zooming, panning, and mouse location information. 21 | In case of multi-layer 'RasterStacks' or 'RasterBricks', RGB image plots 22 | are created (similar to 'raster::plotRGB' - but interactive). 23 | License: MIT + file LICENSE 24 | Encoding: UTF-8 25 | Depends: 26 | R (>= 2.10), 27 | methods 28 | Imports: 29 | htmltools, 30 | htmlwidgets, 31 | lattice, 32 | png, 33 | raster, 34 | viridisLite 35 | Suggests: 36 | shiny, 37 | sf, 38 | sp 39 | LazyData: true 40 | RoxygenNote: 7.2.3 41 | URL: https://r-spatial.github.io/plainview/, https://github.com/r-spatial/plainview 42 | BugReports: https://github.com/r-spatial/plainview/issues 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2019 2 | COPYRIGHT HOLDER: Tim Appelhans 3 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(plainView) 4 | export(plainViewOutput) 5 | export(plainview) 6 | export(renderPlainView) 7 | importFrom(grDevices,col2rgb) 8 | importFrom(grDevices,dev.off) 9 | importFrom(grDevices,grey.colors) 10 | importFrom(grDevices,rgb) 11 | importFrom(lattice,do.breaks) 12 | importFrom(lattice,draw.colorkey) 13 | importFrom(lattice,level.colors) 14 | importFrom(methods,setMethod) 15 | importFrom(png,writePNG) 16 | importFrom(raster,as.matrix) 17 | importFrom(raster,bandnr) 18 | importFrom(raster,filename) 19 | importFrom(raster,fromDisk) 20 | importFrom(raster,ncell) 21 | importFrom(raster,ncol) 22 | importFrom(raster,nrow) 23 | importFrom(raster,projection) 24 | importFrom(raster,raster) 25 | importFrom(raster,sampleRegular) 26 | importFrom(raster,subset) 27 | importFrom(stats,quantile) 28 | importFrom(viridisLite,inferno) 29 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | plainview 0.2.1 (2023-07-11) 2 | 3 | * check R version against character not numeric (mail from R core). 4 | 5 | miscellaneous 6 | 7 | * suggest sf and use translate util in favour of gdalUtils::gdal_translate. 8 | 9 | plainview 0.1.2 (2022-02-07) 10 | 11 | miscellaneous: 12 | 13 | * switch to gdalUtilities::gdal_translate from gdalUtils::gdal_translate as requested by Prof. Brian Ripley (via email). 14 | 15 | plainview 0.1.1 16 | 17 | bug fixes: 18 | 19 | * allow at to be missing and NULL. 20 | 21 | plainview 0.1.0 22 | 23 | * Initial release 24 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # plainview 0.2.1 (2023-07-11) 2 | 3 | * check R version against character not numeric (mail from R core). 4 | 5 | #### 🍬 miscellaneous 6 | 7 | * suggest `sf` and use translate util in favour of `gdalUtils::gdal_translate`. 8 | 9 | ## plainview 0.1.2 (2022-02-07) 10 | 11 | miscellaneous: 12 | 13 | * switch to `gdalUtilities::gdal_translate` from `gdalUtils::gdal_translate` as requested by Prof. Brian Ripley (via email). 14 | 15 | ## plainview 0.1.1 16 | 17 | bug fixes: 18 | 19 | * allow at to be missing and NULL. 20 | 21 | ## plainview 0.1.0 22 | 23 | * Initial release 24 | -------------------------------------------------------------------------------- /R/color.R: -------------------------------------------------------------------------------- 1 | ## hex color conversion 2 | col2Hex <- function(col, alpha = FALSE) { 3 | 4 | mat <- grDevices::col2rgb(col, alpha = TRUE) 5 | if (alpha) { 6 | hx <- grDevices::rgb(mat[1, ]/255, mat[2, ]/255, 7 | mat[3, ]/255, mat[4, ]/255) 8 | } else { 9 | hx <- grDevices::rgb(mat[1, ]/255, mat[2, ]/255, mat[3, ]/255) 10 | } 11 | return(hx) 12 | 13 | } 14 | -------------------------------------------------------------------------------- /R/helpers.R: -------------------------------------------------------------------------------- 1 | # isFALSE for older R version (< 3.5) 2 | is_literally_false = function(x) { 3 | if (getRversion() >= "3.5") { 4 | isFALSE(x) 5 | } else { 6 | is.logical(x) && length(x) == 1L && !is.na(x) && !x 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /R/legend.R: -------------------------------------------------------------------------------- 1 | ## legend for plainview, slideview, cubeview ============================== 2 | rasterLegend <- function(key) { 3 | lattice::draw.colorkey(key = key, draw = TRUE) 4 | } 5 | -------------------------------------------------------------------------------- /R/plainView.R: -------------------------------------------------------------------------------- 1 | if ( !isGeneric('plainView') ) { 2 | setGeneric('plainView', function(x, ...) 3 | standardGeneric('plainView')) 4 | } 5 | 6 | #' View raster objects interactively without background map but in any CRS 7 | #' 8 | #' @description 9 | #' this function produces an interactive view of the specified 10 | #' raster object(s) on a plain grey background but for any CRS. 11 | #' 12 | #' @param x a \code{\link{raster}}* object 13 | #' @param maxpixels integer > 0. Maximum number of cells to use for the plot. 14 | #' If maxpixels < \code{ncell(x)}, sampleRegular is used before plotting. 15 | #' @param col.regions color (palette).See \code{\link{levelplot}} for details. 16 | #' @param at the breakpoints used for the visualisation. See 17 | #' \code{\link{levelplot}} for details. 18 | #' @param na.color color for missing values. 19 | #' @param legend either logical or a list specifying any of the components 20 | #' decribed in the \code{colorkey} section of \link[lattice]{levelplot}. 21 | #' @param verbose should some details be printed during the process 22 | #' @param layer.name the name of the layer to be shown on the map 23 | #' @param gdal logical. If TRUE (default) gdal_translate is used 24 | #' to create the png file for display when possible. See details for further 25 | #' information. 26 | #' @param ... arguments passed on to respective methods 27 | #' 28 | #' @details 29 | #' If the raster object is not in memory 30 | #' (i.e. if \code{raster::inMemory} is \code{FLASE}) 31 | #' and argument \code{gdal} is set to TRUE (default) gdal_translate 32 | #' is used to translate the rsater object to a png file to be rendered in 33 | #' the viewer/browser. This is fast for large rasters. In this case, argument 34 | #' \code{maxpixels} is not used, instead the image is rendered in original resolution. 35 | #' However, this means that RasterLayers will be shown in greyscale. 36 | #' If you want to set a color palette manually, use \code{gdal = FALSE} and 37 | #' (optionally provide) \code{col.regions}.\cr 38 | #' \cr 39 | #' For plainView there are a few keyboard shortcuts defined: 40 | #' \itemize{ 41 | #' \item plus/minus - zoom in/out 42 | #' \item space - toggle antialiasing 43 | #' \item esc - zoom to layer extent 44 | #' \item enter - set zoom to 1 45 | #' \item ctrl - increase panning speed by 10 46 | #' } 47 | #' 48 | #' @author 49 | #' Stephan Woellauer 50 | #' @author 51 | #' Tim Appelhans 52 | #' 53 | #' @examples 54 | #' if (interactive()) { 55 | #' 56 | #' # RasterLayer 57 | #' plainView(poppendorf[[4]]) 58 | #' 59 | #' # RasterStack 60 | #' plainview(poppendorf, r = 4, g = 3, b = 2) # true color 61 | #' plainview(poppendorf, r = 5, g = 4, b = 3) # false color 62 | #' 63 | #' } 64 | #' 65 | #' @docType methods 66 | #' @export plainView 67 | #' @name plainView 68 | #' @rdname plainView 69 | #' @aliases plainView,RasterLayer-method 70 | #' 71 | #' @importFrom grDevices grey.colors dev.off col2rgb rgb 72 | #' @importFrom viridisLite inferno 73 | #' @importFrom raster raster as.matrix subset sampleRegular fromDisk filename bandnr projection nrow ncol ncell 74 | #' @importFrom png writePNG 75 | #' @importFrom lattice do.breaks level.colors draw.colorkey 76 | #' @importFrom stats quantile 77 | #' @importFrom methods setMethod 78 | 79 | ## RasterLayer ============================================================ 80 | 81 | setMethod('plainView', signature(x = 'RasterLayer'), 82 | function(x, 83 | maxpixels = 1e8, 84 | col.regions = viridisLite::inferno, 85 | at, 86 | na.color = "#BEBEBE", 87 | legend = TRUE, 88 | verbose = FALSE, 89 | layer.name = deparse(substitute(x, 90 | env = parent.frame())), 91 | gdal = TRUE, 92 | ...) { 93 | 94 | ## temp dir 95 | dir <- tempfile() 96 | dir.create(dir) 97 | fl <- paste0(dir, "/img", ".png") 98 | 99 | if (raster::fromDisk(x) & gdal) { 100 | # gdalUtilities::gdal_translate( 101 | # src_dataset = raster::filename(x) 102 | # , dst_dataset = fl 103 | # , of = "PNG" 104 | # , b = raster::bandnr(x) 105 | # ) 106 | stopifnot( 107 | "please install.packages('sf') to be able to use plainview for 108 | viewing files from disk" = requireNamespace("sf") 109 | 110 | ) 111 | sf::gdal_utils( 112 | util = "translate" 113 | , source = raster::filename(x) 114 | , destination = fl 115 | , options = c( 116 | "-of", "PNG" 117 | , "-b", as.character(raster::bandnr(x)) 118 | , "-scale" 119 | , "-ot", "Byte" 120 | ) 121 | ) 122 | cat("sf_seems_to_work\n") 123 | } else { 124 | png <- raster2PNG(x, 125 | col.regions = col.regions, 126 | at = at, 127 | na.color = na.color, 128 | maxpixels = maxpixels) 129 | 130 | png::writePNG(png, fl) 131 | } 132 | 133 | leg_fl <- NULL 134 | 135 | if (!is_literally_false(legend)) { 136 | if (raster::fromDisk(x) & gdal) { 137 | col.regions = grDevices::grey.colors(256, start = 0, end = 1, gamma = 1) 138 | } else { 139 | col.regions = col.regions 140 | } 141 | rng <- range(x[], na.rm = TRUE) 142 | if (missing(at) || is.null(at)) at <- lattice::do.breaks(rng, 256) 143 | 144 | if (isTRUE(legend)) { 145 | legend = list(NULL) 146 | } 147 | key = list(col = col.regions, 148 | at = at, 149 | height = 0.9, 150 | space = "right") 151 | # } 152 | 153 | key = utils::modifyList(key, legend) 154 | 155 | leg_fl <- paste0(dir, "/legend", ".png") 156 | png(leg_fl, height = 200, width = 80, units = "px", 157 | bg = "transparent", pointsize = 14, antialias = "none") 158 | rasterLegend(key) 159 | dev.off() 160 | } 161 | 162 | plainViewInternal(filename = fl, 163 | imgnm = layer.name, 164 | leg_fl = leg_fl, 165 | crs = raster::projection(x), 166 | dims = c(raster::nrow(x), 167 | raster::ncol(x), 168 | raster::ncell(x))) 169 | 170 | } 171 | 172 | ) 173 | 174 | # ## Raster Stack/Brick =========================================================== 175 | # #' @describeIn plainView \code{\link{stack}} / \code{\link{brick}} 176 | # 177 | # setMethod('plainView', signature(x = 'RasterStackBrick'), 178 | # function(x, 179 | # map = NULL, 180 | # maxpixels = mapviewOptions(console = FALSE)$maxpixels, 181 | # color = mapViewPalette(7), 182 | # na.color = mapviewOptions(console = FALSE)$nacolor, 183 | # values = NULL, 184 | # legend = FALSE, 185 | # legend.opacity = 1, 186 | # trim = TRUE, 187 | # verbose = mapviewOptions(console = FALSE)$verbose, 188 | # ...) { 189 | # 190 | # if (mapviewOptions(console = FALSE)$platform == "leaflet") { 191 | # leafletPlainRSB(x, 192 | # map, 193 | # maxpixels, 194 | # color, 195 | # na.color, 196 | # values, 197 | # legend, 198 | # legend.opacity, 199 | # trim, 200 | # verbose, 201 | # ...) 202 | # } else { 203 | # NULL 204 | # } 205 | # 206 | # } 207 | # ) 208 | # 209 | # 210 | # 211 | # ## Satellite object ======================================================= 212 | # #' @describeIn plainView \code{\link{satellite}} 213 | # 214 | # setMethod('plainView', signature(x = 'Satellite'), 215 | # function(x, 216 | # ...) { 217 | # 218 | # pkgs <- c("leaflet", "satellite", "magrittr") 219 | # tst <- sapply(pkgs, "requireNamespace", 220 | # quietly = TRUE, USE.NAMES = FALSE) 221 | # 222 | # lyrs <- x@layers 223 | # 224 | # m <- plainView(lyrs[[1]], ...) 225 | # 226 | # if (length(lyrs) > 1) { 227 | # for (i in 2:length(lyrs)) { 228 | # m <- plainView(lyrs[[i]], m, ...) 229 | # } 230 | # } 231 | # 232 | # if (length(getLayerNamesFromMap(m)) > 1) { 233 | # m <- leaflet::hideGroup(map = m, group = layers2bHidden(m)) 234 | # } 235 | # 236 | # out <- new('mapview', object = list(x), map = m) 237 | # 238 | # return(out) 239 | # 240 | # } 241 | # 242 | # ) 243 | # 244 | # 245 | # ## SpatialPixelsDataFrame ================================================= 246 | # #' @describeIn plainView \code{\link{SpatialPixelsDataFrame}} 247 | # #' 248 | # setMethod('plainView', signature(x = 'SpatialPixelsDataFrame'), 249 | # function(x, 250 | # zcol = NULL, 251 | # ...) { 252 | # 253 | # if (mapviewOptions(console = FALSE)$platform == "leaflet") { 254 | # leafletPlainPixelsDF(x, 255 | # zcol, 256 | # ...) 257 | # } else { 258 | # NULL 259 | # } 260 | # 261 | # } 262 | # ) 263 | # 264 | # 265 | # #' 266 | # #' 267 | # #' 268 | # #' 269 | # #' @import htmlwidgets 270 | # #' 271 | # #' @export 272 | 273 | plainViewInternal <- function(filename, imgnm, crs, dims, leg_fl = NULL) { 274 | 275 | x <- list(imgnm = imgnm, 276 | crs = crs, 277 | dims = dims, 278 | legend = !is.null(leg_fl)) 279 | 280 | image_dir <- dirname(filename) 281 | image_file <- basename(filename) 282 | 283 | attachments <- list(image_file) 284 | 285 | if(!is.null(leg_fl)) { 286 | legend_dir <- dirname(leg_fl) #same as image_dir not checked 287 | legend_file <- basename(leg_fl) 288 | attachments <- c(attachments, legend_file) 289 | } 290 | 291 | dep1 <- htmltools::htmlDependency(name = "image", 292 | version = "1", 293 | src = c(file = image_dir), 294 | attachment = attachments) 295 | 296 | deps <- list(dep1) 297 | 298 | sizing <- htmlwidgets::sizingPolicy(padding = 0, browser.fill = TRUE) 299 | 300 | htmlwidgets::createWidget( 301 | name = 'plainView', 302 | x = x, 303 | package = 'plainview', 304 | dependencies = deps, 305 | sizingPolicy = sizing 306 | ) 307 | } 308 | 309 | #' Widget output/render function for use in Shiny 310 | #' 311 | #' @param outputId Output variable to read from 312 | #' @param width,height the width and height of the map 313 | #' (see \code{\link{shinyWidgetOutput}}) 314 | #' 315 | #' @examples 316 | #' if (interactive()) { 317 | #' library(shiny) 318 | #' 319 | #' plt = plainView(poppendorf[[4]]) 320 | #' 321 | #' ui = fluidPage( 322 | #' plainViewOutput("plot") 323 | #' ) 324 | #' 325 | #' server = function(input, output, session) { 326 | #' output$plot <- renderPlainView(plt) 327 | #' } 328 | #' 329 | #' shinyApp(ui, server) 330 | #' 331 | #' } 332 | #' 333 | #' @name plainViewOutput 334 | #' @export 335 | plainViewOutput <- function(outputId, width = '100%', height = '400px'){ 336 | htmlwidgets::shinyWidgetOutput(outputId, 'plainView', 337 | width, height, package = 'plainview') 338 | } 339 | 340 | #' @param expr An expression that generates an HTML widget 341 | #' @param env The environment in which to evaluate expr 342 | #' @param quoted Is expr a quoted expression (with quote())? 343 | #' This is useful if you want to save an expression in a variable 344 | #' 345 | #' @rdname plainViewOutput 346 | #' @export 347 | renderPlainView <- function(expr, env = parent.frame(), quoted = FALSE) { 348 | if (!quoted) { expr <- substitute(expr) } # force quoted 349 | htmlwidgets::shinyRenderWidget(expr, plainViewOutput, env, quoted = TRUE) 350 | } 351 | 352 | 353 | 354 | ## Raster Stack/Brick =========================================================== 355 | #' @describeIn plainView \code{\link{stack}} / \code{\link{brick}} 356 | #' 357 | #' @param r integer. Index of the Red channel, between 1 and nlayers(x) 358 | #' @param g integer. Index of the Green channel, between 1 and nlayers(x) 359 | #' @param b integer. Index of the Blue channel, between 1 and nlayers(x) 360 | 361 | setMethod('plainView', signature(x = 'RasterStackBrick'), 362 | function(x, r = 3, g = 2, b = 1, 363 | na.color = "#BEBEBE", 364 | maxpixels = 1e8, 365 | layer.name = deparse(substitute(x, 366 | env = parent.frame())), 367 | ...) { 368 | 369 | ## temp dir 370 | dir <- tempfile() 371 | dir.create(dir) 372 | fl <- paste0(dir, "/img", ".png") 373 | 374 | # if (raster::filename(x) != "") { 375 | # gdalUtils::gdal_translate(src_dataset = filename(x), 376 | # dst_dataset = fl, 377 | # of = "PNG", 378 | # verbose = TRUE) 379 | # } else { 380 | png <- rgbStack2PNG(x, r = r, g = g, b = b, 381 | na.color = na.color, 382 | maxpixels = maxpixels, 383 | ...) 384 | png::writePNG(png, fl) 385 | #} 386 | 387 | layer.name <- paste0(layer.name, "_", r, ".", g, ".", b) 388 | plainViewInternal(filename = fl, 389 | imgnm = layer.name, 390 | crs = raster::projection(x), 391 | dims = c(raster::nrow(x), 392 | raster::ncol(x), 393 | raster::ncell(x))) 394 | 395 | } 396 | 397 | ) 398 | 399 | 400 | 401 | ## SpatialPixelsDataFrame ================================================= 402 | #' @describeIn plainView \code{\link[sp]{SpatialPixelsDataFrame}} 403 | #' 404 | #' @param zcol attribute name or column number in attribute table 405 | #' of the column to be rendered 406 | #' 407 | setMethod('plainView', signature(x = 'SpatialPixelsDataFrame'), 408 | function(x, 409 | zcol = 1, 410 | ...) { 411 | 412 | if (is.character(zcol)) nm <- zcol else nm <- names(x)[zcol] 413 | x <- raster::raster(x[zcol]) 414 | 415 | plainView(x, layer.name = nm, ...) 416 | 417 | } 418 | ) 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | ## plainview ============================================================== 427 | 428 | if ( !isGeneric('plainview') ) { 429 | setGeneric('plainview', function(...) 430 | standardGeneric('plainview')) 431 | } 432 | 433 | #' @describeIn plainView alias for ease of typing 434 | #' @aliases plainview 435 | #' @export plainview 436 | 437 | setMethod('plainview', signature('ANY'), 438 | function(...) plainView(...)) 439 | 440 | 441 | # 442 | # 443 | # ## Satellite object ======================================================= 444 | # #' @describeIn plainView \code{\link{satellite}} 445 | # 446 | # setMethod('plainView', signature(x = 'Satellite'), 447 | # function(x, 448 | # ...) { 449 | # 450 | # pkgs <- c("leaflet", "satellite", "magrittr") 451 | # tst <- sapply(pkgs, "requireNamespace", 452 | # quietly = TRUE, USE.NAMES = FALSE) 453 | # 454 | # lyrs <- x@layers 455 | # 456 | # m <- plainView(lyrs[[1]], ...) 457 | # 458 | # if (length(lyrs) > 1) { 459 | # for (i in 2:length(lyrs)) { 460 | # m <- plainView(lyrs[[i]], m, ...) 461 | # } 462 | # } 463 | # 464 | # if (length(getLayerNamesFromMap(m)) > 1) { 465 | # m <- leaflet::hideGroup(map = m, group = layers2bHidden(m)) 466 | # } 467 | # 468 | # out <- new('mapview', object = list(x), map = m) 469 | # 470 | # return(out) 471 | # 472 | # } 473 | # 474 | # ) 475 | # 476 | # 477 | 478 | 479 | -------------------------------------------------------------------------------- /R/plainview-package.R: -------------------------------------------------------------------------------- 1 | #' Plot Raster Images Interactively on a Plain HTML Canvas 2 | #' 3 | #' Provides methods for plotting potentially large (raster) images 4 | #' interactively on a plain HTML canvas. 5 | #' Supports plotting of RasterLayer, RasterStack, RasterBrick 6 | #' (from package raster) as well as png files located on disk. Interactivity 7 | #' includes zooming, panning, and mouse location information. In case of 8 | #' multi-layer RasterStacks or RasterBricks, RBG image plots are created 9 | #' (similar to raster::plotRGB - but interactive). 10 | #' 11 | #' @name plainview-package 12 | #' @docType package 13 | #' @title Plot Raster Images Interactively on a Plain HTML Canvas 14 | #' @author Tim Appelhans, Stephan Woellauer 15 | #' \emph{Maintainer:} Tim Appelhans \email{tim.appelhans@gmail.com} 16 | #' 17 | #' @keywords package 18 | #' 19 | NULL 20 | #' 21 | #' @docType data 22 | #' @name poppendorf 23 | #' @title Landsat 8 detail of Franconian Switzerland centered on Poppendorf 24 | #' @description Landsat 8 detail of Franconian Switzerland centered on Poppendorf 25 | #' @details Use of this data requires your agreement to the USGS regulations on 26 | #' using Landsat data. 27 | #' @format \code{"RasterBrick-class"} with 5 bands (bands 1 to 5). 28 | #' @source 29 | #' \url{https://earthexplorer.usgs.gov} 30 | NULL 31 | -------------------------------------------------------------------------------- /R/raster.R: -------------------------------------------------------------------------------- 1 | # Convert RasterLayers to png or RasterStacks/Bricks to RGB png 2 | 3 | ## raster layer ----------------------------------------------------------- 4 | raster2PNG <- function(x, 5 | col.regions, 6 | at, 7 | na.color, 8 | maxpixels) { 9 | 10 | x <- rasterCheckSize(x, maxpixels = maxpixels) 11 | 12 | mat <- t(raster::as.matrix(x)) 13 | 14 | if (missing(at) || is.null(at)) 15 | at <- lattice::do.breaks(range(mat, na.rm = TRUE), 256) 16 | 17 | cols <- lattice::level.colors(mat, 18 | at = at, 19 | col.regions = col.regions) 20 | cols[is.na(cols)] = na.color 21 | cols = col2Hex(cols, alpha = TRUE) 22 | #cols <- clrs(t(mat)) 23 | png_dat <- as.raw(grDevices::col2rgb(cols, alpha = TRUE)) 24 | dim(png_dat) <- c(4, ncol(x), nrow(x)) 25 | 26 | return(png_dat) 27 | } 28 | 29 | 30 | ## raster stack/brick ----------------------------------------------------- 31 | 32 | rgbStack2PNG <- function(x, r, g, b, 33 | na.color, 34 | quantiles = c(0.02, 0.98), 35 | maxpixels, 36 | ...) { 37 | 38 | x <- rasterCheckSize(x, maxpixels = maxpixels) 39 | 40 | x3 <- raster::subset(x, c(r, g, b)) 41 | 42 | mat <- cbind(x[[r]][], 43 | x[[g]][], 44 | x[[b]][]) 45 | 46 | for(i in seq(ncol(mat))){ 47 | z <- mat[, i] 48 | lwr <- stats::quantile(z, quantiles[1], na.rm = TRUE) 49 | upr <- stats::quantile(z, quantiles[2], na.rm = TRUE) 50 | z <- (z - lwr) / (upr - lwr) 51 | z[z < 0] <- 0 52 | z[z > 1] <- 1 53 | mat[, i] <- z 54 | } 55 | 56 | na_indx <- apply(mat, 1, base::anyNA) # rowNA(mat) 57 | cols <- rep(na.color, nrow(mat)) #mat[, 1] # 58 | #cols[na_indx] <- na.color 59 | cols[!na_indx] <- grDevices::rgb(mat[!na_indx, ], alpha = 1) 60 | png_dat <- as.raw(grDevices::col2rgb(cols, alpha = TRUE)) 61 | dim(png_dat) <- c(4, ncol(x), nrow(x)) 62 | 63 | return(png_dat) 64 | } 65 | 66 | 67 | rasterCheckSize <- function(x, maxpixels) { 68 | if (maxpixels < raster::ncell(x)) { 69 | warning(paste("maximum number of pixels for Raster* viewing is", 70 | maxpixels, "; \nthe supplied Raster* has", raster::ncell(x), "\n", 71 | "... decreasing Raster* resolution to", maxpixels, "pixels\n", 72 | "to view full resolution set 'maxpixels = ", raster::ncell(x), "'")) 73 | x <- raster::sampleRegular(x, maxpixels, asRaster = TRUE, useGDAL = TRUE) 74 | } 75 | return(x) 76 | } 77 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r setup, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | eval = FALSE, 11 | comment = "#>", 12 | fig.path = "man/figures/README-", 13 | out.width = "100%" 14 | ) 15 | ``` 16 | 17 | # plainview - Interactively Explore (Raster)Images 18 | 19 | 20 | [![R-CMD-check](https://github.com/r-spatial/plainview/workflows/R-CMD-check/badge.svg)](https://github.com/r-spatial/plainview/actions) 21 | ![monthly](http://cranlogs.r-pkg.org/badges/plainview) 22 | ![total](http://cranlogs.r-pkg.org/badges/grand-total/plainview) 23 | [![CRAN](http://www.r-pkg.org/badges/version/plainview?color=009999)](https://cran.r-project.org/package=plainview) 24 | [![status](https://tinyverse.netlify.com/badge/plainview)](https://CRAN.R-project.org/package=plainview) 25 | 26 | 27 | `plainview` enables interactive exploration of (raster)images. Images will be 28 | rendered on a plain HTML canvas (hence the name of the package). For spatial data 29 | this means that rendering is not restricted to a certain projection (e.g. web 30 | mercator for leaflet or mapview) but rendering is projection independent. It also 31 | means that it is possible to plot large images made up of millions of pixels. 32 | 33 | ## Installation 34 | 35 | You can install the released version of `plainview` from [CRAN](https://CRAN.R-project.org) with: 36 | 37 | ```{r, eval=FALSE} 38 | install.packages("plainview") 39 | ``` 40 | 41 | ## Example 42 | 43 | ```{r layer, eval=FALSE} 44 | # RasterLayer 45 | plainView(poppendorf[[4]]) 46 | ``` 47 | 48 | ![](man/figures/README-layer.png) 49 | 50 | ```{r stack true, eval=FALSE} 51 | # RasterStack 52 | plainview(poppendorf, r = 4, g = 3, b = 2) # true color 53 | ``` 54 | 55 | ![](man/figures/README-stack_true.png) 56 | 57 | ```{r stack false, eval=FALSE} 58 | plainview(poppendorf, r = 5, g = 4, b = 3) # false color 59 | ``` 60 | 61 | ![](man/figures/README-stack_false.png) 62 | 63 | ### Code of Conduct 64 | 65 | Please note that the 'plainview' project is released with a [Contributor Code of Conduct](https://github.com/r-spatial/plainview/blob/master/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. 66 | 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # plainview - Interactively Explore (Raster)Images 5 | 6 | 7 | 8 | [![R-CMD-check](https://github.com/r-spatial/plainview/workflows/R-CMD-check/badge.svg)](https://github.com/r-spatial/plainview/actions) 9 | ![monthly](http://cranlogs.r-pkg.org/badges/plainview) 10 | ![total](http://cranlogs.r-pkg.org/badges/grand-total/plainview) 11 | [![CRAN](http://www.r-pkg.org/badges/version/plainview?color=009999)](https://cran.r-project.org/package=plainview) 12 | [![status](https://tinyverse.netlify.com/badge/plainview)](https://CRAN.R-project.org/package=plainview) 13 | 14 | 15 | `plainview` enables interactive exploration of (raster)images. Images 16 | will be rendered on a plain HTML canvas (hence the name of the package). 17 | For spatial data this means that rendering is not restricted to a 18 | certain projection (e.g. web mercator for leaflet or mapview) but 19 | rendering is projection independent. It also means that it is possible 20 | to plot large images made up of millions of pixels. 21 | 22 | ## Installation 23 | 24 | You can install the released version of `plainview` from 25 | [CRAN](https://CRAN.R-project.org) with: 26 | 27 | ``` r 28 | install.packages("plainview") 29 | ``` 30 | 31 | ## Example 32 | 33 | ``` r 34 | # RasterLayer 35 | plainView(poppendorf[[4]]) 36 | ``` 37 | 38 | ![](man/figures/README-layer.png) 39 | 40 | ``` r 41 | # RasterStack 42 | plainview(poppendorf, r = 4, g = 3, b = 2) # true color 43 | ``` 44 | 45 | ![](man/figures/README-stack_true.png) 46 | 47 | ``` r 48 | plainview(poppendorf, r = 5, g = 4, b = 3) # false color 49 | ``` 50 | 51 | ![](man/figures/README-stack_false.png) 52 | 53 | ### Code of Conduct 54 | 55 | Please note that the ‘plainview’ project is released with a [Contributor 56 | Code of 57 | Conduct](https://github.com/r-spatial/plainview/blob/master/CODE_OF_CONDUCT.md). 58 | By participating in this project you agree to abide by its terms. 59 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://r-spatial.github.io/plainview/ 2 | template: 3 | bootstrap: 5 4 | 5 | -------------------------------------------------------------------------------- /data/poppendorf.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-spatial/plainview/e7d8a620702b6aabfe2d01f9804056f94bb982db/data/poppendorf.rda -------------------------------------------------------------------------------- /inst/htmlwidgets/plainView.js: -------------------------------------------------------------------------------- 1 | HTMLWidgets.widget({ 2 | name: 'plainView', 3 | type: 'output', 4 | initialize: function(el, width, height) {return {}}, 5 | 6 | renderValue: function(el, x, instance) { 7 | var root = el; 8 | var filename = document.getElementById("image-1-attachment").href; 9 | var legend_filename = x.legend ? document.getElementById("image-2-attachment").href : undefined; 10 | var name = x.imgnm; 11 | var crs = x.crs; 12 | var dims = x.dims; 13 | init(root, filename, name, crs, dims, legend_filename); 14 | }, 15 | 16 | resize: function(el, width, height, instance) {} 17 | }); 18 | 19 | var rootNode; 20 | var spanFactor; 21 | var image; 22 | var canvas; 23 | var crisp = true; 24 | var scale = 1; 25 | var offsetX = 0; 26 | var offsetY = 0; 27 | var dragging = false; 28 | var dragX = 0; 29 | var dragY = 0; 30 | var speed = 1; 31 | 32 | function ca(root, name, text) { 33 | var e = document.createElement(name); 34 | root.appendChild(e); 35 | if(text!==undefined) { 36 | e.innerHTML = text; 37 | } 38 | return e; 39 | } 40 | 41 | function init(root, filename, name, crs, dims, legend_filename) { 42 | rootNode = root; 43 | var divInfo = ca(root, "div"); 44 | divInfo.id = "divInfo"; 45 | 46 | var divInfoCRS = ca(root, "div"); 47 | divInfoCRS.id = "divInfoCRS"; 48 | 49 | var divInfoRight = ca(root, "div"); 50 | divInfoRight.id = "divInfoRight"; 51 | 52 | var divInfoPos = ca(divInfoRight, "span"); 53 | divInfoPos.id = "divInfoPos"; 54 | var divInfoZoom = ca(divInfoRight, "span"); 55 | divInfoZoom.id = "divInfoZoom"; 56 | var divLegend = ca(root, "div"); 57 | divLegend.id = "divLegend"; 58 | 59 | ca(divInfoPos, "span", "Pos: ").className = "position"; 60 | spanPos = ca(divInfoPos, "span", "?"); 61 | spanPos.className = "position"; 62 | spanPos.innerHTML = "???"; 63 | ca(divInfoPos, "span", "  "); 64 | 65 | ca(divInfoZoom, "span", "Zoom: ").className = "zoom_factor"; 66 | spanFactor = ca(divInfoZoom, "span", "?"); 67 | spanFactor.className = "zoom_factor"; 68 | 69 | ca(divInfo, "span", "  "); 70 | var spanName = ca(divInfo, "span", "Layer: " + name + 71 | " | Dimensions (nrow, ncol, ncell): " + dims); 72 | spanName.className = "image_name"; 73 | 74 | ca(divInfoCRS, "span", "  "); 75 | var spanCRS = ca(divInfoCRS, "span", "CRS: " + '"' + crs + '"'); 76 | spanCRS.className = "image_crs"; 77 | 78 | canvas = ca(root, "canvas"); 79 | 80 | image = new Image(); 81 | image.onload = init_image; 82 | image.src = filename; 83 | 84 | canvas.onmousedown = onmousedown; 85 | canvas.onmouseup = onmouseup; 86 | canvas.onmousemove = onmousemove; 87 | canvas.onwheel = onwheel; 88 | canvas.onmousewheel = onmousewheel; 89 | canvas.onclick = onclick; 90 | 91 | window.addEventListener("keydown", onkeydown, true); 92 | 93 | if(legend_filename !== undefined) { 94 | var legend_image = new Image(); 95 | legend_image.src = legend_filename; 96 | divLegend.appendChild(legend_image); 97 | } 98 | } 99 | 100 | function init_image() { 101 | var iw = image.width; 102 | var ih = image.height; 103 | var cw = rootNode.clientWidth; 104 | var ch = rootNode.clientHeight; 105 | var fw = cw/iw; 106 | var fh = ch/ih; 107 | scale = fw0); 200 | } 201 | 202 | function onkeydown(e) { 203 | 204 | if(e.which==109 || e.which==173 || e.which==189) { // minus key 205 | var cw = rootNode.clientWidth; 206 | var ch = rootNode.clientHeight; 207 | onzoom(cw/2, ch/2, false); 208 | } 209 | 210 | if(e.which==107 || e.which==171 || e.which==187) { // plus key 211 | var cw = rootNode.clientWidth; 212 | var ch = rootNode.clientHeight; 213 | onzoom(cw/2, ch/2, true); 214 | } 215 | 216 | if(e.which==32) { // space bar 217 | crisp = !crisp; 218 | draw(); 219 | } 220 | 221 | if(e.which==27) { // escape 222 | init_image(); 223 | } 224 | 225 | if(e.which==13) { // enter key 226 | var iw = image.width; 227 | var ih = image.height; 228 | var cw = rootNode.clientWidth; 229 | var ch = rootNode.clientHeight; 230 | var fw = cw/iw; 231 | var fh = ch/ih; 232 | scale = 1; 233 | var sw = iw*scale; 234 | var sh = ih*scale; 235 | offsetX = sw 0. Maximum number of cells to use for the plot. 45 | If maxpixels < \code{ncell(x)}, sampleRegular is used before plotting.} 46 | 47 | \item{col.regions}{color (palette).See \code{\link{levelplot}} for details.} 48 | 49 | \item{at}{the breakpoints used for the visualisation. See 50 | \code{\link{levelplot}} for details.} 51 | 52 | \item{na.color}{color for missing values.} 53 | 54 | \item{legend}{either logical or a list specifying any of the components 55 | decribed in the \code{colorkey} section of \link[lattice]{levelplot}.} 56 | 57 | \item{verbose}{should some details be printed during the process} 58 | 59 | \item{layer.name}{the name of the layer to be shown on the map} 60 | 61 | \item{gdal}{logical. If TRUE (default) gdal_translate is used 62 | to create the png file for display when possible. See details for further 63 | information.} 64 | 65 | \item{...}{arguments passed on to respective methods} 66 | 67 | \item{r}{integer. Index of the Red channel, between 1 and nlayers(x)} 68 | 69 | \item{g}{integer. Index of the Green channel, between 1 and nlayers(x)} 70 | 71 | \item{b}{integer. Index of the Blue channel, between 1 and nlayers(x)} 72 | 73 | \item{zcol}{attribute name or column number in attribute table 74 | of the column to be rendered} 75 | } 76 | \description{ 77 | this function produces an interactive view of the specified 78 | raster object(s) on a plain grey background but for any CRS. 79 | } 80 | \details{ 81 | If the raster object is not in memory 82 | (i.e. if \code{raster::inMemory} is \code{FLASE}) 83 | and argument \code{gdal} is set to TRUE (default) gdal_translate 84 | is used to translate the rsater object to a png file to be rendered in 85 | the viewer/browser. This is fast for large rasters. In this case, argument 86 | \code{maxpixels} is not used, instead the image is rendered in original resolution. 87 | However, this means that RasterLayers will be shown in greyscale. 88 | If you want to set a color palette manually, use \code{gdal = FALSE} and 89 | (optionally provide) \code{col.regions}.\cr 90 | \cr 91 | For plainView there are a few keyboard shortcuts defined: 92 | \itemize{ 93 | \item plus/minus - zoom in/out 94 | \item space - toggle antialiasing 95 | \item esc - zoom to layer extent 96 | \item enter - set zoom to 1 97 | \item ctrl - increase panning speed by 10 98 | } 99 | } 100 | \section{Methods (by class)}{ 101 | \itemize{ 102 | \item \code{plainView(RasterStackBrick)}: \code{\link{stack}} / \code{\link{brick}} 103 | 104 | \item \code{plainView(SpatialPixelsDataFrame)}: \code{\link[sp]{SpatialPixelsDataFrame}} 105 | 106 | \item \code{plainview(ANY)}: alias for ease of typing 107 | 108 | }} 109 | \examples{ 110 | if (interactive()) { 111 | 112 | # RasterLayer 113 | plainView(poppendorf[[4]]) 114 | 115 | # RasterStack 116 | plainview(poppendorf, r = 4, g = 3, b = 2) # true color 117 | plainview(poppendorf, r = 5, g = 4, b = 3) # false color 118 | 119 | } 120 | 121 | } 122 | \author{ 123 | Stephan Woellauer 124 | 125 | Tim Appelhans 126 | } 127 | -------------------------------------------------------------------------------- /man/plainViewOutput.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plainView.R 3 | \name{plainViewOutput} 4 | \alias{plainViewOutput} 5 | \alias{renderPlainView} 6 | \title{Widget output/render function for use in Shiny} 7 | \usage{ 8 | plainViewOutput(outputId, width = "100\%", height = "400px") 9 | 10 | renderPlainView(expr, env = parent.frame(), quoted = FALSE) 11 | } 12 | \arguments{ 13 | \item{outputId}{Output variable to read from} 14 | 15 | \item{width, height}{the width and height of the map 16 | (see \code{\link{shinyWidgetOutput}})} 17 | 18 | \item{expr}{An expression that generates an HTML widget} 19 | 20 | \item{env}{The environment in which to evaluate expr} 21 | 22 | \item{quoted}{Is expr a quoted expression (with quote())? 23 | This is useful if you want to save an expression in a variable} 24 | } 25 | \description{ 26 | Widget output/render function for use in Shiny 27 | } 28 | \examples{ 29 | if (interactive()) { 30 | library(shiny) 31 | 32 | plt = plainView(poppendorf[[4]]) 33 | 34 | ui = fluidPage( 35 | plainViewOutput("plot") 36 | ) 37 | 38 | server = function(input, output, session) { 39 | output$plot <- renderPlainView(plt) 40 | } 41 | 42 | shinyApp(ui, server) 43 | 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /man/plainview-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plainview-package.R 3 | \docType{package} 4 | \name{plainview-package} 5 | \alias{plainview-package} 6 | \title{Plot Raster Images Interactively on a Plain HTML Canvas} 7 | \description{ 8 | Plot Raster Images Interactively on a Plain HTML Canvas 9 | } 10 | \details{ 11 | Provides methods for plotting potentially large (raster) images 12 | interactively on a plain HTML canvas. 13 | Supports plotting of RasterLayer, RasterStack, RasterBrick 14 | (from package raster) as well as png files located on disk. Interactivity 15 | includes zooming, panning, and mouse location information. In case of 16 | multi-layer RasterStacks or RasterBricks, RBG image plots are created 17 | (similar to raster::plotRGB - but interactive). 18 | } 19 | \author{ 20 | Tim Appelhans, Stephan Woellauer 21 | \emph{Maintainer:} Tim Appelhans \email{tim.appelhans@gmail.com} 22 | } 23 | \keyword{package} 24 | -------------------------------------------------------------------------------- /man/poppendorf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plainview-package.R 3 | \docType{data} 4 | \name{poppendorf} 5 | \alias{poppendorf} 6 | \title{Landsat 8 detail of Franconian Switzerland centered on Poppendorf} 7 | \format{ 8 | \code{"RasterBrick-class"} with 5 bands (bands 1 to 5). 9 | } 10 | \source{ 11 | \url{https://earthexplorer.usgs.gov} 12 | } 13 | \description{ 14 | Landsat 8 detail of Franconian Switzerland centered on Poppendorf 15 | } 16 | \details{ 17 | Use of this data requires your agreement to the USGS regulations on 18 | using Landsat data. 19 | } 20 | -------------------------------------------------------------------------------- /plainview.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | StripTrailingWhitespace: Yes 16 | 17 | BuildType: Package 18 | PackageInstallArgs: --no-multiarch --with-keep.source 19 | PackageCheckArgs: --as-cran 20 | PackageRoxygenize: rd,collate,namespace 21 | --------------------------------------------------------------------------------