Last active
December 10, 2015 14:19
-
-
Save danielwestendorf/4446741 to your computer and use it in GitHub Desktop.
Obtain the dominant colors in an image that are drastically different than each other using client side HTML and JS. A la iTunes 11 Albums view.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Dominant Color</title> | |
<style type="text/css"> | |
html, body { | |
font-family: Gotham, Helvetica, Arial, sans-serif; | |
width: 100%; | |
height: 100%; | |
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMYAAADICAAAAACW+sHxAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3QjIwQ0Q3ODE3OEYxMUUyQjY4Njk2NjNDN0U0QzQ0NyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo3QjIwQ0Q3OTE3OEYxMUUyQjY4Njk2NjNDN0U0QzQ0NyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjdCMjBDRDc2MTc4RjExRTJCNjg2OTY2M0M3RTRDNDQ3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjdCMjBDRDc3MTc4RjExRTJCNjg2OTY2M0M3RTRDNDQ3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+ZuIR1gAAVFtJREFUGBkEwQmuJEmuLNi7nC5kusPNjAMEQqpSCRvgERlVr/6Av/+d9Dk/b6iZ6H4EMDY8UABBD5AWKw79WArMj4RuPlSnUsZDzuBUMv0UmZIk8XctQaGlnsIXmrbEdyDvkHtOt8+EiRuumA5QEspxQI1TghId+44mZkkwA0zRWdFL8sB86XaayKHoqzy493JMh8lPC3r4cJyZzxwJkl8Oz7nqvI4D7Bx9NgmufEyWjfbvudh+n2OwK8bEACdRfT3rJHDBFimPLM6JynF6NBDnRV5s3Hw47fsYphebzEwiw3N4VTzr24EbYK59jLWG21xPz8cyc6yqe90ALf4glc/4gbxtsw/2coxr+7w2YA+8jPBHlBJLqGIWcLQJ+d6IwO4O1MEmyErnkV+nJzQlzLlt/hbfVdIFMAgBUwtWWE49MqXcdttsHUHkEOOe2A2vAsS0TU47zM0W9L1jzgGkUGCkMIkS4272l5j8xIxHQR1PxSkCAYalvIEaNrXj+BJcft15DdoxnwTcOcQBVAO9jLYIR8Y5m71Omg+PmxgTdedcas5epA1GKGej0R1qi1z9y8+71FaWbeeHeaISJ4NX3PrH6h80aIt39q8zCbCARPmy7loo/dleViL8vGJCZE+RdI33kQbqYcvNwFcf/KyU8M/xBxFS8GEpBwqO64AdlI+Rd8pvG869KadJckCILwO2fRbhvqF5kBYfXrazjZZgBN4i+4C+di1HGiAOMcjrkNIgWdi3B7h1gTlg4F/bwE5/3vIztCbdPiSiK1oamBhCoR4xOOSYMW6SBlouRw0gA1EjFof1A2vq/7odgzemjidoXJ7/8STw/IbkKbbpt912G+rBPhuJe+01/GuNyv990kYbi7ruGhih2mePOp6aOydiAiBK8HtcOWswrPZ6T9smfxgZ7mJJQfz6XUhOvfExkkTNa5XQc8BGnTmVJXmSzgF4PFmybh/Fp2kAOoK466UhnQBlVX4X0dq2xkQ5lrEJ3tmVD7sD/GMkkp30s5GGYCwxlFarGjvEZq5az5m3oh4osaSrI/hrZf38P+S1wPnUuM+souR6HtdavzJ9Oatznv1aANqP4UH4zKAESapsg4vnmCY049A2/Iqr+dAkkt/WI7sxYX0PDz757fo+I57F2WfHZIQlUfJh2xdgnniys4Hr8Y/wavRTs2Kvg88oGHsRo8pojET+xPBbNsO2QmON79+A4eA7iEWx3IVptl67r2OBZ9pMwbxEQnNJy+uMj6TGJ+tjVa6U2OHuaZtwOgkq9eNsUzHBsMN7lRFm/8jLrgx6/CWaWpeMd5QBYfVL4Hx8l+MQhCe4YZ3wR0c4uLeoOyh72vaD82ZjKviPnQU/cx577mY7mAycTqiTgpDVuBjJcY4HiOGLCeQXfLg+VtA6tOKkJQnQ29cDMjPgZaufrLOqGfHrrt93mtNYOacfxvWR8zyNyMzEAEbZ+EKpnpmBrw4GbggapzFrAH0TdzZ+ANdQfUvtf3HCYkIm+HJopgsrNIltASLds+5SaSeRDuGeYkkHjCIf0ZvH2o6Y7ktIscRQmddpxHcklpr52HCarlO1jOKsD/UwO/4SGfzkTk5gy+XwAMUFUoKM2GmOESGEYVq0mb50QIgfzFFObPwGUp9nj8nuznLcxVYefYyrPmi+HxB0DM7UYY5fpEhI2rrxb5zQiAORVfbbfQzYKI7jpldNXcfVGF5lvNDSHrgX17zC7usbvwlZ3teKM/JBnDPrzp6HQLbqHDn1XLTHApAQLwfuzOQYwI8zQnI9R0bErF8qEWB59iRxMoQdotNzEpMp37E6iknjEn4DeIDWkEjDPY5VBwvnqPPJ5FprnQ97agwcO6MkfjmLPiYnziADUUhGU/ssVhVQXw8idIJgoBeS6pbPSG9YMedREx82C7T9hyQCzJwniA53jAQPVyCL2srQzXhH17NynKHW1C8FBQ+3OfkFSEskIt0p3L+mURk+n/Hc64yOswrZWhy5uM6cTKsIRHmfc/4eH4owjXrfxAlf8ad5VZFKG0S4pS+Oc7mdCpMRa+hgz9nzh/5BCOmXYFCoXgRS9hJwgecUp9Elc4BxWO8f4WsCIDuIbTsnwO/1sn3gI8JX7h9SuEn/LU9rjzgMJsL3LmAn2lTt0+2HyTnIPsgEpZl2cgXcBuV4hgqgW1Je5aGC7U0T/4cHcBzCQbvm56jnZ0JkSpmlYuTFdumVNhCJtMaapb195cK1riTqLjCb5s+6TqhAk0/OMwDuXzZNH20S1W1DBCkN2oVBNFQwckZD76/2apz6n5sD3SLANJpYo4CTmJk4bFMUS2R+gYLOWpfyrkGZNOWXOA7+QGzgr6nmdHN+9w9NyTB2QGjcjSqwA3cbSdLw+cgl9IbsGz8NPZBpOEvWFJ22LBokfcmuvjApS4681PUtwgk0wsZlRGvyeGRRXjM/GBnbUdhAdBBwPPs2nHe84PZ+bRBOP9jH8ap+7yUxpd/8CQg6t95K1oNYnpUx7bzMgpzCjamXWY9g75loqphzCsGzAhLWE5jtvmxyY/EqbnX8w/NbPO/EZLqMvmSWLv4Cr+rGYUTgGczk4PM5FLJPgKxeiJPMfqYp7TuMwEUK64mODk5MAcucMxL2E+keM/7jpd25OyGoaiH360JoDqJbVj9pcDmS6Cs0ejGfkF/80iNFeRFyfB2xdRuVCRCfaPqcqFo1AO4cZyCeki6xddIrw2kes8/CGgZ+ahY5EoQgflFH5oVrAGOXyFUZDURlVXGL29e8ftKBfzjclrnyefgZ0EfHGA+ViQdPAreQeTeNUicuKPGZOiKuBLO+3GHGCh9hwJP4ZaFldIEDVw/9+z3ZolP7Qygn9WSsHDG4r2NPRha9ADk4rpO4oD2UA+wZTWpDbbDBiRzxGyeNAxydHT9CqO7k0S9+hPfxgR8rFu5YoQPpWtYB+/yau4IibvaaroIdYj2VdI73MWPJXw01ENuBbbtoLmqKVoa8PjM+somgZysx35pEPNtn+Qsv8KCJi+ibMwjg+9r10CSSmW6TcuKvYsQwJxAC7huWphjxAxtBHcOXWs9KQGlF/u6ez7pnQlgduEeWuXyCA6aZH4khbCS7tXYfuj9kcGl0WKzlV6jrDLbwjx6P8Oyz1IUDE+c5rot++j1rMMx1X4PkXAUicWVAJybLwaL6Q7oG9Quz6V8J5CMfLqnyvn+cEuVq/rz3DQ688MonttGyLUN4EGAIRt48/7UzhbyCax6fDEBAFapfcsBIMXm/0mXfU94SQlBJyPEaAqopCbpOvwfxVYjd9lYKJfgBRYCdkBnOQ5XGGDYOvqSFp/DvzwqizHdD4tC/g9yK+IH8p013YlEH6jynmU/MweyoZ37HQx+RD+pcCaCVmHpyaOGZAQLqmGm1gLIxIr+akPSUQMY1h8QeExqVPr53m1uRuBc5xpjpOS4+A5ELOS3yYTkLjb5x+8k+PjbiCYNbwoS4QHSPg8YGkD8sPJvMZYlhgqLjy2N+YLi568CaohEqR16hLkpwe/Uy5u+kA/Pm60gNnaOeRVpYqZx7wMaDNcmpGNyAdJO+owfmrR5uF9YfRNE1szlkcm4vyi9Npz8g/PtIPFeIkNIkPI7P0tfDlE0phNOPuW8/a0QqEMLmWzBV6YuCGY4G85bJViBogHQLzMr6plPnrUyD6UrMxQbXfEydC3NJmX3Y4efCTfB0jsQ5GbBclNRZlf8J3EAAHOjJOGDzvuIi7l5JIz3H2eG/ai2ddC58ZzUgTffs4m3TflrV+cGhX+wHlEqofEQVLjQJKf/74zQNqslHxrMd2lw7Pq9ueR2qYi3vNhOQQorm2NXNJXqPoXIQpxZ43iWSMT54GorXNPUAh3BB28utIep/ka4W4cDjj7ntdMsh+GDT18xDsET4ko/RAUK5/dwOtVgUysDBTM0vH2bqVaiwm2+BjMX9ynF/nCnyDeO2mePsDicSaudAlNxNBb6pbUz6xg4N5F2WYeGD8h8aMJDSsv3puAOEVnRlMxbEvoxrYmaPdHYm6KdHBu6pHyOJUYqPEqMH7mQ4x08UnpeO+2h8ZB38+33vf9Mp+0hTN2yix99CgLYR0Lnbe+PANsQgZccIMTJDe2qJCRHEokDeuyHPj22AC5Yf8BSMVhv7C4K5I5U8Q2RsVBzkIdSmwCRArBuHgpgwMRbfQz7gISKC49PAyOMj/Lx/zoizoQOwMficdTNWFnohTzDW95ye4aikB4zRE8BtlZM3OlevMTHYs8gY/3t6Ry+s87/ZvNe3uMb5EJT8XnXO9Wc2nMA4ArzDvyA6E1yrqrlm5RjWeT9rVvhV85uzRwVw0fiEoTMzri/rGw9Y7J8MXdw3lfWSOIXS6550+91QxbGB+Zc7tntDB0zW+MveKgIeOi7ZCWkKZUE+WxSeVBg1V5fuTWZCrxDyRGIzVbpXuFAOLFXHb8MCluv1kstMxs70FE6+2J8LFo6+BQ1TLXgZs6lL5SFUnK8B+RmBe3FqnGFD9dfkwFw5cJYHQgtM3D6C7OW5kyI56MeZ42mSBZJiVw4Oq3F6PilKIUW0PXCiAvyNeWKjcHJUdAA5Chd6NIi2727EKSL6HoEQ8CtTiBjoZRlfpaZ+RrRbdE98pD3v6tZD5Gek91vVP74AjBu+MsgdthjHbIG7mNYBGa+d+GA4D6GB6cPvNOeL6lQ3emPnMvaHke0qRO42ASe55ibcGnSRFpQnKSUahHNS3vpZLwD6f/xTfsRHRLhCOkWnb5T2vyW/ThmeLir5AgXmKv/6cQc+sVTytCiytXve8BuRPs1j1Og+533LPaaGi6xbZQ50jn9w2hhrpyMMZK2JCXA+SvyjnFmCG36CiryTczIGLG9OgudoDK5Z41xf5tBpn3iBOLx+ETOYBFgOeztXIjDrZF8MAoI7BxAi+PwInu8SHAdFxnQlhzg/uOcWrmOHp3lKuwt9L0z/i7GTgOvozYbs9KItfvY0EUPa9UhsknhPcfkS5nCOFi5nIg+BC8HmQxx4jhzbLB4h+ZYPsmDHrrX9hbTxtTrOFPES5C6BQcHYQVHT5zh8HuL8uX+tOPlw3vyyJrO/0U/wXPWsZDycPf/9fNNnPP/+EwTXPR0xWfx2FfP7PFxs4um4zrjjRNb1xZwRJ4tn3eGRd3yZjM4sNmlPtN/R/NL5zeeqFevmc3/PYlXzuftksn2sXlnrxrf7Sq5vRDIrmpXZiLzPn4SHH8qDJJC+S+w2Z5ZFfMBTTo73Il3CUQAZjeCDxxGufG0Qc5OJBehzIdPEZIidQsArM9WwiC/8GudhZbsuHAJMM3npcE2MEgtq+iGCbdsV7lDBY9KMNLwHKZvbcSxgToPWbUL9FxEhP7pw6xXO+IdZ0odBcsLa6E361BpP3KpgnxEA2Xf+zxfJwRQdfDoW1uQaA3B7GDT3Hhyjb5bqiD+EQL4BR1NiMJC/06EEscY+SxsHbVx5dluCZjDMe3DeApY6jgfS7THEL49pu01BUIqO8XPCWXRFQkFUUv7+DEXz7dPp4x+Vkb6bgriBVmaTFdmmPD4Ofj6mx3XpHLynIjVNDqKgv3YVQzFo6pagyMgUw9i9dS+qmNRnX+8IM0NImUpSlPvCPq4g6x5s9WNTT3HGmMcA/5KP2q7nhyUw/PD87ZX3ccfwFfnUICAeJjMBKSqdc5K5HwngYU784t1zceAOjLhmqPXzJOQZgpjJxCUFZkfbPRA5xoU4EzlXnX4/kZVV4EYsoxoj7sPd3dEeQuPVcdWV3uMPYiZ0/U5rSR8NwSIrgEF0VuTPkKiPHNdBm8NXUJat9kc8/1D8nEa1KeAxCYEDpmFzGJYDxtem567yOdpu2PciDHTLA+U7AJgM1gwJPtgh6mgZq9I059aBzyUofUQOSg1mfiZ31D6BG05u8PRQI5aJJcQhDhfKCLwEEBh+ev2q32teWDPurpjfb6z0Jvgsrkjc/PKeJKu+UbWCC3MF8145GXes7HPlNWrd/axmrFz965uYyv8Em5Msnt/vveJsFH+zr/XU9QRPVrOeYJ/19Lc74hsz1rzOisrMi8n7YX7p87t447r4q/N6nl91n/cVtZ67fsZp4O4mVGO/58IBEROTbYxj6eDwmggTbjs+xxweNDOM3DokTZDs98drf5mRLnxdtiMJU4jo3BX1MlQKEiPgmpjAOpwOwj9/E2/3gcOIXbCDxxiybPclK4gEHIW5mrCRIrcBE51kwCDn8h9udqrVWDXFJBd2M07lAtepljXO3TCHDh1C2tahsfa0jmRfq3YY30IxNXzIHJDO092Rv/IsmM5iPlRkrzkmsm4wwLZ79GjrQSfO+dxZdS8gE2slzyPhzbnGiSrgvME5gQVgnmipzIVka9qP6g55xa8jA5StgSGmlNzAz8ckP/N4a/ElobIdAvehb+X7iJLYcABum0jObbx8HpuoMIS+4xRzqFCdI2FKxJpKUp+QHTvpoEkcQiFwQ2qK+CtoVPk6dhgGPDYYBzH81bigcWiMoBJHMtpV3j+oOuleSpiIZp39DbDXCEjpyp0kz1xm3wcQSQ2yvp49cD932Q2J1DKb8EfRwHJEoktQT28KJauGdzPRZ4lN1vxYr+yy484YVOvnN8vk072eBixSbqxYKxeHFMA5xkjqWBgEWh7kvEYxwB+anMCwz/OR8dmxAsaZh62hxW1L+1ihoNLwfv29KEx8o1buKEHqTLG/jU2ODBz6+quwZQZakurxEYuD3pCugX96ex0CLgeW8JArtOcuFR/A369R28ztiRHuOCza582AsZOi8AURBwCCMexDwpb9PGNEMYd/4xcd4RjME3euVXDnLRjZ61zndz0xNguv08lv/YPVmrPZkpk5Y1Vk/sLgc+nFPPNeWTFjZMSZVd1x5tMXn297YpzF2UUocM2H5IomiTrZYRn1v3wVmP6f/s7vKkqX+DixIuNPrmrQuHLw+9Mvzfceu5a5mTrl8s+aDiP/esfkobA90w8M/OrLsL/kwGUIzUGRTeRDHDHx25FTnHIITT+UlwyMO+CKSl74bCEbdvn7veQte1Aactehoioxck85tu/9PaxVS3dTueyARNJ0mwRt888cSEKQv7bz0hDJXX4aqBkCAd2i2X3luGG2Pxqay10RJJSIu5CkijAouEE0J7kJAHYjAO9ptTaVsQZI43iekWsRHJUzoGHJLz5OfbNw3l6ugUC5SLJAxOD2UZrFcZ5fOzRw8GsPVf9jFfBAjNEjTySQPdx/5KXQD6EXLYb4RJL5leFnmqsp989ZxxqpM2UXOfcXVcMGlK2M2/4C1EMEhnXkrRtlG+JqgCvaF0B4C81tscbLGrscOyjDNGXrl7QrXKcowRnyFnnkoH1kl9jgVI44yvYt0jQHMdYgTsPoKzN/UBB8BNbIzkUILq58AtGJrBw1lMVhIBMPxswWXSdOTpyc+ouO+PynUYlI+B3VnQHjJNFDcdfoyjwN+W1Esuk0FdSAxLnSMG8DZZ2zod2gFY1TOa4jlXnqSu7c7M3fOJF8Jh8OcVQTyB+CC8LBk51iLhx3RsMVE3u4opy2SHwjsX+xyy/1nJJ3Co/LN4/NjCSLyTgAXYiHGaEHg3twgt88KvQw2jYrEQDmeL6L4k0dDHemxBPH6EfUzsOrUvw89tWImcl8BK4kVpE9j4zdEjSU8SennKoGdtcaWkbL50bF/H8GqABTiTzHWevP4n9IC3TdWU8dtyhen0HmjJpExgYpn02SUyllzO5av4iRdStBcdfmZNHugJldo81xqtacJxLnk1rFBM8xUs7sf+I7/4s0Fq0Md+I7zh4VNDO69fhJGCbto22b21F6KOYqSbocIu8vLmAG2lz0lPczITqDYAjX31jHLsf+2jnGABOqsvc4Ru4mojIfMNKNOFWmO8+h2DF13tqj9o6kWR1FFflcevQ6BJuJhnzYEoaEzxAEXi3v/SlVXpZTAG17ObcF/jQRFMGNXw6MqJ4sT1QOiakS4FjNdeLfKIDzO2m7u0ezAzrFuAbHFD3RQVWRxKm58EmlfxXCbHdbYX3yC+i7DfOMaqN20noFCQmrZ96rujfo3dDfRPD3I8PpjRM+dZt5SfrTv7xHWmlGoe8fSQ8/Zm/VJbMeHDCHpQd4KD6uNzN1OTFUxOBx1c4pSoBvhVovt48DXxhdKPsDDDGe8gZ2sRaO8pBT3Un5zE0sMw2E0mBYClIMZkMIf2RLvGLOXRCyZXDf1A/sECpIMU3HLuMTcexuovjpcbJFR9E1eOeRikCWWSruSWLmpJMY8KFzPO3UmJhULsvO/V57H4k6gfpQFmm/bAxStMaE8jeB27nGlHHlBGXykSQP8zGpQ5k0IRsDA5du3TsHbq4erniAMf0mWBHVAwkBByk7jQ4ZP2fLifNTXl9ZRTKX5b0ScfpiMIO5pi6iJ0Ki6XXhnxV5SRrL0wkurEA8DOa3DPjiwTXHNVALj6dxfiWryJUyfR04C7VY8l30uFELQdD3vBHfk4xlqMACksiYQfyH5+Sq2TlBTwayUBbuz8/NTgrg8IE/ePJXn83ZZwYqIZeFAz5uPvwfn4KC4COEnOjv0ARW9X85jmMBd7otxwi1g6Fu5/MMoJCNwUVqcgmwonTaA3mLUqd9zMwq6cm2jr6f0ScTXqnx1jwP8GvN7CttET4FS4duigX/jZ9DpSCn79KVha98ziEL1GKY5haC/SOgGJ8LXmhI7mO+TTfiX/2SRdVebR/b3tg/PsMvxrazX/JOhaYTS2u6vI9tQyxjizYW8c6XmNlbN/2XYgcNVBrEZS2AdIjIJ4eZEDv/nAL9fN5j+EdoU3Yhxe2nYP0sTq1uNqCkKh9k3wnIWtViKKAwvhXPk3xkKtCALsngWfBEz7Wgf1T10l9WJD2FVZNy8vRxN79oofUvGf5sgHA53iqu3JtDunPYhMiZjmwCJKkVIOz0/GWcRPjMhk/ITApkRjr6B2EBd7C+5rAaMMMNnw13uHCIQnYJBQT0pIioLKt/acdHdDf1E+hdPuNoMlr+cBg/gOH9eG8IDiI8VKDE+AW4K2w7VUQxP5u89txFXxAj/sbUNOQhnh8XSeEwBvPg2wx4C04AIvsO/H8ydgn8kBcnOTUV/+VNBA8mceM74hTcVErOOWWsrJQRK5G+QEBhb66TD4hTzSIDElrLawcuTRtnY+W9xr26ayoNhsL4dztbf1HzMzJFTLkVfahTnu/ZN8bXOoFb1HnCeGUvGPZKWETrG6CovpvIO37GYtPXBEcExy/y9INccWUkbaK4Vs3JWFOzZlQtx30R1yRpyq6Juci4LqzQaUHmTfAf+FAuwDXmno9EYM04E+y1iJqI28sjF9j5reh5roiYiClPhSluQZH3GTnmIs4z5pVYiKXPFTOxe7Toj7sN5tDkL2tOA3QWKwr3qXCbw7OTF5w1mNkzglglAlfH5xWxpkR2nD4yac5cY3CzM50GujMbXDzIBwN36cnneARgzBh5tWknBxp3rCK6qOTUGPRe5bl2KlmZuTDPBrgcqAqHznH5gx+BZUsya9gK/BvBHIw9FR+BaY7dnQiISt9A/j5oR5jpEIRCIDwMR1G8tMWpnvJqec9H8MakhUHDdL9WKRKb+HbAROM7kPdJrvhwwd64uaPfeoVA8vXSeGHmMrTs+Ai4DQ+IPInM99E7X6adx8JPqMSe0auAHk9MQvs5mFZUmp90dqepVLaCqNUd3SLyBqYWxPi1FX54VpjpvdpEmokF7dNoyI9yxhe5gIqFQYtiPXnWsxa+Y8XqGgAPP64/wkm537p2DNzpi6KDicbwPyWAz4kUgLR+yoI/21CqREtPaHilae9lH5KkwQOKcczl70xTISgt0hTN1yflkAPmKcCUdum5OagiOI4W20j5/B1HTvtr8IQxRICXEYcYlvdSECRh2i4yRT8y369NtCTFMTdIhoryM28XT5FASmJ+mpsoUmX658cUHffAwG+cA5VYXJYASBprOpBYNuhVi8BKElVFx+xWMlgOf7QxBlcWfO16Mleh+vSxl3lz8Xe1AkWq7jinBgk8NWZizIeI6vU0wHm9DxlkGOcKR39hVHLcMrxy1aiHuAlsk0bC+XMCa4/39uphTfQ/Z1hek+GQaYLUPkbkkYh5lmNOQyYmIWp0BP4QQ55Q4vodgAKJWwkHnh2rNq6ch8wr7b/KQEIN4H2Q9BU9z8pgh439JNYDwAaF23YpQr+LJ8UUyTNJnAFPgE6Ou2U9JuU/8AoVaGSPbMxnTIgn/68H9fPOsbmPqZ5r7Ndo3MRBs5Why2YJRq9vuZ12fZN5iput/rcn+rTMG5mIerDAzEwiLQHWTZ4zavwb03lgaM+bTxOxVrHHqGXH9GoOTi/Nwylh6A+Y8hAu52x0T1HIj7z2rxzSn8gByTveY7wITgQg/W7lDvm1IAB4FMqHvZOHjY/5S3HkI5uLEPnaUl42dk9Fo3BcnozqI9azhjx/7XLABccRGMk5BnJ9mIexZV/UOOTY5HaARoNy+yXmtX1cpmVtn/FA38f7FQyTFSqE7wL9gesqDui6RqJDosUnZcrtb1Vp6jQr+hq2HA7W1A6mRUeXeCHEKVl9uFAgJX2GJ+6plOaTz7k6J7Ii12cyDNk5uGYMD5ThrlMoBObgyfUH3sCaxwGrSeY8bJp+axFYmhBlhsTvNZHnv0VEfuJ1EC6vz1TYEqaK2O/4DBGKi0+lkb7zUEWngMdWlhoWB66d0gmhoPNzGUy2wt4wQPsloSGUdAA+YxWxH/r+7NhGpnFVyp6VbJGhbxcef5MSAvG4VSZZayKdAgxsilAZ+Jsf4DbZlNdnfXcR+fHnaUblfQMMkj3567n5MLuaSk7BfBKN+c1f6cXpd1U25wrOUd8c9SAmuRa55s01iapVRBTOJ894yI6cSd7n81jHfGaDdz3RDzHJqBvXOvWuiKubETdX8PvNPzFD8YwnsvIsXAQeNr7fyolF4ubP+3U8+6cjEnx/+HBvPQwCU87NDCMICY3X8g/4Eonb3pUvldd+s5RxQTyV3srv3O5bSCZzxmcEcO6k+3whcPCxTU8FqOMgJnEpOpzgb5YN3g6gkt9yp1pHD/eVh2x/v1M3+OK9sM1B2W1JVSrsxOdHjaRGrLZZ/NZnirIRqH8i4IgSelxjduRLIcOG7XnSVL8sDMfViIgFz0SMwVg3quGn7Q7vDmLCulHKm98Y3X23ncjyikKg5oMiMIsoQeZIzFADjVijSFKEdCkv6rpW5UT5ScxzbhD5AfZaouMovqb8tQY+/+IXr8dFKcYEtzJP4jAZ7wMuO2Hne8puNHzhGB4S6RM1SR5+t+De8XsDhetvxMyJoaB6NJ7AIMoEQ8Qu+BuJmABwu8RZDKZMvDcb5jHSaZBJkHrtc22c9PfQDIxxjH/8A/8RBWhtHRSY5aLmSYm8b6XRAuWCefeMnvHJj9ATDOizybrdG/2gY55jnrMvsLHykMLCANrxhNU3H7OedlKZmfXlbW6/FBAhB06uZyxOjg70OUg+kA/teqRw84Tkk0qSdp6BKoiM5uA6Jxs/sjHc7fzUEhXpvzTHZ0WhUfqxpuao0cs+HRvAD4Xb639Stgga0vTEy2aIgW0tXQdoKXb84zClbdCAuPj0ZUb9JCBi2PBr7gjINRwD85PDxAiAsk9x043vqKnndcRhW3qLUx06d0+RjwVQa9LC8VN99cp7dQ1+7zO/z31x5ZPrZK6ys4rVT65V//3aH/b61c/6B0ye7MqzntufNe9+8nuez7fP7MqKYv23vlj9Xza/q9f1eD18nmrcXxrwP2csX/WAJL+dca4ZndLxXU9lX6z2GbHofL7Pv5nfsro6a+VVy5Brda2n8/szlsTw98eXHCW+LmSAL1jEnk1Jo0wEcOl0+ovDEhCa7i8t+/z/BMELjixJjiXK2M1Doa473Mz4wcEhVamEfeCRmVXdM7P/tTwRxaYQxeIWg/5+m+wNiZS6ZCRSPnPUScFO6NsBnAfHR/v4nHboZ+oGFaWcgpJd9N88kSbp5LPECka2DhNxtUMgmhdciCD0hVHHjp90v2l/8y5RAR/2L+/uw6KazEyhsr8NPA8q0dkykOCuQ/53UvwColcd314oqa8JaBHjHyIHM5nxLSaeWq7UCBUyxSRWL1P83cJxrEVj7zYnzsSg3ysbD4NeNQu3Jg9PftessRKJY+FMoDiZPzbxiOg87lAVS+h8SKYOHe+dgo9QCaSfywZ2XmOkI3YzH7Gt+Qpanu/eJiktr60+xweQrcII7nY12TA7Qml8HW95KaX3F/AHhiywj6YUfF8UvvyN3qXDIRyqYAIiB0jhAcmxIwMKfwcA8n/0+En4xXUxmcJhRN/FAbsrh2pyyYTqSgHHw+IgoAM1zWNA+SgbR+bSPjjq02VSBQtS14BZjLacnT4ik2778S4jc8gsfhkGWsr4onbTJeRcZWisZ65M2sQsBAD2lexwnLKyAKmSenwGuP14brYf5z5jOEP8pnsvZvDXRPwjba+5jVyAxv+4yNyAlSWDNscfulHh+jpN3rOoAJzyh5zD0enNA8yWzY8YYlC+5HDdp7wYiJc8eGUoxfbtePRAgJOD6OAElsG2Xi2IyFBzuKcwAAwzHvsomMnPbzzpc56esG9kob45u/mcXE1ELmYy/Y51siNn/u85/6leHbxirGDejCqcjLUW46yo85vZJ7/xVPW6e53T2Ah+728uVrR/a5KMf/5ZBLv6u2r997efGXGzTr/6ub5Vi4y4vytirQWsiPoy5/ms3/itysd9MO8f/Yz+8+bhX1F5HyFv8AjsEJXXJ4uUcGTZO/ttxizBrs2DZVyi8ok+eIAifPk/qRvRYR6C/iSbfNtnEv9ChIILYFLmsVPp1iCmfnb/8I/zKAiO8c80pFHFKfUGIOAcktStuavVWyYMCZEPZMZh289ELtdxXDfwiKw7D9yKLcR9lkq0nc6FwiQrtsrfFP8u55AnXG8EwTnn8mF7spx8HMiBuAtttjNCBTpz9MBcjQnGmYxTGwM5VUqFZh0FmjE7zcyMzXsEAnl1P20ySv7JPhA4wtxPnZAzA/oDYFGxa74/pGTauYceHyx5CSGZuofIfkqJNd4jXFSNEZsYPy85gHHov+fcgxIOM9R6C2UQx3n0/LNLqsTAMZM8SSgAUWPZ5n76S+TztkNtp8EVFB8P7k0uFXHVsa/CeSGTuSZeR5EvhWI3eSmxU36QDUiItAIhYcY8KRCEgCkP6Fewn+EE3bg6E+gIXd8F0edbSF5zUMnLr0yLWzIxrRafO9aJ7wch2kXMucZz2z+8xuJ9jmZCnfi91Z6FtItdD+85FvfynBD/EM36ffKslhq661UELQPQYsdx/Kj0VCnsp5hp3I51DRdR+NqOnBHno5pUSQG5krMpNfzKKbT7z/Fcf04eUyx059rFbck2rgBfAMK8Pxi5Q5maUPAeA/q8PS1mF3j0K6+URa4WSVvtT2tME7fQQy+AtpEQkzg6ygDf0MFdoUPuTX6iupGBs++8Oc++EHmWfbPr2xndtE9HViK4MOOb3uSNX5wPbqYUOTCrr3mfi1dkFsaMVfUUyaovc8jT0c/TF+NZjHu0UsmbX95FxVoEFrmq4q7QB8jnWrmuL1FQ/ZuI7zwj8EucvRD5BAFE8hw/oIaFvj6l5tw4U81cjvFNwyYKqqsso1jiPv4lYfhOrCg5rrm/oX/SIVfg0BlfDQy5gLy6QV/VfMHK9IWBEDO6bm6h+KpPb4bvh+q/OCS2pbaht2kqxzb58bnhGh8ZiteQgQYR5ps9yDDFXjoEmuo/Zz6tO41nm02jKw3VBo+DTUz9qOm5Iu85MfCWs8dCcBGJfstbzqFciyCv4OjgMxKshQjQjPCMOHVFGSvNvCf4BFDqyh67OvP/DGhMo3dOz040h6r26OE1pCNudk6BTls1xeScxSYK6fLj8NsOh3KPXeCBlRYkH0JfbtC5i/R8/sSyP4cOF4iPOjYTt13lZa35nXAAPGH3WDdsOWYTLhRZBRPoPj9CVdH6RNFEWUbuM53yJ1r4QJC5s+ST3NMGnjfELDixAzHTmggx35VAzG0ojKThJ1EexOICKQgcxb8duPGgE/aw5W9Ga1tb6wCAoXlhUWdQxyTQ6Afg6AWArFwP6ptAUCyABauwJxQonDPzxnNPb9uV+zU5EM3/9Jl9YvjKkbja6LDO0fjPBva4eZKY3I3NrZwt97gvuuzyQ9gqBzOWs4+V9M6kFWehHyeo3dIzc4KUY8rqrCVVEnWoOMibcQ7tmd8TMfe8gidaMRCROkeSUdAUYMb5n1qMe3RPOJAmo2N2Bz3M8LXV8Z17go0ievAseHVPgCeHbPNRri6HOsc85pw/x4jF20ZgApChAaC6TobGYatsDdY9wavXmjp607qtcfnR6xSljpRpayYzCrnG89Vbs0Y/tBVPAAEV8EYoMb/x/F5n216PoE4BBle30gWdMeAxHoAOi7oI8ts6yhZl6udJ6J4PuvU5I4/8zuX4CfusYx/YclWJPr7JH+EEP4FN1VE5lKSLPYDPv+ZBEfJDyq67ySHv7f+T1QnPI8eut7lAPtb4d73kI/VL5/GS6I1H67EMcD3+tfusnpZCzL02sfHCBHmsLA1QTUWEgHEHPpq9i45kbJtgLIyAKltF5fMzpOYvamTkyNvPk7aN7iADQdccLHsBKJ84Bx5SKB/XeDbOd9m2HzLBv3Pcd8ybIzWqEGiFSqEe7wjhoXHEkcBERipkdfaZJ/6DMcZ1qqncX19H3xdMMzAJsrkblSxOwVs+/1dlgiulO05bK/vmgR87sFwTek7AAKWJJ5HLUrDv584NG+AKWYRjmusUA+2lxEs49jfz6OM1loXrwNFrdwzFq4WH72+GiB/HUpUZbUWbbxy7OCY06iDe9DTYbR/lkQYLhGGG0HaDiOzWhIcJVF/awBTLQQKnhMiPAycyG0T8As0hJoVxbqfFtM9jpZiES+ZvjBpLvp85ilXk/7SpjQbG23LB8ADEINJPp3wWyDxwhvlHlAnNuST6PNc8ztklGPWwOectkGQmr1VfiFl8fQUDpLVSMZuQkhIqeKMKi1zTHpjGD8nl5ESduL0Tx7c8qTQwQpuopM6k14xli8UT/i0v3eksCgk2HOiIZncjiJpYY3wJuhOB4VxCZuwrHn5JyjgpX4LRa9IKKz2vWN6BbB6cnStrz26Sc4JfeA6QSVs3mdOTvALJ+XNO9pylN+fOG4+DJPUSS7cGHsArZ8o4x+rL85Jh08yMFbeBCu8InOEraiJzPKHWy5pEGKgXzz6jsSJFMtUPGLJIsjhyoifywCfypguyoIxV5wxnmV225K+nebI5mo/sJtF1CqdxOOdI/nzc4oJK06RNCBXsxB9pkXYEDoAZH7i4lErFpgIZUp+3r2PTT9YRLhFiJpzfENywfwv0HaTtODaEtD2R08zyENG37Cj5lEDUZtgpSuhbeWw9NQQJLOgIu3fRHenWAADsA/qBAgO6LfNXscP3H5tP/J8BjmDo8axta5X5gkoCC0hy0BLKlfeZng1TipM+FmUnnY0b1AAsJRFJcFHM1JTUEwbMhQyyxz2klNlfX+gus7PiszNVACkdGZ0KF/mb6JMk8P0S80brCXAxSxYHplg5tNYmiJ/XZ7vnWFPTokxb91im9mccdjgCf3HLF9eAA2LmRrfjk+5K1ykQi94EeZ4WdqyB5B4Qk83U369sSu0+ku5RKp0HeFAfpejaWw48wqmGTUTsUpmSshPbUmg0+WJtSEsAl43EZqNnL9l5gkvGg/fr3z/Z9uT4ew4fvQAgqRoQRbAzEHurLp6/RM2RcjWnc03WWzmpuQ96IgMa01lDqsKmmoTSxsCeriTGiREUi7FCsCb3wYlmkZEW/wlF2jxlnqBpTW3ME+y2/XymYpyncHLOswbkn+yJ0xtLHlPTnyTLMru+GmvGIspmqM6U5ctyOvWeiMlkNuGcGfGZ6SaxQkgya2mPYEy3vlvO2qOiA1+CTyTimiDIbjB54UtyogsR34dYEySNsWzkI8qlgmJUCZjgev4vMGRV+F9YxNX5zAqPRQ/aL9ePVGL7EJj2FuESpP9FHMuuU0DR5adjZqpKsOPkzDytdjWLFTq+Ps8B0EWrgHEmgkAdbGTaAwc4eYHMzA6onnXNef8tK5ybMd2CUyN45IBbPTh78cEC9ymHV9KbJMbEvTD0XDyBC1BTmp7rJxOBPytluWDX+zYYuIzbxOctBxACFcLVtk1klxwq13qbUHEM6Biv82NL7JH9ewFu9aG+3+exD+fMmNSPygdqb9wOuORk7voffyU/wsMhDX/bcaiZeA1HI2WD7Kn/Hq1FkMijZ4gOA+Srb+t36LFBiP3Ha7QOiDwKEYlTkDPN2gMLW95iCa6ATah2qD4YM7nH+qJZp9J27/gKT+gSRN3FaRLfjkjJNp43YGBKoAsp7FY8Um2tyqXqjGkrWH4u8P7Fc579gckcPQ2JIuwBgTM5gDPLyDyrjFTf/eewsd5x4OCxL3n1SneSACnyFjlv+1wuqhoGYifEHkWI6fal6WYmcLVVJiCNJfsS2YCY+z158xAvlWNpeEsmlNYaOHehiciEB0zgfhrsaHtFHwszvvkR0MT34L4bODBQMSAnRSEH34QfC6u2H6Dvxzh6ln1MKv8G/64xDKziMwsYOQswMDV0PcODI2IZ7Zpbq5x+Elzcp4c4gChXdgCOsvGLvg89i+wBf2DZWOMaq/8OBYLsZfhevFknabGIcbPTpq6C0lfS5NtN3n2fKtcXrGjKKNKUvH5UhhPnODhminxlL82uZEYLhmMa55Fh8yZlESGAzJC65/rmcKsrOJzVX0GIJWY0V+OEdxOU39+cp66TGwAoIc6sKSxmHAhv53fuJ4lGGhwOBpM4+BxvM0SN4IxNQVwTqcmZ3xLA1KO4/+Qm0Gqbt0KUHMTkNRmDOVF5ziRtjhP3+msZ1iV68tV4GvhWivlStWbljawxmONrVUAhpdtkzJmYDNwaTZ7IUZNjwp6j1vze4bfjHhO9wnZnENJWuKTVASelJvOyFmqhlT5ZwDOs10Gg6mfK5kOVW2IHDI4pJIUz5v9CM7Cp2u6Zjjz0WM92iAgDb8EJgrAD8gJFFpXMQy5zFEPkbKjZpmAImDz34RBH0XXIJOgH1yZLkgT4j+y7OWNQNwSscW4vPeBiPKNXFHDjnQcPN2Ccb8zLEPgRGS5z2vZ8ZLzJ6pVw2tRn5QJ71lDW+J1tY8VuAZGJhvQAzAYTZz8Geo/8Hb9mdGK6YcjOm1N4nvuB2L+1k0J4j/NEHobZGUHzq57rPMc41UYOqJHGqaRdjqQuhluo061eFGBGT2LZPGPdQP/ESx6k4OWgvNHV7MPEeGxLmJ4vxh9Zz2FwbvYWcXERirQMCvTdvZtoQr7EPVMcpUbwn4XTlvYLAOfHZIQclwDA5nGIpAm+RwL09DQOwxwmxzpeKgbR8QKV5mJbqQoggvwj+hKHEyn3Oe1UfORnyQgaLyvLAEASJzFhzogZz3nRi/WUVa1eQSKsFyfQsfzs57uMSc5vNhgLPOeAcX1j3X0OPfOJ+y7/Rj0n+3vV0dcp3Vx914xlSHKw7++aV7MWM7DafmflSLAKAE4fJP+pJgZ58ezrfub3XN3nD82W7y7Oz6vlBe7LGa9/DfBKIdhiuaC+i6FSdMJE1OReu928azbjMZ54mYI7zxHX/PfnsFS0yT7EZG0SFHRuzuwPa4ekcnpKgeamMxov5lznqS4wk1/7sNGzz7fPVLFDgWSMDhswDeu+MM+ygP7YgxAx65u7l9EbsPiDhYHywSY6fBDicm7ozxlQ9nPZxUE6Cjfhs77AqNPI78RLgskR5JcD79GKVHaYfb8QYrvlVI2V8CcqB3BOrDXSxz3+SuCLprfbQzjW5kQj1SzWKrQcfSop/eRZjRj4sdJSX8+7iHi97o/kfWwHIYVhvSDaJa74iGjJgdvkrVIC2w4Vu4zE6XSVpK8gcKm0YU8eNlOHJGSIfMCdFgzr93Ptsh1SSB/HRHre4OmGTNnwD15Tjzz8mPbIS3Ynx/kl+doKH8Zbi2EyD7hN0OLPj75RX0ftjFTNvACHAhM1mSMzJhgPpsipQM2uUOolJWgHYvJkNp/mgJR650OOz6LHVNYGNhog5CTNkI2R2aoujydh1QDuK1bPzOjRHsaUQrNymiiwAg/ybhu50JoAI73/AvXqt2D+bKomuYtQDp47W7ZDTtnZDuQQYPNx1Uf0YxNygCKiPGCbVg8sdyV65/XZJvjxkT7zhTe43FQ6JLDkZXhReQg/LxGDy1BpFAVkYx/DIbhC7r4nYUOuVF+fjfvn32ekIp3qeNGIK3mo6O6NA9e/ReJn8LvYcbMCXx/fYGb2N8tXr/NmfYEv42pW1xxrPsYnzpiRxZtxnveZZxIVuVZd63zY97me65+u/9y4n9UVFusei911/bK/M6PPWsVYf7Pvc53Ruboicmas4lq868zzWb+T61m/58kvm0leTLJPFKvjv/fN/9azflhWsE9Y5uBHsB9ckhXimDDgAM19qSCy9iydh+yvIzCuIdwZXvo6RJbu25/X343ym2pBC4r6cTCHNVLEAxAx8xSWfPSPPRp8cUF2ItAQ7Dr98+VmzSIkosX/uhBjoeLh52uJaxdZfgBrc6HUoOoPzhmwJM+p+3xM9Wv398T5rGcm1sonHR0dts45xlz8iA4IKvGY6TOXLunAWIHknUCaRlQ6hs9eNleHY0RknBX5mPN7eLotqacn/JuO0xO/Uwbk6qcBJWfiHgAQE3NgASCrByC5GmiIJhcm84e3luh8sz5mbRxUHvQNmZxjVA5BW+8s6ylAX6/X+yU+MGWkpexbWEEof0SkKA/trLd25UfyOMADqhhyvLRzzwuZjhblixP68Qysr0+7h2F+/kA2Ukv4FUMLD8gRfeARmOHw+T+HYUQukRKIqcYgf9j8pYpd5GFkHKQ+hcSK2Tn+/trDxpcsA+SkFoVQPmgnOHuq+V4xDTnktm74N9rU+/TqwqX7fiW2kBKccFxPV9upPa+3eiFo7XqLCExEKZ3g1uvsexZD+3yIOc5prBzE7QAe95pmhnrOKfxJzDCg3eexf45vyE4Vb5OYshdCTBHTVIBjwiA78BJsngejCWn+W0luhvfGUwExyqHgF/tEGnzzkM9HqBtOVeWGM1WB9W+W+DxHIm2ECX3nro+KqRR8w96HwsQA1AW3VMlggkJgvUkzixP6c5P5EJzPld+oOzIcmB1B3uvuk+Q1nuJkd37JILnin+c8u/v7vbJR5euXa2U8bHYvBhdP8vLzOxmoycyrEd0dxuSqu5953k/+bzzfAuezrsx13+f52yPWl2vVtzwpMe/1RMTqYlcGTmY5u7+smGx+V/2s28voH4tDMqSuNT6bGtQNk7KhXToTULoNE54AV1eJ7HPADowxUymmO0gNfvzKj1PGn+HmIf6KVFEVa/ujZH3+LUtqefaCELVT7BXIPZdhUJx0okRs7MoXj+NXN9B72pGkHgT2OZKcob/nH8jxM/K25Hh6VYOZ9XtpT2Lg24noMiarG/NZvYzT82bkgkfX12EIQJGZXY1F6pBVziBoqmVQdAogunwqT8gwVuXpXg3M9UQnBI1j/J4JHVlDuuaUFIVQ5tU17wpUxHkOZI4pOXDj7wRWjI/8QKwcA5KG7RnsA65jwVlwiwAMckS50ug2dpqbPDwyAcLIpIfLcyRcnHvUHht8v42HbUi0SQpU5lcTysi58zCIOGWlTe7GD+FybMvJ/VjrLY8NUbVxvf9FleESnilH3GHw6d72RjIJNQnXH4wnqyBIT8v7ug3Dedd9XDgR+Y8/wahG1jh1LCPGNbxmP7kegM1mRnTjGnqOrOsk4OAQ3fjlIHPhXi4390XMxXPCyccaZ/4FMtF2pzs6UdNuyFkJicG9MhDW0YlrDDxdnOiTdeb99wMk/idY8sO5E/v+Lv++QBG/xsL1IL8ck/QcwXnAa7otHCAgujkFsuP71mRZC2UljhsMj5eOE+kuShc0dh3yOQ4ojK9PwD7Cg2XEpD+j6QQNIocGFClOiKBEB0fZ2Lb9EkGHYE2sL3gOyCUQDCCvbXP/4c3V9+SF0U/ejDXGEw8Gcl5PnifXF2ehk7wXijHvyUoGr1WTdRIzn6iRXMa+6559WUV9cfsoBsv/k9boECbjrLp5LrIfRl/Nk+Rzd9+4Irw5shmojueb3++yOJnOi95r/ZN5nqsZGFnF53wiv876CdlIjHFkgMkZO3nggMNNjSRM7PDlh/DQ6XnwmdFL4YfZp+Ut51s1hZ/P+/VP7buMZ/gJPfgSpQ5AcH1eu110IgHLV07tg3PnuYNTgZbD9VWcGrhfSNmYU4Y9YgFX+BTAAEFjuBl4iOmxlBBw+xEVm4OJxl8AucVGQyOG24QyR/xGQl3WTI4hCzzXiqbOJ5SEj1xl8AmNJGJjoTmQD1jzGZ24is1cN/HXySuvMIXMfgAggieAmzxQDpTHEnDmqRhBSKIBjnwyc2BlVaTyGtZmSG8E44dvijGbq9hORYrH/8ndHIvcLesAJtVNGX/Vu81UmAsIw7STru495Ko/H3l5jPhzZBzw3rEPOZYCNl/yMiTKZ7u9vekdBgKpbUc9x6R89DPFV735MWJfHM9N/+hG1gDvnFOTmIcqgBRC64ZPKPUHH2U2xxnIXyKUoozGiWAPjVV2P/VVhPt3ALiLtwwOJMFYc9BgpjS6zEWlrjVXzF50w34/59LGpvrJsTAxFgI3pzzrgfLzSf6dHctgtqKBcTM+fLP7rLSapSTArEAKvhw1LexktDd7zUDgJ+ldWJX/MGEMEx3ZuLSyQgd1OrlyDTu5D/KMKFs5+d/rDOImvt+DsxbznHr9P1UqKp+/EX18OAVYxPXX5sja/Fs4p9KjmcG36QE65/mfyXq2tVCeS2gXs4KIZxVPep++8js5J5/8rjnR0Q0Dx8O2/UfDomadT1Sg9OtGz7MBPINnWwor7v+Ky1MF45wk7gozZfdUiQGko3peOSpEgCt/DSzGXOXzS13uPfMeuHkO58ynMNBnw8Lal+e8NeaYWBeOefjwQZTI5LdR0aOchfMwXIsOniacTayeJ0/Wj4cuLHd/potIHGU7e7e03913vr6d4HVMQybURKHS7nD8KwATiCqmoR8dlUEBtxD7DFnB/3HbYdq5W2wEYMiH0gIsilMOzePAGYrcCMghx/kn1Hznks+IHcxjRUEqU1guadvbTTLN5A//9WLvyPVTqNXQMRwKBYEuGWwuUs34rcZdpzmNc/Y0ngn02kj5C5PotrjVvzYeeIyGD6IkzSd4tQ0zq/+yze+hU0YITYhG+DUtgTyB8SxZaoawUU6j8RGg5WHf/Q33Gb+JtshtC/VHuXBTQmDErJ+Dfh6Km/He3yJN2Bo0mIrhHXCVZOQ5ZCzVkA8U2PN+yQCHNl6LyKLLuqYX5dCiinx9XQ4V/YgR4CsY2BdgL3lRqWLNz6TYNPGd7sidE8fGOP+dQ0oOeau83rqUv6Ua/uLlqvyQFAjwL8Wmw7Psp+q5nMRouRFzcPaInlPHoqbWdCxIYLBAII/xQPV3YXwCMBIse3IEE1jIAXo20nRyTTx7AVuln7bumcSIk60sH31fZom1BANNN2vpDvLaY5/xACIxLDUqJ5j3xbYkH9fk1sG/8FHph/3gBwUmSP4Tc/HDBO1sYj0zeEbiZnwvaJ0oPkEjGM9c6ImsfVWQvAqcEgNOFA/AMYZyzoGwtSp14iE4n1xRzIesGTNyOR6TuxLk0PUFSU+NaXvDOTNZBML6JmyyIbPQE+KGG8XJtRjjZyvBnRX4hxUwRQvEab94IBOyQHINlnrG0odOzpHsVO63H5mkmRGIB/NKfsTX4niv9FKsx+1GBeXoKyy1MADYAeqI6mcGJyL7Qfa4yDzPGvgt8jtPgnDaVM7iBE5mqXbO5CcZcEeWJfhjkL6OI3HiMDkKn+D7A6FyiE0Cv64QqpwKHQtGlXebHilbFT0hu/Y+p5eDsaeqkzR3FRLjAxh4/EsCp731xaiPiMXu5M7cQRwUQH3JPUwjTgBLaeA+6OLzj5i4Ik30kQWM0CHbmhI2dgoP+clgpqc0SHMWlCFGf/s/QdN4cDcuyr2Wl5JnrtFjcJSNzh40OYtLKdLAQ7HJqmFqaesvxTcackM7a46NERAp7Z3cbAVQo8RwBasQmDcFJ+Q0jw7LASro7fsal+UifN5Lf5kruEinlRjHzxa75YLgdztcR+oux97cG9uxHuyE63BnbKoPb+ijgMIdH00CPBPj2aWxS7uLULaVx2ZifWxMQAOnAB9BipMI1Ef3/fPmWq5y81PHNjDD7cbu9ZkNQOP1mrrRVT5GebshI5RoOiY+oqI26eQOlx/VXpmwnbszqkQi4j7JPVUD8xuou04Eup6eDxZJJr2HgV6ZoyONicDo77zlyf/ufpmaWdX3ltMTVDijbC+cxqK5ufXfY1ZHAN5WiPNehSSCnsBcxRYswbSdF+s/zsHZeDiBrWFuTqMlqn8O9pLMr+DMqPiF3/+jXYHKvvKEkMkNFw82vuVOfCkzAk2QQdSyNZHNr2755Ap+iXNGXSjqIpJckz6ASc7kk00QCEoW4mIALKxAXR0zHyC+CMIVMT14nER4zoF6lKU1+dgTk8FyxmT9uJFjYjIe5MOaJ/aw0DC8pyL+bjQlID1RYGeDt/vVO6vKhpX24MLDG/k0ylCmVja6CqsvHLqoH1BXf2wxnfhAHZZBIfWcozYOFHFdD3osUn67zU7vNhAMYMglSFQUGgZgsHVyjxWk/bgdBEZ5zP3MnZImRcLE4PV5YYzPX2Mj5JWOXUnoHM5QvvehIiLOtbPB2eo2UkHZgIw85vgNHqrUl7rAIB8TO3LUdq5M7nJsGC/EH5kTybXvC8eNfam3vRIvu1T+zZCjBLiGdf6zi5WrpIjo58X7gPlP+87RYjXRuXTaPHICsG1BOvQ+f8l7CbW8xomxwnpIGrmWxMcoqYtchnuRnoY+SwH9QnCunZYVh1B0NQkSs2350F2XtJCJ9B4PB7hCtfmPDlJPCigrEJwGtHUNnGd4Dr+X7IU2cOppWv3z1vfjqt9DIP74tUnuNvL1r8319cIu0jjcebw+OM4kiFtR/tEpDJ2fF8dh/FYOxp5TaklA578PruNEQwUbZEhKi+4G4edff6rM4CU9tmbaYJcKdI0AeKqE7DnU3pvFsYQs5b+ErT0g5LFBYR9uOj/QIyg/S+nFh6xvaeP7zFjFnMwy4pR7/O/dzxMneNVcRDniOa99MFkKog1+PcGTIyMbX8+hg3XzdI1aK30usLZaqRpKdfR5uVdAQi00q7X5cMyeJ9dXL9OrxmF1o6H2/wheOwfIvpPjwdd60NIobLOsnyNMSVNb5AylBcSLWMgFmCRcOxJjhUerjK/Hmt/iovSScSid6wqewqyz9/OjcWHVcH4iYpwfv0nGI+oNxkMUZT9rj0bxvEvP22Oey7WGJ3fHSTs4kv9BdfTB1MwLHFhYmb4iOUBOLvvG9jfqZyzDFMh8FAkbQwRZU3795NTl81y6vCZbgzII75aB4jT7DCigC3hwx5FtpMK8jGifti2HSqIb0/UM8ZZAA3hG4LpJnYXyicE1ngHF6em1VNGcsYzjgiiAxFjjwVm3hxnMkdF3Ovy7yeCPyt0vXzgYh34m8MLxOY2vBGQwhA1zzMH52If7x7gmTpoqxMU+8vGPLzCkP7iHQnYwVPW8X8aF4xjH9PzopSqaO4mUi6IAfab+/wXBCY7sSJIlwLhOor47uOiCh6dqi8JIgpGVVY0e9P2vMiI51IEmJJwQN1IOkeYmTPnnET7ZmK8mcRYOp53Z4+OYzAC4d9Uf8ixpM6VaUQro0BjthmQ+rVlPXvbv6J6Lu2wUDECNlq47tWSQ4TIKsGIoVTSgmk+7ij7aqZUvMtH7qY2IwIq3XZ5gvm09kQBmdnI8w85Fyqm34MzKwtCbr5XzeosDIzJolVT2CWS10dTwEyqqk/LngeeyFPFPMz/chOVNAO7W2aM3sc03DfV8QWv4q7GxxI0tvnGdRvEw7h8e4s3RALXTVWy1gNhgP7StRs0k/LR2qBzDjqIqLMNJicXEDhxdTlOxnn4S/AzNBh0+4nvamLBiIgUphxI/Nu7K4WYvBi9S0zB8rroY4Yi5MoB3tl7jYde7HmcLAsdxJUe7Mh/WPXu2UdnYVlAS/2WkvW0yl2gIusXKSdZ4Y414eqKNyKrn//FqFxPrmlFzvAOVaA3WiCgyJiL59Mk5yYjnrvXCq3EM9Gf2lfYTvmWAdpTF8DlEFj/+/UsQ3I9hpwcYwaagCrM4QiwbsZnxdHUOyFw8aLq9fmRqd2k4SEFGeyFK/+yq0VqQaGQLhwMjHnof7CKZKt/vJGh8zGIeiYRz4aQYmEYkLEZEaASGS+siKclep/xcxtEcycG4y4iCsCAuJRu3duF2VN6ZwFvs1Y3YZzyg2lyTOyago8/ZaAGiG4F291WtVXJIy3tEvX2NlmCgggthtgZXtj5bDhZ1guPuf/+baz21+H9o7fo7IKeYnBdA/I6rPdcJ4B8k0UFdFjny/FnvKYc2w81zCgr5EQyBuohsApSi6gzFqbxNx/gDHAimHb1/adIWytitf+m0QIO7ipywi+q3iSWAA8K6DIG+22potOxoh9YlNRHmFF1gb2ekneSLIYScG74ontPoYpvjpTGEGEhooAVs4idRMz3JeKazrywKpHeeM3EKql46qt3rfqM6sTgUKHTDtlIfy5n0q1v5HuzIq12t6UZerdnMZOPy5GYL7e9onMarBgKVa+JBAVHBya5X9YEZbSAGvZFtaENEqEEfJFCv6WTHlcF2V9e7A8RPObrDuZOUw95zoxym2+bIbdPJPYCTzb+UoEN46GfvkOtrE5bpmeJrV+DcTzLTEB8R+YvcfCKOBjhVFYzTFmAUe3bm8dBmsC/KJvX5Iz665keaJ3670NDU3ti7fM5xQpoY0Z+DMFGA6F+jEeKUn2euERHTs1/R54pr/rPQzvU74nmzJe+Hgz3Y8x4rHMG6EL319g7WyEgyCous+J18VyYf47PWLNZg51w22sN7BjGeMW+mZ01WMf65n6v3TO22ZnhmvjlrRA6PehkDsTjfOzniPwxLTo8xa9TzznpmZ1wrfobh6kdgb1Py3EOciCaqGBhQOj+fUa4UMfZDbOzapOOQzzmrMwE3ciNUtMiEyd8+WpBAh5THVJoaZAa/X+DYkQSWY6gICIUoO7s3Hv9ykxMxj+PFQT0PwfMvRwiYX8GyXoATIyUnkp/++On5Y3oURDblqo56mra7A5FyK3vTqYBn9eZKWEFRksJo0RcenNnCNtJIMUqcd2qFMIWTIMoBcDQabGloHN7Y9omZajeaI0eu2fk0gOUkJ9d/2cmgTSYoWHlLrYDkkuUxqmXKaNMx+y+v5PWjFJwHvkfQ2JRofaC12L+puwShQpGkmHXMMsCGHIwDchZT4zz5gYjRiSMFR0kGx60TCg+AitTPNyzzY8Mk4vuZtqmw5JlDuwHhcq86h325HcNOgQ779q/X5w9PttxTokFwaYshVDsF9smSQZdDfuzIgabS6kow38Fbe8Kh/0z7UG/ZGsLVlElMlqZXHpcBghdp/uYxacUyrGl59j5HDaBaR+v4p9dKkqwxLmpYziuGmSXQoj2cNziZ4EAYq7lfhJJr181MVaLxFw8SIsAayFh1gnX7KC16G/gxSG4HKl5KZgqGtAlo010vMoIqsP24dw3k/tfed5PW4Yxjti8187tUvmaHIfjtLPZHEJ3lgEsAmSaHZ1gvEh9K4zYCNlSMMRXVQQB8zSK/b14IDft6uemxnfivHG2FG4S8odlcfCSMe1alH/qz5p2se3INrnxiJnsgcnAYMYoNIJVgf+MZMX/fcY8+R/1WTJIr7jH65MWxxnu/14wYc2bl6Bmc71CPqHgDLN4VI1eLi46BGhhzmNfM+55cd7uS16zguqoX656P9ZwxGDZ8jH+KtcZYeffK34l3kFx3/dgZQ07y5HPmOBs/ChmFPOKFRI4EEFHXdk4JDrZv38+nyaiZ36N/Tsr32GUcvOPkavmyIHTO8VHIcbiY4DlwT+CzUVo7dQX7QQqoxu/3Y+SJyb4f58nuW82TswHofggspHGPZtMn3RAIquzvAc+crfz86abVuLuOMG3SxcTpo7sTVyTgDoupt/t4MrjAoD0j5n8iGyGdZhraz4Hiag/XeAakMK3wDW+QwdWSiC6qoo2Bh6whQ89uMcjXyQWAATXM8l8ywOemn033e1KXvFVDbCUQs+urQI6GGoC2HxXxbMcuqz5NNkJFDKfBKSEtE3FgnCEB503YgpqMoYgD/YPz1LS4PdufbuCBxz1fHY2QzxTe/cNKgaQCst1ax54EIbb5OA+B/cVbrQRlFGnHNtyZTDdxse/Jj5sYQZ/yGAOaQaPJCdh3DQPihxNVTrNRAtUBu1WyZ5KC55YLlMqXho6EEWQyzoAIMKWJorFZJcDUyBzrpGf0hzItr2xZFUUgSrYGrrDzTNtFWpd32Zw+HfHCm1P7aghCLLM1YjwlIQZSpXuNGr/lKHiOg9EGFiKZ+LEN1NPr6FfznbfuOvMcaHRA+hkzhmW+/FMuO5Euxq++hKsh889Hmqk0+ViJkDSPyBHmbez/4uAJPzIvuPD756AK7DANgZnIYdIIil1EpZaIfOw+BdhIEAjZtSSEgiZiSXeH4ORx+sMGpnBBf65pg71JTc5YvMeM8TAVI357xnzGpKwCwCuK0e/F6e3J9//qXRyjMVpfGFfDtbLuOfiyX33d6OuuQq2/s8VIz8iIzCAzetTTJp0XBwdHFKIh+vu7+izwBgLvdf/n8UGOxEJxjME5xluBVj0i2ScnXfnTuoK6Let+2DBaN6Htn48a+mGoDhHMLJAY310GeiHgBaZHVie+M0D6Mc5hZ8kZ8vWu+TlUFGHqkc7rRA60KKNTNpRI4OFhEKccuonr40ZoNMp20EW7N6EY6IYuISjhDkb/HrrZYeCp/O4aP8wocnYLgmDyUWN3y7olBAgWoA52DOAGRgCZBfTeLgCdXW3KMOXs3ERJumCAQli2QEPGEg4mrHW60uOssuv2I4w0aysaW/t7tMnMu1XBVM8YYxUNj6SgPRjX3RckbUew2/7kOD1P6/oDYKoEH58UmWM/V51KZyO/H2kB978dvguGKExeCbdxO2Tqf62BswDlIU4eE7sKCxgiqacK0fXOniUF4jQAzL9IuLH6GeNzRE+myR/gZDpux2YLJ4QipuLVG117G13ooWE3Lkwx1kE1YwjlZ42b6Jm8fh/01onGHofakiEQTW2dgIepQ0okSiZAqmo+DYEJAwJ3NetsqkSsfBaMNLBDhxgGzTruzjWpt93IcSUZHOZ6ZzNCKMl/QB2VoCYgHcFsPnM27BxUYGnT9DQ2ovLmL10CP4RglEqbExT6Ie5ccTSAKl+B4chOY3Zy58cm5pjGTGcUflsNUGmLLlNqp+4yym9LVztFIj09e+O/PWp5Y2xdwmUUSNvOuOidApul54N95alT0a0+qrRQLF8uopODIuAtR0NgcL9Zm+CV3ewHtNBYipe1QN7/S7vvNjnWf2PTrQNbZrx3v/MhXKp7vyYeyeRo2ASg8h2ckT0zR4y5HjISDpsXqTJjwWdap6MqkDMvAx+r1lqacgIC4TNaoTmYQLTWhqwVxFNY45oA7eDf1Xsk7K2B4dKQlvmjm3XdvnoEkcbna8MAHUm07yYeMg5+hXJ2WLYEDz8Ql5qkhnATUs/vjv2s+JO67abP6+Xs9UehO71pdjSN2sGSaNcnbwFk4jRhToW4xh+aACJuA4d87WmCFOGXKvOE7u088mDoQ0VCdnAXfoSoY/ywxaAfit/ykDBUWBZuyl2q0TpEbslEZwTZrtcTLZeJySSU0vsUS+2EViQV9mZTaERMgvtDuzuK+abINtzt4r08BH0aTdklwLvdZNyZ6UVJsXImC9Qjbq2GEbQwvJytvXO18FmgeLJq/IQc2GXTdrl4fifBLR/7U6UiOkVKThnCCiijaYV6H2vsIn8lPmDsm8h5lkiwUTl4TDH1ChpNWuxQNxxvDshOup9etFv+6CMbYF26/6XtOLaPn183Ie1zW/Fr9gd67p9Iip/pGiFAQCoETHHZxKg4r5/WryQXjQVAGoUGzKK6APNL6lZG9Fb9GmCFs+hdp1d0ExP0ELxDOxisgSsXMgGPt2VTMjkWSNbiDtaFrN6xkVPjcD7IsR2NbodH0kcwNRhJN4Y4x6UD6RVjrTMae+WNbF4s2N/McbYfVZ+cRVOEMxNehbhgDU0wqIKTmkUk4TwHOYEZQYMPa5k5YjAQyA5UWPNlfJ5E5vyNrgb0HOQdImeD/M97YgZZg0G4sFsL/lsI/+1ZMTJ19HCUNhSgiREYxCQGM2rO3i8T6ScTnRUYP8Ku1i1X6+Gn9bSzkAcHaQa0aRrkOwali3XHmkyR4AjjnYKEExjIZ7DRmKghWOQgOgEtlYNWo/xBQwXM0es8WGH7qOOOeWv1sZ4wqRwY5TeKiGzRDdc5CIHSGWbeSfhznBWtKNprVT0/BMeNyZN2RP+MtJO7nX8Q+JcLvqm0JFd1GYptkjuaGnNeGERAAQ+xXpsTDJBRtvlU8SMFPQ4kITv0BM+EHmYBSar1AyIAch5BQYwJpMsYIjCKIhhEl+gfkYsD2ITwP+OkvTxhhmOMU50/DRmnhAYPc+Ng2DUIeSRFpmnn2azNxUwOUUr2ywBCO1cKKruN40Rrt9/4NZtn/99W5UXe5CJ7ZxYpqk4A9ThWRxIskZ1agFytoa1aN7x8IDOeiYqQfv57zbttjSxT4z4I0Cv6eS4bllcgsv1/GNWgXvk3VgIAAAAASUVORK5CYII=); | |
color: #eee; | |
font-size: 22px; | |
} | |
#source a {color: #eee;} | |
#browser-not-supported, #source { | |
color: #eee; | |
text-align: center; | |
} | |
#drop-zone { | |
width: 90%; | |
margin: 40px auto; | |
/*padding: 10% 0;*/ | |
display: none; | |
position: relative; | |
z-index: 0; | |
border: 2px dashed #eee; | |
} | |
#image-view { | |
margin-top: 20px; | |
width: 90%; | |
margin: auto; | |
} | |
#results .wrapper {text-align: center; border: 2px solid black; margin-bottom: 20px; font-size: 16px; padding: 20px 0; } | |
#drop-zone p { | |
position: relative; | |
text-align: center; | |
z-index: 0; | |
padding: 10% 0; | |
} | |
#drop-zone input { | |
position: absolute; | |
z-index: 1; | |
top: 0; | |
text-align: center; | |
width: 100%; | |
height: 100%; | |
opacity: 0; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="drop-zone"> | |
<p>Click or Drop image here</p> | |
<input type="file" id="file-input" multiple=true> | |
</div> | |
<div id="browser-not-supported"> | |
<h2>Oh No!</h2> | |
<p>Your browser doesn't support this fancy new stuff. Try upgrading to a modern browser and trying again.</p> | |
</div> | |
<div id="image-view"> | |
<div id='results'> | |
</div> | |
</div> | |
<div id="source"><a href="https://gist.github.com/4446741">View Source</a></div> | |
<script type="text/javascript"> | |
function compareColor(a, b) { | |
if (a.count > b.count) { | |
return -1; | |
} else { | |
return 1; | |
} | |
}; | |
//Define pixel | |
//Pixel represents a single pixel from an image | |
function Pixel(r, g, b) { | |
this.r = parseInt(r); | |
this.g = parseInt(g); | |
this.b = parseInt(b); | |
this.count = 1; //If created, there is at least one instance | |
}; | |
//css format RGB | |
Pixel.prototype.cssRGB = function() { | |
return 'rgb('+this.r+', '+this.g+', '+this.b+')'; | |
}; | |
//convert to a ColorLChab object | |
Pixel.prototype.toLChab = function() { | |
return new ColorRGB(this.r / 255, this.g / 255, this.b / 255).toLinearRGB().toXYZ().toLab().toLChab() | |
}; | |
//Define SelectedImage | |
function SelectedImage(file) { | |
this.file = file; | |
this.imageData; | |
this.image; | |
this.primaryColor; | |
this.secondaryColor; | |
this.delta; | |
}; | |
//read the file | |
SelectedImage.prototype.readFile = function() { | |
var reader = new FileReader(); | |
reader.onload = (function(selectedImage) { | |
return function(e) { | |
selectedImage.imageData = e.target.result; | |
selectedImage.findDominantColors(); | |
}; | |
})(this); | |
reader.readAsDataURL(this.file); | |
}; | |
//find the dominant colors | |
SelectedImage.prototype.findDominantColors = function() { | |
var image = new Image(); | |
image.src = this.imageData; | |
image.style.maxWidth = "100%"; | |
image.onload = (function(selectedImage) { | |
//we need to wait for the image to load to get the dimensions | |
return function(e) { | |
selectedImage.image = e.target | |
var canvasObject = document.createElement('canvas'); | |
canvasObject.width = selectedImage.image.width; | |
canvasObject.height = selectedImage.image.height; | |
var ctx = canvasObject.getContext('2d'); | |
ctx.drawImage(selectedImage.image, 0, 0); | |
var imagePixels = ctx.getImageData(0,0, selectedImage.image.width, selectedImage.image.height); | |
var dominatColorTable = new Object(); | |
for(var i = 0; i < imagePixels.data.length; i+=4) { | |
if (imagePixels.data[i+3] != 0) { | |
//the pixel isn't transparent | |
var pixel = new Pixel(imagePixels.data[i], imagePixels.data[i+1], imagePixels.data[i+2]); | |
var pixelString = ''+imagePixels.data[i]+','+imagePixels.data[i+1]+','+imagePixels.data[i+2]; | |
if (dominatColorTable[pixelString]) {dominatColorTable[pixelString].count++} else {dominatColorTable[pixelString] = pixel}; | |
} else { | |
//pixel is transparent | |
}; | |
}; | |
colorTableArray = new Array(); | |
for(color in dominatColorTable) {colorTableArray.push(dominatColorTable[color])}; | |
colorTableArray.sort(compareColor); | |
//Need to group colors | |
var primaryColor = colorTableArray[0]; | |
var secondaryColor; | |
var secondaryLChab; | |
var delta; | |
var primaryLChab = primaryColor.toLChab(); | |
//Find the next primary color that is substantially different parseInt() | |
for (var i = 1; i < colorTableArray.length; i++) { | |
secondaryColor = colorTableArray[i]; | |
secondaryLChab = secondaryColor.toLChab(); | |
delta = deltaE2000(primaryLChab, secondaryLChab).toFixed(2); | |
if (delta > 17) break; //This determines how big the difference in colors needs to be (lower is more similar) | |
}; | |
selectedImage.primaryColor = primaryColor; | |
selectedImage.secondaryColor = secondaryColor; | |
selectedImage.delta = delta; | |
showDominantColor(selectedImage); | |
} | |
})(this); | |
}; | |
function showDominantColor(selectedImage) { | |
var wrapper = document.createElement('div'); | |
wrapper.className = "wrapper"; | |
wrapper.appendChild(selectedImage.image); | |
var p = document.createElement('p'); | |
// console.log(selectedImage); | |
p.innerHTML = 'Filename: ' + selectedImage.file.name + '<br>Filesize: ' + selectedImage.file.size + '<br>Type: ' + selectedImage.file.type + '<br>Primary Color: ' + selectedImage.primaryColor.cssRGB() + '<br>Secondary Color: ' + selectedImage.secondaryColor.cssRGB() + '<br>Distance Between Colors: ' + selectedImage.delta; | |
p.style.color = selectedImage.primaryColor.cssRGB(); | |
wrapper.style.backgroundColor = selectedImage.secondaryColor.cssRGB(); | |
wrapper.style.borderColor = selectedImage.primaryColor.cssRGB(); | |
wrapper.appendChild(p); | |
document.getElementById('results').appendChild(wrapper); | |
} | |
function handleDragOver(event) { | |
event.stopPropagation(); | |
event.preventDefault(); | |
event.dataTransfer.dropEffect = 'copy'; | |
}; | |
function handleFileSelect(event) { | |
event.stopPropagation(); | |
event.preventDefault(); | |
var files; | |
if (event.type == "drop") { | |
//The file was dropped | |
console.log("File was dropped"); | |
files = event.dataTransfer.files; | |
} else if (event.type == "change") { | |
//The input was selected | |
console.log("File was selected via the input"); | |
files = event.target.files; | |
}; | |
for (var i = 0; files.length > i; i++) { | |
var file = files[i]; | |
if (file.type.match('image.*')) { | |
//the file is an image, so let's continue processing | |
var selectedImage = new SelectedImage(file) | |
selectedImage.readFile(); | |
} | |
}; | |
}; | |
function listenForFiles() { | |
var dropZone = document.getElementById('drop-zone'); | |
var fileInput = document.getElementById('file-input'); | |
//listen for the drag and drop events | |
dropZone.addEventListener('dragover', handleDragOver, false); | |
dropZone.addEventListener('drop', handleFileSelect, false); | |
//listen for the input change event | |
fileInput.addEventListener('change', handleFileSelect, false); | |
}; | |
if (window.File && window.FileReader && window.FileList && window.Blob) { | |
//The demo is supported by the browser, show the drop zone and continue with magic | |
document.getElementById('browser-not-supported').style.display = "none"; | |
document.getElementById('drop-zone').style.display = "block"; | |
listenForFiles(); | |
}; | |
/* | |
Color conversions | |
Copyright (c) 2011, Cory Nelson ([email protected]) | |
All rights reserved. | |
Redistribution and use in source and binary forms, with or without | |
modification, are permitted provided that the following conditions are met: | |
* Redistributions of source code must retain the above copyright | |
notice, this list of conditions and the following disclaimer. | |
* Redistributions in binary form must reproduce the above copyright | |
notice, this list of conditions and the following disclaimer in the | |
documentation and/or other materials provided with the distribution. | |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY | |
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
When possible, constants are given as accurate pre-computed rationals. When not, | |
they are given at double precision with a comment on how to compute them. | |
*/ | |
// http://svn.int64.org/viewvc/int64/colors/colors.js | |
function clamp(x, min, max) | |
{ | |
if(x < min) return min; | |
if(x > max) return max; | |
return x; | |
} | |
function clamphue(hue) | |
{ | |
hue %= Math.PI * 2; | |
if(hue < 0) | |
{ | |
hue += Math.PI * 2; | |
} | |
return hue; | |
} | |
function ColorLShuv(L, S, h, clamped) | |
{ | |
this.clamped = clamped || L < 0 || L > 100; // TODO: what is S min/max? | |
this.L = clamp(L, 0, 100); | |
this.S = S; | |
this.h = clamphue(h); | |
this.toLChuv = function() | |
{ | |
return new ColorLChuv(this.L, this.S * this.L, this.h); | |
}; | |
} | |
function ColorLChuv(L, C, h, clamped) | |
{ | |
this.clamped = clamped || L < 0 || L > 100 || C < 0 || C > 7.40066582332174237e2; | |
this.L = clamp(L, 0, 100); | |
this.C = clamp(C, 0, 7.40066582332174237e2); // 240/316141*sqrt(950343809713) | |
this.h = clamphue(h); | |
this.toLShuv = function() | |
{ | |
return new ColorLShuv(this.L, this.C / this.L, this.h, this.clamped); | |
}; | |
this.toLuv = function() | |
{ | |
var h = clamphue(this.h); | |
return new ColorLuv(this.L, Math.cos(h) * this.C, Math.sin(h) * this.C, this.clamped); | |
}; | |
} | |
function ColorLuv(L, u, v, clamped) | |
{ | |
this.clamped = clamped || L < 0 || L > 100 || u < -81304600/316141 || v > 54113280/316141; // TODO: what is u max, and v min?? | |
this.L = clamp(L, 0, 100); | |
this.u = (u < -81304600/316141) ? -81304600/316141 : u; | |
this.v = (v > 54113280/316141) ? 54113280/316141 : v; | |
this.toLChuv = function() | |
{ | |
return new ColorLChuv( | |
this.L, | |
Math.sqrt(this.u * this.u + this.v * this.v), | |
Math.atan2(this.v, this.u), | |
this.clamped); | |
}; | |
this.toXYZ = function() | |
{ | |
var rdiv = Color.refX + Color.refY * 15 + Color.refZ * 3; | |
var ur = Color.refX * 4 / rdiv; | |
var vr = Color.refY * 9 / rdiv; | |
if(L > 8) | |
{ | |
var Y = (this.L + 16) / 116; | |
Y = Y * Y * Y; | |
} | |
else | |
{ | |
var Y = this.L * (27/24389); | |
} | |
var a = (this.L * 52 / (this.u + this.L * 13 * ur) - 1) / 3; | |
var b = -5 * Y; | |
var d = (this.L * 39 / (this.v + this.L * 13 * vr) - 5) * Y; | |
var X = (d - b) / (a + 1/3); | |
var Z = X * a + b; | |
return new ColorXYZ(X, Y, Z, this.clamped); | |
}; | |
} | |
function ColorLChab(L, C, h, clamped) | |
{ | |
this.clamped = clamped || L < 0 || L > 100 || C < 0 || C > 4.64238345442629658e2; | |
this.L = clamp(L, 0, 100); | |
this.C = clamp(C, 0, 4.64238345442629658e2); // 2500*sqrt(1/29) | |
this.h = clamphue(h); | |
this.toLab = function() | |
{ | |
var h = clamphue(this.h); | |
return new ColorLab(this.L, Math.cos(h) * this.C, Math.sin(h) * this.C, this.clamped); | |
}; | |
} | |
function ColorLab(L, a, b, clamped) | |
{ | |
this.clamped = clamped || L < 0 || L > 100 || a < -12500/29 || a > 12500/29 || b < -5000/29 || b > 5000/29; | |
this.L = clamp(L, 0, 100); | |
this.a = clamp(a, -12500/29, 12500/29); | |
this.b = clamp(b, -5000/29, 5000/29); | |
this.toXYZ = function() | |
{ | |
function toXYZc(c) | |
{ | |
var c3 = c * c * c; | |
if(c3 > 216 / 24389) return c3; | |
return c * (108/841) - (432/24389); | |
} | |
var Y = (this.L + 16) / 116; | |
return new ColorXYZ( | |
toXYZc(Y + this.a / 500) * Color.refX, | |
toXYZc(Y) * Color.refY, | |
toXYZc(Y - this.b / 200) * Color.refZ, | |
this.clamped); | |
}; | |
this.toLChab = function() | |
{ | |
return new ColorLChab( | |
this.L, | |
Math.sqrt(this.a * this.a + this.b * this.b), | |
Math.atan2(this.b, this.a), | |
this.clamped); | |
}; | |
} | |
function ColorxyY(x, y, Y, clamped) | |
{ | |
this.clamped = clamped || x < 0 || x > 1 || y < 0 || y > 1 || Y < 0 || Y > 1; | |
this.x = clamp(x, 0, 1); | |
this.y = clamp(y, 0, 1); | |
this.Y = clamp(Y, 0, 1); | |
this.toXYZ = function() | |
{ | |
if(Math.abs(this.y) != 0) | |
{ | |
var mul = this.Y / this.y; | |
return new ColorXYZ(this.x * mul, this.Y, (1 - this.x - this.y) * mul); | |
} | |
else | |
{ | |
return new ColorXYZ(0, 0, 0); | |
} | |
}; | |
} | |
function ColorXYZ(X, Y, Z, clamped) | |
{ | |
this.clamped = clamped || X < 0 || X > Color.refX || Y < 0 || Y > Color.refY || Z < 0 || Z > Color.refZ; | |
this.X = clamp(X, 0, Color.refX); | |
this.Y = clamp(Y, 0, Color.refY); | |
this.Z = clamp(Z, 0, Color.refZ); | |
this.toLinearRGB = function() | |
{ | |
return new ColorLinearRGB( | |
this.X * (641589/197960) + this.Y * (-608687/395920) + this.Z * (-49353/98980), | |
this.X * (-42591639/43944050) + this.Y * (82435961/43944050) + this.Z * (1826061/43944050), | |
this.X * (49353/887015) + this.Y * (-180961/887015) + this.Z * (49353/46685), | |
this.clamped); | |
}; | |
this.toxyY = function() | |
{ | |
var div = this.X + this.Y + this.Z; | |
if(Math.abs(div) == 0) | |
{ | |
div = 1; | |
} | |
return new ColorxyY(this.X / div, this.Y / div, this.Y, this.clamped); | |
}; | |
this.toLab = function() | |
{ | |
function toLabc(c) | |
{ | |
if (c > 216 / 24389) return Math.pow(c, 1 / 3); | |
return c * (841 / 108) + (4 / 49); | |
} | |
var X = toLabc(this.X / Color.refX); | |
var Y = toLabc(this.Y / Color.refY); | |
var Z = toLabc(this.Z / Color.refZ); | |
return new ColorLab(116 * Y - 16, 500 * (X - Y), 200 * (Y - Z), this.clamped); | |
}; | |
this.toLuv = function() | |
{ | |
var rdiv = Color.refX + Color.refY * 15 + Color.refZ * 3; | |
var ur = Color.refX * 4 / rdiv; | |
var vr = Color.refY * 9 / rdiv; | |
var div = this.X + this.Y * 15 + this.Z * 3; | |
if(Math.abs(div) == 0) | |
{ | |
div = 1; | |
} | |
var u = this.X * 4 / div; | |
var v = this.Y * 9 / div; | |
var yr = this.Y / Color.refY; | |
if(yr > 216/24389) | |
{ | |
var L = Math.pow(yr, 1 / 3) * 116 - 16; | |
} | |
else | |
{ | |
var L = yr * (24389/27); | |
} | |
return new ColorLuv(L, L * 13 * (u - ur), L * 13 * (v - vr), this.clamped); | |
}; | |
} | |
function ColorLinearRGB(R, G, B, clamped) | |
{ | |
this.clamped = clamped || R < 0 || R > 1 || G < 0 || G > 1 || B < 0 || B > 1; | |
this.R = clamp(R, 0, 1); | |
this.G = clamp(G, 0, 1); | |
this.B = clamp(B, 0, 1); | |
this.toRGB = function() | |
{ | |
function toRGBc(c) | |
{ | |
if(c > 0.0031308) return Math.pow(c, 1 / 2.4) * 1.055 - 0.055; | |
return c * 12.92; | |
} | |
return new ColorRGB(toRGBc(this.R), toRGBc(this.G), toRGBc(this.B), this.clamped); | |
}; | |
this.toXYZ = function() | |
{ | |
return new ColorXYZ( | |
this.R * (5067776/12288897) + this.G * (4394405/12288897) + this.B * (4435075/24577794), | |
this.R * (871024/4096299) + this.G * (8788810/12288897) + this.B * (887015/12288897), | |
this.R * (79184/4096299) + this.G * (4394405/36866691) + this.B * (70074185/73733382), | |
this.clamped); | |
}; | |
} | |
function ColorHSV(H, S, V, clamped) | |
{ | |
this.clamped = clamped || S < 0 || S > 1 || V < 0 || V > 1; | |
this.H = clamphue(H); | |
this.S = clamp(S, 0, 1); | |
this.V = clamp(V, 0, 1); | |
this.toRGB = function() | |
{ | |
if(this.S <= 0) | |
{ | |
return new ColorRGB(this.V, this.V, this.V, this.clamped); | |
} | |
var H = clamphue(this.H) / 60; | |
var C = this.V * this.S; | |
var m = this.V - C; | |
var X = C * (1 - Math.abs(H % 2 - 1)) + m; | |
C += m; | |
if(H >= 5) return new ColorRGB(C, m, X, this.clamped); | |
if(H >= 4) return new ColorRGB(X, m, C, this.clamped); | |
if(H >= 3) return new ColorRGB(m, X, C, this.clamped); | |
if(H >= 2) return new ColorRGB(m, C, X, this.clamped); | |
if(H >= 1) return new ColorRGB(X, C, m, this.clamped); | |
return new ColorRGB(C, X, m, this.clamped); | |
}; | |
} | |
function ColorHSL(H, S, L, clamped) | |
{ | |
this.clamped = clamped || S < 0 || S > 1 || L < 0 || L > 1; | |
this.H = clamphue(H); | |
this.S = clamp(S, 0, 1); | |
this.L = clamp(L, 0, 1); | |
this.toRGB = function() | |
{ | |
if(this.S <= 0) | |
{ | |
return new ColorRGB(this.S, this.S, this.S, this.clamped); | |
} | |
var H = clamphue(this.H) / 60; | |
var C = (1 - Math.abs(this.L * 2 - 1)) * this.S; | |
var m = this.L - C * 0.5; | |
var X = C * (1 - Math.abs(H % 2 - 1)) + m; | |
C += m; | |
if(H >= 5) return new ColorRGB(C, m, X, this.clamped); | |
if(H >= 4) return new ColorRGB(X, m, C, this.clamped); | |
if(H >= 3) return new ColorRGB(m, X, C, this.clamped); | |
if(H >= 2) return new ColorRGB(m, C, X, this.clamped); | |
if(H >= 1) return new ColorRGB(X, C, m, this.clamped); | |
return new ColorRGB(C, X, m, this.clamped); | |
}; | |
} | |
function ColorRGB(R, G, B, clamped) | |
{ | |
this.clamped = clamped || R < 0 || R > 1 || G < 0 || G > 1 || B < 0 || B > 1; | |
this.R = clamp(R, 0, 1); | |
this.G = clamp(G, 0, 1); | |
this.B = clamp(B, 0, 1); | |
this.toHSV = function() | |
{ | |
var min = Math.min(this.R, this.G, this.B); | |
var max = Math.max(this.R, this.G, this.B); | |
var delta = max - min; | |
if(Math.abs(delta) != 0) | |
{ | |
var S = delta / max; | |
if(max == this.R) var H = (this.G - this.B) / delta; | |
else if(max == this.G) var H = (this.B - this.R) / delta + 2; | |
else var H = (this.R - this.G) / delta + 4; | |
} | |
else | |
{ | |
var H = 0; | |
var S = 0; | |
} | |
return new ColorHSV(H * 60, S, max, this.clamped); | |
}; | |
this.toHSL = function() | |
{ | |
var min = Math.min(this.R, this.G, this.B); | |
var max = Math.max(this.R, this.G, this.B); | |
var delta = max - min; | |
var L = (max + min) * 0.5; | |
if(Math.abs(delta) != 0) | |
{ | |
if(L < 0.5) var S = delta / (max + min); | |
else var S = delta / (2 - max - min); | |
if(max == this.R) var H = (this.G - this.B) / delta; | |
else if(max == this.G) var H = (this.B - this.R) / delta + 2; | |
else var H = (this.R - this.G) / delta + 4; | |
} | |
else | |
{ | |
var H = 0; | |
var S = 0; | |
} | |
return new ColorHSL(H * 60, S, L, this.clamped); | |
}; | |
this.toLinearRGB = function() | |
{ | |
function toLinearRGBc(c) | |
{ | |
if(c > 0.04045) return Math.pow((c + 0.055) / 1.055, 2.4); | |
return c / 12.92; | |
} | |
return new ColorLinearRGB(toLinearRGBc(this.R), toLinearRGBc(this.G), toLinearRGBc(this.B), this.clamped); | |
}; | |
this.toYUV = function() | |
{ | |
var mat = Color.yuvmatrix; | |
var y = this.R * mat.rScale + this.G * mat.gScale + this.B * mat.bScale; | |
var u = (this.B - y) / (1 - mat.bScale) * 0.5 + 0.5; | |
var v = (this.R - y) / (1 - mat.rScale) * 0.5 + 0.5; | |
return new ColorYUV(y, u, v, this.clamped); | |
}; | |
this.toYIQ = function() | |
{ | |
return new ColorYIQ( | |
this.R * 0.299 + this.G * 0.587 + this.B * 0.114, | |
this.R * 0.5 + this.G * -0.23038159508364756 + this.B * -0.26961840491635244 + 0.5, | |
this.R * -0.202349432337541121 + this.G * 0.5 + this.B * -0.297650567662458879 + 0.5, | |
this.clamped); | |
}; | |
} | |
function ColorYUV(Y, U, V, clamped) | |
{ | |
this.clamped = clamped || Y < 0 || Y > 1 || U < 0 || V > 1 || V < 0 || V > 1; | |
this.Y = clamp(Y, 0, 1); | |
this.U = clamp(U, 0, 1); | |
this.V = clamp(V, 0, 1); | |
this.toRGB = function() | |
{ | |
var mat = Color.yuvmatrix; | |
var u = (this.U - 0.5) / 0.5 * (1 - mat.bScale); | |
var v = (this.V - 0.5) / 0.5 * (1 - mat.rScale); | |
var r = v + this.Y; | |
var b = u + this.Y; | |
var g = (this.Y - r * mat.rScale - b * mat.bScale) / mat.gScale; | |
return new ColorRGB(r, g, b, this.clamped); | |
}; | |
} | |
function ColorYIQ(Y, I, Q, clamped) | |
{ | |
this.clamped = clamped || Y < 0 || Y > 1 || I < 0 || I > 1 || Q < 0 || Q > 1; | |
this.Y = clamp(Y, 0, 1); | |
this.I = clamp(I, 0, 1); | |
this.Q = clamp(Q, 0, 1); | |
this.toRGB = function() | |
{ | |
var i = this.I - 0.5; | |
var q = this.Q - 0.5; | |
return new ColorRGB( | |
this.Y + i * 1.13933588212202582 - q * 0.649035964281386078, | |
this.Y - i * 0.32416610079155499 + q * 0.676636193255190191, | |
this.Y - i * 1.31908708412142932 - q * 1.78178677298826495, | |
this.clamped); | |
}; | |
} | |
// CIE Delta E 1976 | |
// JND: ~2.3 | |
function deltaE1976(lab1, lab2) | |
{ | |
var delta_L = lab1.L - lab2.L; | |
var delta_a = lab1.a - lab2.a; | |
var delta_b = lab1.b - lab2.b; | |
return Math.sqrt(delta_L * delta_L + delta_a * delta_a + delta_b * delta_b); | |
} | |
// CIE Delta E 1994 | |
function deltaE1994(lab1, lab2, type) | |
{ | |
var C1 = Math.sqrt(lab1.a * lab1.a + lab1.b * lab1.b); | |
var C2 = Math.sqrt(lab2.a * lab2.a + lab2.b * lab2.b); | |
var delta_L = lab1.L - lab2.L; | |
var delta_C = C1 - C2; | |
var delta_a = lab1.a - lab2.a; | |
var delta_b = lab1.b - lab2.b; | |
var delta_H = Math.sqrt(delta_a * delta_a + delta_b * delta_b - delta_C * delta_C); | |
if(type == 'graphic arts') | |
{ | |
delta_C /= C1 * 0.045 + 1; | |
delta_H /= C1 * 0.015 + 1; | |
} | |
else if(type == 'textiles') | |
{ | |
delta_L *= 0.5; | |
delta_C /= C1 * 0.048 + 1; | |
delta_H /= C1 * 0.014 + 1; | |
} | |
return Math.sqrt(delta_L * delta_L + delta_C * delta_C + delta_H * delta_H); | |
} | |
// CIE Delta E 2000 | |
// Note: maximum is about 158 for colors in the sRGB gamut. | |
function deltaE2000(lch1, lch2) | |
{ | |
var avg_L = (lch1.L + lch2.L) * 0.5; | |
var delta_L = lch2.L - lch1.L; | |
var avg_C = (lch1.C + lch2.C) * 0.5; | |
var delta_C = lch1.C - lch2.C; | |
var avg_H = (lch1.h + lch2.h) * 0.5; | |
if(Math.abs(lch1.h - lch2.h) > Math.PI) | |
{ | |
avg_H += Math.PI; | |
} | |
var delta_H = lch2.h - lch1.h; | |
if(Math.abs(delta_H) > Math.PI) | |
{ | |
if(lch2.h <= lch1.h) delta_H += Math.PI * 2; | |
else delta_H -= Math.PI * 2; | |
} | |
delta_H = Math.sqrt(lch1.C * lch2.C) * Math.sin(delta_H) * 2; | |
var T = 1 | |
- 0.17 * Math.cos(avg_H - Math.PI / 6) | |
+ 0.24 * Math.cos(avg_H * 2) | |
+ 0.32 * Math.cos(avg_H * 3 + Math.PI / 30) | |
- 0.20 * Math.cos(avg_H * 4 - Math.PI * 7/20); | |
var SL = avg_L - 50; | |
SL *= SL; | |
SL = SL * 0.015 / Math.sqrt(SL + 20) + 1; | |
var SC = avg_C * 0.045 + 1; | |
var SH = avg_C * T * 0.015 + 1; | |
var delta_Theta = avg_H / 25 - Math.PI * 11/180; | |
delta_Theta = Math.exp(delta_Theta * -delta_Theta) * (Math.PI / 6); | |
var RT = Math.pow(avg_C, 7); | |
RT = Math.sqrt(RT / (RT + 6103515625)) * Math.sin(delta_Theta) * -2; // 6103515625 = 25^7 | |
delta_L /= SL; | |
delta_C /= SC; | |
delta_H /= SH; | |
return Math.sqrt(delta_L * delta_L + delta_C * delta_C + delta_H * delta_H + RT * delta_C * delta_H); | |
} | |
var Color = | |
{ | |
refX: 31271/32902, // normalized standard observer D65. | |
refY: 1, | |
refZ: 35827/32902, | |
yuvmatrices: | |
{ | |
'bt601': | |
{ | |
name: 'ITU-R BT.601 (DVD, JPEG, Youtube)', | |
rScale: 0.299, | |
gScale: 0.587, | |
bScale: 0.114 | |
}, | |
'bt709': | |
{ | |
name: 'ITU-R BT.709 (HDTV)', | |
rScale: 0.2125, | |
gScale: 0.7154, | |
bScale: 0.0721 | |
}, | |
'smpte240m': | |
{ | |
name: 'SMPTE 240M (very old HDTV)', | |
rScale: 0.212, | |
gScale: 0.701, | |
bScale: 0.087 | |
}, | |
'fcc': | |
{ | |
name: 'FCC', | |
rScale: 0.3, | |
gScale: 0.59, | |
bScale: 0.11 | |
} | |
}, | |
colorspaces: | |
{ | |
'rgb': | |
{ | |
name: 'RGB', | |
components: ['Red', 'Green', 'Blue'], | |
componentInfo: | |
[ | |
{ minimum: 0, maximum: 1, scale: 255 }, | |
{ minimum: 0, maximum: 1, scale: 255 }, | |
{ minimum: 0, maximum: 1, scale: 255 } | |
], | |
toColor: function(x) { return new ColorRGB(x[0], x[1], x[2]); }, | |
toGeneric: function(x) { return [ x.R, x.G, x.B ]; }, | |
conversions: | |
{ | |
'hsl': function(x) { return x.toHSL(); }, | |
'hsv': function(x) { return x.toHSV(); }, | |
'yuv': function(x) { return x.toYUV(); }, | |
'yiq': function(x) { return x.toYIQ(); }, | |
'linear_rgb': function(x) { return x.toLinearRGB(); } | |
} | |
}, | |
'linear_rgb': | |
{ | |
name: 'Linear RGB', | |
components: ['Red', 'Green', 'Blue'], | |
componentInfo: | |
[ | |
{ minimum: 0, maximum: 1, scale: 1023 }, | |
{ minimum: 0, maximum: 1, scale: 1023 }, | |
{ minimum: 0, maximum: 1, scale: 1023 } | |
], | |
toColor: function(x) { return new ColorLinearRGB(x[0], x[1], x[2]); }, | |
toGeneric: function(x) { return [ x.R, x.G, x.B ]; }, | |
conversions: | |
{ | |
'rgb': function(x) { return x.toRGB(); }, | |
'xyz': function(x) { return x.toXYZ(); }, | |
} | |
}, | |
'hsl': | |
{ | |
name: 'HSL', | |
components: ['Hue', 'Saturation', 'Lightness'], | |
componentInfo: | |
[ | |
{ minimum: 0, maximum: 359, scale: 1 }, | |
{ minimum: 0, maximum: 1, scale: 255 }, | |
{ minimum: 0, maximum: 1, scale: 255 } | |
], | |
toColor: function(x) { return new ColorHSL(x[0], x[1], x[2]); }, | |
toGeneric: function(x) { return [ x.H, x.S, x.L ]; }, | |
conversions: | |
{ | |
'rgb': function(x) { return x.toRGB(); } | |
} | |
}, | |
'hsv': | |
{ | |
name: 'HSV', | |
components: ['Hue', 'Saturation', 'Value'], | |
componentInfo: | |
[ | |
{ minimum: 0, maximum: 359, scale: 1 }, | |
{ minimum: 0, maximum: 1, scale: 255 }, | |
{ minimum: 0, maximum: 1, scale: 255 } | |
], | |
toColor: function(x) { return new ColorHSV(x[0], x[1], x[2]); }, | |
toGeneric: function(x) { return [ x.H, x.S, x.V ]; }, | |
conversions: | |
{ | |
'rgb': function(x) { return x.toRGB(); } | |
} | |
}, | |
'yuv': | |
{ | |
name: 'Y′UV', | |
components: ['Luma', 'Chroma U', 'Chroma V'], | |
componentInfo: | |
[ | |
{ minimum: 0, maximum: 1, scale: 255 }, | |
{ minimum: 0, maximum: 1, scale: 255 }, | |
{ minimum: 0, maximum: 1, scale: 255 } | |
], | |
toColor: function(x) { return new ColorYUV(x[0], x[1], x[2]); }, | |
toGeneric: function(x) { return [ x.Y, x.U, x.V ]; }, | |
conversions: | |
{ | |
'rgb': function(x) { return x.toRGB(); } | |
} | |
}, | |
'yiq': | |
{ | |
name: 'Y′IQ', | |
components: ['Luma', 'Chroma I', 'Chroma Q'], | |
componentInfo: | |
[ | |
{ minimum: 0, maximum: 1, scale: 255 }, | |
{ minimum: 0, maximum: 1, scale: 255 }, | |
{ minimum: 0, maximum: 1, scale: 255 } | |
], | |
toColor: function(x) { return new ColorYIQ(x[0], x[1], x[2]); }, | |
toGeneric: function(x) { return [ x.Y, x.I, x.Q ]; }, | |
conversions: | |
{ | |
'rgb': function(x) { return x.toRGB(); } | |
} | |
}, | |
'xyy': | |
{ | |
name: 'CIE xyY', | |
components: ['x', 'y', 'Y'], | |
componentInfo: | |
[ | |
{ minimum: 0, maximum: 1, scale: 100 }, | |
{ minimum: 0, maximum: 1, scale: 100 }, | |
{ minimum: 0, maximum: 1, scale: 100 } | |
], | |
toColor: function(x) { return new ColorxyY(x[0], x[1], x[2]); }, | |
toGeneric: function(x) { return [ x.x, x.y, x.Y ]; }, | |
conversions: | |
{ | |
'xyz': function(x) { return x.toXYZ(); } | |
} | |
}, | |
'xyz': | |
{ | |
name: 'CIE XYZ', | |
components: ['X', 'Y', 'Z'], | |
componentInfo: | |
[ | |
{ minimum: 0, maximum: 0.9505, scale: 100 }, | |
{ minimum: 0, maximum: 1, scale: 100 }, | |
{ minimum: 0, maximum: 1.089, scale: 100 } | |
], | |
toColor: function(x) { return new ColorXYZ(x[0], x[1], x[2]); }, | |
toGeneric: function(x) { return [ x.X, x.Y, x.Z ]; }, | |
conversions: | |
{ | |
'linear_rgb': function(x) { return x.toLinearRGB(); }, | |
'lab': function(x) { return x.toLab(); }, | |
'luv': function(x) { return x.toLuv(); }, | |
'xyy': function(x) { return x.toxyY(); } | |
} | |
}, | |
'lab': | |
{ | |
name: 'CIE L*a*b*', | |
components: ['Lightness', 'a', 'b'], | |
componentInfo: | |
[ | |
{ minimum: 0, maximum: 100, scale: 1 }, | |
{ minimum: -12500/29, maximum: 12500/29, scale: 1 }, | |
{ minimum: -5000/29, maximum: 5000/29, scale: 1 } | |
], | |
toColor: function(x) { return new ColorLab(x[0], x[1], x[2]); }, | |
toGeneric: function(x) { return [ x.L, x.a, x.b ]; }, | |
conversions: | |
{ | |
'xyz': function(x) { return x.toXYZ(); }, | |
'LChab': function(x) { return x.toLChab(); } | |
} | |
}, | |
'LChab': | |
{ | |
name: function(c) | |
{ | |
c.appendChild(document.createTextNode('CIE L*C*h')); | |
var sub = document.createElement('sub'); | |
sub.appendChild(document.createTextNode('ab')); | |
c.appendChild(sub); | |
}, | |
components: ['Lightness', 'Chroma', 'Hue'], | |
componentInfo: | |
[ | |
{ minimum: 0, maximum: 100, scale: 1 }, | |
{ minimum: 0, maximum: 4.64238345442629658e2, scale: 1 }, | |
{ minimum: 0, maximum: Math.PI*2, scale: 180/Math.PI } | |
], | |
toColor: function(x) { return new ColorLChab(x[0], x[1], x[2]); }, | |
toGeneric: function(x) { return [ x.L, x.C, x.h ]; }, | |
conversions: | |
{ | |
'lab': function(x) { return x.toLab(); } | |
} | |
}, | |
'luv': | |
{ | |
name: 'CIE L*u*v*', | |
components: ['Lightness', 'u', 'v'], | |
componentInfo: | |
[ | |
{ minimum: 0, maximum: 100, scale: 1 }, | |
{ minimum: -81304600/316141, maximum: 720, scale: 1 }, | |
{ minimum: -160, maximum: 54113280/316141, scale: 1 } | |
], | |
toColor: function(x) { return new ColorLuv(x[0], x[1], x[2]); }, | |
toGeneric: function(x) { return [ x.L, x.u, x.v ]; }, | |
conversions: | |
{ | |
'xyz': function(x) { return x.toXYZ(); }, | |
'LChuv': function(x) { return x.toLChuv(); } | |
} | |
}, | |
'LChuv': | |
{ | |
name: function(c) | |
{ | |
c.appendChild(document.createTextNode('CIE L*C*h')); | |
var sub = document.createElement('sub'); | |
sub.appendChild(document.createTextNode('uv')); | |
c.appendChild(sub); | |
}, | |
components: ['Lightness', 'Chroma', 'Hue'], | |
componentInfo: | |
[ | |
{ minimum: 0, maximum: 100, scale: 1 }, | |
{ minimum: 0, maximum: 7.40066582332174237e2, scale: 1 }, | |
{ minimum: 0, maximum: Math.PI*2, scale: 180/Math.PI } | |
], | |
toColor: function(x) { return new ColorLChuv(x[0], x[1], x[2]); }, | |
toGeneric: function(x) { return [ x.L, x.C, x.h ]; }, | |
conversions: | |
{ | |
'luv': function(x) { return x.toLuv(); }, | |
'lshuv': function(x) { return x.toLShuv(); } | |
} | |
}, | |
'lshuv': | |
{ | |
name: function(c) | |
{ | |
c.appendChild(document.createTextNode('CIE L*Sh')); | |
var sub = document.createElement('sub'); | |
sub.appendChild(document.createTextNode('uv')); | |
c.appendChild(sub); | |
}, | |
components: ['Lightness', 'Saturation', 'Hue'], | |
componentInfo: | |
[ | |
{ minimum: 0, maximum: 100, scale: 1 }, | |
{ minimum: 0, maximum: 4.5, scale: 25 }, | |
{ minimum: 0, maximum: Math.PI*2, scale: 180/Math.PI } | |
], | |
toColor: function(x) { return new ColorLShuv(x[0], x[1], x[2]); }, | |
toGeneric: function(x) { return [ x.L, x.S, x.h ]; }, | |
conversions: | |
{ | |
'LChuv': function(x) { return x.toLChuv(); } | |
} | |
} | |
} | |
}; | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment