0.8.6
This commit is contained in:
199
leaf.php
199
leaf.php
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Leaf - Tools for Book Scans
|
// Leaf - Tools for Book Scans
|
||||||
$version = "0.8.4";
|
$version = "0.8.6";
|
||||||
$debug = 1;
|
$debug = 1;
|
||||||
$time_start = microtime(true);
|
$time_start = microtime(true);
|
||||||
date_default_timezone_set("America/Los_Angeles");
|
date_default_timezone_set("America/Los_Angeles");
|
||||||
@@ -23,13 +23,25 @@ function levels_ps_to_imgk($string) {
|
|||||||
if (count($parts) != 3) {
|
if (count($parts) != 3) {
|
||||||
msg("Invalid levels string",1);
|
msg("Invalid levels string",1);
|
||||||
} else {
|
} else {
|
||||||
$black = ($parts[0]/253)."%";
|
$black = (number_format(($parts[0]/253),5)*100)."%";
|
||||||
$white = (number_format(($parts[1]/255),5)*100)."%";
|
$white = (number_format(($parts[1]/255),5)*100)."%";
|
||||||
$gamma = $parts[2];
|
$gamma = $parts[2];
|
||||||
return $black.",".$white.",".$gamma;
|
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) {
|
function multiexec($thread, $x, $null = true) {
|
||||||
global $debug;
|
global $debug;
|
||||||
$batch = array_chunk($thread,$x);
|
$batch = array_chunk($thread,$x);
|
||||||
@@ -45,14 +57,15 @@ function multiexec($thread, $x, $null = true) {
|
|||||||
} else {
|
} else {
|
||||||
$echo = implode("", $msg);
|
$echo = implode("", $msg);
|
||||||
}
|
}
|
||||||
if ($null) {
|
if ($debug || !$null) {
|
||||||
$exec = implode(" > /dev/null & ",$cmd)." & wait";
|
$pipe = "";
|
||||||
} else {
|
} else {
|
||||||
$exec = implode(" & ",$cmd)." & wait";
|
$pipe = " 2>&1";
|
||||||
}
|
}
|
||||||
|
$exec = implode($pipe." & ",$cmd).$pipe." & wait";
|
||||||
echo $echo;
|
echo $echo;
|
||||||
if ($debug) {
|
if ($debug) {
|
||||||
echo "\n\n".$exec."\n\n";
|
echo "\n".str_replace($pipe." & ", "\n\n", $exec)."\n";
|
||||||
}
|
}
|
||||||
@exec($exec);
|
@exec($exec);
|
||||||
}
|
}
|
||||||
@@ -118,6 +131,10 @@ function args($query) {
|
|||||||
return chop($argv[count($argv)-1], "/")."/";
|
return chop($argv[count($argv)-1], "/")."/";
|
||||||
} elseif ($query == "levels" && isset($opt['levels'])) {
|
} elseif ($query == "levels" && isset($opt['levels'])) {
|
||||||
return levels_ps_to_imgk($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])) {
|
} elseif (isset($opt[$query])) {
|
||||||
return $opt[$query];
|
return $opt[$query];
|
||||||
} else {
|
} else {
|
||||||
@@ -191,7 +208,8 @@ deskew detect rotation angles
|
|||||||
depaper divide page with itself using mask (better despine)
|
depaper divide page with itself using mask (better despine)
|
||||||
-mask=<file> mask file for spine-left image
|
-mask=<file> mask file for spine-left image
|
||||||
-mpush=<levels> levels for divide map (ex. \"0-253,0-255,0-2\")
|
-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
|
despine remove shadow from spine
|
||||||
-levels=<params> levels for overlay (ex. \"0-253,0-255,0-2\")
|
-levels=<params> levels for overlay (ex. \"0-253,0-255,0-2\")
|
||||||
-width=<pixels> (300) spine width in pixels
|
-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\")
|
-levels=<params> photoshop levels adjustment (ex. \"0-253,0-255,0-2\")
|
||||||
-px=<num> png size multiplier
|
-px=<num> png size multiplier
|
||||||
-plevels=<params> png levels adjustment (otherwise calculated from adjust)
|
-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
|
match move files and set crop values to match source dir
|
||||||
-source=<dir> read FROM 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)
|
profile apply xmp profile to images (requires exiv2 > 0.25)
|
||||||
-file=<file> xmp profile
|
-file=<file> xmp profile
|
||||||
resort reorder image sequence by adding a new image
|
resort reorder image sequence by adding a new image
|
||||||
@@ -238,6 +261,34 @@ strip strip exif crop values from images with exiftool
|
|||||||
echo $help;
|
echo $help;
|
||||||
fin();
|
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
|
// Note: Brightness_table
|
||||||
//////////////////////
|
//////////////////////
|
||||||
@@ -265,6 +316,12 @@ if (!file_exists(args("mask"))) {
|
|||||||
msg("Can't open mask",1);
|
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."/*.*"))) {
|
if (count(glob($dest."/*.*"))) {
|
||||||
msg("Files already exist in ".$dest.". Move to trash?",2);
|
msg("Files already exist in ".$dest.". Move to trash?",2);
|
||||||
exec("/opt/local/bin/trash -a ".$dest);
|
exec("/opt/local/bin/trash -a ".$dest);
|
||||||
@@ -273,17 +330,32 @@ if (count(glob($dest."/*.*"))) {
|
|||||||
mkdir($dest);
|
mkdir($dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msg("Building threads...");
|
||||||
|
|
||||||
$files = glob(args("dir")."*.*");
|
$files = glob(args("dir")."*.*");
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
$ext = pathinfo($file,PATHINFO_EXTENSION);
|
$ext = pathinfo($file,PATHINFO_EXTENSION);
|
||||||
$result = $dest."/".basename($file);
|
$result = $dest."/".basename($file);
|
||||||
list ($width, $height) = getimagesize($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) {
|
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 {
|
} 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;
|
$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);
|
$thread[] = array($msg, $cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +420,6 @@ foreach ($files as $file) {
|
|||||||
$quality = $default_quality;
|
$quality = $default_quality;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$msg = $file." matched, despining...";
|
$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);
|
$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")) {
|
if (args("mix")) {
|
||||||
@@ -429,7 +500,7 @@ fin();
|
|||||||
// Note: Generate
|
// Note: Generate
|
||||||
//////////////////////
|
//////////////////////
|
||||||
} elseif (args("app") == "generate") {
|
} elseif (args("app") == "generate") {
|
||||||
echo Welcome("Generate final jpg images");
|
echo Welcome("Generate final images");
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
$dest = rtrim(args("dir"), '/')."_generated";
|
$dest = rtrim(args("dir"), '/')."_generated";
|
||||||
@@ -484,7 +555,7 @@ foreach ($files as $file) {
|
|||||||
}
|
}
|
||||||
if ($parts[0] == "bitmap") {
|
if ($parts[0] == "bitmap") {
|
||||||
$bitmap[] = array($file,$width,$height);
|
$bitmap[] = array($file,$width,$height);
|
||||||
} elseif ($parts[1] == "True") {
|
} elseif ($parts[1] == "True" || $parts[0] == "grayscale") {
|
||||||
$grey[] = array($file,$width,$height);
|
$grey[] = array($file,$width,$height);
|
||||||
} elseif ($ratio < 3) {
|
} elseif ($ratio < 3) {
|
||||||
$color[] = array($file,$width,$height);
|
$color[] = array($file,$width,$height);
|
||||||
@@ -559,13 +630,15 @@ if (isset($spine)) {
|
|||||||
|
|
||||||
foreach ($jpg as $parts) {
|
foreach ($jpg as $parts) {
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
$file = $parts[0];
|
$file = $parts[0];
|
||||||
$output = $dest."/".basename($file);
|
$output = $dest."/".basename($file);
|
||||||
|
|
||||||
if (isset($parts[3]) && $parts[3] == 1) {
|
if (isset($parts[3]) && $parts[3] == 1) {
|
||||||
|
|
||||||
$msg = "Processing greyscale page ".$file." @ ".$dims."!";
|
$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) {
|
} elseif (isset($parts[3]) && $parts[3] == 2) {
|
||||||
|
|
||||||
@@ -578,6 +651,11 @@ foreach ($jpg as $parts) {
|
|||||||
$msg = "Processing color page ".$file." @ ".$dims."!";
|
$msg = "Processing color page ".$file." @ ".$dims."!";
|
||||||
$cmd = "convert -resize ".$dims."\! ";
|
$cmd = "convert -resize ".$dims."\! ";
|
||||||
|
|
||||||
|
if (args("modulate")) {
|
||||||
|
$msg .= " (".args("modulate").")";
|
||||||
|
$cmd .= "-modulate ".args("modulate")." ";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args("levels")) {
|
if (args("levels")) {
|
||||||
@@ -585,6 +663,11 @@ foreach ($jpg as $parts) {
|
|||||||
$cmd .= "-level ".args("levels")." ";
|
$cmd .= "-level ".args("levels")." ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args("unsharp")) {
|
||||||
|
$msg .= " (".args("unsharp").")";
|
||||||
|
$cmd .= "-unsharp ".args("unsharp")." ";
|
||||||
|
}
|
||||||
|
|
||||||
$msg .= " [Q=".$quality."]";
|
$msg .= " [Q=".$quality."]";
|
||||||
$cmd .= "-quality ".$quality." ".$file." ".$output;
|
$cmd .= "-quality ".$quality." ".$file." ".$output;
|
||||||
|
|
||||||
@@ -602,14 +685,7 @@ multiexec($thread_b,$xt);
|
|||||||
|
|
||||||
if (isset($bitmap)) {
|
if (isset($bitmap)) {
|
||||||
|
|
||||||
foreach ($bitmap as $parts) {
|
if (!args("pt")) {
|
||||||
|
|
||||||
$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("levels")) {
|
if (args("levels")) {
|
||||||
$adjust = args("levels");
|
$adjust = args("levels");
|
||||||
@@ -625,13 +701,74 @@ if (isset($bitmap)) {
|
|||||||
if (args("plevels")) {
|
if (args("plevels")) {
|
||||||
$radjust = args("plevels");
|
$radjust = args("plevels");
|
||||||
} else {
|
} else {
|
||||||
$radjust = ($black+60)."%".",".($white-15)."%".",".($gamma-.7);
|
$radjust = ($black+60)."%".",".($white-15)."%".",".($gamma-.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
$msg .= " (".$radjust.")";
|
msg("Checking bitmap output for brightness...");
|
||||||
$cmd .= "-level ".$radjust." ";
|
$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_c[] = array($msg, $cmd);
|
||||||
$thread_d[] = array(".","exiftool -overwrite_original -PixelsPerUnitX=".$pngdpi." -PixelsPerUnitY=".$pngdpi." ".$output);
|
$thread_d[] = array(".","exiftool -overwrite_original -PixelsPerUnitX=".$pngdpi." -PixelsPerUnitY=".$pngdpi." ".$output);
|
||||||
@@ -1560,10 +1697,16 @@ if (!args("nomap")) {
|
|||||||
|
|
||||||
$size = $deskew_size."x".$deskew_size;
|
$size = $deskew_size."x".$deskew_size;
|
||||||
|
|
||||||
if (substr(basename($file), 0, 3) % 2 == 0) {
|
if (strtolower($ext) == "dng") {
|
||||||
$cmd = "convert ".$file." -auto-orient -crop ".$area_right." -level ".$deskew_contrast."%,".(100-$deskew_contrast)."% -colorspace Gray -resize ".$size." ".$dmfile;
|
$adj = "0%,".(100-$deskew_contrast)."%";
|
||||||
} else {
|
} 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;
|
$msg = "Creating dmap for ".$file;
|
||||||
|
|||||||
Reference in New Issue
Block a user