0.8.6
This commit is contained in:
199
leaf.php
199
leaf.php
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
// Leaf - Tools for Book Scans
|
||||
$version = "0.8.4";
|
||||
$version = "0.8.6";
|
||||
$debug = 1;
|
||||
$time_start = microtime(true);
|
||||
date_default_timezone_set("America/Los_Angeles");
|
||||
@@ -23,13 +23,25 @@ function levels_ps_to_imgk($string) {
|
||||
if (count($parts) != 3) {
|
||||
msg("Invalid levels string",1);
|
||||
} else {
|
||||
$black = ($parts[0]/253)."%";
|
||||
$black = (number_format(($parts[0]/253),5)*100)."%";
|
||||
$white = (number_format(($parts[1]/255),5)*100)."%";
|
||||
$gamma = $parts[2];
|
||||
return $black.",".$white.",".$gamma;
|
||||
}
|
||||
}
|
||||
|
||||
function unsharp_ps_to_imgk($string) {
|
||||
$parts = explode(",", $string);
|
||||
if (count($parts) != 3) {
|
||||
msg("Invalid levels string",1);
|
||||
} else {
|
||||
$radius = "0x".($parts[1]+1);
|
||||
$amount = $parts[0]/100;
|
||||
$threshold = $parts[2]/255;
|
||||
return $radius."+".$amount."+".$threshold;
|
||||
}
|
||||
}
|
||||
|
||||
function multiexec($thread, $x, $null = true) {
|
||||
global $debug;
|
||||
$batch = array_chunk($thread,$x);
|
||||
@@ -45,14 +57,15 @@ function multiexec($thread, $x, $null = true) {
|
||||
} else {
|
||||
$echo = implode("", $msg);
|
||||
}
|
||||
if ($null) {
|
||||
$exec = implode(" > /dev/null & ",$cmd)." & wait";
|
||||
if ($debug || !$null) {
|
||||
$pipe = "";
|
||||
} else {
|
||||
$exec = implode(" & ",$cmd)." & wait";
|
||||
$pipe = " 2>&1";
|
||||
}
|
||||
$exec = implode($pipe." & ",$cmd).$pipe." & wait";
|
||||
echo $echo;
|
||||
if ($debug) {
|
||||
echo "\n\n".$exec."\n\n";
|
||||
echo "\n".str_replace($pipe." & ", "\n\n", $exec)."\n";
|
||||
}
|
||||
@exec($exec);
|
||||
}
|
||||
@@ -118,6 +131,10 @@ function args($query) {
|
||||
return chop($argv[count($argv)-1], "/")."/";
|
||||
} elseif ($query == "levels" && isset($opt['levels'])) {
|
||||
return levels_ps_to_imgk($opt['levels']);
|
||||
} elseif ($query == "plevels" && isset($opt['plevels'])) {
|
||||
return levels_ps_to_imgk($opt['plevels']);
|
||||
} elseif ($query == "unsharp" && isset($opt['unsharp'])) {
|
||||
return unsharp_ps_to_imgk($opt['unsharp']);
|
||||
} elseif (isset($opt[$query])) {
|
||||
return $opt[$query];
|
||||
} else {
|
||||
@@ -191,7 +208,8 @@ deskew detect rotation angles
|
||||
depaper divide page with itself using mask (better despine)
|
||||
-mask=<file> mask file for spine-left image
|
||||
-mpush=<levels> levels for divide map (ex. \"0-253,0-255,0-2\")
|
||||
-mix=<0-100> percentage mix with original (90% = mostly og)
|
||||
-mix=<0-100> (null) percentage mix with original (90% = mostly og)
|
||||
-skip=<label> (null) skip files with this label
|
||||
despine remove shadow from spine
|
||||
-levels=<params> levels for overlay (ex. \"0-253,0-255,0-2\")
|
||||
-width=<pixels> (300) spine width in pixels
|
||||
@@ -216,8 +234,13 @@ generate create final jpg images for pdf creation
|
||||
-levels=<params> photoshop levels adjustment (ex. \"0-253,0-255,0-2\")
|
||||
-px=<num> png size multiplier
|
||||
-plevels=<params> png levels adjustment (otherwise calculated from adjust)
|
||||
-pt=<0-255> use threshold method with photoshop level value
|
||||
-pc=<2,2!,3> (2) colors for final png (2! = intermediary dithering)
|
||||
-unsharp=<params> photoshop unsharp parameters (ex. \"100,1,0\")
|
||||
match move files and set crop values to match source dir
|
||||
-source=<dir> read FROM dir
|
||||
notes save leaf shell history to text file
|
||||
-lines=<num> (100) lines to read from bash_history
|
||||
profile apply xmp profile to images (requires exiv2 > 0.25)
|
||||
-file=<file> xmp profile
|
||||
resort reorder image sequence by adding a new image
|
||||
@@ -238,6 +261,34 @@ strip strip exif crop values from images with exiftool
|
||||
echo $help;
|
||||
fin();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Note: Notes
|
||||
//////////////////////
|
||||
} elseif (args("app") == "notes") {
|
||||
echo Welcome("Save shell commands to text file");
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (args("lines")) {
|
||||
$lines = args("lines");
|
||||
} else {
|
||||
$lines = 100;
|
||||
}
|
||||
|
||||
$notes = shell_exec("tail -n ".$lines." /Users/peter/.bash_history");
|
||||
foreach (explode("\n", $notes) as $line) {
|
||||
if (substr($line, 0, 4) == "leaf") {
|
||||
$keep[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($keep[0])) {
|
||||
msg("Error reading bash history",1);
|
||||
} else {
|
||||
file_put_contents("leaf_notes.txt", implode("\n", $keep));
|
||||
}
|
||||
|
||||
fin();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Note: Brightness_table
|
||||
//////////////////////
|
||||
@@ -265,6 +316,12 @@ if (!file_exists(args("mask"))) {
|
||||
msg("Can't open mask",1);
|
||||
}
|
||||
|
||||
if (!args("mpush")) {
|
||||
msg("Please specify divide levels with mpush",1);
|
||||
} else {
|
||||
$mpush = levels_ps_to_imgk(args("mpush"));
|
||||
}
|
||||
|
||||
if (count(glob($dest."/*.*"))) {
|
||||
msg("Files already exist in ".$dest.". Move to trash?",2);
|
||||
exec("/opt/local/bin/trash -a ".$dest);
|
||||
@@ -273,17 +330,32 @@ if (count(glob($dest."/*.*"))) {
|
||||
mkdir($dest);
|
||||
}
|
||||
|
||||
msg("Building threads...");
|
||||
|
||||
$files = glob(args("dir")."*.*");
|
||||
foreach ($files as $file) {
|
||||
$ext = pathinfo($file,PATHINFO_EXTENSION);
|
||||
$result = $dest."/".basename($file);
|
||||
list ($width, $height) = getimagesize($file);
|
||||
$divided = "\( ".$file." \( ".$file." -colorspace gray -level ".$mpush." \) -compose Divide_Src -composite \)";
|
||||
if (substr(basename($file), 0, 3) % 2 == 0) {
|
||||
$cmd = "convert test.jpg \( ".$file." \( ".args("mask")."[".$width."x".$height."] -rotate 180 \) -alpha Off -compose CopyOpacity -composite \) -compose Over -composite ".$result;
|
||||
$cmd = "convert ".$file." \( ".$divided." \( ".args("mask")."[".$width."x".$height."!] -flop \) -alpha Off -compose CopyOpacity -composite \) -compose Over -composite ".$result;
|
||||
} else {
|
||||
$cmd = "convert test.jpg \( ".$file." ".args("mask")."[".$width."x".$height."] -alpha Off -compose CopyOpacity -composite \) -compose Over -composite ".$result;
|
||||
$cmd = "convert ".$file." \( ".$divided." ".args("mask")."[".$width."x".$height."!] -alpha Off -compose CopyOpacity -composite \) -compose Over -composite ".$result;
|
||||
}
|
||||
if (args("mix")) {
|
||||
$pass1 = str_replace("convert", "convert \(", $cmd);
|
||||
$pass2 = str_replace("-composite ".$result, "-composite \) ".$file." -auto-orient -compose dissolve -define compose:args=".args("mix")." -composite ".$result, $pass1);
|
||||
$cmd = $pass2;
|
||||
}
|
||||
$msg = "Converting ".$file;
|
||||
if (args("skip")) {
|
||||
$label = trim(shell_exec("exiftool -s -s -s -Label ".$file));
|
||||
if ($label == args("skip")) {
|
||||
$msg .= " <Skipping label=".args("skip").">";
|
||||
$cmd = "cp ".$file." ".$result;
|
||||
}
|
||||
}
|
||||
$thread[] = array($msg, $cmd);
|
||||
}
|
||||
|
||||
@@ -348,7 +420,6 @@ foreach ($files as $file) {
|
||||
$quality = $default_quality;
|
||||
}
|
||||
|
||||
|
||||
$msg = $file." matched, despining...";
|
||||
$cmd = "convert ".$file." \( ".$file." -auto-orient -crop ".$crop." -colorspace gray -level ".$adjust." \) -auto-orient -geometry ".$geo." -compose Divide_Src -composite -quality ".$quality." ".$dest."/".basename($file);
|
||||
if (args("mix")) {
|
||||
@@ -429,7 +500,7 @@ fin();
|
||||
// Note: Generate
|
||||
//////////////////////
|
||||
} elseif (args("app") == "generate") {
|
||||
echo Welcome("Generate final jpg images");
|
||||
echo Welcome("Generate final images");
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
$dest = rtrim(args("dir"), '/')."_generated";
|
||||
@@ -484,7 +555,7 @@ foreach ($files as $file) {
|
||||
}
|
||||
if ($parts[0] == "bitmap") {
|
||||
$bitmap[] = array($file,$width,$height);
|
||||
} elseif ($parts[1] == "True") {
|
||||
} elseif ($parts[1] == "True" || $parts[0] == "grayscale") {
|
||||
$grey[] = array($file,$width,$height);
|
||||
} elseif ($ratio < 3) {
|
||||
$color[] = array($file,$width,$height);
|
||||
@@ -559,13 +630,15 @@ if (isset($spine)) {
|
||||
|
||||
foreach ($jpg as $parts) {
|
||||
|
||||
continue;
|
||||
|
||||
$file = $parts[0];
|
||||
$output = $dest."/".basename($file);
|
||||
|
||||
if (isset($parts[3]) && $parts[3] == 1) {
|
||||
|
||||
$msg = "Processing greyscale page ".$file." @ ".$dims."!";
|
||||
$cmd = "convert -resize ".$dims."\! -colorspace gray ";
|
||||
$cmd = "convert -resize ".$dims."\! -colorspace gray -type TrueColor ";
|
||||
|
||||
} elseif (isset($parts[3]) && $parts[3] == 2) {
|
||||
|
||||
@@ -578,6 +651,11 @@ foreach ($jpg as $parts) {
|
||||
$msg = "Processing color page ".$file." @ ".$dims."!";
|
||||
$cmd = "convert -resize ".$dims."\! ";
|
||||
|
||||
if (args("modulate")) {
|
||||
$msg .= " (".args("modulate").")";
|
||||
$cmd .= "-modulate ".args("modulate")." ";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (args("levels")) {
|
||||
@@ -585,6 +663,11 @@ foreach ($jpg as $parts) {
|
||||
$cmd .= "-level ".args("levels")." ";
|
||||
}
|
||||
|
||||
if (args("unsharp")) {
|
||||
$msg .= " (".args("unsharp").")";
|
||||
$cmd .= "-unsharp ".args("unsharp")." ";
|
||||
}
|
||||
|
||||
$msg .= " [Q=".$quality."]";
|
||||
$cmd .= "-quality ".$quality." ".$file." ".$output;
|
||||
|
||||
@@ -602,14 +685,7 @@ multiexec($thread_b,$xt);
|
||||
|
||||
if (isset($bitmap)) {
|
||||
|
||||
foreach ($bitmap as $parts) {
|
||||
|
||||
$file = $parts[0];
|
||||
$ext = pathinfo($file,PATHINFO_EXTENSION);
|
||||
$output = $dest."/".basename($file,$ext)."png";
|
||||
|
||||
$msg = "Processing bitmap page ".$file." @ ".$pngdims."!";
|
||||
$cmd = "convert -resize ".$pngdims."\! ";
|
||||
if (!args("pt")) {
|
||||
|
||||
if (args("levels")) {
|
||||
$adjust = args("levels");
|
||||
@@ -625,13 +701,74 @@ if (isset($bitmap)) {
|
||||
if (args("plevels")) {
|
||||
$radjust = args("plevels");
|
||||
} else {
|
||||
$radjust = ($black+60)."%".",".($white-15)."%".",".($gamma-.7);
|
||||
$radjust = ($black+60)."%".",".($white-15)."%".",".($gamma-.8);
|
||||
}
|
||||
|
||||
$msg .= " (".$radjust.")";
|
||||
$cmd .= "-level ".$radjust." ";
|
||||
msg("Checking bitmap output for brightness...");
|
||||
$testfile = $bitmap[0][0];
|
||||
$level = chop(shell_exec("convert \( ".$testfile." -resize ".$pngdims."\! -level ".$radjust." -monochrome -colors 2 -depth 1 \) -colorspace Gray -format \"%[fx:quantumrange*image.mean]\" info:"));
|
||||
|
||||
$cmd .= "-monochrome -colors 2 -depth 1 -negate ".$file." ".$output;
|
||||
if ($level < 20000) {
|
||||
msg("Image is dark, applying negate");
|
||||
$negate = "-negate ";
|
||||
} else {
|
||||
msg("Image is bright, skipping negate");
|
||||
$negate = "";
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
$threshold = (number_format((args("pt")/255),5)*100)."%";
|
||||
|
||||
}
|
||||
|
||||
foreach ($bitmap as $parts) {
|
||||
|
||||
$file = $parts[0];
|
||||
$ext = pathinfo($file,PATHINFO_EXTENSION);
|
||||
$output = $dest."/".basename($file,$ext)."png";
|
||||
|
||||
$msg = "Processing bitmap page ".$file." @ ".$pngdims."!";
|
||||
|
||||
if (args("pt")) {
|
||||
|
||||
if (args("pc") == "2!") { // a b&w bitmap image with an intermediary antialiased step (darker text)
|
||||
|
||||
$msg .= " (".$threshold.", ".$pl.")";
|
||||
$cmd = "convert \( \( \( ".$file." -threshold ".$threshold." \) -set colorspace sRGB -type truecolor \) -resize ".$pngdims."\! \) -threshold 95% ".$output;
|
||||
|
||||
} elseif (args("pc") == "3") { // a b&w bitmap image with an additional color for antialiasing
|
||||
|
||||
$msg .= " (".$threshold.", ".$pl.")";
|
||||
$cmd = "convert \( \( \( ".$file." -threshold ".$threshold." \) -set colorspace sRGB -type truecolor \) -resize ".$pngdims."\! \) -set colorspace Grayscale -colors 4 -depth 2 ".$output;
|
||||
|
||||
} else { // a b&w bitmap image
|
||||
|
||||
$msg .= " (".$threshold.")";
|
||||
$cmd = "convert -resize ".$pngdims."\! -threshold ".$threshold." ".$file." ".$output;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (args("pc") == "2!") { // a b&w bitmap image with an intermediary antialiased step (darker text)
|
||||
|
||||
$msg .= " (".$radjust.", ".$pl.")";
|
||||
$cmd = "convert \( \( \( ".$file." -level ".$radjust." -monochrome -colors 2 -depth 1 ".$negate."\) -set colorspace sRGB -type truecolor \) -resize ".$pngdims."\! \) -threshold 95% ".$output;
|
||||
|
||||
} elseif (args("pc") == "3") { // a b&w bitmap image with an additional color for antialiasing
|
||||
|
||||
$msg .= " (".$radjust.", ".$pl.")";
|
||||
$cmd = "convert \( ".$file." -level ".$radjust." -resize ".$pngdims."\! \) -set colorspace Grayscale -colors 4 -depth 2 ".$output;
|
||||
|
||||
} else { // a b&w bitmap image
|
||||
|
||||
$msg .= " (".$radjust.")";
|
||||
$cmd = "convert -resize ".$pngdims."\! -level ".$radjust." -monochrome -colors 2 -depth 1 ".$negate.$file." ".$output;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$thread_c[] = array($msg, $cmd);
|
||||
$thread_d[] = array(".","exiftool -overwrite_original -PixelsPerUnitX=".$pngdpi." -PixelsPerUnitY=".$pngdpi." ".$output);
|
||||
@@ -1560,10 +1697,16 @@ if (!args("nomap")) {
|
||||
|
||||
$size = $deskew_size."x".$deskew_size;
|
||||
|
||||
if (substr(basename($file), 0, 3) % 2 == 0) {
|
||||
$cmd = "convert ".$file." -auto-orient -crop ".$area_right." -level ".$deskew_contrast."%,".(100-$deskew_contrast)."% -colorspace Gray -resize ".$size." ".$dmfile;
|
||||
if (strtolower($ext) == "dng") {
|
||||
$adj = "0%,".(100-$deskew_contrast)."%";
|
||||
} else {
|
||||
$cmd = "convert ".$file." -auto-orient -crop ".$area_left." -level ".$deskew_contrast."%,".(100-$deskew_contrast)."% -colorspace Gray -resize ".$size." ".$dmfile;
|
||||
$adj = $deskew_contrast."%,".(100-$deskew_contrast)."%";
|
||||
}
|
||||
|
||||
if (substr(basename($file), 0, 3) % 2 == 0) {
|
||||
$cmd = "convert ".$file." -auto-orient -crop ".$area_right." -level ".$adj." -colorspace Gray -resize ".$size." ".$dmfile;
|
||||
} else {
|
||||
$cmd = "convert ".$file." -auto-orient -crop ".$area_left." -level ".$adj." -colorspace Gray -resize ".$size." ".$dmfile;
|
||||
}
|
||||
|
||||
$msg = "Creating dmap for ".$file;
|
||||
|
||||
Reference in New Issue
Block a user