more code cleanup

This commit is contained in:
Lokesh Dhakar
2011-11-03 17:54:22 -04:00
parent a32716930d
commit 8bf268e309
15 changed files with 383 additions and 319 deletions

View File

@@ -0,0 +1,28 @@
# Color Thief
by Lokesh Dhakar - [Blog](http://lokeshdhakar.com) - [Twitter](http://twitter.com/lokeshdhakar)
A script for grabbing the dominant color or a representative color palette from an image. Uses javascript and canvas.
## [Demo](http://lokeshdhakar.com/projects/color-thief)
##Requirements
* jQuery
* quantize.js
##Usage
###getDominantColor(sourceImage)
returns {r: num, g: num, b: num}
Use the median cut algorithm provided by quantize.js to cluster similar
colors and return the base color from the largest cluster.
###createPalette(sourceImage, colorCount)
returns array[ {r: num, g: num, b: num}, {r: num, g: num, b: num}, ...]
Use the median cut algorithm provided by quantize.js to cluster similar
colors.
BUGGY: Function does not always return the requested amount of colors. It can be +/- 2.
Licensed under the [Creative Commons Attribution 2.5 License](http://creativecommons.org/licenses/by/2.5/)

View File

@@ -67,48 +67,108 @@ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav,
/* line 9, ../sass/app.sass */
body, input, textarea {
margin: 40px;
color: #555555;
color: #aaaaaa;
background: #222222;
font: 16px/1.625em "Varela Round", "lucida grande", tahoma, sans-serif;
font-weight: 400;
-webkit-font-smoothing: antialiased;
}
/* line 17, ../sass/app.sass */
/* line 18, ../sass/app.sass */
h1, h2, h3, h4, h5, h6 {
font-family: "Terminal Dosis", "lucida grande", tahoma, sans-serif;
line-height: 1em;
font-weight: 600;
margin-bottom: 0.5em;
}
/* line 23, ../sass/app.sass */
/* line 24, ../sass/app.sass */
h1 {
font-size: 60px;
font-size: 72px;
line-height: 0.5em;
margin-bottom: 0.3em;
}
/* line 28, ../sass/app.sass */
h1 small {
font-size: 20px;
}
/* line 31, ../sass/app.sass */
h1:hover .char1 {
color: greenyellow;
}
/* line 33, ../sass/app.sass */
h1:hover .char2 {
color: indianred;
}
/* line 35, ../sass/app.sass */
h1:hover .char3 {
color: khaki;
}
/* line 37, ../sass/app.sass */
h1:hover .char4 {
color: lightsteelblue;
}
/* line 39, ../sass/app.sass */
h1:hover .char5 {
color: violet;
}
/* line 41, ../sass/app.sass */
h1:hover .char6 {
color: skyblue;
}
/* line 43, ../sass/app.sass */
h1:hover .char7 {
color: lightseagreen;
}
/* line 45, ../sass/app.sass */
h1:hover .char8 {
color: tan;
}
/* line 47, ../sass/app.sass */
h1:hover .char9 {
color: darkmagenta;
}
/* line 49, ../sass/app.sass */
h1:hover .char10 {
color: tomato;
}
/* line 51, ../sass/app.sass */
h1:hover .char11 {
color: goldenrod;
}
/* line 26, ../sass/app.sass */
/* line 55, ../sass/app.sass */
h2 {
font-size: 24px;
font-size: 40px;
line-height: 1.2em;
text-align: center;
}
/* line 30, ../sass/app.sass */
/* line 60, ../sass/app.sass */
h3 {
font-size: 18px;
font-size: 16px;
letter-spacing: 0.1em;
text-transform: uppercase;
}
/* line 34, ../sass/app.sass */
/* line 65, ../sass/app.sass */
h4 {
font-size: 20px;
margin-bottom: 1.25em;
}
/* line 69, ../sass/app.sass */
p {
margin-bottom: 1.25em;
}
/* line 38, ../sass/app.sass */
/* line 73, ../sass/app.sass */
strong {
font-weight: bold;
}
/* Forms */
/* line 44, ../sass/app.sass */
/* line 79, ../sass/app.sass */
input[type=text],
input[type=password],
textarea {
@@ -127,159 +187,130 @@ textarea {
border-radius: 4px;
}
/* line 55, ../sass/app.sass */
/* line 90, ../sass/app.sass */
input[type=text]:focus,
textarea:focus {
color: #373737;
}
/* line 59, ../sass/app.sass */
/* line 94, ../sass/app.sass */
textarea {
padding-left: 3px;
width: 98%;
}
/* line 63, ../sass/app.sass */
/* line 98, ../sass/app.sass */
input[type=text] {
padding: 3px;
}
/* Links */
/* line 67, ../sass/app.sass */
/* line 102, ../sass/app.sass */
a {
color: #555555;
color: #5f92aa;
text-decoration: none;
}
/* line 70, ../sass/app.sass */
/* line 105, ../sass/app.sass */
a:hover {
color: #09a1ec;
color: #afc8d4;
}
/* line 75, ../sass/app.sass */
.button {
text-transform: uppercase;
font-family: "Terminal Dosis", "lucida grande", tahoma, sans-serif;
font-weight: 700;
letter-spacing: 0.1em;
olor: #555555;
display: block;
float: left;
position: relative;
line-height: 1;
padding: 0.6em 1.5em 0.5em 1.5em;
border: 1px solid transparent;
-moz-box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.1), 0 2px 5px 0 rgba(0, 0, 0, 0.25);
-webkit-box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.1), 0 2px 5px 0 rgba(0, 0, 0, 0.25);
-o-box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.1), 0 2px 5px 0 rgba(0, 0, 0, 0.25);
box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.1), 0 2px 5px 0 rgba(0, 0, 0, 0.25);
background-color: #eeeeee;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
-o-border-radius: 4px;
-ms-border-radius: 4px;
-khtml-border-radius: 4px;
border-radius: 4px;
border: 1px solid #d6d6d6;
margin-bottom: 6px;
}
/* line 92, ../sass/app.sass */
.button:hover {
background-color: #f1f1f1;
}
/* line 94, ../sass/app.sass */
.button:active {
-moz-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.1);
-webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.1);
-o-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.1);
box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.1);
top: 2px;
margin-bottom: 4px;
border-bottom-width: 0;
/* line 109, ../sass/app.sass */
header {
padding-bottom: 40px;
text-align: center;
}
/* Buttons with dark backgrounds */
/* line 103, ../sass/app.sass */
.button.nav,
.button.warn,
.button.primary,
.nav-previous .button,
.nav-next .button {
color: white;
text-shadow: rgba(0, 0, 0, 0.2) 1px 1px 0;
}
/* line 112, ../sass/app.sass */
.button.nav,
.nav-previous .button,
.nav-next .button {
background-color: #09a1ec;
border-color: #0891d4;
}
/* line 117, ../sass/app.sass */
.button.nav:hover,
.nav-previous .button:hover,
.nav-next .button:hover {
background-color: #33b6f7;
}
/* line 123, ../sass/app.sass */
.button.warn {
background-color: #ee8833;
border-color: #ec7818;
}
/* line 126, ../sass/app.sass */
.button.warn:hover {
background-color: #f1a05c;
}
/* line 131, ../sass/app.sass */
.button.primary {
background-color: #6bb445;
border-color: #6bb445;
}
/* line 134, ../sass/app.sass */
.button.primary:hover {
background-color: #88c568;
}
/* line 143, ../sass/app.sass */
h1 {
font-size: 36px;
margin-bottom: 0.5em;
}
/* line 150, ../sass/app.sass */
/* line 113, ../sass/app.sass */
.imageSection {
overflow: hidden;
*zoom: 1;
margin-bottom: 40px;
margin-bottom: 80px;
}
/* line 153, ../sass/app.sass */
.imageSection img {
/* line 116, ../sass/app.sass */
.imageSection .imageWrap {
width: 400px;
height: 300px;
float: left;
position: relative;
margin-right: 20px;
border: 1px solid #444444;
background: url(../img/dark_checkered_bg.png);
}
/* line 156, ../sass/app.sass */
/* line 124, ../sass/app.sass */
.imageSection .imageWrap .targetImage {
position: absolute;
top: 50%;
left: 50%;
margin-left: -200px;
margin-top: -150px;
}
/* line 131, ../sass/app.sass */
.imageSection .colors {
width: 400px;
float: left;
}
/* line 159, ../sass/app.sass */
/* line 134, ../sass/app.sass */
.imageSection .colors .function {
overflow: hidden;
*zoom: 1;
clear: left;
margin-bottom: 10px;
}
/* line 162, ../sass/app.sass */
.imageSection .colors .function .swatch {
/* line 138, ../sass/app.sass */
.imageSection .colors .function .swatches .swatch {
width: 40px;
height: 20px;
margin: 0 4px 4px 0;
background: #dddddd;
float: left;
-moz-transition: all 0.2s;
-webkit-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
}
/* line 145, ../sass/app.sass */
.imageSection .colors .function .swatches .swatch:hover {
-moz-transform: scale(1.2, 1.2);
-webkit-transform: scale(1.2, 1.2);
-o-transform: scale(1.2, 1.2);
-ms-transform: scale(1.2, 1.2);
transform: scale(1.2, 1.2);
-moz-box-shadow: 0 1px 10px black;
-webkit-box-shadow: 0 1px 10px black;
-o-box-shadow: 0 1px 10px black;
box-shadow: 0 1px 10px black;
}
/* line 148, ../sass/app.sass */
.imageSection .colors .function .swatches .swatch:first-child {
-moz-border-radius-topleft: 4px;
-webkit-border-top-left-radius: 4px;
-o-border-top-left-radius: 4px;
-ms-border-top-left-radius: 4px;
-khtml-border-top-left-radius: 4px;
border-top-left-radius: 4px;
-moz-border-radius-bottomleft: 4px;
-webkit-border-bottom-left-radius: 4px;
-o-border-bottom-left-radius: 4px;
-ms-border-bottom-left-radius: 4px;
-khtml-border-bottom-left-radius: 4px;
border-bottom-left-radius: 4px;
}
/* line 150, ../sass/app.sass */
.imageSection .colors .function .swatches .swatch:last-child {
-moz-border-radius-topright: 4px;
-webkit-border-top-right-radius: 4px;
-o-border-top-right-radius: 4px;
-ms-border-top-right-radius: 4px;
-khtml-border-top-right-radius: 4px;
border-top-right-radius: 4px;
-moz-border-radius-bottomright: 4px;
-webkit-border-bottom-right-radius: 4px;
-o-border-bottom-right-radius: 4px;
-ms-border-bottom-right-radius: 4px;
-khtml-border-bottom-right-radius: 4px;
border-bottom-right-radius: 4px;
}
/* line 169, ../sass/app.sass */
/* line 153, ../sass/app.sass */
canvas {
display: none;
}

BIN
img/10.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
img/3.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

BIN
img/4.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

BIN
img/5.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

BIN
img/dark_checkered_bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -6,7 +6,7 @@
<link href='http://fonts.googleapis.com/css?family=Varela+Round|Terminal+Dosis:400,700,600' rel='stylesheet' type='text/css'>
<title>Image Palette</title>
<title>Color Thief</title>
<meta name="description" content="">
<meta name="author" content="">
@@ -20,140 +20,85 @@
<div id="container">
<header>
<h1>Image Palette</h1>
<h1>Color Thief</h1>
<h4><a href="http://lokeshdhakar.com">by Lokesh Dhakar</a></small></h4>
<p>A script for grabbing the dominant color or a representative color palette from an image. Uses javascript and canvas.</p>
<p><a href="http://www.lokeshdhakar.com/">Read more on my blog</a> | <a href="https://github.com/lokesh/color-thief">Get the code on Github</a>
</p>
</header>
<h2>Examples</h2>
<div id="main" role="main">
<div class="imageSection">
<img src="img/icon1.png" />
<div class="colors">
<div class="function dominantColor">
<h3>getDominantColor()</h3>
</div>
<div class="function medianCutPalette">
<h3>createMedianCutPalette()</h3>
</div>
</div>
</div>
<div class="imageSection">
<img src="img/icon2.gif" />
<div class="colors">
<div class="function dominantColor">
<h3>getDominantColor()</h3>
</div>
<div class="function medianCutPalette">
<h3>createMedianCutPalette()</h3>
</div>
</div>
</div>
<div class="imageSection">
<img src="img/icon3.png" />
<div class="colors">
<div class="function dominantColor">
<h3>getDominantColor()</h3>
</div>
<div class="function medianCutPalette">
<h3>createMedianCutPalette()</h3>
</div>
</div>
</div>
<div class="imageSection">
<img src="img/4.png" />
<div class="colors">
<div class="function dominantColor">
<h3>getDominantColor()</h3>
</div>
<div class="function medianCutPalette">
<h3>createMedianCutPalette()</h3>
</div>
</div>
</div>
<div class="imageSection">
<img src="img/5.png" />
<div class="colors">
<div class="function dominantColor">
<h3>getDominantColor()</h3>
</div>
<div class="function medianCutPalette">
<h3>createMedianCutPalette()</h3>
</div>
</div>
</div>
<div class="imageSection">
<img src="img/6.jpeg" />
<div class="colors">
<div class="function dominantColor">
<h3>getDominantColor()</h3>
</div>
<div class="function medianCutPalette">
<h3>createMedianCutPalette()</h3>
</div>
</div>
</div>
</div>
<footer>
</footer>
</div> <!--! end of #container -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.6.2.min.js"><\/script>')</script>
<script src="js/libs/quantize.js"></script>
<script src="js/libs/jquery.imagesloaded.js"></script>
<script src="js/libs/jquery.lettering.js"></script>
<script src="js/libs/mustache.js"></script>
<script src="js/libs/quantize.js"></script>
<script src="js/color-thief.js"></script>
<!-- Using Mustache templating -->
<script id='template' type='text/x-mustache'>
{{#files}}
<div class="imageSection">
<div class="imageWrap">
<img class="targetImage" src="img/{{.}}" />
</div>
<div class="colors">
<div class="function dominantColor">
<h3>Dominant Color</h3>
<div class="swatches"></div>
</div>
<div class="function medianCutPalette">
<h3>Palette</h3>
<div class="swatches"></div>
</div>
</div>
</div>
{{/files}}
</script>
<script>
$(document).ready(function(){
// Use mustache.js templating to create layout
var images = { files: [ "1.jpg", "10.jpg", "2.jpg", "icon1.png"] };
var html = Mustache.to_html($('#template').html(), images);
$('#main').append(html);
var view = {
title: "Joe",
calc: function() {
return 2 + 4;
}
}
// Use lettering.js to give letter by letter styling control for the h1 title
$("h1").lettering();
var template = "{{title}} spends {{calc}}";
var html = Mustache.to_html(template, view);
$('body').prepend(html);
// Once images are loaded, loop through each one, getting dominant color
// and palette and displaying them.
$('img').imagesLoaded(function(){
$('img').each(function(index){
var dominantColor = getDominantColor(this);
var medianPalette = createPalette(this, 10);
var imageSection = $(this).closest('.imageSection');
var switchEl;
// Get the dominant color and palette for this image
var dominantColor = getDominantColor(this),
medianPalette = createPalette(this, 10),
imageSection = $(this).closest('.imageSection'),
swatchEl;
// Dominant Color
swatchEl = $('<div>', {
'class': 'swatch'
}).css('background-color','rgba('+dominantColor.r+','+dominantColor.g+ ','+dominantColor.b+', 1)');
imageSection.find('.dominantColor .swatches').append(swatchEl);
imageSection.find('.dominantColor').append(swatchEl);
var medianCutPalette = imageSection.find('.medianCutPalette');
$.each(medianPalette, function(index, value){
// Palette
var medianCutPalette = imageSection.find('.medianCutPalette .swatches');
$.each(medianPalette, function(index, value){
swatchEl = $('<div>', {
'class': 'swatch'
}).css('background-color','rgba('+value[0]+','+value[1]+ ','+value[2]+', 1)');

View File

@@ -45,7 +45,6 @@ CanvasImage.prototype.clear = function() {
}
CanvasImage.prototype.update = function(imageData) {
console.log('worked');
this.context.putImageData(imageData, 0, 0);
}
@@ -57,6 +56,10 @@ CanvasImage.prototype.getImageData = function() {
return this.context.getImageData(0, 0, this.width, this.height);
}
CanvasImage.prototype.removeCanvas = function() {
$(this.canvas).remove();
}
/*
* getDominantColor(sourceImage)
@@ -89,6 +92,9 @@ function getDominantColor(sourceImage){
var cmap = MMCQ.quantize(pixelArray, 5);
var newPalette = cmap.palette();
// Clean up
image.removeCanvas();
return {r: newPalette[0][0], g: newPalette[0][1], b: newPalette[0][2]};
}
@@ -127,6 +133,9 @@ function createPalette(sourceImage, colorCount){
var cmap = MMCQ.quantize(pixelArray, colorCount);
var newPalette = cmap.palette();
// Clean up
image.removeCanvas();
return newPalette;
}

View File

@@ -0,0 +1,66 @@
/*global jQuery */
/*!
* Lettering.JS 0.6.1
*
* Copyright 2010, Dave Rupert http://daverupert.com
* Released under the WTFPL license
* http://sam.zoy.org/wtfpl/
*
* Thanks to Paul Irish - http://paulirish.com - for the feedback.
*
* Date: Mon Sep 20 17:14:00 2010 -0600
*/
(function($){
function injector(t, splitter, klass, after) {
var a = t.text().split(splitter), inject = '';
if (a.length) {
$(a).each(function(i, item) {
inject += '<span class="'+klass+(i+1)+'">'+item+'</span>'+after;
});
t.empty().append(inject);
}
}
var methods = {
init : function() {
return this.each(function() {
injector($(this), '', 'char', '');
});
},
words : function() {
return this.each(function() {
injector($(this), ' ', 'word', ' ');
});
},
lines : function() {
return this.each(function() {
var r = "eefec303079ad17405c889e092e105b0";
// Because it's hard to split a <br/> tag consistently across browsers,
// (*ahem* IE *ahem*), we replaces all <br/> instances with an md5 hash
// (of the word "split"). If you're trying to use this plugin on that
// md5 hash string, it will fail because you're being ridiculous.
injector($(this).children("br").replaceWith(r).end(), r, 'line', '');
});
}
};
$.fn.lettering = function( method ) {
// Method calling logic
if ( method && methods[method] ) {
return methods[ method ].apply( this, [].slice.call( arguments, 1 ));
} else if ( method === 'letters' || ! method ) {
return methods.init.apply( this, [].slice.call( arguments, 0 ) ); // always pass an array
}
$.error( 'Method ' + method + ' does not exist on jQuery.lettering' );
return this;
};
})(jQuery);

View File

@@ -1,8 +1,9 @@
$color: #555
$bgColor: #222
$color: #aaa
$headingColor: #222
$altColor: scale-color($color, $lightness: 50%)
$lightGray: #eee
$blue: #09a1ec
$blue: #5f92aa
$orange: #e83
$green: #6bb445

View File

@@ -9,6 +9,7 @@
body, input, textarea
margin: 40px
color: $color
background: $bgColor
font: 16px/1.625em 'Varela Round',"lucida grande",tahoma,sans-serif
font-weight: 400
-webkit-font-smoothing: antialiased
@@ -18,18 +19,52 @@ h1,h2,h3,h4,h5,h6
font-family: 'Terminal Dosis', 'lucida grande', tahoma, sans-serif
line-height: 1em
font-weight: 600
margin-bottom: .5em
h1
font-size: 60px
font-size: 72px
line-height: .5em
margin-bottom: .3em
small
font-size: 20px
&:hover
.char1
color: greenyellow
.char2
color: indianred
.char3
color: khaki
.char4
color: lightsteelblue
.char5
color: violet
.char6
color: skyblue
.char7
color: lightseagreen
.char8
color: tan
.char9
color: darkmagenta
.char10
color: tomato
.char11
color: goldenrod
h2
font-size: 24px
font-size: 40px
line-height: 1.2em
text-align: center
h3
font-size: 18px
font-size: 16px
letter-spacing: 0.1em
text-transform: uppercase
h4
font-size: 20px
margin-bottom: 1.25em
p
margin-bottom: 1.25em
@@ -65,106 +100,55 @@ input[type=text]
/* Links */
a
color: $color
color: $blue
text-decoration: none
&:hover
color: $blue
color: scale-color($blue, $lightness: 50%)
.button
text-transform: uppercase
font-family: 'Terminal Dosis', 'lucida grande', tahoma, sans-serif
font-weight: 700
letter-spacing: 0.1em
olor: #555
display: block
float: left
position: relative
line-height: 1
padding: .6em 1.5em .5em 1.5em
border: 1px solid transparent
+box-shadow( inset 0 2px 0 rgba(255, 255, 255, 0.1), 0 2px 5px 0 rgba(0,0,0, .25))
background-color: $lightGray
+border-radius($radius)
border: 1px solid scale-color($lightGray, $lightness: -10%)
margin-bottom: 6px
&:hover
background-color: scale-color($lightGray, $lightness: 20%)
&:active
+box-shadow( inset 0 2px 0 rgba(0, 0, 0, 0.1))
top: 2px
margin-bottom: 4px
border-bottom-width: 0
/* Buttons with dark backgrounds */
.button.nav,
.button.warn,
.button.primary,
.nav-previous .button,
.nav-next .button
color: #fff
@include text-shadow(rgba(0,0,0, 0.2) 1px 1px 0)
.button.nav,
.nav-previous .button,
.nav-next .button
background-color: $blue
border-color: scale-color($blue, $lightness: -10%)
&:hover
background-color: scale-color($blue, $lightness: 20%)
.button.warn
background-color: $orange
border-color: scale-color($orange, $lightness: -10%)
&:hover
background-color: scale-color($orange, $lightness: 20%)
.button.primary
background-color: $green
border-color: $green
&:hover
background-color: scale-color($green, $lightness: 20%)
h1
font-size: 36px
margin-bottom: .5em
h3
header
padding-bottom: 40px
text-align: center
.imageSection
+clearfix
margin-bottom: 40px
img
margin-bottom: 80px
.imageWrap
width: 400px
height: 300px
float: left
position: relative
margin-right: 20px
border: 1px solid #444
background: url(../img/dark_checkered_bg.png)
.targetImage
position: absolute
top: 50%
left: 50%
margin-left: -200px
margin-top: -150px
.colors
width: 400px
float: left
.function
+clearfix
clear: left
margin-bottom: 10px
.swatch
width: 40px
height: 20px
margin: 0 4px 4px 0
background: #ddd
float: left
.swatches
.swatch
width: 40px
height: 20px
margin: 0 4px 4px 0
background: #ddd
float: left
+transition(all .2s)
&:hover
+scale(1.2, 1.2)
+box-shadow(0 1px 10px rgba(0,0,0,1))
&:first-child
+border-left-radius($radius)
&:last-child
+border-right-radius($radius)
canvas
display: none