Image color picker in javascript that work without canvas in every browser
Posted by jcubic in Programming on January 8, 2013
If you want to create color picker from image in javascript you probably will use canvas, but what if you need it work in IE as I needed. You can use some server side help to fetch pixels data from the server. I use php for that and GD library. The code is below.
Server side code that return json pixel data
<?php
function rgb($color) {
$result[] = ($color >> 16) & 0xFF;
$result[] = ($color >> 8) & 0xFF;
$result[] = $color & 0xFF;
return $result;
}
function imagecreatefrom($filename) {
$path = pathinfo($filename);
switch($path['extension']) {
case 'png':
return imagecreatefrompng($filename);
case 'jpg':
return imagecreatefromjpeg($filename);
case 'gif':
return imagecreatefromgif($filename);
default:
return null;
}
}
function getImageData($filename) {
list($width, $height) = getimagesize($filename);
$image = imagecreatefrom($filename);
$image_data = array();
for ($y = 0; $y < $height; ++$y) {
$row = array();
for ($x = 0; $x < $width; ++$x) {
$row[] = rgb(imagecolorat($image, $x, $y));
}
$image_data[] = $row;
}
return $image_data;
}
if (isset($_GET['filename'])) {
$filename = $_GET['filename'];
if (file_exists($filename)) {
$result = array(
'error' => null,
'result' => getImageData($filename)
);
} else {
$result = array(
'error' => "The file '$filename' don't exist",
'result' => null
);
}
} else {
$result = array(
'error' => "You need to put filename",
'result' => null
);
}
header('Content-Type: application/json');
echo json_encode($result);
?>
Then you can fetch the data using ajax and add get invidial pixels on mousemove
var img = $('img');
$.getJSON('image_data.php', {filename: img.attr('src')}, function(data) {
if (data.error) {
alert(data.error);
} else {
$('.eyedropper').click(function() {
picker = true;
return false;
});
img.mousemove(function(e) {
if (picker) {
var x = Math.round(e.pageX - offset.left);
var y = Math.round(e.pageY - offset.top);
if (x >= 0) {
$('.color').css('background-color',
'rgb('+data.result[y][x].join(',')+')');
}
}
}).click(function(e) {
picker = false;
});
}
});
Now all you need to have is element with class eyedropper like a link in your html:
<a href="#" class="eyedropper">pick the color</a>
Mastering Emacs – Search inside minibufer
Posted by jcubic in Programming on September 23, 2012
This is by far best feature in Emacs that you can use interactive search inside Minibuffer. If you want to find a function that you don’t know exact name, I do this a lot – who will remember function names in Emacs, you can use:
C-h f C-s
And search for functions. How cool is that? Almost all functions that have completion inside minibuffer work with search like
- C-x b C-s – search for buffer to switch
- C-h <KEY> C-s – search for help
When I switch to Emacs 24, I found that M-x C-s don’t work. So you can’t search for interactive function to execute. But you can get it back. As describe by this Emacs Bug Ticket by putting this to you .emacs file.
(defun read-extended-command ()
"Read command name to invoke in `execute-extended-command'."
(minibuffer-with-setup-hook
(lambda ()
(set (make-local-variable 'minibuffer-default-add-function)
(lambda ()
;; Get a command name at point in the original buffer
;; to propose it after M-n.
(let ((def (with-current-buffer
(window-buffer (minibuffer-selected-window))
(and (commandp (function-called-at-point))
(format "%S" (function-called-at-point)))))
(all (sort (minibuffer-default-add-completions)
(lambda (a b) (string< a b)))))
(if def
(cons def (delete def all))
all)))))
;; Read a string, completing from and restricting to the set of
;; all defined commands. Don't provide any initial input.
;; Save the command read on the extended-command history list.
(completing-read
(concat (cond
((eq current-prefix-arg '-) "- ")
((and (consp current-prefix-arg)
(eq (car current-prefix-arg) 4)) "C-u ")
((and (consp current-prefix-arg)
(integerp (car current-prefix-arg)))
(format "%d " (car current-prefix-arg)))
((integerp current-prefix-arg)
(format "%d " current-prefix-arg)))
;; This isn't strictly correct if `execute-extended-command'
;; is bound to anything else (e.g. [menu]).
;; It could use (key-description (this-single-command-keys)),
;; but actually a prompt other than "M-x" would be confusing,
;; because "M-x" is a well-known prompt to read a command
;; and it serves as a shorthand for "Extended command: ".
"M-x ")
obarray 'commandp t nil 'extended-command-history)))
And tell me, why you will ever need Ido-mode
One note about that, when you use one interactive function inside another one you will need to call C-g twice to exit minibuffer
How To Add Translation Feature To Twitter
Posted by jcubic in Programming on August 19, 2012
I don’t know about you but, I follow few peple that sometimes tweet in different language then English. And English is the only foreign language I know. So if I want to see what they tweet about sometimes I use google translate to read the content.
I always thought that it will be nice feature for Twitter to have translate button, so I created one, using WebSockets and Ruby.
So how I did this, first I downloaded websockets ruby library from github web-socket-ruby, I already had translation script written in Ruby that use google translate, so I added websocket server to it.
#!/usr/bin/ruby
require 'net/http'
require 'uri'
require 'optparse'
require 'json'
require 'socket'
require 'web_socket'
class NotConnectedException < Exception
end
def server(port, domains)
server = WebSocketServer.new(
:accepted_domains => domains,
:port => port)
puts("Server is running at port %d" % server.port)
server.run() do |ws|
puts("Connection accepted")
puts("Path: #{ws.path}, Origin: #{ws.origin}")
if ws.path == "/translate"
ws.handshake()
while data = ws.receive()
printf("Received: %p\n", data)
data = JSON.parse(data)
response = translate(data['text'], nil, data['to_lang']).join("\n")
ws.send(response)
printf("Sent: %p\n", response)
end
else
ws.handshake("404 Not Found")
end
puts("Connection closed")
end
end
def escape(o)
o.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
'%' + $1.unpack('H2' * $1.size).join('%').upcase
}.tr(' ', '+')
end
def translate(text, from=nil, to=nil, cookie=nil)
url = URI.parse("http://translate.google.com/translate_a/t")
query = "?hl=en&client=t&text=#{escape(text)}&multires=1&otf=1&pc=0&sc=1&ie=UTF-8&oe=UTF-8"
query += "&sl=" + (from ? from : 'auto')
if to
query += "&tl=#{to}"
end
begin
http = Net::HTTP.new(url.host)
res = http.get(url.path + query)
res.response['content-type'] =~ /charset=(.*)/
charset = $1
JSON.parse(res.body.gsub(/,{2,}/, ',').gsub(/,\]/, ']'))[0].map {|i|
# google sometimes put spaces around numbers
i[0].gsub(/\{ *([0-9]) *\}/, '{\1}')
}
rescue NoMethodError
raise NotConnectedException
rescue SocketError
raise NotConnectedException
rescue
end
end
def msg(str, type='info')
system("zenity --#{type} --title='translation' --text='#{str}'")
end
params = ARGV.getopts('i:o:gcsp:')
def error(msg, gui=false)
if gui
msg(msg, 'error')
else
puts msg
end
end
def usage()
puts "usage:"
puts "translate [-i <INPUT LANG>] -o <OUTPUT LANG> [MORE OPTIONS]"
puts "-g - show zenity dialog"
puts "-c - get input from clipboard"
puts "-s - run as server"
puts "-p - server port"
end
begin
if params['s']
begin
server(params['p'] ? params['p'].to_i() : 8080, 'twitter.com')
rescue Interrupt
puts "Server Exit"
end
else
if params['c']
input = `xclip -o -sel clip`
else
input = ARGF.read()
end
translation = translate(input, params['i'], params['o'])
if params['g']
msg(translation.join(". "))
else
translation.each{|sentence|
if sentence != ''
puts sentence
end
}
end
end
rescue JSON::ParserError => e
error("Response Error: " + e.message, params['g'])
rescue NotConnectedException
error("sorry but it seems that your internet connection is down", params['g'])
end
Then I created this bookmarklet. (I notice that profile page use jQuery.noConflict() so I can’t access it from bookmarklet. So here is updated code that insert jQuery script again – in use continuation to block execution of the script until jQuery is loaded). To use bookmarklet just copy code below and insert into url address bar when twitter tab is active
javascript:(function(continuation) {
function attr(elem, key, value) {
elem.setAttribute(document.createAttribute(key, value));
}
var script = (function() {
var head = document.getElementsByTagName('head')[0];
return function(src) {
var script = document.createElement('script');
script.setAttribute('src', src);
script.setAttribute('type', 'text/javascript');
script.setAttribute('async', 'false');
head.appendChild(script);
return script;
};
})();
script('https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js');
var interval = 100;
setTimeout(function() {
if (jQuery) {
continuation(jQuery.noConflict());
} else {
setTimeout(arguments.callee, interval);
}
}, interval);
})(function($) {
function translator(fun, lang) {
var socket = new WebSocket("ws://localhost:8080/translate");
socket.onopen = function() {
console.log("Socket has been opened!");
};
socket.onclose = function() {
console.log("closed");
};
return fun(function(text, respond) {
socket.onmessage = function(msg) {
respond(msg.data);
};
var data = JSON.stringify({to_lang: lang, text: text});
socket.send(data);
});
}
var translate_tweet = translator(function(translate) {
return function(content) {
var tweet_container = content.find('.js-tweet-text');
var tweet = tweet_container.html();
content.data('original', tweet);
var links = [];
var i = 0;
tweet = tweet.replace(/<a[^>]+>[^<]+<\/a>|<a[^>]+><s>(#|@)<\/s><b>[^<]+<\/b><\/a>/g, function(link) {
links.push(link);
return '{' + i++ + '}';
});
translate(tweet, function(result) {
for (var i=links.length; i--;) {
result = result.replace('{' + i + '}', links[i]);
}
tweet_container.html(result);
var actions = content.find('.tweet-actions');
if (actions.find('.action-orig-container').length == 0) {
actions.append('<li class="action-orig-container"><a href="#">Original</a></li>');
}
});
};
}, prompt('Select Language: af - afrikaans, sk - albánskej, ar - عربي, be - Беларускі, bg - Български, zh - 荃湾, zh - 太阳, hr - Hrvatski, cs - Český, da - Danske, et - Eesti, tl - filipiński, fi - Suomi, fr - Français, gl - galijski, el - Ελληνικά, iw - עברית, hi - हिन्दी, es - Español, nl - Nederlands, id - indonezyjski, ga - Gaeilge, is - Íslenska, ja - 日本語, yi - ייִדיש, ca - Català, ko - 한국의, lt - Lietuvos, lv - Latvijas, mk - Македонски, ms - Melayu, mt - Malti, de - Deutsch, no - Norsk, fa - فارسی, pl - polski, ru - Русский, ro - Română, sr - Српски, sk - Slovenský, sl - Slovenski, sw - Swahili, sv - Svenska, th - ภาษาไทย, tr - Türk, uk - Український, cy - walijski, hu - Magyar, vi - Việt, it - Italiano'));
$('.content').unbind('mouseover').live('mouseover', function() {
var $this = $(this);
if ($this.find('.action-trans-container').length == 0) {
$this.find('.action-fav-container').
after('<li class="action-trans-container"><a href="#">Translate</a></li>');
}
});
$('.action-orig-container').unbind('onclick').live('click', function() {
var content = $(this).parents('.content');
content.find('.js-tweet-text').html(content.data('original'));
content.find('.action-orig-container').remove();
return false;
});
$('.action-trans-container').unbind('onclick').live('click', function() {
translate_tweet($(this).parents('.content'));
return false;
});
});
CODE LICENSE: you can use the code for whatever purpose you like it’s realeas on Sharing Agreement.
ERC notifications on channels where there was activity after some inactivity
Posted by jcubic in Programming on July 24, 2012
I need to monitor few IRC channels and I use Emacs so I write simple elisp function that I append to erc-insert-pre-hook and it notify me when there is some activity on those channels. I made this mainly because I what to know if someone visit #openclipart channel (because people where visiting ask question and leave after few minutes, there is no much activity on this channel)
(setq inactivity-buffer-alist '(("#openclipart" (inactivity . 900))
("#hackerrank" (inactivity . 900))
("#aiki" (inactivity . 900))))
(defun channel-activity (string &rest ignore)
"notification when there is activity on a erc channel after inactivity"
(let* ((buffer (buffer-name))
(buffer-alist-pair (assoc buffer inactivity-buffer-alist))
(buffer-alist (cdr buffer-alist-pair))
(current-time (current-time)))
(if (not (null buffer-alist))
(let ((last-time-pair (assoc 'last-time buffer-alist))
(inactivity (cdr (assoc 'inactivity buffer-alist))))
(if (not (and (string-match "^\\*\\*\\*" string)
(string-match "[freenode-info]" string)))
(progn
(if (or (null last-time-pair)
(> (float-time (time-subtract current-time
(cdr last-time-pair)))
inactivity))
(async-exec-command "mpg123 -q /home/kuba/Pobrane/beep-6.mp3"))
(if (null last-time-pair)
(setf (cdr buffer-alist-pair)
(append buffer-alist
(list (cons 'last-time current-time))))
(setf (cdr last-time-pair) current-time))))))))
(add-hook 'erc-insert-pre-hook 'channel-activity)
You can add your channels to inactivity-buffer-alist along with time of inactivity (in miliseconds)
The function I use for notification is play sound using (async-exec-command "mpg123 -q /home/kuba/Pobrane/beep-6.mp3") – normal shell command was stoping execution of Emacs for few seconds
The code for this function is as follow
(defun async-exec-command (command &rest success)
(interactive)
(let* ((buffer-name (generate-new-buffer-name "**shell**"))
(buffer (get-buffer-create buffer-name))
(process (apply #'start-process
(append (list buffer-name buffer)
(split-string command " ")))))
(lexical-let ((buffer buffer) (success (car success)) (command command))
(set-process-sentinel process
(if success (lambda (process str)
(if (string= str "finished\n")
(save-excursion
(set-buffer buffer)
(let ((content (buffer-string)))
(kill-buffer buffer)
(funcall success content)))))
(lambda (proces str)
(kill-buffer buffer)))))
(concat "execute: " command)))
How to have access to a shell without ssh or telnet using jQuery terminal
Posted by jcubic in Programming on June 9, 2012
If you have, like I did, a virtual server on hosting service, that support cgi but give have access to a shell and php have passthru disabled you still can have access to a shell, even if you can’t install anything on that machine – like anyterm.
There is this project, which I did, called jQuery terminal, that emulate a Unix terminal. All you need is interpreter that will execute shell commands.
Lots of hosting services disable php passthru but leave cgi script, so if you have them you can create simple shell like this one:
#!/bin/bash
echo -en "Content-Type: text/plain\r\n\r\n"
query=$(/usr/bin/python -c "import urllib; print urllib.unquote_plus('$QUERY_STRING')")
eval $query 2>&1
I use python subprocess to decode QUERY_STRING. Probably it can be done using some Unix tools.
On my server I use Python CGI script like this one:.
#!/usr/bin/python
import cgi
import subprocess as sub
try:
from json import dumps as json_serialize
except ImportError:
def json_serialize(obj):
result = ''
t = type(obj)
if t == types.StringType:
result += '"%s"' % obj.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n')
elif t == types.NoneType:
result += 'null'
elif t == types.IntType or t == types.FloatType:
result += str(obj)
elif t == types.LongType:
result += str(int(obj))
elif t == types.TupleType:
result += '[' + ','.join(map(json_serialize, list(obj))) + ']'
elif t == types.ListType:
result += '[' + ','.join(map(json_serialize, obj)) + ']'
elif t == types.DictType:
array = ['"%s":%s' % (k,json_serialize(v)) for k,v in obj.iteritems()]
result += '{' + ','.join(array) + '}'
else:
result += '"unknown type - ' + type(obj).__name__ + '"'
return result
class Singleton(object):
__single = None
def __init__(self):
Singleton.__single = self
def __new__(cls):
if Singleton.__single:
return Singleton.__single
else:
return super(Singleton, cls).__new__(cls)
class Form(Singleton):
def __init__(self):
super(Form)
self.form = cgi.FieldStorage()
def __getitem__(self, name):
return self.form.getvalue(name)
def execv(command, path):
command = 'cd %s && %s && pwd 1>&2' % (path, command)
proc = sub.Popen(['/bin/bash', '-c', command],
stdout=sub.PIPE, stderr=sub.PIPE)
stderr = proc.stderr.read()[:-1]
stdout = proc.stdout.read()[:-1]
if not os.path.exists(stderr):
raise Exception(stdout, stderr)
return {
"cwd": stderr,
"stdout": re.sub('.\x08', '', stdout)
}
if __name__ == '__main__':
print "Content-Type: text/plain"
print
form = Form()
if token() == form['token']:
response = {}
try:
response['result'] = execv(form['command'], form['path'])
except Exception, e:
response['error'] = e.args[1]
response['result'] = {'stdout': e.args[0], 'cwd': form['path']}
else:
response['error'] = None
else:
response = {'error': 'You are not authorized', 'result': None}
stdout.write(json_serialize(response))
You have enabled passthru in php you can write your shell in php.
Now when you have access to a shell you need to setup interface using jQuery terminal.
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Shell</title>
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="terminal/js/jquery.mousewheel-min.js"></script>
<script src="terminal/js/jquery.terminal.js"></script>
<link href="terminal/css/jquery.terminal.css" rel="stylesheet"/>
<style>
.terminal a.ui-slider-handle:focus { outline: none; }
body { margin: 0; padding: 0; }
html { background-color: #000; }
.clear { clear: both; }
/* This works only in Safari and Google Chrome */
@media screen and (-webkit-min-device-pixel-ratio:0) {
.terminal, .terminal .terminal-output, .terminal .terminal-output div,
.terminal .terminal-output div div, .cmd, .terminal .cmd span, .terminal .cmd div {
font-weight: bold;
}
}
</style>
<script>
$(function() {
var pwd, last_dir, home_dir;
var terminal = $('#shell').terminal(function(command, term) {
if (command.replace(/^ *(.*) *$/, '$1') == '-') {
pwd = last_dir;
return;
}
term.pause();
$.post("/cgi-bin/cmd.py", {
token: term.token(),
command: command.replace(/(\\)?~/, function($0,$1) {
return $1 ? $0 : home_dir;
}),
path: pwd
}, function(response) {
term.echo(response.result.stdout);
pwd = response.result.cwd;
term.resume();
});
}, {
login: function(user, password, authenticate) {
$.post("/cgi-bin/cmd.py", {
user: user,
password: password
}, function(token) {
if (token) {
home_dir = pwd = last_dir = '/home/ + user;
}
authenticate(token);
});
},
prompt: function(callback) {
var username = terminal.login_name();
var re = new RegExp("^" + '/home/' + username);
var username = '[[;#44D544;]' + username + ']';
var path = '[[;#5555FF;]' + pwd.replace(re, '~') + ']';
callback(username + '[[;#989898;]:]' + path + '[[;#989898;]$] ');
},
name: 'shell'
}).css({
overflow: 'auto'
});
$(window).resize(function() {
terminal.css('height', $(window).height()-20);
}).resize();
});
</script>
</head>
<body>
<div id="shell"></div>
</body>
</html>
My Poster for Libre Graphics Meeting
Posted by jcubic in Graphic Design on February 4, 2012
My Poster to Libre Graphics Meeting Conference – conference about open source software use to create graphics of any kind. you can also download pdf version


