Skip to content

Instantly share code, notes, and snippets.

@johnnoel
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johnnoel/9079452 to your computer and use it in GitHub Desktop.
Save johnnoel/9079452 to your computer and use it in GitHub Desktop.
Creates "barcode" style images from video files, kind of like http://moviebarcode.tumblr.com/
<?php
$videoFiles = array();
if ($_SERVER['argc'] <= 1) {
die('No files passed in command line');
}
array_shift($_SERVER['argv']);
$videoFiles = $_SERVER['argv'];
sort($videoFiles);
foreach ($videoFiles as $videoFile) {
if (!file_exists($videoFile)) {
die(sprintf('Unable to read file %s', $videoFiles));
}
$hash = hash('md5', $videoFile);
$path = dirname($videoFile).DIRECTORY_SEPARATOR.$hash.DIRECTORY_SEPARATOR;
if ((file_exists($path) && !is_dir($path)) || (!file_exists($path) && !mkdir($path))) {
die(sprintf('Unable to create directory %s', $path));
}
shell_exec('ffmpeg -i '.escapeshellarg($videoFile).' -q:v 1 "'.$path.'img%06d.jpg"');
shell_exec('gm mogrify -resize 1x720! -format png "'.$path.'\\*.jpg"');
$pngFiles = array();
$di = new DirectoryIterator($path);
foreach ($di as $file) {
if ($file->isDot() || $file->isDir()) {
continue;
}
$ext = pathinfo($file->getPathname(), PATHINFO_EXTENSION);
if (strtolower($ext) === 'png') {
$pngFiles[] = $file->getPathname();
}
}
$total = count($pngFiles);
$batch = 1000;
$comboFiles = array();
for ($i = 0; $i <= $total; $i += $batch) {
$batchStr = sprintf('%06d', $i).'-'.sprintf('%06d', ($i + $batch));
$batchPath = $path.$batchStr.DIRECTORY_SEPARATOR;
if (!file_exists($batchPath) && !mkdir($batchPath)) {
die('Unable to create directory (batch)');
}
sort($pngFiles);
$batchFiles = array_splice($pngFiles, 0, $batch);
foreach ($batchFiles as $file) {
rename($file, $batchPath.basename($file));
}
shell_exec('gm montage +frame +shadow +label -tile '.$batch.'x1 -geometry +0+0 "'.$batchPath.'*.png" "'.$path.$batchStr.'.png"');
$comboFiles[] = $batchStr.'.png';
}
$comboPath = $path.'combo'.DIRECTORY_SEPARATOR;
if (!file_exists($comboPath) && !mkdir($comboPath)) {
die('Unable to create directory (combo)');
}
foreach ($comboFiles as $comboFile) {
rename($path.$comboFile, $comboPath.$comboFile);
}
shell_exec('gm montage +frame +shadow +label -tile '.count($comboFiles).'x1 -geometry +0+0 "'.$comboPath.'*.png" "'.$path.'\\max.png"');
shell_exec('gm convert -resize 1280x720! "'.$path.'\\max.png" "'.dirname($videoFile).'\\'.pathinfo($videoFile, PATHINFO_FILENAME).'.png"');
shell_exec('rmdir /S /Q '.$path);
}
<?php
function rgb($int) {
$r = ($int >> 16) & 0xFF;
$g = ($int >> 8) & 0xFF;
$b = $int & 0xFF;
return array($r, $g, $b);
}
function hsl($a) {
//http://stackoverflow.com/questions/11923659/javascript-sort-rgb-values
list($r, $g, $b) = rgb($a);
$max = max($r, $g, $b);
$min = min($r, $g, $b);
$h = $s = $l = ($max + $min) / 2;
if ($max == $min) {
$h = $s = 0;
} else {
$d = $max - $min;
if ($l > 0.5) {
$tmp = (2 - $max - $min);
$s = ($tmp === 0) ? 0 : $d / $tmp;
} else {
$s = ($d / ($max + $min));
}
switch ($max) {
case $r:
$h = ($g - $b) / $d + (($g < $b) ? 6 : 0);
break;
case $g:
$h = ($b - $r) / $d + 2;
break;
case $b:
$h = ($r - $g) / $d + 4;
break;
}
$h /= 6;
}
return array($h, $s, $l);
}
function sort_basic($a, $b) {
if ($a[2] == $b[2]) {
return 0;
}
return ($a[2] < $b[2]) ? -1 : 1;
}
function sort_brightness($a, $b) {
list($ar, $ag, $ab) = rgb($a[2]);
list($br, $bg, $bb) = rgb($b[2]);
$brightnessA = ($ar + $ag + $ab) / 3;
$brightnessB = ($br + $bg + $bb) / 3;
if ($brightnessA == $brightnessB) {
return 0;
}
return ($brightnessA < $brightnessB) ? -1 : 1;
}
function sort_luminance($a, $b) {
list($ar, $ag, $ab) = rgb($a[2]);
list($br, $bg, $bb) = rgb($b[2]);
$luminanceA = (0.2126 * $ar) + (0.7152 * $ag) + (0.0722 * $ab);
$luminanceB = (0.2126 * $br) + (0.7152 * $bg) + (0.0722 * $bb);
if ($luminanceA == $luminanceB) {
return 0;
}
return ($luminanceA < $luminanceB) ? -1 : 1;
}
function sort_hue($a, $b) {
list($ar, $ag, $ab) = rgb($a[2]);
list($br, $bg, $bb) = rgb($b[2]);
$hueA = atan2(sqrt(3) * ($ag - $ab), 2 * ($ar - $ag - $ab));
$hueB = atan2(sqrt(3) * ($bg - $bb), 2 * ($br - $bg - $bb));
if ($hueA == $hueB) {
return 0;
}
return ($hueA < $hueB) ? -1 : 1;
}
function sort_hsl($a, $b) {
list ($ah, $as, $al) = hsl($a[2]);
list ($bh, $bs, $bl) = hsl($b[2]);
if ($ah == $bh) {
if ($as == $bs) {
if ($al == $bl) {
return 0;
}
return ($al < $bl) ? -1 : 1;
}
return ($as < $bs) ? -1 : 1;
}
return ($ah < $bh) ? -1 : 1;
}
function sort_hls($a, $b) {
list ($ah, $as, $al) = hsl($a[2]);
list ($bh, $bs, $bl) = hsl($b[2]);
if ($ah == $bh) {
if ($al == $bl) {
if ($as == $bs) {
return 0;
}
return ($as < $bs) ? -1 : 1;
}
return ($al < $bl) ? -1 : 1;
}
return ($ah < $bh) ? -1 : 1;
}
function sort_lhs($a, $b) {
list ($ah, $as, $al) = hsl($a[2]);
list ($bh, $bs, $bl) = hsl($b[2]);
if ($al == $bl) {
if ($ah == $bh) {
if ($as == $bs) {
return 0;
}
return ($as < $bs) ? -1 : 1;
}
return ($ah < $bh) ? -1 : 1;
}
return ($al < $bl) ? -1 : 1;
}
function sort_lsh($a, $b) {
list ($ah, $as, $al) = hsl($a[2]);
list ($bh, $bs, $bl) = hsl($b[2]);
if ($al == $bl) {
if ($as == $bs) {
if ($ah == $bh) {
return 0;
}
return ($ah < $bh) ? -1 : 1;
}
return ($as < $bs) ? -1 : 1;
}
return ($al < $bl) ? -1 : 1;
}
$file = '[rori] Hentai Ouji to Warawanai Neko - 01 [76056615].png';
$sorts = array('basic', 'brightness', 'luminance', 'hue', 'hsl', 'lhs', 'lsh', 'hls');
$modes = array('stretch', 'column', 'pixel');
$gdOrig = imagecreatefrompng($file);
$w = imagesx($gdOrig); $h = imagesy($gdOrig);
foreach ($modes as $mode) {
$pixels = array();
$gdTmp = null;
echo $mode.':'.PHP_EOL;
switch ($mode) {
case 'pixel':
for ($x = 0; $x < $w; $x++) {
for ($y = 0; $y < $h; $y++) {
$pixels[] = array($x, $y, imagecolorat($gdOrig, $x, $y));
}
}
break;
case 'column':
case 'stretch':
shell_exec('gm convert -resize '.$w.'x1! '.escapeshellarg($file).' tmp.png');
$gdTmp = imagecreatefrompng('tmp.png');
for ($x = 0; $x < $w; $x++) {
$pixels[] = array($x, 0, imagecolorat($gdTmp, $x, 0));
}
break;
}
foreach ($sorts as $sort) {
echo $sort.PHP_EOL;
$gdNew = imagecreatetruecolor($w, $h);
usort($pixels, 'sort_'.$sort);
switch ($mode) {
case 'pixel':
for ($x = 0; $x < $w; $x++) {
for ($y = 0; $y < $h; $y++) {
$offset = ($x * $h) + $y;
$pixel = $pixels[$offset];
list($r, $g, $b) = rgb($pixel[2]);
$colour = imagecolorallocate($gdNew, $r, $g, $b);
imagesetpixel($gdNew, $x, $y, $colour);
}
}
break;
case 'column':
foreach ($pixels as $k => $v) {
// $k = newpos
// $v[0] = oldpos
imagecopy($gdNew, $gdOrig, $k, 0, $v[0], 0, 1, $h);
}
break;
case 'stretch':
foreach ($pixels as $k => $v) {
imagecopyresized($gdNew, $gdTmp, $k, 0, $v[0], 0, 1, $h, 1, 1);
}
break;
}
$name = $mode.'-'.$sort.'.png';
imagepng($gdNew, $name);
imagedestroy($gdNew);
}
if ($gdTmp !== null) {
imagedestroy($gdTmp);
$gdTmp = null;
unlink('tmp.png');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment