0.6.9
This commit is contained in:
369
leaf.php
369
leaf.php
@@ -2,9 +2,10 @@
|
||||
<?php
|
||||
|
||||
// Leaf - Tools for Book Scans
|
||||
$version = "0.6.8";
|
||||
$version = "0.6.9";
|
||||
$time_start = microtime(true);
|
||||
date_default_timezone_set("America/Los_Angeles");
|
||||
$xt = 3; // threads
|
||||
|
||||
// Functions
|
||||
|
||||
@@ -19,7 +20,10 @@ function multiexec($thread, $x) {
|
||||
}
|
||||
$echo = implode("\n", $msg);
|
||||
$exec = implode(" > /dev/null & ",$cmd)." & wait";
|
||||
echo $echo."\n";
|
||||
echo $echo;
|
||||
if (strlen($echo) > 1) {
|
||||
echo "\n";
|
||||
}
|
||||
exec($exec);
|
||||
}
|
||||
}
|
||||
@@ -141,9 +145,15 @@ $help = "Leaf $version
|
||||
USAGE: leaf [mode] [-options] directory
|
||||
|
||||
Modes:
|
||||
clean remove scratch files
|
||||
crop define EXIF crop values using template files
|
||||
-crops=<num> specify how many files to use
|
||||
desort remove image sequence prefix
|
||||
deskew detect rotation angles
|
||||
-max=<num> angles greater than this value are ignored, default .4
|
||||
-pad=<num> pixels to pad around crop area, default 80
|
||||
-contrast=<num> contrast boost, default 20
|
||||
-size=<num> size in pixels of dmap, default 2200
|
||||
divide wrapper for imagemagick Divide_Src
|
||||
-map=<file> specify brightness file
|
||||
-adjust=<params> levels adjustment (ex. \"0%,98%,.9\")
|
||||
@@ -158,6 +168,9 @@ resort reorder image sequence by adding a new image
|
||||
-file=<file> file to insert
|
||||
-x=<num> position of inserted file
|
||||
review print a table of image dimension statistics
|
||||
rotate batch transform rotate (lossy)
|
||||
-x=<angle> rotation angle, default=90
|
||||
-q=<0-100> jpeg quality, default read from source or 95
|
||||
setdpi set image dpi with exiftool
|
||||
-x=<dpi> specify dpi
|
||||
-height=<inches> calculate dpi from specified height
|
||||
@@ -169,6 +182,68 @@ strip strip exif crop values from images with exiftool
|
||||
echo $help;
|
||||
fin();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Note: Clean
|
||||
//////////////////////
|
||||
} elseif (args("app") == "clean") {
|
||||
echo Welcome("Remove scratch dir");
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
msg("Remove scratch files?",2);
|
||||
if (!is_dir("scratch")) {
|
||||
msg("Problem with scratch dir",2);
|
||||
} else {
|
||||
foreach (glob("scratch/*.*") as $file) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
fin();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Note: Rotate
|
||||
//////////////////////
|
||||
} elseif (args("app") == "rotate") {
|
||||
echo Welcome("Batch rotate (lossy)");
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
$default_quality = 95;
|
||||
|
||||
$files = glob(args("dir")."*.{jpg,JPG,tif,TIF}", GLOB_BRACE);
|
||||
|
||||
if (args("x")) {
|
||||
$angle = args("x");
|
||||
} else {
|
||||
$angle = 90;
|
||||
}
|
||||
|
||||
$dest = rtrim(args("dir"), '/')."_rotated";
|
||||
if (count(glob($dest."/*.*"))) {
|
||||
msg("Files already exist in destination ".$dest,1);
|
||||
} elseif (!is_dir($dest)) {
|
||||
mkdir($dest);
|
||||
}
|
||||
|
||||
foreach ($files as $file) {
|
||||
$ext = pathinfo($file,PATHINFO_EXTENSION);
|
||||
$output = $dest."/".basename($file,$ext)."jpg";
|
||||
if (args("q")) {
|
||||
$quality = args("q");
|
||||
} elseif (strtolower($ext) == "jpg") {
|
||||
$quality = @exec("identify -format '%Q' ".$file);
|
||||
} else {
|
||||
$quality = $default_quality;
|
||||
}
|
||||
$msg = "Rotating ".$file." ".$angle." to ".$output." with Q=".$quality;
|
||||
$cmd = "convert -rotate ".$angle." -quality ".$quality." ".$file." ".$output;
|
||||
$thread[] = array($msg, $cmd);
|
||||
}
|
||||
|
||||
msg("Beginning multithreaded convert with ".$xt." threads");
|
||||
multiexec($thread,$xt);
|
||||
|
||||
fin();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Note: Profile
|
||||
//////////////////////
|
||||
@@ -666,7 +741,6 @@ fin();
|
||||
echo Welcome("Composite image from brightness map");
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
$xt = 8;
|
||||
$files = glob(args("dir")."*.{jpg,JPG,tif}", GLOB_BRACE);
|
||||
|
||||
if (!args("map")) {
|
||||
@@ -800,16 +874,96 @@ fin();
|
||||
echo Welcome("Detect skew angle and apply to EXIF tags");
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
$deskew_max_angle = ".4";
|
||||
$deskew_padding = 80;
|
||||
$deskew_contrast = 20;
|
||||
$deskew_size = 2200;
|
||||
if (args("max")) {
|
||||
$deskew_max_angle = args("max");
|
||||
} else {
|
||||
$deskew_max_angle = .4;
|
||||
}
|
||||
|
||||
$files = glob(args("dir")."*.jpg");
|
||||
if (null !== args("pad")) {
|
||||
$deskew_padding = args("pad");
|
||||
echo "pad = ".args("pad");
|
||||
} else {
|
||||
$deskew_padding = 80;
|
||||
}
|
||||
|
||||
if (null !== args("contrast")) {
|
||||
$deskew_contrast = args("contrast");
|
||||
} else {
|
||||
$deskew_contrast = 20;
|
||||
}
|
||||
|
||||
if (args("size")) {
|
||||
$deskew_size = args("size");
|
||||
} else {
|
||||
$deskew_size = 2200;
|
||||
}
|
||||
|
||||
die;
|
||||
|
||||
$files = glob(args("dir")."*.{jpg,JPG,dng,DNG}", GLOB_BRACE);
|
||||
|
||||
echo "Scanning for crop values: ";
|
||||
|
||||
if (!args("nomap")) {
|
||||
|
||||
msg("Creating dmaps...");
|
||||
foreach ($files as $file) {
|
||||
|
||||
$ext = pathinfo($file,PATHINFO_EXTENSION);
|
||||
$dmfile = "scratch/".basename($file, ".".$ext)."_dmap.jpg";
|
||||
|
||||
if (!file_exists($dmfile)) {
|
||||
|
||||
$parts = chop(shell_exec("exiftool -s -s -s -XMP-crs:CropTop -XMP-crs:CropRight -XMP-crs:CropLeft -XMP-crs:CropBottom -ImageWidth -ImageHeight ".$file." 2>&1"));
|
||||
@list($top, $right, $left, $bottom, $check_width, $check_height) = explode("\n", $parts);
|
||||
if (!$top | !$right | !$left | !$bottom) { msg($file." missing crop information!",1); }
|
||||
|
||||
$jpeg_width = $check_height;
|
||||
$jpeg_height = $check_width;
|
||||
|
||||
$top_pixels = floor( $jpeg_width * $top );
|
||||
$right_pixels = $jpeg_height - floor( $right * $jpeg_height );
|
||||
$left_pixels = floor( $jpeg_height * $left );
|
||||
$bottom_pixels = $jpeg_width - floor( $bottom * $jpeg_width );
|
||||
|
||||
$width = $jpeg_width - ( $top_pixels + $bottom_pixels );
|
||||
$height = $jpeg_height - ( $left_pixels + $right_pixels );
|
||||
|
||||
$area_left = ( $width + $deskew_padding*2 )."x".( $height + $deskew_padding*2 )."+".( $bottom_pixels - $deskew_padding )."+".( $left_pixels - $deskew_padding );
|
||||
$area_right = ( $width + $deskew_padding*2 )."x".( $height + $deskew_padding*2 )."+".( $top_pixels - $deskew_padding )."+".( $right_pixels - $deskew_padding );
|
||||
|
||||
//echo "\n\n(Area left = ".$area_left.", Area right = ".$area_right.")";
|
||||
|
||||
$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;
|
||||
} else {
|
||||
$cmd = "convert ".$file." -auto-orient -crop ".$area_left." -level ".$deskew_contrast."%,".(100-$deskew_contrast)."% -colorspace Gray -resize ".$size." ".$dmfile;
|
||||
}
|
||||
|
||||
$msg = "Creating dmap for ".$file;
|
||||
$thread[] = array($msg, $cmd);
|
||||
|
||||
echo ".";
|
||||
|
||||
} else {
|
||||
|
||||
$thread[] = array("Dmap for ".$file." already exists", "true");
|
||||
|
||||
echo "o";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
if (is_array($thread)) {
|
||||
|
||||
msg("Creating dmaps with ".$xt." threads");
|
||||
multiexec($thread,$xt);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@@ -817,45 +971,73 @@ if (!args("nomap")) {
|
||||
|
||||
}
|
||||
|
||||
if (shell_exec("exiftool -s -s -s -CropAngle ".$files[0]." 2>&1")) {
|
||||
msg("Crop angle detected on ".$files[0].", continue?",2);
|
||||
}
|
||||
$thread = null;
|
||||
|
||||
echo "\n";
|
||||
msg("Detecting skew...");
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
if (args("nomap")) {
|
||||
$dmfile = $file;
|
||||
} else {
|
||||
$dmfile = "scratch/".basename($file, ".jpg")."_dmap.jpg";
|
||||
$ext = pathinfo($file,PATHINFO_EXTENSION);
|
||||
$dmfile = "scratch/".basename($file, ".".$ext)."_dmap.jpg";
|
||||
}
|
||||
|
||||
$result = shell_exec("deskew -o /tmp/null -l 99 \"".$dmfile."\" 2>&1");
|
||||
$arr = explode("Skew angle found: ", $result);
|
||||
$angle = substr($arr[1], 0, 4);
|
||||
echo $file.": ".$angle;
|
||||
$msg = $file.": ".$angle;
|
||||
if ($angle > $deskew_max_angle | $angle < ($deskew_max_angle*-1)) {
|
||||
echo " (too big)";
|
||||
$msg .= " (too big)";
|
||||
} else {
|
||||
$angles[$file] = $angle;
|
||||
}
|
||||
echo "\n";
|
||||
msg($msg);
|
||||
}
|
||||
|
||||
// echo "\nWriting angles to EXIF: ";
|
||||
//
|
||||
// foreach ($files as $file) {
|
||||
//
|
||||
// if (isset($angles[$file])) {
|
||||
// exec("exiftool -overwrite_original -XMP-crs:CropAngle=".$angles[$file]." ".$file);
|
||||
// echo ".";
|
||||
// } else {
|
||||
// // erase top edge crop to indicate rotation was not applied
|
||||
// exec("exiftool -overwrite_original -XMP-crs:CropTop=0 ".$file." 2>&1");
|
||||
// }
|
||||
// }
|
||||
echo "\n\n";
|
||||
|
||||
// }
|
||||
echo "Checking for existing rotation: ";
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
if(shell_exec("exiftool -s -s -s -CropAngle ".$file." 2>&1")) {
|
||||
|
||||
$msg = $file." already has a CropAngle";
|
||||
$cmd = "true";
|
||||
echo "o";
|
||||
|
||||
} else {
|
||||
|
||||
if (isset($angles[$file])) {
|
||||
|
||||
$msg = "Writing CropAngle ".$angles[$file]." to ".$file;
|
||||
$cmd = "exiftool -overwrite_original -XMP-crs:CropAngle=".$angles[$file]." ".$file;
|
||||
echo ".";
|
||||
|
||||
} else {
|
||||
|
||||
$msg = "No CropAngle for ".$file.", writing Rating=1";
|
||||
$cmd = "exiftool -overwrite_original -Rating=1 ".$file;
|
||||
echo ",";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$thread[] = array($msg, $cmd);
|
||||
|
||||
}
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
if (is_array($thread)) {
|
||||
|
||||
msg("Writing EXIF tags with ".$xt." threads");
|
||||
//multiexec($thread,$xt);
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Elif
|
||||
@@ -867,135 +1049,6 @@ echo Welcome("Program name \"".$argv[1]."\" not found");
|
||||
|
||||
die;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Settings
|
||||
|
||||
$tif_dir = "null";
|
||||
$input_dir = "avision_jpg";
|
||||
$xmp_profile = "avision_null.xmp";
|
||||
$compare_threshold = "1";
|
||||
$deskew_max_angle = ".4";
|
||||
$deskew_padding = 80;
|
||||
$deskew_contrast = 20;
|
||||
$deskew_size = 2200;
|
||||
$multicrops = 8;
|
||||
|
||||
|
||||
if (file_exists($tif_dir)) {
|
||||
echo "Checking jpegs: ";
|
||||
foreach (glob($tif_dir."/*") as $file) {
|
||||
$jpegfile = str_replace("tif", "jpg", $file);
|
||||
if (!file_exists($jpegfile)) {
|
||||
exec("convert -quality 95 ".$file." ".$jpegfile);
|
||||
echo ".";
|
||||
} else {
|
||||
echo "o";
|
||||
}
|
||||
}
|
||||
echo "\n\n";
|
||||
}
|
||||
|
||||
$files = glob($input_dir."/*.jpg");
|
||||
|
||||
|
||||
|
||||
//Deskew
|
||||
|
||||
echo "Creating dmaps: ";
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
$dmfile = "scratch/".basename($file, ".jpg")."_dmap.jpg";
|
||||
|
||||
if (file_exists($dmfile)) {
|
||||
|
||||
echo "o";
|
||||
|
||||
} else {
|
||||
|
||||
//$jpeg_width = "7228";
|
||||
//$jpeg_height = "9000";
|
||||
|
||||
$parts = chop(shell_exec("exiftool -s -s -s -XMP-crs:CropTop -XMP-crs:CropRight -XMP-crs:CropLeft -XMP-crs:CropBottom ".$file." 2>&1"));
|
||||
list($top, $right, $left, $bottom) = explode("\n", $parts);
|
||||
if (!$top | !$right | !$left | !$bottom) { echo $file." missing crop information!\n"; die; }
|
||||
|
||||
$jpeg_width = chop(shell_exec("exiftool -s -s -s -ImageWidth ".$files[0]." 2>&1"));
|
||||
$jpeg_height = chop(shell_exec("exiftool -s -s -s -ImageHeight ".$files[0]." 2>&1"));
|
||||
|
||||
$top_pixels = floor( $jpeg_height * $top );
|
||||
$bottom_pixels = $jpeg_height - floor( $bottom * $jpeg_height );
|
||||
$left_pixels = floor( $jpeg_width * $left );
|
||||
|
||||
$width = $jpeg_width - $left_pixels;
|
||||
$height = $jpeg_height - ( $top_pixels + $bottom_pixels );
|
||||
|
||||
$area_left = ( $width + $deskew_padding )."x".( $height + $deskew_padding*2 )."+0+".( $bottom_pixels - $deskew_padding );
|
||||
$area_right = ( $width + $deskew_padding )."x".( $height + $deskew_padding*2 )."+".( $left_pixels - $deskew_padding )."+".( $top_pixels - $deskew_padding );
|
||||
|
||||
//echo "(Area left = ".$area_left.", ";
|
||||
//echo "Area right = ".$area_right.")";
|
||||
|
||||
$size = $deskew_size."x".$deskew_size;
|
||||
|
||||
if (substr(basename($file), 0, 3) % 2 == 0) {
|
||||
exec("convert ".$file." -auto-orient -crop ".$area_right." -level ".$deskew_contrast."%,".(100-$deskew_contrast)."% -colorspace Gray -resize ".$size." ".$dmfile);
|
||||
} else {
|
||||
exec("convert ".$file." -auto-orient -crop ".$area_left." -level ".$deskew_contrast."%,".(100-$deskew_contrast)."% -colorspace Gray -resize ".$size." ".$dmfile);
|
||||
}
|
||||
echo ".";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
if (shell_exec("exiftool -s -s -s -CropAngle ".$files[0]." 2>&1")) {
|
||||
echo "CropAngle detected, skipping deskew.\n";
|
||||
} else {
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
$dmfile = "scratch/".basename($file, ".jpg")."_dmap.jpg";
|
||||
$result = shell_exec("deskew -o /tmp/null -l 99 \"".$dmfile."\" 2>&1");
|
||||
$arr = explode("Skew angle found: ", $result);
|
||||
$angle = substr($arr[1], 0, 4);
|
||||
echo $file.": ".$angle;
|
||||
if ($angle > $deskew_max_angle | $angle < ($deskew_max_angle*-1)) {
|
||||
echo " (too big)";
|
||||
} else {
|
||||
$angles[$file] = $angle;
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
echo "\nWriting angles to EXIF: ";
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
if (isset($angles[$file])) {
|
||||
exec("exiftool -overwrite_original -XMP-crs:CropAngle=".$angles[$file]." ".$file);
|
||||
echo ".";
|
||||
} else {
|
||||
// erase top edge crop to indicate rotation was not applied
|
||||
exec("exiftool -overwrite_original -XMP-crs:CropTop=0 ".$file." 2>&1");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// check bridge labels
|
||||
// for i in *; do exiftool -s -s -s -Label $i; done
|
||||
|
||||
|
||||
Reference in New Issue
Block a user