summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--js/asdf.js4
-rw-r--r--shader-picker.html464
2 files changed, 465 insertions, 3 deletions
diff --git a/js/asdf.js b/js/asdf.js
index 0e173a1..2b929ac 100644
--- a/js/asdf.js
+++ b/js/asdf.js
@@ -20,7 +20,6 @@ asdf.fetch = function (opt){
'data': params,
'dataType': "jsonp",
'success': function(urls){
- console.log(urls);
asdf.fetching = false;
opt.success && opt.success(urls)
},
@@ -65,8 +64,7 @@ dumpfm.fetch = function(opt){
dumpfm.fetching = false;
for (var i = 0, len = urls.length; i < len; i++) {
var url = urls[i].url;
- console.log(url)
- if (url.match(/\/^\d+\//)) {
+ if (url.match(/^\/\d+\//)) {
url = "http://dump.fm/images/" + url;
}
else {
diff --git a/shader-picker.html b/shader-picker.html
new file mode 100644
index 0000000..a6d1e12
--- /dev/null
+++ b/shader-picker.html
@@ -0,0 +1,464 @@
+<!doctype html>
+<html>
+<head>
+<title>Shader</title>
+<style type="text/css">
+html,body { margin: 0; padding: 0; }
+#url { width: 450px; }
+#width,#height,#framecount,#framedelay,#frameinterval,#background { width: 30px; }
+#shader { width: 100%; height: 247px; font-family: fixed; }
+#controls { width: 450px; }
+#frames { width: 435px; min-height: 100px; border: 1px solid #ddd; line-height: 0; }
+#frames div { margin: 1px; padding: 0; position: relative; border: 1px solid #eee; cursor: -webkit-grab; }
+.dragging { cursor: -webkit-grabbing !important; }
+.ui-sortable-helper { cursor: -webkit-grabbing !important; }
+#frames canvas { display: block }
+#frames .remove { position: absolute; top: 5px; right: 5px; color: #f00; padding: 3px; border: 0;background: white; font-size: 10px; line-height: 10px; }
+.paused { background: black; color: white; border-width: 1px; padding: 1px 3px 2px 4px; }
+.paused { outline: 0 !important; }
+div { display: inline-block; padding: 10px;}
+#gallery,#controls,#workspace,#rendered{ float: left; }
+#rendered img { min-width: 500px; display: block; }
+#render,#save { font-weight: bold; }
+#render { float: right; }
+#instructions { position: absolute;top:20px;right:20px; width:190px;height:465px; box-shadow:5px 5px 10px rgba(0,0,0,0.3); background:rgba(255,255,255,0.8); display: none; cursor: -webkit-grab; }
+#instructions iframe {width: 100%;height:100%;margin:0;padding:0;border:0;}
+#instructions.dragging iframe { pointer-events: none; }
+#instructions .close { position: absolute; top: 5px; right: 5px; color: #f00; padding: 3px; border: 0;background: white; font-size: 10px; line-height: 10px; }
+.close,.remove { cursor: pointer; }
+#uploaded-url { display: none; width: 300px; }
+form { display: inline-block; }
+#gallery-images img { max-width: 200px; height: 90px; margin: 5px; }
+#gallery { clear: right; width:100%;}
+</style>
+</head>
+<body>
+
+<div id="gallery">
+ <form id="gallery-search">
+ <input type="text" id="dumpfm-search-query" value="duck bill">
+ <button id="gallery-search">DUMP SEARCH</button>
+ </form>
+ <button id="gallery-random">IM RANDOM</button>
+ <span id="status"></span>
+ <div id="gallery-images"></div>
+</div>
+
+<div id="controls">
+
+ <input type="text" id="url" value="img/1376516658960-dumpfm-DoritoWitch-TimeFLyTrans0001.png">
+ <br>
+ <br>
+
+ <textarea id="shader"></textarea>
+ <br>
+ <br>
+
+ frames <input type="text" id="framecount" value="1">
+ interval <input type="text" id="frameinterval" value="0.1s">
+ <button id="add-frame">+add frame</button>
+ <button id="remove-all-frames">clear</button>
+ <button id="render" disabled>render</button>
+ <br>
+
+ <div id="frames"></div>
+ <br>
+ <br>
+
+ gif delay <input type="text" id="framedelay" value="0.1s">
+ background <input type="text" id="background" value="#fff">
+ <br>
+ <br>
+ <button id="help">help</button>
+ <button id="demo">demo</button>
+ <button id="dither-demo">dither</button>
+ <br>
+</div>
+
+<div id="workspace"></div>
+
+<div id="rendered">
+ <button id="reset">reset</button>
+ <button id="pause">pause</button>
+ <button id="step-forward">&gt;&gt;</button>
+ <span id="status"></span>
+ <button id="save" disabled>save</button>
+ <button id="upload" disabled>upload</button>
+ <br>
+ <input type="text" id="uploaded-url">
+</div>
+
+<div id="instructions"><iframe src="instructions.html"></iframe><button class="close">x</button></div>
+</body>
+<script type="text/javascript" src="js/vendor/gif-encode/util.js"></script>
+<script type="text/javascript" src="js/vendor/gif-encode/tube.js"></script>
+<script type="text/javascript" src="js/vendor/gif-encode/client.js"></script>
+<script type="text/javascript" src="js/vendor/gif.js"></script>
+<script type="text/javascript" src="js/vendor/FileSaver/FileSaver.js"></script>
+<script type="text/javascript" src="js/vendor/dataUriToBlob.js"></script>
+<script type="text/javascript" src="js/vendor/jquery/jquery.min.js"></script>
+<script type="text/javascript" src="js/vendor/jquery-ui-1.10.3.custom.min.js"></script>
+<script type="text/javascript" src="js/vendor/canvasquery.js"></script>
+<script type="text/javascript" src="js/canvasquery.dither.js"></script>
+<script type="text/javascript" src="js/asdf.js"></script>
+<script type="text/javascript" src="js/image.js"></script>
+<script type="text/javascript" src="js/gallery.js"></script>
+<script type="text/javascript" src="js/color.js"></script>
+<script type="text/javascript" src="js/image.js"></script>
+<script type="text/javascript" src="js/util.js"></script>
+<script type="text/javascript">
+
+var cc = cq(0,0).appendTo("#workspace")
+var w, h
+var lastGif
+
+$(init)
+
+var mousex, mousey
+
+function init(){
+ $("#url").change(load)
+ $("#reset").click(reset)
+ $("#pause").click(pause)
+ $("#step-forward").click(step_forward)
+ $("#add-frame").click(add_frame)
+ $("#demo").click(function(){ demo("#first") })
+ $("#dither-demo").click(function(){ demo("#second") })
+ $("#frames").sortable({
+ start: drag_start,
+ stop: drag_stop
+ });
+ $(document).on("mousemove", function(e) {
+ mousex = event.pageX
+ mousey = event.pageY
+ })
+ $(document).on("click","#frames .remove",remove_frame)
+ $("#framecount").change(function(){
+ var val = $(this).int()
+ if (val < 1 || isNaN(val)) $(this).val(val = 1)
+ if (val == 1) $("#add-frame").html("+add frame")
+ else $("#add-frame").html("+add frames")
+ })
+ $("#background").change(function(){
+ document.body.style.backgroundColor = $("#background").string()
+ })
+ $("#frames").disableSelection();
+ $("#remove-all-frames").click(remove_all_frames)
+ $("#render").click(render)
+ $("#save").click(save)
+ $("#upload").click(upload)
+ $("#help,#instructions .close").click(function(){ $("#instructions").toggle() })
+ $("#instructions").draggable({
+ start: drag_start,
+ stop: drag_stop
+ })
+ $("#instructions").disableSelection();
+
+ demo('#first')
+ load()
+ $(window).on("scroll", function(){ scrolling = true })
+
+ gallery.choose = choose
+ gallery.init()
+ console.log("gallery init")
+
+ requestAnimationFrame(animate)
+}
+function choose (){
+ imageURL = this.src
+ loading = true
+ $("#url").val(imageURL)
+ loadImage(imageURL, ready)
+}
+
+function drag_start(){ dragging = true; $(this).addClass("dragging") }
+function drag_stop(){ dragging = false; $(".dragging").removeClass("dragging") }
+function demo(el){
+ $el = $(el)
+ s = $el.html()
+ $("#shader").html(s)
+}
+function load(){
+ loading = true
+ var imageURL = $("#url").val()
+ loadImage(imageURL, ready)
+}
+
+function reset(){
+ start_t = old_t
+ pause_t = 0
+ $("#rendered img").remove()
+ draw(0)
+}
+function pause(state){
+ $("#pause").toggleClass("paused", paused = typeof state == "boolean" ? state : ! paused).html(paused ? "paused" : "pause")
+}
+function step_forward(){
+ var step = $("#framedelay").float() * 1000 || 100
+ old_t += step
+ draw(old_t)
+}
+var timeout, raf_id, start_t = 0, old_t = 0, pause_t = 0
+var paused = false, dragging = false, rendering = false, scrolling = false;
+var fps = 30;
+function animate(t){
+ raf_id = requestAnimationFrame(animate);
+
+ var step_t = t - old_t
+ old_t = t
+
+ if (paused || dragging || rendering || scrolling) {
+ pause_t += step_t
+ scrolling = false
+ return
+ }
+
+ // var timing = +(new Date())
+ draw(t)
+ // timing = +(new Date()) - timing
+ fps = avg(fps, 1000/step_t, 4)
+ status(~~(fps) + " fps")
+}
+function draw(t) {
+ t -= start_t
+ t -= pause_t
+ frame = giveFrame(t)
+ shade(frame, t)
+}
+
+var frame, img_frame;
+function giveFrame(t){
+ if (window.gif) {
+ if (gif.currentFrame) {
+ return gif.frames[gif.currentFrame(t)]
+ }
+ else {
+ return gif.frames[0]
+ }
+ }
+ else if (window.img) {
+ return img_frame
+ }
+ else {
+ return cq(w, h)
+ }
+}
+function ready(){
+ loading = false
+ if (window.gif) {
+ frame = gif.frames[0]
+ }
+ else {
+ fc = cq(img.width, img.height)
+ fc.drawImage(img, 0, 0)
+ frame = img_frame = { ctx: fc.context }
+ }
+ w = cc.canvas.width = frame.ctx.canvas.width
+ h = cc.canvas.height = frame.ctx.canvas.height
+}
+
+function shade(frame, t){
+ if (! t || isNaN(t)) throw Error ("No time specified")
+ if (! frame) throw Error ("No frame specified")
+ try {
+ var f = $("#shader").val()
+ if (!f.length) return;
+ var shader = new Function('x','y','t','d', f)
+ }
+ catch (e) {
+ throw Error ("Shader compilation error")
+ }
+
+ var imageData = frame.ctx.getImageData(0,0,w,h)
+ var data = imageData.data
+
+ var cloneData = frame.ctx.getImageData(0,0,w,h)
+ var clone = cloneData.data
+
+ try {
+ var realw = w, realh = h
+ for (var x = 0; x < w; x++) {
+ for (var y = 0; y < h; y++) {
+ q = 4*(y*w+x)
+ r = data[q], g = data[q+1], b = data[q+2], a = data[q+3]
+ result = shader(x,y,t,clone)
+ data[q] = r
+ data[q+1] = g
+ data[q+2] = b
+ data[q+3] = a
+ w = realw, h = realh
+ }
+ }
+ }
+ catch(e){
+ throw Error ("Shader execution error")
+ }
+ cc.putImageData(imageData,0,0)
+}
+
+function add_frame(){
+ var frame_count = $("#framecount").int()
+ if (frame_count < 2) {
+ add_single_frame()
+ }
+ else {
+ add_frames(frame_count)
+ }
+}
+function add_single_frame(){
+ var $el = $("<div>")
+ $el.html( $("#frame-template").html() )
+ var frame = cc.clone().appendTo($el.find(".frame")[0])
+ frame.canvas.className = "fullsize"
+ frame.canvas.style.display = "none"
+ var thumb = cc.clone().resize(100,100).appendTo($el.find(".frame")[0])
+ $("#frames").append($el)
+ $("#render").enable()
+}
+function add_frames(frame_count){
+ rendering = true
+ var t = old_t - start_t - pause_t
+ var frame_delay = $("#frameinterval").float() * 1000
+ var frame
+ for (var i = 0; i < frame_count; i++) {
+ frame = giveFrame(t)
+ t += frame_delay
+ shade(frame, t)
+ add_single_frame()
+ }
+ rendering = false
+}
+function remove_frame(){
+ $(this).closest("div").remove()
+ if ($("#frames div").length == 0) {
+ $("#render").disable()
+ }
+}
+function remove_all_frames(){
+ $("#frames").empty()
+}
+
+function render (){
+ if (rendering) return
+ rendering = true
+ encoder.reset()
+ var delay = $("#framedelay").float() * 1000 || 100
+ $("#frames canvas.fullsize").each(function(){
+ var frame = cq(this.width, this.height).fillStyle($("#background").string()).fillRect(0,0,this.width, this.height).drawImage(this,0,0)
+ encoder.addFrame(frame.canvas, delay)
+ })
+ $("#pause,#render,#add-frame").disable()
+ $("#rendered").find("img").remove()
+ $("#rendered").show()
+ // really bad results with neuquant?
+ // status("quantizing")
+ // encoder.quantize()
+ status("encoding")
+ try {
+ encoder.encode()
+ } catch (e) {
+ $("#pause,#render,#add-frame").enable()
+ rendering = false
+ status(e)
+ throw e
+ }
+ $("#render").html("rendering")
+}
+
+function status(s){
+ $("#status").html(s)
+}
+
+var encoder = new GifEncoder()
+
+encoder.on("quantized", function(url){
+ status("encoding")
+ encoder.encode()
+})
+
+encoder.on("encoded-frame", function(done,count){
+ status("encoded " + done + " / " + count)
+})
+
+encoder.on("rendered", function(bytes){
+ status(filesize(bytes.length))
+})
+
+encoder.on("rendered-url", function(url){
+ var image = new Image ()
+ lastGif = image.src = url
+ $("#rendered").append(image)
+ $("#save,#upload,#rendered").show()
+ $("#pause,#render,#add-frame,#save,#upload").enable()
+ $("#render").html("render")
+ rendering = false
+ pause(true)
+})
+
+function save (){
+ if (! lastGif) return;
+ var filename = document.getElementById("url").value.replace(/^.*\//,"").replace(/\.gif.*$/,"")
+ var blob = dataUriToBlob(lastGif)
+ saveAs(blob, filename + "-" + (+new Date()) + ".gif");
+}
+
+function upload(){
+ var filename = document.getElementById("url").value.replace(/^.*\//,"").replace(/\.gif.*$/,"")
+ var blob = dataUriToBlob(lastGif)
+ uploadImage({
+ blob: blob,
+ filename: filename + "-" + (+new Date()) + ".gif",
+ username: "",
+ success: function(data){
+
+ // data.url
+ // data.filesize
+ // data.success
+
+ console.log(data);
+ status("uploaded");
+
+ $("#uploaded-url").show().focus().val(data.url)
+ },
+ error: function(data){
+ console.log(data)
+ status("error uploading: " + data.error)
+ }
+ });
+}
+
+</script>
+<script type="text/html" id="frame-template">
+<button class="remove">x</button>
+<span class="frame"></span>
+</script>
+<script type="text/javascript-shader" id="first">
+t /= 500
+if (a == 0) { r = g = b = x; t /= -3 }
+r *= (Math.sin(t*x/y) + 1)/2
+g *= (Math.cos(t*y/x) + 0.4)/2
+b *= (Math.sin(t) + 1.5)/2
+a = y
+
+</script>
+<script type="text/javascript-shader" id="second">
+xx = x, yy = y
+
+var d = ((x % 2) + 2 * (y % 2)) - 2
+
+x += w/2
+y -= h/2
+t/=-200
+y/=96
+x/=50
+v = (Math.sin(t+x*y) + 1.0) / 2
+v = (0.6) * v - 0.4 + Math.random()
+
+v = clamp( v*64 + 128 , 0, 255)
+v += d*32
+if (a == 0) r = g = b = xx/w * 255
+a = v > 128 ? v:0
+
+</script>
+</html>
+