@ -0,0 +1 @@ |
||||
node_modules |
@ -0,0 +1,25 @@ |
||||
.problem-description { |
||||
background:#f5f2f0; |
||||
font-family:consolas; |
||||
line-height:24px; |
||||
padding:20px; |
||||
} |
||||
|
||||
.results-matrix { |
||||
font-size:0; |
||||
text-align:center; |
||||
} |
||||
|
||||
.results-matrix img { |
||||
border:3px solid #414141; |
||||
vertical-align:middle; |
||||
width: 100%; |
||||
} |
||||
|
||||
.results-matrix a { |
||||
display:inline-block; |
||||
line-height:125px; |
||||
margin:5px 2px; |
||||
vertical-align:top; |
||||
width:110px; |
||||
} |
After Width: | Height: | Size: 395 KiB |
After Width: | Height: | Size: 391 KiB |
After Width: | Height: | Size: 390 KiB |
After Width: | Height: | Size: 403 KiB |
After Width: | Height: | Size: 400 KiB |
After Width: | Height: | Size: 231 KiB |
After Width: | Height: | Size: 365 KiB |
After Width: | Height: | Size: 386 KiB |
After Width: | Height: | Size: 356 KiB |
After Width: | Height: | Size: 386 KiB |
After Width: | Height: | Size: 385 KiB |
After Width: | Height: | Size: 307 KiB |
After Width: | Height: | Size: 332 KiB |
After Width: | Height: | Size: 336 KiB |
After Width: | Height: | Size: 327 KiB |
After Width: | Height: | Size: 335 KiB |
After Width: | Height: | Size: 332 KiB |
After Width: | Height: | Size: 240 KiB |
After Width: | Height: | Size: 396 KiB |
After Width: | Height: | Size: 400 KiB |
After Width: | Height: | Size: 397 KiB |
After Width: | Height: | Size: 405 KiB |
After Width: | Height: | Size: 402 KiB |
After Width: | Height: | Size: 392 KiB |
After Width: | Height: | Size: 390 KiB |
After Width: | Height: | Size: 388 KiB |
After Width: | Height: | Size: 396 KiB |
After Width: | Height: | Size: 402 KiB |
After Width: | Height: | Size: 401 KiB |
After Width: | Height: | Size: 125 KiB |
After Width: | Height: | Size: 382 KiB |
After Width: | Height: | Size: 390 KiB |
After Width: | Height: | Size: 399 KiB |
After Width: | Height: | Size: 389 KiB |
After Width: | Height: | Size: 385 KiB |
After Width: | Height: | Size: 382 KiB |
After Width: | Height: | Size: 369 KiB |
After Width: | Height: | Size: 379 KiB |
After Width: | Height: | Size: 393 KiB |
After Width: | Height: | Size: 374 KiB |
After Width: | Height: | Size: 387 KiB |
After Width: | Height: | Size: 318 KiB |
@ -0,0 +1,377 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<title>D3</title> |
||||
|
||||
<link rel="stylesheet" href="css/style.css"> |
||||
<link rel="stylesheet" href="/beb-2016/css/style.css"> |
||||
<link rel="stylesheet" href="/beb-2016/css/prism.css"> |
||||
</head> |
||||
<body> |
||||
|
||||
<h1>Pixel Palettes</h1> |
||||
|
||||
<!-- http://gogs.benburlingham.com/ben.burlingham/pixel-palettes --> |
||||
|
||||
Tried my hand at <a href="http://codegolf.stackexchange.com/questions/33172/american-gothic-in-the-palette-of-mona-lisa-rearrange-the-pixels">this interesting challenge</a>: |
||||
|
||||
<p class='problem-description'> |
||||
|
||||
You are given two true color images, the Source and the Palette. They do not necessarily have the same dimensions but it is guaranteed that their areas are the same, i.e. they have the same number of pixels. |
||||
|
||||
<br><br> |
||||
|
||||
Your task is to create an algorithm that makes the most accurate looking copy of the Source by only using the pixels in the Palette. Each pixel in the Palette must be used exactly once in a unique position in this copy. The copy must have the same dimensions as the Source. |
||||
</p> |
||||
|
||||
<p> |
||||
<a href="http://codegolf.stackexchange.com/questions/33172/american-gothic-in-the-palette-of-mona-lisa-rearrange-the-pixels/35960#35960">My solution</a> is not everything I wished, but it was a fun exercise. |
||||
</p> |
||||
|
||||
<p> |
||||
The code basically takes a random pixel and uses a binary search to find a match in the target palette, weighted for the red component. Here are the results for that approach. |
||||
</p> |
||||
|
||||
<h2>Results</h2> |
||||
|
||||
<p> |
||||
Images are links, diagonals are originals. |
||||
</p> |
||||
|
||||
<div class='results-matrix'> |
||||
<a href='/pixel-palettes/img/gothic.png' target='_new'> |
||||
<img src="/pixel-palettes/img/gothic.png" alt="Gothic original"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/gothic-mona.png' target='_new'> |
||||
<img src="/pixel-palettes/img/gothic-mona.png" alt="Gothic -> Mona Lisa"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/gothic-scream.png' target='_new'> |
||||
<img src="/pixel-palettes/img/gothic-scream.png" alt="Gothic -> Scream"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/gothic-spheres.png' target='_new'> |
||||
<img src="/pixel-palettes/img/gothic-spheres.png" alt="Gothic -> Spheres"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/gothic-starry.png' target='_new'> |
||||
<img src="/pixel-palettes/img/gothic-starry.png" alt="Gothic -> Starry Night"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/gothic-stream.png' target='_new'> |
||||
<img src="/pixel-palettes/img/gothic-stream.png" alt="Gothic -> Stream"> |
||||
</a> |
||||
|
||||
<a href='/pixel-palettes/img/mona-gothic.png' target='_new'> |
||||
<img src="/pixel-palettes/img/mona-gothic.png" alt="Mona -> Gothic"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/mona.png' target='_new'> |
||||
<img src="/pixel-palettes/img/mona.png" alt="Mona Lisa original"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/mona-scream.png' target='_new'> |
||||
<img src="/pixel-palettes/img/mona-scream.png" alt="Mona -> Scream"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/mona-spheres.png' target='_new'> |
||||
<img src="/pixel-palettes/img/mona-spheres.png" alt="Mona -> Spheres"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/mona-starry.png' target='_new'> |
||||
<img src="/pixel-palettes/img/mona-starry.png" alt="Mona -> Starry Night"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/mona-stream.png' target='_new'> |
||||
<img src="/pixel-palettes/img/mona-stream.png" alt="Mona -> Stream"> |
||||
</a> |
||||
|
||||
<a href='/pixel-palettes/img/scream-gothic.png' target='_new'> |
||||
<img src="/pixel-palettes/img/scream-gothic.png" alt="Scream -> Gothic"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/scream-mona.png' target='_new'> |
||||
<img src="/pixel-palettes/img/scream-mona.png" alt="Scream -> Mona Lisa"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/scream.png' target='_new'> |
||||
<img src="/pixel-palettes/img/scream.png" alt="Scream original"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/scream-spheres.png' target='_new'> |
||||
<img src="/pixel-palettes/img/scream-spheres.png" alt="Scream -> Spheres"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/scream-starry.png' target='_new'> |
||||
<img src="/pixel-palettes/img/scream-starry.png" alt="Scream -> Starry Night"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/scream-stream.png' target='_new'> |
||||
<img src="/pixel-palettes/img/scream-stream.png" alt="Scream -> Stream"> |
||||
</a> |
||||
|
||||
<a href='/pixel-palettes/img/spheres-gothic.png' target='_new'> |
||||
<img src="/pixel-palettes/img/spheres-gothic.png" alt="Spheres -> Gothic"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/spheres-mona.png' target='_new'> |
||||
<img src="/pixel-palettes/img/spheres-mona.png" alt="Spheres -> Mona Lisa"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/spheres-scream.png' target='_new'> |
||||
<img src="/pixel-palettes/img/spheres-scream.png" alt="Spheres -> Scream"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/spheres.png' target='_new'> |
||||
<img src="/pixel-palettes/img/spheres.png" alt="Spheres original"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/spheres-starry.png' target='_new'> |
||||
<img src="/pixel-palettes/img/spheres-starry.png" alt="Spheres -> Starry Night"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/spheres-stream.png' target='_new'> |
||||
<img src="/pixel-palettes/img/spheres-stream.png" alt="Spheres -> Stream"> |
||||
</a> |
||||
|
||||
<a href='/pixel-palettes/img/starry-gothic.png' target='_new'> |
||||
<img src="/pixel-palettes/img/starry-gothic.png" alt="Starry -> Gothic"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/starry-mona.png' target='_new'> |
||||
<img src="/pixel-palettes/img/starry-mona.png" alt="Starry -> Mona Lisa"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/starry-scream.png' target='_new'> |
||||
<img src="/pixel-palettes/img/starry-scream.png" alt="Starry -> Scream"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/starry-spheres.png' target='_new'> |
||||
<img src="/pixel-palettes/img/starry-spheres.png" alt="Starry -> Spheres"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/starry.png' target='_new'> |
||||
<img src="/pixel-palettes/img/starry.png" alt="Starry Night original"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/starry-stream.png' target='_new'> |
||||
<img src="/pixel-palettes/img/starry-stream.png" alt="Starry -> Stream"> |
||||
</a> |
||||
|
||||
<a href='/pixel-palettes/img/stream-gothic.png' target='_new'> |
||||
<img src="/pixel-palettes/img/stream-gothic.png" alt="Stream -> Gothic"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/stream-mona.png' target='_new'> |
||||
<img src="/pixel-palettes/img/stream-mona.png" alt="Stream -> Mona Lisa"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/stream-scream.png' target='_new'> |
||||
<img src="/pixel-palettes/img/stream-scream.png" alt="Stream -> Scream"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/stream-spheres.png' target='_new'> |
||||
<img src="/pixel-palettes/img/stream-spheres.png" alt="Stream -> Spheres"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/stream-starry.png' target='_new'> |
||||
<img src="/pixel-palettes/img/stream-starry.png" alt="Stream -> Starry Night"> |
||||
</a> |
||||
<a href='/pixel-palettes/img/stream.png' target='_new'> |
||||
<img src="/pixel-palettes/img/stream.png" alt="Stream original"> |
||||
</a> |
||||
</div> |
||||
|
||||
|
||||
<h2>Source code</h2> |
||||
|
||||
<pre class='line-numbers'><code class='language-javascript'>var startTime = new Date().getTime(); |
||||
|
||||
var fs = require("fs"); |
||||
var pngjs = require("pngjs").PNG; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
var Pixels = function() {}; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
Pixels.prototype = { |
||||
source: null, |
||||
confirm: null, |
||||
target: null, |
||||
result: {}, |
||||
}; |
||||
|
||||
/** |
||||
* Heavy lifting done here. |
||||
*/ |
||||
Pixels.prototype.repalettize = function() { |
||||
// Indices is count from 0 to LxW, used to reference pixels in the tgtPalette, which are 8? bits wide. |
||||
var indices = []; |
||||
for (var y = 0; y < P.target.height; y++) { |
||||
for (var x = 0; x < P.target.width; x++) { |
||||
indices.push((P.target.width * y + x) << 2); |
||||
} |
||||
} |
||||
|
||||
var len = indices.length; |
||||
P.result.asBuffer = new Buffer(P.target.height * P.target.width * 4); |
||||
P.result.asArray = []; |
||||
|
||||
var i, ii; |
||||
|
||||
while (len) { |
||||
i = Math.floor(Math.random() * len); |
||||
ii = indices[i]; |
||||
|
||||
// Find RGB in source, no need for alpha channel. |
||||
matchIndex = P.findMatch( |
||||
zeropad(P.target.asBuffer[ii], 3) + |
||||
zeropad(P.target.asBuffer[ii + 1], 3) + |
||||
zeropad(P.target.asBuffer[ii + 2], 3) |
||||
); |
||||
|
||||
matchRgb = P.source.asArray[matchIndex]; |
||||
|
||||
P.result.asArray.push(matchRgb); |
||||
|
||||
P.result.asBuffer[ii] = matchRgb.substr(0, 3) * 1; |
||||
P.result.asBuffer[ii + 1] = matchRgb.substr(3, 3) * 1; |
||||
P.result.asBuffer[ii + 2] = matchRgb.substr(6, 3) * 1; |
||||
P.result.asBuffer[ii + 3] = 255; |
||||
|
||||
indices.splice(i, 1); |
||||
P.source.asArray.splice(matchIndex, 1); |
||||
len = indices.length; |
||||
} |
||||
|
||||
var resultImg = new pngjs({ |
||||
filterType: 4 |
||||
}); |
||||
|
||||
resultImg.data = P.result.asBuffer; |
||||
resultImg.width = P.target.width; |
||||
resultImg.height = P.target.height; |
||||
resultImg.pack().pipe(fs.createWriteStream('result.png')); |
||||
|
||||
var endTime = new Date().getTime(); |
||||
console.log((endTime - startTime) / 1000 + " seconds, confirming"); |
||||
|
||||
P.doConfirm(P.confirm.asArray, P.result.asArray) ? |
||||
console.log('OK - Source array and result array match.') : |
||||
console.log('ERROR! Source array and result array do not match!'); |
||||
}; |
||||
|
||||
/** |
||||
* Slightly modified binary search tree. |
||||
*/ |
||||
Pixels.prototype.findMatch = function(rgb0) { |
||||
var start = 0; |
||||
var end = P.source.asArray.length; |
||||
var mid; |
||||
|
||||
while (start + 1 < end) { |
||||
mid = Math.floor((end - start) / 2 + start); |
||||
if (P.source.asArray[mid] < rgb0) { |
||||
start = mid; |
||||
} |
||||
else { |
||||
end = mid; |
||||
} |
||||
} |
||||
|
||||
return start; |
||||
}; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
Pixels.prototype.doConfirm = function(arr1, arr2) { |
||||
var len1 = arr1.length; |
||||
var len2 = arr2.length; |
||||
|
||||
if (len1 !== len2) { |
||||
return false; |
||||
} |
||||
|
||||
arr1.sort(); |
||||
arr2.sort(); |
||||
|
||||
for (var i = 0; i < len1; i++) { |
||||
if (arr1[i] !== arr2[i]) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
}; |
||||
|
||||
/** |
||||
* Reads an image from a path, generates required information, and passes information to callback. |
||||
*/ |
||||
Pixels.prototype.read = function(path0, callback0) { |
||||
var width = 0; |
||||
var height = 0; |
||||
var asBuffer = null; |
||||
var asArray = null; |
||||
|
||||
fs.createReadStream(path0).pipe(new pngjs({ filterType: 4 })) |
||||
.on('metadata', function(meta0) { |
||||
width = meta0.width; |
||||
height = meta0.height; |
||||
}) |
||||
.on('parsed', function(buffer0) { |
||||
var x, y, i; |
||||
var arr = []; |
||||
for (y = 0; y < height; y++) { |
||||
for (x = 0; x < width; x++) { |
||||
i = y * width + x << 2; |
||||
|
||||
arr.push(zeropad(buffer0[i], 3) + zeropad(buffer0[i + 1], 3) + zeropad(buffer0[i + 2], 3)); |
||||
} |
||||
} |
||||
|
||||
callback0({ |
||||
width: width, |
||||
height: height, |
||||
asBuffer: buffer0, |
||||
asArray: arr, |
||||
}); |
||||
}); |
||||
}; |
||||
|
||||
/** |
||||
* sprintf implementation to ensure 9-digit pixels for sorting. |
||||
*/ |
||||
var zeropad = function(str0, len0) { |
||||
str0 = str0.toString(); |
||||
while (str0.length < len0) { |
||||
str0 = "0" + str0; |
||||
} |
||||
return str0; |
||||
}; |
||||
|
||||
/** |
||||
* Ansynchronous file reads will execute and call this function. After they're all finished, the processing can begin. |
||||
*/ |
||||
var filesRead = 0; |
||||
var thenContinue = function(data0) { |
||||
filesRead++; |
||||
|
||||
if (filesRead === 3) { |
||||
P.source.asArray.sort(); |
||||
P.repalettize(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Information for the source image, where the pixels are taken from. |
||||
*/ |
||||
var thenSaveSource = function(obj0) { |
||||
P.source = obj0; |
||||
thenContinue(); |
||||
} |
||||
|
||||
/** |
||||
* A copy of the source data used after processing to ensure source pixels match result pixels. |
||||
*/ |
||||
var thenSaveConfirm = function(obj0) { |
||||
P.confirm = obj0; |
||||
thenContinue(); |
||||
} |
||||
|
||||
/** |
||||
* Information for the target images, which the pixels are matched to. |
||||
*/ |
||||
var thenSaveTarget = function(obj0) { |
||||
P.target = obj0; |
||||
thenContinue(); |
||||
} |
||||
|
||||
//===== Entry point |
||||
var P = new Pixels(); |
||||
P.read('scream.png', thenSaveSource); |
||||
P.read('scream.png', thenSaveConfirm); |
||||
P.read('starry.png', thenSaveTarget); |
||||
</code></pre> |
||||
|
||||
<script type="text/javascript" src='../beb-2016/js/ui.js'></script> |
||||
<script type="text/javascript" src='../beb-2016/js/prism.js'></script> |
||||
</body> |
||||
</html> |
@ -0,0 +1,8 @@ |
||||
{ |
||||
"name": "pixels", |
||||
"version": "1.0.0", |
||||
"devDependencies": { |
||||
"chalk": "^0.5.1", |
||||
"pngjs": "^0.4.0" |
||||
} |
||||
} |
@ -0,0 +1,211 @@ |
||||
var startTime = new Date().getTime(); |
||||
|
||||
var fs = require("fs"); |
||||
var pngjs = require("pngjs").PNG; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
var Pixels = function() {}; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
Pixels.prototype = { |
||||
source: null, |
||||
confirm: null, |
||||
target: null, |
||||
result: {}, |
||||
}; |
||||
|
||||
/** |
||||
* Heavy lifting done here. |
||||
*/ |
||||
Pixels.prototype.repalettize = function() { |
||||
// Indices is count from 0 to LxW, used to reference pixels in the tgtPalette, which are 8? bits wide.
|
||||
var indices = []; |
||||
for (var y = 0; y < P.target.height; y++) { |
||||
for (var x = 0; x < P.target.width; x++) { |
||||
indices.push((P.target.width * y + x) << 2); |
||||
} |
||||
} |
||||
|
||||
var len = indices.length; |
||||
P.result.asBuffer = new Buffer(P.target.height * P.target.width * 4); |
||||
P.result.asArray = []; |
||||
|
||||
var i, ii; |
||||
|
||||
while (len) { |
||||
i = Math.floor(Math.random() * len); |
||||
ii = indices[i]; |
||||
|
||||
// Find RGB in source, no need for alpha channel.
|
||||
matchIndex = P.findMatch( |
||||
zeropad(P.target.asBuffer[ii], 3) + |
||||
zeropad(P.target.asBuffer[ii + 1], 3) + |
||||
zeropad(P.target.asBuffer[ii + 2], 3) |
||||
); |
||||
|
||||
matchRgb = P.source.asArray[matchIndex]; |
||||
|
||||
P.result.asArray.push(matchRgb); |
||||
|
||||
P.result.asBuffer[ii] = matchRgb.substr(0, 3) * 1; |
||||
P.result.asBuffer[ii + 1] = matchRgb.substr(3, 3) * 1; |
||||
P.result.asBuffer[ii + 2] = matchRgb.substr(6, 3) * 1; |
||||
P.result.asBuffer[ii + 3] = 255; |
||||
|
||||
indices.splice(i, 1); |
||||
P.source.asArray.splice(matchIndex, 1); |
||||
len = indices.length; |
||||
} |
||||
|
||||
var resultImg = new pngjs({ |
||||
filterType: 4 |
||||
}); |
||||
|
||||
resultImg.data = P.result.asBuffer; |
||||
resultImg.width = P.target.width; |
||||
resultImg.height = P.target.height; |
||||
resultImg.pack().pipe(fs.createWriteStream('result.png')); |
||||
|
||||
var endTime = new Date().getTime(); |
||||
console.log((endTime - startTime) / 1000 + " seconds, confirming"); |
||||
|
||||
P.doConfirm(P.confirm.asArray, P.result.asArray) ? |
||||
console.log('OK - Source array and result array match.') : |
||||
console.log('ERROR! Source array and result array do not match!'); |
||||
}; |
||||
|
||||
/** |
||||
* Slightly modified binary search tree. |
||||
*/ |
||||
Pixels.prototype.findMatch = function(rgb0) { |
||||
var start = 0; |
||||
var end = P.source.asArray.length; |
||||
var mid; |
||||
|
||||
while (start + 1 < end) { |
||||
mid = Math.floor((end - start) / 2 + start); |
||||
if (P.source.asArray[mid] < rgb0) { |
||||
start = mid; |
||||
} |
||||
else { |
||||
end = mid; |
||||
} |
||||
} |
||||
|
||||
return start; |
||||
}; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
Pixels.prototype.doConfirm = function(arr1, arr2) { |
||||
var len1 = arr1.length; |
||||
var len2 = arr2.length; |
||||
|
||||
if (len1 !== len2) { |
||||
return false; |
||||
} |
||||
|
||||
arr1.sort(); |
||||
arr2.sort(); |
||||
|
||||
for (var i = 0; i < len1; i++) { |
||||
if (arr1[i] !== arr2[i]) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
}; |
||||
|
||||
/** |
||||
* Reads an image from a path, generates required information, and passes information to callback. |
||||
*/ |
||||
Pixels.prototype.read = function(path0, callback0) { |
||||
var width = 0; |
||||
var height = 0; |
||||
var asBuffer = null; |
||||
var asArray = null; |
||||
|
||||
fs.createReadStream(path0).pipe(new pngjs({ filterType: 4 })) |
||||
.on('metadata', function(meta0) { |
||||
width = meta0.width; |
||||
height = meta0.height; |
||||
}) |
||||
.on('parsed', function(buffer0) { |
||||
var x, y, i; |
||||
var arr = []; |
||||
for (y = 0; y < height; y++) { |
||||
for (x = 0; x < width; x++) { |
||||
i = y * width + x << 2; |
||||
|
||||
arr.push(zeropad(buffer0[i], 3) + zeropad(buffer0[i + 1], 3) + zeropad(buffer0[i + 2], 3)); |
||||
} |
||||
} |
||||
|
||||
callback0({ |
||||
width: width, |
||||
height: height, |
||||
asBuffer: buffer0, |
||||
asArray: arr, |
||||
}); |
||||
}); |
||||
}; |
||||
|
||||
/** |
||||
* sprintf implementation to ensure 9-digit pixels for sorting. |
||||
*/ |
||||
var zeropad = function(str0, len0) { |
||||
str0 = str0.toString(); |
||||
while (str0.length < len0) { |
||||
str0 = "0" + str0; |
||||
} |
||||
return str0; |
||||
}; |
||||
|
||||
/** |
||||
* Ansynchronous file reads will execute and call this function. After they're all finished, the processing can begin. |
||||
*/ |
||||
var filesRead = 0; |
||||
var thenContinue = function(data0) { |
||||
filesRead++; |
||||
|
||||
if (filesRead === 3) { |
||||
P.source.asArray.sort(); |
||||
P.repalettize(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Information for the source image, where the pixels are taken from. |
||||
*/ |
||||
var thenSaveSource = function(obj0) { |
||||
P.source = obj0; |
||||
thenContinue(); |
||||
} |
||||
|
||||
/** |
||||
* A copy of the source data used after processing to ensure source pixels match result pixels. |
||||
*/ |
||||
var thenSaveConfirm = function(obj0) { |
||||
P.confirm = obj0; |
||||
thenContinue(); |
||||
} |
||||
|
||||
/** |
||||
* Information for the target images, which the pixels are matched to. |
||||
*/ |
||||
var thenSaveTarget = function(obj0) { |
||||
P.target = obj0; |
||||
thenContinue(); |
||||
} |
||||
|
||||
//===== Entry point
|
||||
var P = new Pixels(); |
||||
P.read('scream.png', thenSaveSource); |
||||
P.read('scream.png', thenSaveConfirm); |
||||
P.read('starry.png', thenSaveTarget); |