[
  {
    "path": ".gitignore",
    "content": "#rails specific\n*.sqlite3\nconfig/database.yml\nlog/*\ntmp/*\n\n## generic files to ignore\n*~\n*.lock\n*.DS_Store\n*.swp\n*.out\n\npublic/uploads/*"
  },
  {
    "path": "Gemfile",
    "content": "source 'https://rubygems.org'\n\ngem 'sinatra'\n"
  },
  {
    "path": "README.txt",
    "content": "12 Sep 2012\n\nPreprocessing (scaling down) images on client side before uploading\n\nBecause people often upload 5MB big 3000x2000px PNGs that are then scaled down to 100x100px JPEGs on server - waste of time and bandwidth\n\n1. user selects image(s)\n2. script opens the image using FileReader API\n3. script appends it to new Image object (not displayed at all actually) \n4. new Image objects is drawn into new Canvas object, that is scaled down to desired dimensions\n5. display the canvas, ie. a preview of the image to be uploaded\n6. take the pic from canvas as JPEG in dataURI format\n7. send it to server\n8. save it on server side\n\n(c) Josef Richter"
  },
  {
    "path": "main.rb",
    "content": "require 'rubygems'\nrequire 'sinatra'\nrequire 'base64'\n\nget '/' do\n  erb :upload\nend\n\npost '/submit' do\n  \n  newimages = []\n  now = Time.now.to_i.to_s #timestamp string\n  \n  params[:images].each_with_index do |image, index|\n\n    imagedata = image.split(',')[1] #basically remove the header\n    filename = 'uploads/'+ now + '_' + (index+1).to_s + '.jpg' #construct the new filename\n    \n    # write the file\n    File.open('public/'+filename, 'wb') do|f|\n      f.write(Base64.decode64(imagedata))\n    end\n    \n    newimages << filename\n    \n  end\n  \n  erb :received, :locals => {:images => newimages}\n  \nend"
  },
  {
    "path": "public/preprocess.js",
    "content": "var fileinput = document.getElementById('fileinput');\n\nvar max_width = fileinput.getAttribute('data-maxwidth');\nvar max_height = fileinput.getAttribute('data-maxheight');\n\nvar preview = document.getElementById('preview');\n\nvar form = document.getElementById('form');\n\nfunction processfile(file) {\n  \n    if( !( /image/i ).test( file.type ) )\n        {\n            alert( \"File \"+ file.name +\" is not an image.\" );\n            return false;\n        }\n\n    // read the files\n    var reader = new FileReader();\n    reader.readAsArrayBuffer(file);\n    \n    reader.onload = function (event) {\n      // blob stuff\n      var blob = new Blob([event.target.result]); // create blob...\n      window.URL = window.URL || window.webkitURL;\n      var blobURL = window.URL.createObjectURL(blob); // and get it's URL\n      \n      // helper Image object\n      var image = new Image();\n      image.src = blobURL;\n      //preview.appendChild(image); // preview commented out, I am using the canvas instead\n      image.onload = function() {\n        // have to wait till it's loaded\n        var resized = resizeMe(image); // send it to canvas\n        var newinput = document.createElement(\"input\");\n        newinput.type = 'hidden';\n        newinput.name = 'images[]';\n        newinput.value = resized; // put result from canvas into new hidden input\n        form.appendChild(newinput);\n      }\n    };\n}\n\nfunction readfiles(files) {\n  \n    // remove the existing canvases and hidden inputs if user re-selects new pics\n    var existinginputs = document.getElementsByName('images[]');\n    var existingcanvases = document.getElementsByTagName('canvas');\n    while (existinginputs.length > 0) { // it's a live list so removing the first element each time\n      // DOMNode.prototype.remove = function() {this.parentNode.removeChild(this);}\n      form.removeChild(existinginputs[0]);\n      preview.removeChild(existingcanvases[0]);\n    } \n  \n    for (var i = 0; i < files.length; i++) {\n      processfile(files[i]); // process each file at once\n    }\n    fileinput.value = \"\"; //remove the original files from fileinput\n    // TODO remove the previous hidden inputs if user selects other files\n}\n\n// this is where it starts. event triggered when user selects files\nfileinput.onchange = function(){\n  if ( !( window.File && window.FileReader && window.FileList && window.Blob ) ) {\n    alert('The File APIs are not fully supported in this browser.');\n    return false;\n    }\n  readfiles(fileinput.files);\n}\n\n// === RESIZE ====\n\nfunction resizeMe(img) {\n  \n  var canvas = document.createElement('canvas');\n\n  var width = img.width;\n  var height = img.height;\n\n  // calculate the width and height, constraining the proportions\n  if (width > height) {\n    if (width > max_width) {\n      //height *= max_width / width;\n      height = Math.round(height *= max_width / width);\n      width = max_width;\n    }\n  } else {\n    if (height > max_height) {\n      //width *= max_height / height;\n      width = Math.round(width *= max_height / height);\n      height = max_height;\n    }\n  }\n  \n  // resize the canvas and draw the image data into it\n  canvas.width = width;\n  canvas.height = height;\n  var ctx = canvas.getContext(\"2d\");\n  ctx.drawImage(img, 0, 0, width, height);\n  \n  preview.appendChild(canvas); // do the actual resized preview\n  \n  return canvas.toDataURL(\"image/jpeg\",0.7); // get the data from canvas as 70% JPG (can be also PNG, etc.)\n\n}\n"
  },
  {
    "path": "views/received.erb",
    "content": "<%# params[:images].each do |img| %>\n  <!-- <img src=\"<%#= img %>\"/> -->\n<%# end %>\n\n<!-- anyway, better do the above I guess  -->\n<% images.each do |img| %>\n  <img src=\"<%= img %>\">\n<% end %>"
  },
  {
    "path": "views/upload.erb",
    "content": "<form id=\"form\" action=\"submit\" method=\"post\" accept-charset=\"utf-8\" enctype=\"multipart/form-data\">\n  <input id=\"fileinput\" data-maxwidth=\"620\" data-maxheight=\"620\" type=\"file\" name=\"file[]\" multiple/>\n  <input type=\"submit\" value=\"Upload &rarr;\">\n</form>\n\n<div id=\"preview\"></div>\n\n<script src=\"preprocess.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n"
  }
]