123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- class Uploadable extends Class
- constructor: (@handleSave) ->
- @node = null
- @resize_width = 50
- @resize_height = 50
- @preverse_ratio = true # Keep image originial ratio
- @try_png = false # Try to convert to png
- @png_limit = 2200 # Use png instead of jpg is smaller than this size
- @image_preview = new ImagePreview()
- @pixel_chars = @image_preview.pixel_chars
- @
- storeNode: (node) =>
- @node = node
- scaleHalf: (image) ->
- canvas = document.createElement("canvas")
- canvas.width = image.width / 2
- canvas.height = image.height / 2
- ctx = canvas.getContext("2d")
- ctx.drawImage(image, 0, 0, canvas.width, canvas.height)
- return canvas
- resizeImage: (file, width, height, cb) =>
- image = new Image()
- image.onload = =>
- @log "Resize image loaded"
- canvas = document.createElement("canvas")
- if @preverse_ratio
- [canvas.width, canvas.height] = @image_preview.calcSize(image.width, image.height, width, height)
- else
- canvas.width = width
- canvas.height = height
- ctx = canvas.getContext("2d")
- ctx.fillStyle = "#FFF"
- ctx.fillRect(0, 0, canvas.width, canvas.height)
- while image.width > width * 2
- image = @scaleHalf(image)
- ctx.drawImage(image, 0, 0, canvas.width, canvas.height)
- # Try to optimize to png
- if @try_png
- quant = new RgbQuant({colors: 128, method: 1})
- quant.sample(canvas)
- quant.palette(true)
- canvas_quant = drawPixels(quant.reduce(canvas), width)
- optimizer = new CanvasTool.PngEncoder(canvas_quant, { bitDepth: 8, colourType: CanvasTool.PngEncoder.ColourType.TRUECOLOR })
- image_base64uri = "data:image/png;base64," + btoa(optimizer.convert())
- if image_base64uri.length > @png_limit
- # Too large, convert to jpg
- @log "PNG too large (#{image_base64uri.length} bytes), convert to jpg instead"
- image_base64uri = canvas.toDataURL("image/jpeg", 0.8)
- else
- image_base64uri = canvas.toDataURL("image/jpeg", 0.8)
- @log "Size: #{image_base64uri.length} bytes"
- cb image_base64uri, canvas.width, canvas.height
- image.onerror = (e) =>
- @log "Image upload error", e
- Page.cmd "wrapperNotification", ["error", "Invalid image, only jpg format supported"]
- cb null
- if file.name
- image.src = URL.createObjectURL(file)
- else
- image.src = file
- handleUploadClick: (e) =>
- @log "handleUploadClick", e
- script = document.createElement("script")
- script.src = "js-external/pngencoder.js"
- document.head.appendChild(script)
- input = document.createElement('input')
- document.body.appendChild(input)
- input.type = "file"
- input.style.visibility = "hidden"
- input.onchange = (e) =>
- @log "Uploaded"
- @resizeImage input.files[0], @resize_width, @resize_height, (image_base64uri, width, height) =>
- @log "Resized", width, height
- if image_base64uri
- @handleSave(image_base64uri, width, height)
- input.remove()
- input.click()
- return false
- render: (body) =>
- h("div.uploadable",
- h("a.icon.icon-upload", {href: "#Upload", onclick: @handleUploadClick})
- body()
- )
- getPixelData: (data) =>
- color_db = {}
- colors = []
- colors_next_id = 0
- pixels = []
- for i in [0..data.length-1] by 4
- r = data[i]
- g = data[i+1]
- b = data[i+2]
- #r = r - (r % 64)
- #g = g - (g % 64)
- #b = b - (b % 64)
- r = Math.round(r/17)
- g = Math.round(g/17)
- b = Math.round(b/17)
- hex = Number(0x1000 + r*0x100 + g*0x10 + b).toString(16).substring(1)
- if i == 0
- @log r, g, b, data[i+3], hex
- if !color_db[hex]
- color_db[hex] = @pixel_chars[colors_next_id]
- colors.push(hex)
- colors_next_id += 1
- pixels.push(color_db[hex])
- return [colors, pixels]
- getPreviewData: (image_base64uri, target_width, target_height, cb) ->
- image = new Image()
- image.src = image_base64uri
- image.onload = =>
- image_width = image.width
- image_height = image.height
- canvas = document.createElement("canvas")
- [canvas.width, canvas.height] = @image_preview.calcSize(image.width, image.height, target_width, target_height)
- ctx = canvas.getContext("2d")
- ctx.fillStyle = "#FFF"
- ctx.fillRect(0, 0, canvas.width, canvas.height)
- while image.width > target_width * 2
- image = @scaleHalf(image)
- ctx.drawImage(image, 0, 0, canvas.width, canvas.height)
- quant = new RgbQuant({colors: 16, method: 1})
- quant.sample(canvas)
- quant.palette(true)
- canvas = drawPixels(quant.reduce(canvas), canvas.width)
- ctx = canvas.getContext("2d")
- image_data = ctx.getImageData(0, 0, canvas.width, canvas.height)
- pixeldata = @getPixelData(image_data.data)
- back = [image_width, image_height, pixeldata[0].join(""), pixeldata[1].join("")].join(",")
- @log "Previewdata size:", back.length
- cb back
- window.Uploadable = Uploadable
|