Commit 9125ed31 authored by Benjamin Schudel's avatar Benjamin Schudel
Browse files

feat: first draft of image upload

parent 7107f88d
Pipeline #35061 passed with stage
in 1 minute and 42 seconds
......@@ -40,5 +40,6 @@ module.exports = {
'no-multi-spaces': 0,
'no-named-as-default-member': 0,
'arrow-parens': 0,
'prefer-template': 0,
}
}
......@@ -38,4 +38,9 @@ export default [
path: '/gradients',
redirect: '/gradients/new',
},
{
name: 'upload',
path: '/upload',
component: views.UploadView,
},
];
/* globals document, Image */
export default class ImagePalette {
constructor() {
this.canvas = document.createElement('canvas');
}
get width() {
return this.canvas.width;
}
get height() {
return this.canvas.height;
}
get ctx() {
return this.canvas.getContext('2d');
}
get imageData() {
return this.ctx.getImageData(0, 0, this.width, this.height);
}
async get(data) {
await this.loadDataIntoCanvas(data);
return this.extractColors();
}
loadDataIntoCanvas(data) {
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => {
this.ctx.drawImage(image, 0, 0);
resolve();
};
image.onerror = (e) => {
reject(e);
};
image.src = data;
});
}
extractColors() {
const { data } = this.imageData;
const colors = [];
const map = [];
for (let i = 0, n = data.length; i < n; i += 4) {
const [r, g, b, a] = data.slice(i, i + 4);
const color = { r, g, b, a };
const hexa = this.constructor.toHexa(r, g, b, a);
const index = map.indexOf(hexa);
if (index > -1) {
colors[index].count++;
} else {
colors.push({
rgba: color,
hexa,
count: 1,
});
map.push(hexa);
}
}
return colors;
}
static toHexa(r, g, b, a) {
function reducer(r, v) {
return r + (`0${Number(v).toString(16)}`).slice(-2);
}
return [r, g, b, a].reduce(reducer, '#');
}
}
/*
$('#example').click(function(){
getColors();
});
var colorList = {};
function getColors(){
var canvas = document.getElementById('example');
var context = canvas.getContext('2d');
var imageWidth = canvas.width;
var imageHeight = canvas.height;
var imageData = context.getImageData(0, 0, imageWidth, imageHeight);
var data = imageData.data;
var i, n;
// quickly iterate over all pixels
for(i = 0, n = data.length; i < n; i += 4) {
var r = data[i];
var g = data[i + 1];
var b = data[i + 2];
var hex = rgb2hex("rgb("+r+","+g+","+b+")");
if (!(hex in colorList)){
colorList[hex]=1;
} else {
colorList[hex]++;
}
}
var key;
var keys = Object.keys(colorList);
keys.sort();
var tmpArr = [];
for (i =0; i < keys.length; i++){
hex=keys[i];
tmpArr.push("<li>"+hex+": " + colorList[hex] + "</li>");
}
$('#list').append(tmpArr.join(""));
}
//rgb to hex function
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
*/
......@@ -13,5 +13,8 @@ export default {
}, {
name: '3D Space',
route: 'three',
}, {
name: 'Upload',
route: 'upload',
}],
};
......@@ -2,10 +2,12 @@ import GradientView from './views/GradientView';
import MixerView from './views/MixerView';
import AccessibilityView from './views/AccessibilityView';
import ThreeView from './views/ThreeView';
import UploadView from './views/UploadView';
export default {
GradientView,
MixerView,
AccessibilityView,
ThreeView,
UploadView,
};
<template>
<div class="upload-view">
<picture-input
ref="pictureInput"
width="600"
height="600"
margin="16"
accept="image/jpeg,image/png"
size="10"
:removable="true"
:customStrings="{
upload: '<h1>Bummer!</h1>',
drag: 'Drag a 😺 GIF or GTFO'
}"
@change="onChange"
></picture-input>
<ui-color-palette
name="Colors"
:colors="colors"
readonly
></ui-color-palette>
</div>
</template>
<script>
import PictureInput from 'vue-picture-input';
import ImagePalette from '../scripts/ImagePalette';
export default {
name: 'upload-view',
data() {
return {
colors: [],
};
},
methods: {
getColorPalette(image) {
const ip = new ImagePalette();
ip.get(image)
.then((colors) => {
this.colors = colors.map(({ rgba }) => {
const { r, g, b, a } = rgba;
return {
value: {
r,
g,
b,
a: (1 / 255) * a,
},
};
});
}).catch((e) => {
console.log(e);
});
},
onChange() {
const { image } = this.$refs.pictureInput;
this.getColorPalette(image);
},
},
components: {
PictureInput,
},
};
</script>
<style lang="scss">
@import "../styles/core";
</style>
......@@ -7040,6 +7040,10 @@ vue-loader@^9.9.5:
vue-template-compiler "^2.0.5"
vue-template-es2015-compiler "^1.2.2"
vue-picture-input@^2.1.6:
version "2.1.6"
resolved "https://registry.yarnpkg.com/vue-picture-input/-/vue-picture-input-2.1.6.tgz#6a47af68d19c9122cdd20de980d3b113b0a614be"
vue-router@^2.0.1:
version "2.8.1"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-2.8.1.tgz#9833c9ee57ac83beb0269056fefee71713f20695"
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment