Last active
December 26, 2015 17:19
-
-
Save stla/7186022 to your computer and use it in GitHub Desktop.
Shiny ImageMagick - single file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| library(shiny) | |
| library(shinyIncubator) | |
| library(shinyAce) | |
| options(shiny.maxRequestSize = -1) | |
| platform <- sessionInfo()$R.version$platform | |
| linux <- stringr::str_detect(platform, "linux") | |
| logo <- function(img,link, height="200px") tags$a(href=link, tags$img(src=img, height=height)) | |
| sourcecode <- function(link){ | |
| tags$a(href=link, | |
| style="float:right; padding-right:10px;padding-top:10px; color:yellow; background-color:red; font-family:arial; font-size:20px", | |
| ">>source code<<") | |
| } | |
| ProgressBar <- function(session, max, message="in progress...", detail=""){ | |
| withProgress(session, min=1, max=max, expr={ | |
| for(i in 1:max) { | |
| setProgress(message = message, | |
| detail = detail, | |
| value=i) | |
| print(i) | |
| Sys.sleep(0.1) | |
| } | |
| }) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| shinyServer(function(input, output, session) { | |
| DONE <- reactiveValues() | |
| ## uploading ## | |
| output$upload <- renderUI({ | |
| if(!is.null(input$files)){ | |
| if(is.null(DONE[["image0"]])) return(NULL) | |
| actionButton("info",">>image info (see/hide)<<") | |
| }else fileInput("files", "Upload a JPEG file:", multiple = FALSE) | |
| }) | |
| Upload <- reactive({ | |
| if(is.null(input$files)) return(NULL) | |
| input$files | |
| }) | |
| output$filesInfo <- renderTable({ | |
| Upload() | |
| }) | |
| ## image info ## | |
| output$imageinfo <- renderUI({ | |
| if(is.null(input$files) | is.null(input$info)) return(NULL) | |
| if(input$info%%2==0) return(NULL) | |
| ProgressBar(session,max=30) | |
| files <- filesNames() | |
| comm <- paste("identify -verbose", files$infile) | |
| info <- if(linux) system(comm, intern=TRUE) else shell(comm, intern=TRUE) | |
| aceEditor("aceinfo", | |
| value=paste(info, collapse="\n"), | |
| mode="plain_text", theme="monokai", height="200px", fontSize=14, readOnly=TRUE) | |
| }) | |
| ## zoom ## | |
| output$scaleUI <- renderUI({ | |
| if(is.null(Upload())) return(NULL) | |
| sliderInput("scale", "Zoom", min=10, max=200, value=100, step=2) | |
| }) | |
| ## get file names ## | |
| filesNames <- reactive({ | |
| if(is.null(input$files)) return(NULL) | |
| files <- Upload() | |
| infile <- files$datapath | |
| infile.path <- dirname(infile) | |
| infile.name <- files$name | |
| outfile.name <- paste0("compressed_",infile.name) | |
| outfile <- paste0(infile.path,"/",outfile.name) | |
| list(path=infile.path, infile=infile, outfile=outfile, infile.name=infile.name, outfile.name=outfile.name) | |
| }) | |
| ## rendering original image ## | |
| output$image0 <- renderImage({ | |
| if(is.null(input$files)) return(NULL) | |
| files <- filesNames() | |
| # calculate progress bar time proportional to file size | |
| maxprogress <- floor(file.info(files$infile)$size / 30000) + 1 | |
| ProgressBar(session, max=maxprogress, | |
| message = 'Rendering in progress', | |
| detail = 'This may take a while...') | |
| DONE[["image0"]] <- "ok" | |
| outfile <- files$infile | |
| list(src = outfile, | |
| alt = "This is alternate text", | |
| contentType="image/jpeg") | |
| }, deleteFile = FALSE) | |
| output$image <- renderUI({ | |
| if(is.null(input$scale)) return(NULL) | |
| scale <- as.numeric(input$scale) | |
| imageOutput("image0", width=paste0(input$scale,"%")) | |
| }) | |
| ## compression settings ## | |
| getCommand <- reactive({ | |
| paste0("convert -strip -interlace Plane -gaussian-blur ", input$blur, " -quality ", input$quality, "%") | |
| }) | |
| observe({ # image magick command | |
| updateAceEditor(session, "magick", | |
| value=getCommand(), | |
| mode="r", theme="cobalt") | |
| }) | |
| observe({ # stop the app if user acts after download | |
| input$go | |
| input$blur | |
| input$compression | |
| input$tab | |
| deleted <- isolate(DONE[["deleted"]]) | |
| if(is.null(deleted)) return(NULL) | |
| stopApp() | |
| }) | |
| Compress <- reactive({ # run compression | |
| input$go # makes reactivity to the go button | |
| files <- filesNames() | |
| comm0 <- isolate(getCommand()) | |
| comm <- paste(comm0, files$infile, files$outfile) | |
| if(stringr::str_detect(platform, "linux")) system(comm) else shell(comm) | |
| }) | |
| ## compress and render image ## | |
| output$cimage <- renderImage({ | |
| files <- filesNames() | |
| # calculate progress bar time proportional to file size | |
| maxprogress <- floor(file.info(files$outfile)$size / 40000) + 1 | |
| ProgressBar(session, max=maxprogress) | |
| DONE[["cimage"]] <- "ok" | |
| files <- filesNames() | |
| list(src = files$outfile, | |
| alt = "This is alternate text") | |
| }, delete=FALSE) | |
| output$cimageUI0 <- renderUI({ | |
| scale <- as.numeric(input$scale) | |
| imageOutput("cimage", width=paste0(scale,"%")) | |
| }) | |
| output$cimageUI <- renderUI({ | |
| maxprogress <- 30 | |
| if(is.null(input$files)) return(NULL) | |
| deleted <- !is.null(isolate(DONE[["deleted"]])) | |
| if(input$go==0 | deleted) return(h2("Preview will appear here")) | |
| ProgressBar(session,max=maxprogress) | |
| Compress() | |
| DONE[["magick"]] <- TRUE | |
| uiOutput("cimageUI0") # reactivity to input$scale only | |
| }) | |
| ## compressed image info ## | |
| output$cimageTableInfo <- renderTable({ | |
| if(is.null(DONE[["magick"]])) return(NULL) | |
| input$go | |
| files <- filesNames() | |
| if(!is.null(DONE[["deleted"]])){ | |
| tabl <- data.frame("size (Mo)"=rep("0 (deleted)",2), check.names=TRUE) | |
| rownames(tabl) <- c(files$infile.name, files$outfile.name) | |
| return(tabl) | |
| } | |
| if(!(files$outfile.name %in% list.files(files$path))) return(NULL) | |
| tabl <- subset(file.info(files$infile, files$outfile), select=size) | |
| tabl$size <- round(tabl$size/1000000,1) | |
| colnames(tabl) <- "size (Mo)" | |
| rownames(tabl) <- c(files$infile.name, files$outfile.name) | |
| tabl | |
| }) | |
| output$cimageinfobutton <- renderUI({ | |
| if(is.null(DONE[["cimage"]])) return(NULL) | |
| actionButton("cimageinfo", ">>>Image info (see/hide)<<<") | |
| }) | |
| output$cimageinfo <- renderUI({ | |
| if(is.null(input$files) | is.null(input$cimageinfo)) return(NULL) | |
| if(input$cimageinfo%%2==0) return(NULL) | |
| ProgressBar(session,max=10) | |
| files <- filesNames() | |
| comm <- paste("identify -verbose", files$outfile) | |
| info <- if(linux) system(comm, intern=TRUE) else shell(comm, intern=TRUE) | |
| aceEditor("aceinfocimage", | |
| value=paste(info, collapse="\n"), | |
| mode="plain_text", theme="monokai", height="200px", fontSize=14, readOnly=TRUE) | |
| }) | |
| ## tab: Compressed Image ## | |
| output$tab2 <- renderUI({ | |
| if(is.null(input$files)) return(h2("Preview will appear here")) | |
| input$go | |
| uiOutput("cimageUI") | |
| }) | |
| ## download compressed image ## | |
| output$download <- downloadHandler( | |
| filename = filesNames()$outfile.name, | |
| content = function(file){ | |
| file.copy(filesNames()$outfile, file) | |
| # delete all files after download | |
| file.remove(unlist(filesNames()[c("infile","outfile")])) | |
| DONE[["deleted"]] <- TRUE | |
| } | |
| ) | |
| output$downloadUI <- renderUI({ | |
| if(is.null(DONE[["cimage"]])) return(NULL) | |
| downloadButton("download", label="Download") | |
| }) | |
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| shinyUI(pageWithSidebar( | |
| headerPanel("ImageMagick compression - single JPEG file", | |
| tags$head( | |
| logo(img="http://www.imagemagick.org/image/logo.jpg", link="http://www.imagemagick.org/script/index.php"), | |
| sourcecode(link="https://gist.github.com/stla/7186022") | |
| ) | |
| ), | |
| sidebarPanel( | |
| conditionalPanel( | |
| condition='input.tab=="Original image"', | |
| uiOutput("upload"), | |
| br() | |
| ), | |
| conditionalPanel( | |
| condition='input.tab=="Compressed image"', | |
| numericInput("quality", "compression (%)", value=80, step=2), | |
| numericInput("blur", "gaussian blur", value=0.05, step=0.01) | |
| ), | |
| uiOutput("scaleUI"), | |
| conditionalPanel( | |
| condition='input.tab=="Compressed image"', | |
| uiOutput("cimageinfobutton"), | |
| tableOutput("cimageTableInfo") | |
| ) | |
| ), | |
| mainPanel( | |
| progressInit(), | |
| tabsetPanel( | |
| tabPanel("Original image", | |
| tableOutput("filesInfo"), | |
| uiOutput("imageinfo"), | |
| uiOutput("image") | |
| ), | |
| tabPanel("Compressed image", | |
| h4("This ImageMagick command is ready to be executed:"), | |
| aceEditor("magick", | |
| value="", | |
| mode="r", theme="cobalt", height="10px", fontSize=14, readOnly=TRUE), | |
| div(class='row-fluid', | |
| div(class='span6', | |
| actionButton("go", "Run this ImageMagick command") | |
| ), | |
| div(class='span6', | |
| uiOutput("downloadUI") | |
| ) | |
| ), | |
| helpText(HTML("<p> >>><a href = \"http://stackoverflow.com/questions/7261855/recommendation-for-compress-jpg-files-with-image-magick\">recommendations for JPEG recompressing</a><<<")), | |
| uiOutput("cimageinfo"), | |
| uiOutput("tab2") | |
| ), | |
| id="tab" | |
| ) | |
| ) | |
| )) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment