mirror of
https://github.com/Sheldan/canvas.git
synced 2026-03-03 15:27:03 +00:00
circleBs: fixing buttons
clusterFilter: initial version
This commit is contained in:
BIN
clusterFilter/src/example.jpg
Normal file
BIN
clusterFilter/src/example.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 284 KiB |
54
clusterFilter/src/index.html
Normal file
54
clusterFilter/src/index.html
Normal file
@@ -0,0 +1,54 @@
|
||||
<!doctype html>
|
||||
<html class="no-js" lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<title>clusterFilter</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
html, body, div, canvas {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
html, body { width:100%; height:100%; }
|
||||
canvas { display:block; }
|
||||
#clearBtn { left: 0px; }
|
||||
#download { left: 60px; top: 3px; }
|
||||
.controls {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 10px
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="controls">
|
||||
A cluster is a point of color in which the pixels might be concentrated in. <br>
|
||||
<label for="equidistant_cluster">Equally distributed colors (random colors if unchecked)</label>
|
||||
<input type="checkbox" checked="checked" id="equidistant_cluster" onchange="setNewClusterFunction()">
|
||||
<input type="button" onclick="generateClusters()" value="Regenerate image">
|
||||
<br>
|
||||
<select id="fun_select" onchange="setNewFunction()">
|
||||
<option value="1">Every pixel moves to half the distance between it and the cluster</option>
|
||||
<option value="2">Sets the pixels to exactly the cluster color (only the cluster colors)</option>
|
||||
<option value="3">Move the pixels in the direction to the cluster (and maybe over it)</option>
|
||||
</select>
|
||||
<span id="dist_wrapper">
|
||||
<label for="dist_in">Distance to move the pixels</label>
|
||||
<input type="number" id="dist_in" onblur="updateConfig()" min="0">
|
||||
</span>
|
||||
<label for="cluster_in">Amount of clusters (essentially amount of colors, bigger number might crash)</label>
|
||||
<input type="number" id="cluster_in" onblur="updateConfig()" min="0">
|
||||
<br>
|
||||
<label for=img_upload>Change image: (bigger images cause slowdown)</label>
|
||||
<input type="file" onchange="previewFile()" id="img_upload"> <a id="download" onclick="downloadCanvas()">Download</a>
|
||||
<br>
|
||||
</div>
|
||||
<img src="example.jpg" id="src_image">
|
||||
<canvas id="src_canvas" style="display: none"></canvas>
|
||||
<canvas id="final_canvas"></canvas>
|
||||
<script type="module" src="js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
273
clusterFilter/src/js/main.js
Normal file
273
clusterFilter/src/js/main.js
Normal file
@@ -0,0 +1,273 @@
|
||||
import {
|
||||
docReady, getCoordinates, formatInterval, getIndexForCoordinate, downloadCanvasWithoutButton
|
||||
} from "canvas-common";
|
||||
|
||||
|
||||
|
||||
var src_canvas;
|
||||
var final_canvas;
|
||||
var ctx;
|
||||
var final_ctx;
|
||||
var final_imageData;
|
||||
var final_data;
|
||||
var inputFields = {};
|
||||
|
||||
var input_data;
|
||||
|
||||
var config = {
|
||||
size: {
|
||||
width: 640,
|
||||
height: 923
|
||||
},
|
||||
clusterFilter: {
|
||||
dist: 120,
|
||||
fun: halfWayDistance,
|
||||
clusterFun: getEquidistantPoints,
|
||||
clusterAmount: 8,
|
||||
cubeSize: 255
|
||||
}
|
||||
};
|
||||
|
||||
var imageInfo;
|
||||
var clusterCenter;
|
||||
|
||||
function renderImageAndGetData(img, targetContext) {
|
||||
targetContext.drawImage(img, 0, 0);
|
||||
var imgData = targetContext.getImageData(0, 0, config.size.width, config.size.height);
|
||||
return imgData.data;
|
||||
}
|
||||
|
||||
function resetImageInfo(data, copyClusterData) {
|
||||
for (var i = 0; i < data.length; i += 4) {
|
||||
var coor = getCoordinates(config, i);
|
||||
var x = coor.x;
|
||||
var y = coor.y;
|
||||
imageInfo[y][x] = {
|
||||
red: data[i],
|
||||
green: data[i + 1],
|
||||
blue: data[i + 2],
|
||||
alpha: data[i + 3],
|
||||
cluster: copyClusterData ? imageInfo[y][x].cluster : undefined
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function createImageInfo() {
|
||||
var img = document.getElementById('src_image');
|
||||
config.size.width = img.clientWidth;
|
||||
config.size.height = img.clientHeight;
|
||||
if (config.size.width == 0) {
|
||||
config.size.width = 500;
|
||||
}
|
||||
if (config.size.height == 0) {
|
||||
config.size.height = 500;
|
||||
}
|
||||
src_canvas.width = config.size.width;
|
||||
src_canvas.height = config.size.height;
|
||||
final_canvas.width = config.size.width;
|
||||
final_canvas.height = config.size.height;
|
||||
|
||||
imageInfo = new Array(config.size.height);
|
||||
for (var i = 0; i < config.size.height; i++) {
|
||||
imageInfo[i] = new Array(config.size.width);
|
||||
}
|
||||
// draw the image here, because resizing causes the context to loose its imageData (it seems)
|
||||
input_data = renderImageAndGetData(img, ctx);
|
||||
resetImageInfo(input_data, false);
|
||||
}
|
||||
function recreateClusterAndClusterDistance() {
|
||||
var timeBefore = new Date();
|
||||
clusterCenter = config.clusterFilter.clusterFun();
|
||||
createImageInfo();
|
||||
for (var y = 0; y < config.size.height; y++) {
|
||||
for (var x = 0; x < config.size.width; x++) {
|
||||
var colorInfoAtThisPos = imageInfo[y][x];
|
||||
var minDist = Number.MAX_VALUE;
|
||||
var foundCluster = -1;
|
||||
for (var clusterIndex = 0; clusterIndex < config.clusterFilter.clusterAmount; clusterIndex++) {
|
||||
var clusterPoint = clusterCenter[clusterIndex];
|
||||
var dist = Math.sqrt(Math.pow(colorInfoAtThisPos.red - clusterPoint.x, 2) +
|
||||
Math.pow(colorInfoAtThisPos.green - clusterPoint.y, 2) +
|
||||
Math.pow(colorInfoAtThisPos.blue - clusterPoint.z, 2));
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
foundCluster = clusterIndex;
|
||||
}
|
||||
}
|
||||
colorInfoAtThisPos.cluster = {clusterIndex: foundCluster, dist: minDist};
|
||||
}
|
||||
}
|
||||
|
||||
var timeAfter = new Date();
|
||||
formatInterval(timeBefore, timeAfter, "cluster distance and imageInfo creation took ...");
|
||||
}
|
||||
|
||||
function halfWayDistance(colorInfoAtThisPos, unused) {
|
||||
colorInfoAtThisPos.red = (colorInfoAtThisPos.red + clusterCenter[colorInfoAtThisPos.cluster.clusterIndex].x) / 2;
|
||||
colorInfoAtThisPos.green = (colorInfoAtThisPos.green + clusterCenter[colorInfoAtThisPos.cluster.clusterIndex].y) / 2;
|
||||
colorInfoAtThisPos.blue = (colorInfoAtThisPos.blue + clusterCenter[colorInfoAtThisPos.cluster.clusterIndex].z) / 2;
|
||||
}
|
||||
|
||||
function exactlyCluster(colorInfoAtThisPos, unused) {
|
||||
colorInfoAtThisPos.red = clusterCenter[colorInfoAtThisPos.cluster.clusterIndex].x;
|
||||
colorInfoAtThisPos.green = clusterCenter[colorInfoAtThisPos.cluster.clusterIndex].y;
|
||||
colorInfoAtThisPos.blue = clusterCenter[colorInfoAtThisPos.cluster.clusterIndex].z;
|
||||
}
|
||||
|
||||
function addDistanceToPoint(colorInfoAtThisPos, dist) {
|
||||
var vect = {
|
||||
x: colorInfoAtThisPos.red - clusterCenter[colorInfoAtThisPos.cluster.clusterIndex].x,
|
||||
y: colorInfoAtThisPos.green - clusterCenter[colorInfoAtThisPos.cluster.clusterIndex].y,
|
||||
z: colorInfoAtThisPos.blue - clusterCenter[colorInfoAtThisPos.cluster.clusterIndex].z
|
||||
};
|
||||
vect.x /= dist;
|
||||
vect.y /= dist;
|
||||
vect.z /= dist;
|
||||
|
||||
colorInfoAtThisPos.red += vect.x * config.clusterFilter.dist;
|
||||
colorInfoAtThisPos.green += vect.y * config.clusterFilter.dist;
|
||||
colorInfoAtThisPos.blue += vect.z * config.clusterFilter.dist;
|
||||
}
|
||||
|
||||
function getEquidistantPoints() {
|
||||
var clusterCenter = [];
|
||||
var increment = config.clusterFilter.cubeSize / Math.cbrt(config.clusterFilter.clusterAmount);
|
||||
for (var x = 0; x < config.clusterFilter.cubeSize; x += increment) {
|
||||
for (var y = 0; y < config.clusterFilter.cubeSize; y += increment) {
|
||||
for (var z = 0; z < config.clusterFilter.cubeSize; z += increment) {
|
||||
clusterCenter.push({x: x, y: y, z: z});
|
||||
}
|
||||
}
|
||||
}
|
||||
return clusterCenter;
|
||||
}
|
||||
function getRandomClusters() {
|
||||
var clusterCenter = [];
|
||||
for (var i = 0; i < config.clusterFilter.clusterAmount; i++) {
|
||||
clusterCenter.push({
|
||||
x: Math.random() * config.clusterFilter.cubeSize,
|
||||
y: Math.random() * config.clusterFilter.cubeSize,
|
||||
z: Math.random() * config.clusterFilter.cubeSize
|
||||
});
|
||||
}
|
||||
return clusterCenter;
|
||||
}
|
||||
function applyClusterFilter() {
|
||||
var timeBefore = new Date();
|
||||
resetImageInfo(input_data, true);
|
||||
final_imageData = final_ctx.createImageData(config.size.width, config.size.height);
|
||||
final_data = final_imageData.data;
|
||||
for (var y = 0; y < config.size.height; y++) {
|
||||
for (var x = 0; x < config.size.width; x++) {
|
||||
var colorInfoAtThisPos = imageInfo[y][x];
|
||||
config.clusterFilter.fun(colorInfoAtThisPos, colorInfoAtThisPos.cluster.dist);
|
||||
}
|
||||
}
|
||||
|
||||
for (var y = 0; y < config.size.height; y++) {
|
||||
for (var x = 0; x < config.size.width; x++) {
|
||||
var colorInfoAtThisPos = imageInfo[y][x];
|
||||
var index = getIndexForCoordinate(config, x, y);
|
||||
final_data[index] = colorInfoAtThisPos.red;
|
||||
final_data[index + 1] = colorInfoAtThisPos.green;
|
||||
final_data[index + 2] = colorInfoAtThisPos.blue;
|
||||
final_data[index + 3] = colorInfoAtThisPos.alpha;
|
||||
}
|
||||
}
|
||||
|
||||
final_ctx.putImageData(final_imageData, 0, 0);
|
||||
var timeAfter = new Date();
|
||||
formatInterval(timeBefore, timeAfter, "rendering took...");
|
||||
}
|
||||
|
||||
docReady(function () {
|
||||
src_canvas = document.getElementById('src_canvas');
|
||||
final_canvas = document.getElementById('final_canvas');
|
||||
ctx = src_canvas.getContext("2d");
|
||||
final_ctx = final_canvas.getContext("2d");
|
||||
inputFields['clusterAmount'] = document.getElementById('cluster_in');
|
||||
inputFields['clusterAmount'].value = config.clusterFilter.clusterAmount;
|
||||
inputFields['distance'] = document.getElementById('dist_in');
|
||||
inputFields['distance'].value = config.clusterFilter.dist;
|
||||
inputFields['distanceWrapper'] = document.getElementById('dist_wrapper');
|
||||
inputFields['distanceWrapper'].display = 'none';
|
||||
var newImg = new Image();
|
||||
newImg.src = "example.jpg";
|
||||
newImg.id = 'src_image';
|
||||
newImg.onload = function () {
|
||||
createImageInfo();
|
||||
recreateClusterAndClusterDistance();
|
||||
applyClusterFilter();
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
|
||||
window.setNewFunction = setNewFunction;
|
||||
window.setNewClusterFunction = setNewClusterFunction;
|
||||
window.downloadCanvas = downloadCanvasClusterFilter;
|
||||
window.previewFile = previewFile;
|
||||
window.updateConfig = updateConfig;
|
||||
window.generateClusters = generateClusters;
|
||||
|
||||
function downloadCanvasClusterFilter() {
|
||||
downloadCanvasWithoutButton('clusterFilter', final_canvas);
|
||||
}
|
||||
|
||||
|
||||
function setNewFunction() {
|
||||
var selectedWAy = document.getElementById('fun_select').value;
|
||||
if (selectedWAy == 1) {
|
||||
config.clusterFilter.fun = halfWayDistance;
|
||||
inputFields['distanceWrapper'].display = 'none';
|
||||
} else if (selectedWAy == 2) {
|
||||
config.clusterFilter.fun = exactlyCluster;
|
||||
inputFields['distanceWrapper'].display = 'none';
|
||||
} else {
|
||||
config.clusterFilter.fun = addDistanceToPoint;
|
||||
inputFields['distanceWrapper'].display = 'none';
|
||||
}
|
||||
applyClusterFilter();
|
||||
}
|
||||
|
||||
function setNewClusterFunction() {
|
||||
if (document.getElementById('equidistant_cluster').checked) {
|
||||
config.clusterFilter.clusterFun = getEquidistantPoints;
|
||||
} else {
|
||||
config.clusterFilter.clusterFun = getRandomClusters;
|
||||
}
|
||||
recreateClusterAndClusterDistance();
|
||||
applyClusterFilter();
|
||||
}
|
||||
|
||||
function generateClusters() {
|
||||
recreateClusterAndClusterDistance();
|
||||
applyClusterFilter();
|
||||
}
|
||||
|
||||
function updateConfig() {
|
||||
config.clusterFilter.dist = inputFields['distance'].value;
|
||||
var newClusterAmount = inputFields['clusterAmount'].value;
|
||||
if (config.clusterFilter.clusterAmount != newClusterAmount) {
|
||||
config.clusterFilter.clusterAmount = newClusterAmount;
|
||||
recreateClusterAndClusterDistance();
|
||||
}
|
||||
applyClusterFilter();
|
||||
}
|
||||
|
||||
function previewFile() {
|
||||
var preview = document.getElementById('src_image');
|
||||
var file = document.getElementById('img_upload').files[0]; //sames as here
|
||||
var reader = new FileReader();
|
||||
reader.onloadend = function () {
|
||||
preview.src = reader.result;
|
||||
recreateClusterAndClusterDistance();
|
||||
applyClusterFilter();
|
||||
};
|
||||
|
||||
if (file) {
|
||||
reader.readAsDataURL(file);
|
||||
} else {
|
||||
preview.src = "";
|
||||
}
|
||||
}
|
||||
24
clusterFilter/src/js/plugins.js
Normal file
24
clusterFilter/src/js/plugins.js
Normal file
@@ -0,0 +1,24 @@
|
||||
// Avoid `console` errors in browsers that lack a console.
|
||||
(function() {
|
||||
var method;
|
||||
var noop = function () {};
|
||||
var methods = [
|
||||
'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
|
||||
'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
|
||||
'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
|
||||
'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn'
|
||||
];
|
||||
var length = methods.length;
|
||||
var console = (window.console = window.console || {});
|
||||
|
||||
while (length--) {
|
||||
method = methods[length];
|
||||
|
||||
// Only stub undefined methods.
|
||||
if (!console[method]) {
|
||||
console[method] = noop;
|
||||
}
|
||||
}
|
||||
}());
|
||||
|
||||
// Place any jQuery/helper plugins in here.
|
||||
Reference in New Issue
Block a user