Init
This commit is contained in:
72
README.md
72
README.md
@@ -1,2 +1,74 @@
|
|||||||
# Leaf
|
# Leaf
|
||||||
|
|
||||||
|
```man
|
||||||
|
USAGE: leaf [mode] [-options] directory
|
||||||
|
|
||||||
|
Modes:
|
||||||
|
autocrop crop using row/column brightness method
|
||||||
|
-levels=<params> levels adjustment for resulting image (ex. "0-253,0-2,0-255")
|
||||||
|
-trim=<t,r,l,b> pixels to trim from top, right, left, bottom
|
||||||
|
build combine images into a pdf with img2pdf
|
||||||
|
clean remove scratch files
|
||||||
|
crop define EXIF crop values using template files
|
||||||
|
-crops=<num> (6) specify how many files to use
|
||||||
|
desort remove image sequence prefix
|
||||||
|
deskew detect rotation angles
|
||||||
|
-max=<num> (.4) angles greater than this value are ignored
|
||||||
|
-pad=<num> (80) pixels to pad around crop area
|
||||||
|
-contrast=<num> (20) levels attenuation
|
||||||
|
-size=<num> (2200) dmap size in pixels
|
||||||
|
-nomap don't use dmaps
|
||||||
|
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-2,0-255")
|
||||||
|
-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-2,0-255")
|
||||||
|
-width=<pixels> (300) spine width in pixels
|
||||||
|
-q=<0-100> (auto) jpeg quality, default read from source or 95
|
||||||
|
divide wrapper for imagemagick Divide_Src
|
||||||
|
-map=<file> specify brightness file
|
||||||
|
-mpush=<levels> levels for map (ex. "0-253,0-2,0-255") or "auto"
|
||||||
|
-blur=<pixels> apply in-place blur to map (slow/dumb)
|
||||||
|
-levels=<params> levels adjustment for resulting image (ex. "0-253,0-2,0-255")
|
||||||
|
-q=<quality> (95) quality out of 100
|
||||||
|
-pages map file is for LR rotated pages
|
||||||
|
-mix=<0-100> percentage mix with original (90% = mostly og)
|
||||||
|
dupes Find duplicate images using computed PHASH on thumbnails
|
||||||
|
-threshold=<num> (10) match threshold
|
||||||
|
-walk=<num> (5) comparison scope (compare n image to n, n+1, n+2, etc)
|
||||||
|
fixpdf de-rotate all pages in a pdf
|
||||||
|
-file=<pdf> pdf file in target dir
|
||||||
|
generate create final jpg images for pdf creation
|
||||||
|
-pixels=<num> scale to x pixels on longest side
|
||||||
|
-inches=<num> set dpi to x inches on longest side
|
||||||
|
-q=<0-100> (90) jpeg quality
|
||||||
|
-levels=<params> photoshop levels adjustment (ex. "0-253,0-2,0-255")
|
||||||
|
-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")
|
||||||
|
-skipc skip color images
|
||||||
|
-skipg skip grayscale images
|
||||||
|
-skipb skip bitmap images
|
||||||
|
match move files and set crop values to match source dir
|
||||||
|
-source=<dir> read FROM dir
|
||||||
|
profile apply xmp profile to images (requires exiv2 > 0.25)
|
||||||
|
-file=<file> xmp profile
|
||||||
|
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> (90) rotation angle
|
||||||
|
-q=<0-100> (auto) 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
|
||||||
|
sort sort files as AAABBB -> ABABAB
|
||||||
|
-m=<num> (auto) specify midpoint (cover image)
|
||||||
|
-prerotated images are already rotated
|
||||||
|
strip strip exif crop values from images with exiftool
|
||||||
|
```
|
||||||
424
leaf.php
Normal file
424
leaf.php
Normal file
@@ -0,0 +1,424 @@
|
|||||||
|
#!/usr/bin/php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// Leaf - Tools for Book Scans
|
||||||
|
$version = "0.5.8";
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
|
||||||
|
function Welcome($msg) {
|
||||||
|
global $version;
|
||||||
|
$out = "\033[1;1H\033[2J"; // clear screen
|
||||||
|
$out .= bashcolor("Leaf Version: ".$version, "white", "magenta")." ".shell_exec("date");
|
||||||
|
$out .= $msg."\n\n";
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getClosest($search, $arr) {
|
||||||
|
$closest = null;
|
||||||
|
foreach ($arr as $item) {
|
||||||
|
if ($closest === null || abs($search - $closest) > abs($item - $search)) {
|
||||||
|
$closest = $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $closest;
|
||||||
|
}
|
||||||
|
|
||||||
|
$colors = array_merge(array("blue","green","cyan","red","purple","brown","yellow","light blue","light green", "light cyan", "light red", "light purple"),array_fill(0, 500, "light gray"));
|
||||||
|
|
||||||
|
function bashcolor($str,$fgcolor="white",$bgcolor=null) {
|
||||||
|
static $fgcolors = array('black' => '0;30', 'dark gray' => '1;30', 'blue' => '0;34', 'light blue' => '1;34', 'green' => '0;32', 'light green' => '1;32', 'cyan' => '0;36', 'light cyan' => '1;36', 'red' => '0;31', 'light red' => '1;31', 'purple' => '0;35', 'light purple' => '1;35', 'brown' => '0;33', 'yellow' => '1;33', 'light gray' => '0;37', 'white' => '1;37', 'underline' => '4');
|
||||||
|
static $bgcolors = array('black' => '40', 'red' => '41', 'green' => '42', 'yellow' => '43', 'blue' => '44', 'magenta' => '45', 'cyan' => '46', 'light gray' => '47');
|
||||||
|
$out="";
|
||||||
|
if (!isset($fgcolors[$fgcolor])) { $fgcolor='white'; }
|
||||||
|
if (!isset($bgcolors[$bgcolor])) { $bgcolor=null; }
|
||||||
|
if ($fgcolor) { $out .= "\033[{$fgcolors[$fgcolor]}m"; }
|
||||||
|
if ($bgcolor) { $out .= "\033[{$bgcolors[$bgcolor]}m"; }
|
||||||
|
$out .= $str."\033[0m";
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Convert: convert a dir of tiffs to jpeg for processing
|
||||||
|
//////////////////////
|
||||||
|
if ($argv[1] == "convert") {
|
||||||
|
echo Welcome("Convert to jpeg");
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Elif
|
||||||
|
//////////////////////
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Header
|
||||||
|
|
||||||
|
echo "\033[1;1H\033[2J"; // clear screen
|
||||||
|
echo "Welcome to avision_jpg version ".$version."\n";
|
||||||
|
echo "Processing ".basename($_SERVER["PWD"])."\n";
|
||||||
|
echo "---------------------------------------------------------------------------\n\n";
|
||||||
|
|
||||||
|
// Dirs
|
||||||
|
|
||||||
|
if (!file_exists($input_dir)) {
|
||||||
|
if (!file_exists($tif_dir)) {
|
||||||
|
echo "No input dirs, exiting\n";
|
||||||
|
die;
|
||||||
|
} else {
|
||||||
|
mkdir ($input_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists($xmp_profile)) {
|
||||||
|
echo "No xmp profile, exiting\n";
|
||||||
|
die;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists("scratch")) {
|
||||||
|
mkdir("scratch");
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
// Renumber files
|
||||||
|
|
||||||
|
if (glob($input_dir."/001-*.jpg")) {
|
||||||
|
|
||||||
|
echo "It appears files have been numbered, skipping.\n";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
echo "Checking thumbnails: ";
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$tnfile = "scratch/".basename($file, ".jpg")."_thumb.jpg";
|
||||||
|
if (!file_exists($tnfile)) {
|
||||||
|
echo ".";
|
||||||
|
exec("vipsthumbnail ".$file." --size 160x160 -o ../".$tnfile." 2>&1");
|
||||||
|
} else {
|
||||||
|
echo "o";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n\nPlease specify the midpoint (cover image) or enter \"none\"\n";
|
||||||
|
$midpoint_key = trim(fgets(fopen("php://stdin","r")));
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
if ($midpoint_key != "none") {
|
||||||
|
if (!glob($input_dir."/*".$midpoint_key."*.jpg")) {
|
||||||
|
echo "Can't find midpoint matching '".$midpoint_key."', exiting\n";
|
||||||
|
die;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$tnfile = "scratch/".basename($file, ".jpg")."_thumb.jpg";
|
||||||
|
if ($i > 1) {
|
||||||
|
$prev = $files[array_search($file,$files)-1];
|
||||||
|
$prevtnfile = "scratch/".basename($prev, ".jpg")."_thumb.jpg";
|
||||||
|
$thingy = shell_exec("compare -metric ae -fuzz '10%' ".$tnfile." ".$prevtnfile." /tmp/null 2>&1");
|
||||||
|
echo $tnfile." <> ".$prevtnfile." = ".$thingy."\n";
|
||||||
|
if ($thingy < $compare_threshold) {
|
||||||
|
echo "Possible duplicates: ".basename($file)." <> ".basename($prev).". Press return to compare.";
|
||||||
|
fgets(fopen("php://stdin","r"));
|
||||||
|
exec("open ".$prev." ".$file." -b com.apple.Preview");
|
||||||
|
echo "0 (default) = Keep ".basename($file)."; 1 = Keep ".basename($prev)."; 2 = Keep both files\nResponse: ";
|
||||||
|
$line = trim(fgets(fopen("php://stdin","r")));
|
||||||
|
if(!$line){
|
||||||
|
echo "Keeping ".basename($file)."\n";
|
||||||
|
unset($files[array_search($prev,$files)]);
|
||||||
|
} elseif ($line == 1) {
|
||||||
|
echo "Keeping file ".basename($prev)."\n";
|
||||||
|
unset($files[array_search($file,$files)]);
|
||||||
|
} elseif ($line == 2) {
|
||||||
|
echo "Keeping both files\n";
|
||||||
|
} else {
|
||||||
|
echo "Invalid response, skipping\n";
|
||||||
|
}
|
||||||
|
echo "Resuming...\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
$e = 2; $o = 1;
|
||||||
|
|
||||||
|
if ($midpoint_key == "none") {
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$new = $input_dir."/".sprintf('%03d',$o)."-".basename($file);
|
||||||
|
$ops[$o] = array($file,$new);
|
||||||
|
$o++;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$num = substr($file, -7, 3);
|
||||||
|
if ($num < $midpoint_key) {
|
||||||
|
$new = $input_dir."/".sprintf('%03d',$e)."-".basename($file);
|
||||||
|
$ops[$e] = array($file,$new);
|
||||||
|
$e = $e+2;
|
||||||
|
} else {
|
||||||
|
$new = $input_dir."/".sprintf('%03d',$o)."-".basename($file);
|
||||||
|
$ops[$o] = array($file,$new);
|
||||||
|
$o = $o+2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ksort($ops);
|
||||||
|
|
||||||
|
foreach ($ops as $op) {
|
||||||
|
echo $op[0]." will be renamed ".$op[1]."\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\nType \"ok\" to skip comparison\n\n";
|
||||||
|
|
||||||
|
while (trim(fgets(fopen("php://stdin","r"))) != "ok") {
|
||||||
|
echo "Press return to compare another spread or type \"ok\" when finished\n\n";
|
||||||
|
$start = floor(rand(count($ops)-(count($ops)*.2),count($ops))/2)*2;
|
||||||
|
$left = $ops[$start][0];
|
||||||
|
$right = $ops[$start+1][0];
|
||||||
|
exec("open ".$left." ".$right." -b com.apple.Preview");
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\nMoving files!\n";
|
||||||
|
foreach ($ops as $key => $op) {
|
||||||
|
rename($op[0],$op[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$files = glob($input_dir."/[0-9][0-9][0-9]-*.jpg");
|
||||||
|
|
||||||
|
// Apply profile and orientation
|
||||||
|
|
||||||
|
if (shell_exec("exiftool -s -s -s -Orientation ".$files[0]." 2>&1")) {
|
||||||
|
echo "\nOrientation already applied, skipping.\n\n";
|
||||||
|
} else {
|
||||||
|
echo "\nApplying XMP profile & orientation: ";
|
||||||
|
foreach ($files as $file) {
|
||||||
|
exec("cat ".$xmp_profile." | exiv2 -iXX- ".$file);
|
||||||
|
if (substr(basename($file), 0, 3) % 2 != 0) {
|
||||||
|
exec("exiftool -overwrite_original -n -Orientation=3 ".$file);
|
||||||
|
}
|
||||||
|
echo ".";
|
||||||
|
}
|
||||||
|
echo "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define crop area
|
||||||
|
|
||||||
|
while (isset($proceed) != true) {
|
||||||
|
|
||||||
|
echo "Set crop areas: [x] to skip, [d] to define, [s] to scan.\n";
|
||||||
|
$input = trim(fgets(fopen("php://stdin","r")));
|
||||||
|
|
||||||
|
switch ($input) {
|
||||||
|
|
||||||
|
case "x":
|
||||||
|
$proceed = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "s":
|
||||||
|
echo "Checking Crops: ";
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$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) {
|
||||||
|
$key = preg_replace("/[^0-9]/","",substr($file, -8, 4));
|
||||||
|
$crops[$key]['top'] = $top;
|
||||||
|
$crops[$key]['right'] = $right;
|
||||||
|
$crops[$key]['left'] = $left;
|
||||||
|
$crops[$key]['bottom'] = $bottom;
|
||||||
|
echo "*";
|
||||||
|
} else {
|
||||||
|
echo "-";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$proceed = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "d":
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$seq[preg_replace("/[^0-9]/","",substr($file, -8, 4))] = $file;
|
||||||
|
}
|
||||||
|
ksort($seq);
|
||||||
|
$seg = floor(count($seq)/$multicrops)-1;
|
||||||
|
$picks = array();
|
||||||
|
foreach (range(1, $multicrops, 1) as $val) {
|
||||||
|
$picks[] = array_values(array_slice($seq, $val*$seg, 1))[0];
|
||||||
|
}
|
||||||
|
foreach ($picks as $file) {
|
||||||
|
echo $file."\n";
|
||||||
|
}
|
||||||
|
trim(fgets(fopen("php://stdin","r")));
|
||||||
|
exec("open ".implode(" ",$picks)." -b com.adobe.Photoshop");
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($crops) && count($crops) > count($files)/2) {
|
||||||
|
echo "\nIt looks like multicrop has already been applied, skipping.\n\n";
|
||||||
|
} elseif (isset($crops) && count($crops)) {
|
||||||
|
echo "Crop areas have been detected as follows. Press return to write to files.\n";
|
||||||
|
foreach ($crops as $key => $parts) {
|
||||||
|
echo "\n";
|
||||||
|
echo $key."\t\tTop: ".bashcolor($parts['top'], $colors[array_search($key,array_keys($crops))]);
|
||||||
|
echo "\tRight: ".bashcolor($parts['right'], $colors[array_search($key,array_keys($crops))]);
|
||||||
|
echo "\tLeft: ".bashcolor($parts['left'], $colors[array_search($key,array_keys($crops))]);
|
||||||
|
echo "\tBottom: ".bashcolor($parts['bottom'], $colors[array_search($key,array_keys($crops))]);
|
||||||
|
}
|
||||||
|
echo "\n";
|
||||||
|
trim(fgets(fopen("php://stdin","r")));
|
||||||
|
echo "Crop Mapping:\n";
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$key = preg_replace("/[^0-9]/","",substr($file, -8, 4));
|
||||||
|
$closekey = getClosest($key, array_keys($crops));
|
||||||
|
$parts = $crops[$closekey];
|
||||||
|
echo "\n";
|
||||||
|
echo $file."\t\tTop: ".bashcolor($parts['top'], $colors[array_search($closekey,array_keys($crops))]);
|
||||||
|
echo "\tRight: ".bashcolor($parts['right'], $colors[array_search($closekey,array_keys($crops))]);
|
||||||
|
echo "\tLeft: ".bashcolor($parts['left'], $colors[array_search($closekey,array_keys($crops))]);
|
||||||
|
echo "\tBottom: ".bashcolor($parts['bottom'], $colors[array_search($closekey,array_keys($crops))]);
|
||||||
|
exec("exiftool -overwrite_original -XMP-crs:HasCrop=1 -XMP-crs:AlreadyApplied=0 -XMP-crs:CropTop=".$parts['top']." -XMP-crs:CropRight=".$parts['right']." -XMP-crs:CropLeft=".$parts['left']." -XMP-crs:CropBottom=".$parts['bottom']." ".$file);
|
||||||
|
}
|
||||||
|
echo "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open files
|
||||||
|
|
||||||
|
echo "\nFinished! Press return to open all files in Photoshop\n";
|
||||||
|
fgets(fopen("php://stdin","r"));
|
||||||
|
exec("open ".implode(" ",$files)." -b com.adobe.Photoshop");
|
||||||
|
|
||||||
|
?>
|
||||||
Reference in New Issue
Block a user