Annotation of scaleomat/scaleomat.pl, revision 1.4

1.1       casties     1: #!/usr/bin/perl
                      2: 
1.3       casties     3: #  Copyright (C) 2003,2004 Robert Casties, IT-Group MPIWG
                      4: # 
                      5: #  This program is free software; you can redistribute it and/or modify it
                      6: #  under the terms of the GNU General Public License as published by the Free
                      7: #  Software Foundation; either version 2 of the License, or (at your option)
                      8: #  any later version.
                      9: # 
                     10: #  Please read license.txt for the full details. A copy of the GPL may be found
                     11: #  at http://www.gnu.org/copyleft/lgpl.html
                     12: # 
                     13: #  You should have received a copy of the GNU General Public License along with
                     14: #  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
                     15: #  Place, Suite 330, Boston, MA 02111-1307 USA
                     16: 
1.2       casties    17: use strict;
1.4     ! casties    18: use sigtrap qw(die normal-signals);
1.2       casties    19: 
                     20: # MPIWG libraries
                     21: use lib '/usr/local/mpiwg/scripts';
                     22: use MPIWGlib;
                     23: 
                     24: 
1.1       casties    25: $| = 1; # unblock IO
                     26: 
1.4     ! casties    27: my $version = "V0.9.3 (ROC 18.11.2004)";
1.1       casties    28: 
                     29: $debug = 0;
                     30: 
1.2       casties    31: my $simulate = 0;
                     32: 
                     33: my $do_descend = 1;
1.1       casties    34: 
1.2       casties    35: my $dir_perm = 0775;
                     36: my $file_perm = 0664;
1.1       casties    37: 
                     38: umask 000; # to make shure we can actually use these perms
                     39: 
1.2       casties    40: my $overwrite = 0; # overwrite already converted files
1.1       casties    41: 
1.2       casties    42: # image file extensions and formats
                     43: my %img_type_ext = ("tif" => "TIFF", "tiff" => "TIFF", "gif" => "GIF", 
                     44:        "jpg" => "JPEG", "png" => "PNG");
                     45: # destination image file extensions
                     46: my %target_ext_type = ("TIFF" => "jpg", "JPEG" => "jpg");
                     47: 
                     48: # default scale settings
                     49: my $scalesize = 2048; # pixel of longest side
                     50: my $scale_relative = 0; # scale by relative factor instead of destination size
                     51: my $jpeg_quality = 75; # default JPEG compression quality
                     52: my $use_encoder = 0; # autodetect encoder
                     53: 
                     54: # programs to use
                     55: my $identifier;
                     56: my $tiffinfo;
                     57: my $jpegloader;
                     58: my $tiffloader;
                     59: my $quantizer;
                     60: my $scaler;
                     61: my $jpegwriter;
                     62: my $pngwriter;
                     63: my $converter;
1.1       casties    64: 
                     65: ##########################################################################
                     66: # subroutines
                     67: #
                     68: 
                     69: #
                     70: # checksoft()
                     71: #
                     72: # returns if all necessary external programs are installed
                     73: #
                     74: sub checksoft {
                     75: 
                     76:     my @softdirs = ("/usr/X11R6/bin", "/usr/bin", "/usr/local/bin");
                     77: 
                     78:     $identifier = findfile(\@softdirs, "identify")
                     79:    or die("ABORT: neccessary external program not found: identify");
1.2       casties    80:     $tiffinfo = findfile(\@softdirs, "tiffinfo")
                     81:    or die("ABORT: neccessary external program not found: tiffinfo");
1.1       casties    82:     $jpegloader = findfile(\@softdirs, "jpegtopnm")
                     83:    or die("ABORT: neccessary external program not found: jpegtopnm");
                     84:     $tiffloader = findfile(\@softdirs, "tifftopnm")
                     85:    or die("ABORT: neccessary external program not found: tifftopnm");
                     86:     $quantizer = findfile(\@softdirs, "pbmtopgm")
                     87:    or die("ABORT: neccessary external program not found: pbmtopgm");
                     88:     $scaler = findfile(\@softdirs, "pnmscale")
                     89:    or die("ABORT: neccessary external program not found: pnmscale");
                     90:     $jpegwriter = findfile(\@softdirs, "ppmtojpeg")
                     91:    or die("ABORT: neccessary external program not found: ppmtojpeg");
                     92:     $pngwriter = findfile(\@softdirs, "pnmtopng")
                     93:    or die("ABORT: neccessary external program not found: pnmtopng");
                     94:     $converter = findfile(\@softdirs, "convert")
                     95:    or die("ABORT: neccessary external program not found: convert");
                     96: 
                     97: }
                     98: 
                     99: 
                    100: 
                    101: #
                    102: # findir(\@basedirs, $subdir)
                    103: #
                    104: # check directories in @basedirs+$subdir and return the first existing basedir
                    105: #
                    106: sub findir {
                    107:     my($dirlist, $subdir) = @_;
                    108: 
                    109:     foreach my $dir (@$dirlist) {
                    110:    if (-d "$dir/$subdir") {
                    111:        return "$dir";
                    112:    }
                    113:     }
                    114:     return;
                    115: }
                    116: 
                    117: #
                    118: # findfile(\@basedirs, $filename)
                    119: #
                    120: # check @basedirs+$filename and return the first existing file
                    121: #
                    122: sub findfile {
                    123:     my($dirlist, $fn) = @_;
                    124: 
                    125:     foreach my $dir (@$dirlist) {
                    126:    if (-f "$dir/$fn") {
                    127:        return "$dir/$fn";
                    128:    }
                    129:     }
                    130:     return;
                    131: }
                    132: 
                    133: 
1.4     ! casties   134: sub cleanpath {
        !           135:     my ($path, $startslash) = @_;
        !           136: 
        !           137:     if ($path =~ /^(\/)*(.*?)\/*$/) {
        !           138:    if ($startslash) {
        !           139:        print "$path --> $1$2\n";
        !           140:        return $1 . $2;
        !           141:    } else {
        !           142:        print "$path --> $2\n";
        !           143:        return $2;
        !           144:    }
        !           145:     }
        !           146:     print "hä? $path\n";
        !           147:     return $path;
        !           148: }
        !           149: 
1.1       casties   150: #
1.2       casties   151: # ($basename, $extension) = splitfn($filename)
                    152: #
                    153: # split filename into base and (lowercase) extension
                    154: #
                    155: sub splitfn {
                    156:     my ($filepath) = @_;
                    157:     if ($filepath =~ /^(.*)\.(\w+)$/) {
                    158:    return ($1, lc($2));
                    159:     }
                    160:     return;
                    161: }
                    162: 
                    163: 
                    164: #
1.1       casties   165: # mmkdir($dirname)
                    166: #
                    167: # create directory recursively and check permissions
                    168: #
                    169: sub mmkdir {
                    170:     my($dirname) = @_;
                    171:     my $newdir;
                    172: 
                    173:     # does the directory already exist?
1.2       casties   174:     if (-d $dirname) {
                    175:    chmod $dir_perm, $dirname or do {
1.4     ! casties   176:        logger('WARNING', "unable to change permission on $dirname!");
1.1       casties   177:    };
                    178:    return 1;
                    179:     }
                    180:     # split directory name by levels
                    181:     my @dirlist = split /\//, $dirname;
                    182:     my @newlist = ();
                    183:     my $dir = join("/", @dirlist);
                    184:     # test backwards which directories exist
                    185:     while (not -d $dir) {
1.2       casties   186:    last unless ($dir);
1.1       casties   187:    # move missing elements from the end of @dirlist to @newlist
                    188:    unshift @newlist, pop @dirlist;
                    189:    $dir = join("/", @dirlist);
                    190:     }
                    191:     # create missing directories level by level
                    192:     foreach $newdir (@newlist) {
                    193:    push @dirlist, $newdir;
                    194:    $dir = join("/", @dirlist);
                    195:    mkdir "$dir", $dir_perm or do {
1.2       casties   196:        logger('ERROR', "unable to create $dir!");
1.1       casties   197:        return 0;
                    198:    }
                    199:     }
                    200:     return 1;
                    201: }
                    202: 
                    203: #
1.2       casties   204: # ($type, $width, $height) = identify($filepath)
                    205: #
                    206: sub identify {
                    207:     my ($filepath) = @_;
1.4     ! casties   208:     my $pictype = "";
        !           209:     my $picwidth = 0;
        !           210:     my $picheight = 0;
1.2       casties   211:     my $bitdepth = 0;
                    212:     # use quickident first
                    213:     $pictype = quickident($filepath);
                    214:     # optimize tiff identification
                    215:     if (($pictype)&&($pictype eq 'TIFF')) {
                    216:    logger('DEBUG', "running tiffinfo $tiffinfo");
                    217:    if (open(IDENT, "nice -10 $tiffinfo '$filepath' 2>/dev/null |")) {
                    218:        while (<IDENT>) {
                    219:        chomp;
                    220:        if (/Image Width:\s*(\d+)\s*Image Length:\s*(\d+)/) {
1.4     ! casties   221:            $picwidth = $1 if ($1 > $picwidth);
        !           222:            $picheight = $2 if ($2 > $picheight);
1.2       casties   223:            next;
                    224:        }
                    225:        if (/Bits\/Sample:\s*(\d+)/) {
1.4     ! casties   226:            $bitdepth = $1 if ($1 > $bitdepth);
1.2       casties   227:            next;
                    228:        }
                    229:        }
                    230:        if ($picwidth) {
1.4     ! casties   231:        logger('DEBUG', "TIFF $picwidth x $picheight");
1.2       casties   232:        return ($pictype, $picwidth, $picheight, $bitdepth);
                    233:        }
                    234:    }
                    235:     }
                    236:     # run ident to get image type and dimensions
                    237:     logger('DEBUG', "running identifier $identifier");
                    238:     if (open(IDENT, "nice -10 $identifier -ping -format '%w %h %m\n' '$filepath' 2>/dev/null |")) {
                    239:    my @id = <IDENT>;
                    240:    my $picinfo = $id[0];
                    241:    close IDENT;
                    242:    chomp $picinfo;
                    243:    logger('DEBUG', "PIC is '$picinfo'");
                    244:    if ($picinfo =~ /^(\d+) (\d+) (\w+)$/) {
                    245:        $picwidth = $1;
                    246:        $picheight = $2;
                    247:        $pictype = $3;
                    248:    }
                    249:     } else {
                    250:    logger('DEBUG', "unable to identify $filepath!");
                    251:     }
                    252:     return ($pictype, $picwidth, $picheight, $bitdepth);
                    253: }
                    254: 
                    255: #
                    256: # $type = quickident($filepath);
                    257: #
                    258: sub quickident {
                    259:     my ($filepath) = @_;
                    260:     logger('DEBUG', "running quickident");
                    261:     # look at file extension
                    262:     my ($filebase, $fileext) = splitfn($filepath);
                    263:     if ($fileext) {
                    264:    return $img_type_ext{$fileext};
                    265:     }
                    266:     return;
                    267: }
                    268: 
                    269: 
                    270: #
                    271: # $error = scale_jpeg(\$args);
                    272: #
                    273: # scale JPEG images to JPEG using netpbm tools
1.1       casties   274: #
1.2       casties   275: # args needed: $srcdir, $filename, $destdir, 
                    276: #              $scalesize, $scale_rel, $picwidth, $picheight
1.1       casties   277: #
1.2       casties   278: sub scale_jpeg {
                    279:     my ($args) = @_;
                    280: 
                    281:     my $srcdir = $$args{'srcdir'};
                    282:     my $filename = $$args{'filename'};
                    283:     my $destdir = $$args{'destdir'};
                    284:     my $scalesize = $$args{'scalesize'};
                    285:     my $scale_rel = $$args{'scale_rel'};
                    286:     my $scaleopt;
                    287: 
                    288:     # convert jpg -> jpg
                    289:     my ($basename, $fileext) = splitfn($filename);
                    290:     my $newfn = $basename . ".jpg";
                    291:     logger('INFO', "Convert(jpg): $filename -> $newfn");
                    292:     return 1 if ($simulate);
                    293: 
                    294:     if ($scale_rel) {
                    295:    # scale relative -- no size needed, only scaling factor
                    296:    $scaleopt = $scalesize;
                    297:     } else {
                    298:    # scale to size -- size needed
                    299:    my $pictype = $$args{'pictype'};
                    300:    my $picwidth = $$args{'picwidth'};
                    301:    my $picheight = $$args{'picheight'};
                    302:    if (! $picwidth) {
                    303:        ($pictype, $picwidth, $picheight) = identify("$srcdir/$filename");
                    304:        if ((! $pictype)||($picwidth == 0)||($picheight == 0)) {
                    305:        logger('ERROR', "unable to identify $srcdir/$filename!");
                    306:        return 1;
                    307:        }
                    308:    }
                    309:    if ($picheight > $picwidth) {
                    310:        $scaleopt = $scalesize / $picheight;
                    311:        logger('DEBUG', "PIC is portrait");
                    312:    } else {
                    313:        $scaleopt = $scalesize / $picwidth;
                    314:        logger('DEBUG', "PIC is landscape");
                    315:    }
                    316:    if ($scaleopt >= 1) {
                    317:        $scaleopt = 1;
                    318:        logger('DEBUG', "PIC is already smaller");
                    319:    }
                    320:     }
1.1       casties   321: 
1.2       casties   322:     if (!$scaleopt) {
                    323:    logger('ERROR', "unable to calculate scaling options!");
                    324:    return 1;
1.1       casties   325:     }
1.2       casties   326: 
                    327:     # convert
                    328:     logger('DEBUG', "nice -10 $jpegloader '$srcdir/$filename' 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $jpegwriter > '$destdir/$newfn' 2>/dev/null");
                    329:     return 0 if ($simulate);
                    330:     if (system("nice -10 $jpegloader '$srcdir/$filename' 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $jpegwriter > '$destdir/$newfn' 2>/dev/null") != 0) {
                    331:    logger('ERROR', "error converting '$srcdir/$filename'!");
                    332:    unlink "$destdir/$newfn";
                    333:    return 1;
1.1       casties   334:     }
1.2       casties   335: 
                    336:     # change permissions
                    337:     chmod $file_perm, "$destdir/$newfn" or
                    338:    logger('WARNING', "unable to set permission on '$destdir/$newfn'");
                    339: 
                    340:     if (! -s "$destdir/$newfn") {
                    341:    # file broken (size 0)
                    342:    logger('ERROR', "created file '$destdir/$newfn' broken -- will be removed!");
                    343:    unlink "$destdir/$newfn";
                    344:    return 1;
1.1       casties   345:     }
1.2       casties   346:     return 0;
1.1       casties   347: }
                    348: 
                    349: 
                    350: #
1.2       casties   351: # $error = scale_tiff_jpeg2(\$args);
                    352: #
                    353: # scale TIFF images to JPEG using ImageMagick convert
1.1       casties   354: #
1.2       casties   355: # args needed: $srcdir, $filename, $destdir, 
                    356: #              $scalesize, $scale_rel, $picwidth, $picheight
1.1       casties   357: #
1.2       casties   358: sub scale_tiff_jpeg2 {
                    359:     my ($args) = @_;
                    360: 
                    361:     my $srcdir = $$args{'srcdir'};
                    362:     my $filename = $$args{'filename'};
                    363:     my $destdir = $$args{'destdir'};
                    364:     my $scalesize = $$args{'scalesize'};
                    365:     my $scale_rel = $$args{'scale_rel'};
                    366:     my $scaleopt;
                    367: 
                    368:     my ($basename, $fileext) = splitfn($filename);
                    369:     my $newfn = $basename . ".jpg";
                    370:     logger('INFO', "Convert(tiff2): $filename -> $newfn");
                    371:     return 1 if ($simulate);
                    372: 
                    373:     if ($scale_rel) {
                    374:    # scale relative -- no size needed, only scaling factor
                    375:    $scaleopt = $scalesize;
                    376:     } else {
                    377:    # scale to size -- size needed
                    378:    my $pictype = $$args{'pictype'};
                    379:    my $picwidth = $$args{'picwidth'};
                    380:    my $picheight = $$args{'picheight'};
                    381:    if (! $picwidth) {
                    382:        ($pictype, $picwidth, $picheight) = identify("$srcdir/$filename");
                    383:        if ((! $pictype)||($picwidth == 0)||($picheight == 0)) {
                    384:        logger('ERROR', "unable to identify $srcdir/$filename!");
                    385:        return 1;
                    386:        }
                    387:    }
                    388:    if ($picheight > $picwidth) {
                    389:        $scaleopt = $scalesize / $picheight;
                    390:        logger('DEBUG', "PIC is portrait");
                    391:    } else {
                    392:        $scaleopt = $scalesize / $picwidth;
                    393:        logger('DEBUG', "PIC is landscape");
                    394:    }
                    395:    if ($scaleopt >= 1) {
                    396:        $scaleopt = 1;
                    397:        logger('DEBUG', "PIC is already smaller");
                    398:    }
                    399:     }
1.1       casties   400: 
1.2       casties   401:     if (!$scaleopt) {
                    402:    logger('ERROR', "unable to calculate scaling options!");
                    403:    return 1;
1.1       casties   404:     }
                    405: 
1.2       casties   406:     if ($scale_rel) {
                    407:    my $per_scale = 100 * $scaleopt;
                    408:    logger('DEBUG', "nice -10 $converter -quality $jpeg_quality -scale $per_scale\% '$srcdir/$filename' '$destdir/$newfn' 2>/dev/null");
                    409:    return 0 if ($simulate);
                    410:    if (system("nice -10 $converter -quality $jpeg_quality -scale $per_scale\% '$srcdir/$filename' '$destdir/$newfn' 2>/dev/null\n") != 0) {
                    411:        logger('ERROR', "error converting '$srcdir/$filename'!");
                    412:        return 1;
                    413:    }
                    414:     } else {
                    415:    logger('DEBUG', "nice -10 $converter -quality $jpeg_quality -scale ${scalesize}x${scalesize} '$srcdir/$filename' '$destdir/$newfn' 2>/dev/null");
                    416:    return 0 if ($simulate);
                    417:    if (system("nice -10 $converter -quality $jpeg_quality -scale ${scalesize}x${scalesize} '$srcdir/$filename' '$destdir/$newfn' 2>/dev/null\n") != 0) {
                    418:        logger('ERROR', "error converting '$srcdir/$filename'!");
                    419:        return 1;
1.1       casties   420:    }
                    421:     }
1.2       casties   422: 
                    423:     # change permissions
                    424:     chmod $file_perm, "$destdir/$newfn" or
                    425:    logger('WARNING', "unable to set permission on '$destdir/$newfn'");
                    426: 
                    427:     if (! -s "$destdir/$newfn") {
                    428:    # file broken (size 0)
                    429:    logger('ERROR', "created file '$destdir/$newfn' broken -- will be removed!");
                    430:    unlink "$destdir/$newfn";
                    431:    return 1;
                    432:     }
                    433:     return 0;
                    434: }
                    435: 
                    436: 
                    437: #
                    438: # $error = scale_tiff_jpeg(\$args);
                    439: #
                    440: # scale TIFF images to JPEG using netpbm tools
                    441: #
                    442: # args needed: $srcdir, $filename, $destdir, 
                    443: #              $scalesize, $scale_rel, $picwidth, $picheight
                    444: #
                    445: sub scale_tiff_jpeg {
                    446:     my ($args) = @_;
                    447: 
                    448:     my $srcdir = $$args{'srcdir'};
                    449:     my $filename = $$args{'filename'};
                    450:     my $destdir = $$args{'destdir'};
                    451:     my $scalesize = $$args{'scalesize'};
                    452:     my $scale_rel = $$args{'scale_rel'};
                    453:     my $scaleopt;
                    454: 
                    455:     # convert jpg -> jpg
                    456:     my ($basename, $fileext) = splitfn($filename);
                    457:     my $newfn = $basename . ".jpg";
                    458:     logger('INFO', "Convert(tiff1): $filename -> $newfn");
                    459:     return 1 if ($simulate);
                    460: 
                    461:     if ($scale_rel) {
                    462:    # scale relative -- no size needed, only scaling factor
                    463:    $scaleopt = $scalesize;
                    464:     } else {
                    465:    # scale to size -- size needed
                    466:    my $pictype = $$args{'pictype'};
                    467:    my $picwidth = $$args{'picwidth'};
                    468:    my $picheight = $$args{'picheight'};
                    469:    if (! $picwidth) {
                    470:        ($pictype, $picwidth, $picheight) = identify("$srcdir/$filename");
                    471:        if ((! $pictype)||($picwidth == 0)||($picheight == 0)) {
                    472:        logger('ERROR', "unable to identify $srcdir/$filename!");
1.1       casties   473:        return 1;
                    474:        }
                    475:    }
1.2       casties   476:    if ($picheight > $picwidth) {
                    477:        $scaleopt = $scalesize / $picheight;
                    478:        logger('DEBUG', "PIC is portrait");
                    479:    } else {
                    480:        $scaleopt = $scalesize / $picwidth;
                    481:        logger('DEBUG', "PIC is landscape");
                    482:    }
                    483:    if ($scaleopt >= 1) {
                    484:        $scaleopt = 1;
                    485:        logger('DEBUG', "PIC is already smaller");
1.1       casties   486:    }
1.2       casties   487:     }
                    488: 
                    489:     if (!$scaleopt) {
                    490:    logger('ERROR', "unable to calculate scaling options!");
1.1       casties   491:    return 1;
                    492:     }
                    493: 
1.2       casties   494:     # convert
                    495:     logger('DEBUG', "nice -10 $tiffloader '$srcdir/$filename' 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $jpegwriter --quality $jpeg_quality > '$destdir/$newfn' 2>/dev/null");
                    496:     return 0 if ($simulate);
                    497:     if (system("nice -10 $tiffloader '$srcdir/$filename' 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $jpegwriter --quality $jpeg_quality > '$destdir/$newfn' 2>/dev/null") != 0) {
                    498:    logger('ERROR', "error converting '$srcdir/$filename'!");
                    499:    unlink "$destdir/$newfn";
                    500:    return 1;
                    501:     }
                    502: 
                    503:     # change permissions
                    504:     chmod $file_perm, "$destdir/$newfn" or
                    505:    logger('WARNING', "unable to set permission on '$destdir/$newfn'");
                    506: 
                    507:     if (! -s "$destdir/$newfn") {
                    508:    # file broken (size 0)
                    509:    logger('ERROR', "created file '$destdir/$newfn' broken -- will be removed!");
                    510:    unlink "$destdir/$newfn";
                    511:    return 1;
                    512:     }
                    513:     return 0;
                    514: }
                    515: 
                    516: 
                    517: 
                    518: #
                    519: # $error = scale_tiff_png(\$args);
                    520: #
                    521: # scale TIFF images to PNG using netpbm tools
                    522: #
                    523: # args needed: $srcdir, $filename, $destdir, 
                    524: #              $scalesize, $scale_rel, $picwidth, $picheight
                    525: #
                    526: sub scale_tiff_png {
                    527:     my ($args) = @_;
                    528: 
                    529:     my $srcdir = $$args{'srcdir'};
                    530:     my $filename = $$args{'filename'};
                    531:     my $destdir = $$args{'destdir'};
                    532:     my $scalesize = $$args{'scalesize'};
                    533:     my $bitdepth = $$args{'bitdepth'};
                    534:     my $scale_rel = $$args{'scale_rel'};
                    535:     my $scaleopt;
                    536: 
                    537:     # convert jpg -> jpg
                    538:     my ($basename, $fileext) = splitfn($filename);
                    539:     my $newfn = $basename . ".png";
                    540:     logger('INFO', "Convert(tiff3): $filename -> $newfn");
                    541: 
                    542:     if ($scale_rel) {
                    543:    # scale relative -- no size needed, only scaling factor
                    544:    $scaleopt = $scalesize;
                    545:     } else {
                    546:    # scale to size -- size needed
                    547:    my $pictype = $$args{'pictype'};
                    548:    my $picwidth = $$args{'picwidth'};
                    549:    my $picheight = $$args{'picheight'};
                    550:    if (! $picwidth) {
                    551:        ($pictype, $picwidth, $picheight, $bitdepth) = identify("$srcdir/$filename");
                    552:        if ((! $pictype)||($picwidth == 0)||($picheight == 0)) {
                    553:        logger('ERROR', "unable to identify $srcdir/$filename!");
1.1       casties   554:        return 1;
                    555:        }
                    556:    }
1.2       casties   557:    if ($picheight > $picwidth) {
                    558:        $scaleopt = $scalesize / $picheight;
                    559:        logger('DEBUG', "PIC is portrait");
1.1       casties   560:    } else {
1.2       casties   561:        $scaleopt = $scalesize / $picwidth;
                    562:        logger('DEBUG', "PIC is landscape");
                    563:    }
                    564:    if ($scaleopt >= 1) {
                    565:        $scaleopt = 1;
                    566:        logger('DEBUG', "PIC is already smaller");
1.1       casties   567:    }
1.2       casties   568:     }
                    569: 
                    570:     if (!$scaleopt) {
                    571:    logger('ERROR', "unable to calculate scaling options!");
1.1       casties   572:    return 1;
                    573:     }
                    574: 
1.2       casties   575:     # convert
                    576:     my $cmd = "nice -10 $tiffloader \'$srcdir/$filename\' 2>/dev/null ";
                    577:     if ($bitdepth == 1) {
                    578:    # antialiasing bilevel images
                    579:    $cmd .= "| nice -10 $quantizer 2 2 2>/dev/null ";
                    580:     }
                    581:     $cmd .= "| nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $pngwriter > '$destdir/$newfn' 2>/dev/null";
                    582:     logger('DEBUG', "$cmd");
                    583:     return 0 if ($simulate);
                    584:     if (system($cmd) != 0) {
                    585:    logger('ERROR', "error converting '$srcdir/$filename'!");
                    586:    unlink "$destdir/$newfn";
                    587:    return 1;
                    588:     }
                    589: 
                    590:     # change permissions
                    591:     chmod $file_perm, "$destdir/$newfn" or
                    592:    logger('WARNING', "unable to set permission on '$destdir/$newfn'");
                    593: 
                    594:     if (! -s "$destdir/$newfn") {
                    595:    # file broken (size 0)
                    596:    logger('ERROR', "created file '$destdir/$newfn' broken -- will be removed!");
                    597:    unlink "$destdir/$newfn";
                    598:    return 1;
                    599:     }
                    600:     return 0;
                    601: }
                    602: 
                    603: 
                    604: #
                    605: # $error = convert_file($srcdir, $filename, $destdir);
                    606: #
                    607: # convert file
                    608: #
                    609: sub convert_file {
                    610:     my($srcdir, $filename, $destdir) = @_;
                    611:     my $filebase;
                    612:     my $fileext;
                    613:     my $newfn;
                    614:     my $pictype;
                    615:     my $picwidth;
                    616:     my $picheight;
                    617:     my $bitdepth;
                    618:     my $error = 0;
                    619:  
                    620:     logger('DEBUG', "convert_file ($srcdir, $filename, $destdir)");
                    621: 
                    622:     if (not (( -f "$srcdir/$filename") && (-r _))) {
                    623:    logger('ERROR', "unable to read file '$srcdir/$filename'");
                    624:    return 1;
                    625:     }
                    626: 
                    627:     # get base name and extension
                    628:     if ($filename =~ /^(.*)\.(\w+)$/) {
                    629:    $filebase = $1;
                    630:    $fileext = $2;
                    631:     }
                    632: 
1.1       casties   633:     #
1.2       casties   634:     # quick check if target image exists
1.1       casties   635:     #
1.2       casties   636:     $pictype = quickident("$srcdir/$filename");
                    637:     if ($pictype) {
                    638:    my $newext = $target_ext_type{$pictype};
                    639:    if ($newext) {
                    640:        $newfn = $filebase . ".$newext";
                    641:        # check if file exists
                    642:        if (-f "$destdir/$newfn") {
                    643:        logger('DEBUG', "CONV file exists: $newfn");
                    644:        if (! $overwrite) {
                    645:            logger('INFO', "File already converted: $newfn");
                    646:            return 0;
                    647:        }
1.1       casties   648:        }
1.2       casties   649:    } else {
                    650:        logger('DEBUG', "target extension for $pictype unknown!");
1.1       casties   651:    }
1.2       casties   652:     } else {
                    653:    # quick ident failed -- do it slowly
                    654: 
                    655:    ($pictype, $picwidth, $picheight, $bitdepth) = identify("$srcdir/$filename");
                    656:    if ((! $pictype)||($picwidth == 0)||($picheight == 0)) {
                    657:        logger('WARNING', "unknown file type '$srcdir/$filename'");
1.1       casties   658:        return 0;
                    659:    }
                    660:     }
                    661: 
1.2       casties   662:     # collect arguments for the conversion
                    663:     my %args;
                    664:     $args{'srcdir'} = $srcdir;
                    665:     $args{'destdir'} = $destdir;
                    666:     $args{'filename'} = $filename;
                    667:     $args{'pictype'} = $pictype;
                    668:     $args{'picwidth'} = $picwidth;
                    669:     $args{'picheight'} = $picheight;
                    670:     $args{'bitdepth'} = $bitdepth;
                    671:     $args{'srcdir'} = $srcdir;
                    672:     $args{'scalesize'} = $scalesize;
                    673:     $args{'scale_rel'} = $scale_relative;
                    674: 
                    675:     # decide conversion based on image type and encoding preferences
                    676:     if ($pictype eq 'JPEG') {
                    677:    $args{'jpeg_qual'} = $jpeg_quality;
                    678:    #default encoder
                    679:    $error = scale_jpeg(\%args);
                    680:     } elsif ($pictype eq 'TIFF') {
                    681:    if ($use_encoder) {
                    682:        # use specific encoder
                    683:        if ($use_encoder eq 'tiff_jpeg') {
                    684:        $error = scale_tiff_jpeg(\%args);
                    685:        } elsif ($use_encoder eq 'tiff_jpeg2') {
                    686:        $error = scale_tiff_jpeg2(\%args);
                    687:        } elsif ($use_encoder eq 'tiff_png') {
                    688:        $error = scale_tiff_png(\%args);
                    689:        }
                    690:    } else {
                    691:        # default
                    692:        $error = scale_tiff_jpeg(\%args);
                    693:    }
                    694:     } else {
                    695:    logger('WARNING', "unknown file type: $pictype ($srcdir/$filename)");
                    696:     }
                    697:     return $error;
                    698: }
1.1       casties   699: 
                    700: 
                    701: #
                    702: # walk_convert_dir($dirname)
                    703: #
                    704: # Descend recursively through $dirname and work on all files
                    705: #
                    706: sub walk_convert_dir {
1.2       casties   707:     my($srcdir, $workdir, $destdir) = @_;
1.1       casties   708:     my $errcnt = 0;
                    709:     my $newfn;
                    710: 
1.2       casties   711:     opendir WORKDIR, "$srcdir/$workdir" or do {
                    712:    logger('ERROR', "Unable to open directory $srcdir/$workdir!");
1.1       casties   713:    return 0;
                    714:     };
                    715: 
                    716:     my @dirlist = readdir(WORKDIR);
                    717: 
                    718:     closedir WORKDIR;
                    719: 
                    720:     if ($do_descend) {
                    721:    foreach (sort @dirlist) {
1.2       casties   722:        next if (/^[.]+$/);
                    723:        next if ($junk_files{$_});
                    724:        if (-d "$srcdir/$workdir/$_") {
                    725:        walk_convert_dir($srcdir, "$workdir/$_", $destdir);
1.1       casties   726:        }
                    727:    }
                    728:     }
                    729: 
1.2       casties   730:     logger('INFO', "Working on $workdir");
                    731:     logger('INFO', "Reading from $srcdir/$workdir.");
                    732:     logger('INFO', "Writing to $destdir/$workdir");
1.1       casties   733: 
1.2       casties   734:     # create destination directory
1.1       casties   735:     if (not ($simulate)) {
1.2       casties   736:    mmkdir("$destdir/$workdir") or do {
                    737:        logger("ERROR", "unable to create directory '$destdir/$workdir'");
1.1       casties   738:        $errcnt++;
                    739:        return 0;
                    740:    };
                    741:     }
1.2       casties   742: 
1.1       casties   743:     foreach (sort @dirlist) {
1.2       casties   744:    # skip dot-directories
1.1       casties   745:    if (/^[.]+.*$/) {
                    746:        next;
                    747:    }
1.2       casties   748:    if (-f "$srcdir/$workdir/$_") {
                    749:        $errcnt += convert_file("$srcdir/$workdir", "$_", "$destdir/$workdir");
1.1       casties   750:    }
                    751:     }
                    752: 
                    753:     if ($errcnt) {
1.2       casties   754:    logger('INFO', "There were $errcnt errors converting '$workdir'!");
1.1       casties   755:     } else {
1.2       casties   756:    logger('INFO', "Finished converting $workdir!");
1.1       casties   757:     }
                    758: 
                    759:     return 1;
                    760: }
                    761: 
                    762: 
                    763: #
                    764: # convert_dir($from_dir)
                    765: #
                    766: # Convert directory "from_dir" and its subdirectories
                    767: #
                    768: sub convert_dir {
1.2       casties   769:     my ($srcdir, $workdir, $destdir) = @_;
1.1       casties   770: 
1.2       casties   771:     logger('INFO', "** Converting Scans **");
                    772:     logger('INFO', "Starting in directory '$srcdir/$workdir'");
1.1       casties   773:     
1.2       casties   774:     walk_convert_dir($srcdir, $workdir, $destdir);
1.1       casties   775: 
                    776:     # touch source directory so digilib rescans the thumbnails
1.2       casties   777:     #logger('DEBUG', "/usr/bin/touch $source_base_dirs[0]/$workdir");
                    778:     system("/usr/bin/touch '$srcdir/$workdir'");
1.1       casties   779: 
1.2       casties   780:     logger('DONE', "** Finished converting scans **");
1.1       casties   781:     return 1;
                    782: }
                    783: 
                    784: 
                    785: 
                    786: 
                    787: 
                    788: 
                    789: ###############################################################
                    790: ## Main
                    791: 
1.2       casties   792: if ($#ARGV < 3) {
1.1       casties   793:     print "Scale-O-Mat $version\n";
1.2       casties   794:     print "  use: scaleomat.pl -src=src-base -dest=dest-base -dir=workdir [...]\n";
                    795:     print "    reads from scr-base/workdir and writes to dest-base/workdir\n";
                    796:     print "    -scaleto=destination size\n";
                    797:     print "    -scaleby=magnification factor.\n";
                    798:     print "    -jpegqual=JPEG quality (0-100)\n";
                    799:     print "    -replace=yes replaces existing files (default=skip).\n";
                    800:     print "    -encoder=tiff_png|tiff_jpeg|tiff_jpeg2\n";
1.1       casties   801:     exit 1;
                    802: }
                    803: 
                    804: # test software installation
1.2       casties   805: checksoft();
                    806: 
                    807: # read command line parameters
                    808: my $args = parseargs();
                    809: 
                    810: # source dir
1.4     ! casties   811: my $srcdir = cleanpath($$args{'src'}, 1);
1.1       casties   812: 
1.2       casties   813: # destination dir
1.4     ! casties   814: my $destdir = cleanpath($$args{'dest'}, 1);
1.2       casties   815: 
                    816: # working dir
1.4     ! casties   817: my $workdir = cleanpath($$args{'dir'});
1.2       casties   818: 
                    819: # destination size
                    820: if ($$args{'scaleby'}) {
                    821:     $scale_relative = 1;
                    822:     $scalesize = $$args{'scaleby'};
                    823:     logger('INFO', "Scaling relative by factor $scalesize");
                    824: }
                    825: if ($$args{'scaleto'}) {
                    826:     $scale_relative = 0;
                    827:     $scalesize = $$args{'scaleto'};
                    828:     logger('INFO', "Scaling absolute to size $scalesize");
                    829: }
                    830: 
                    831: # JPEG quality
                    832: if ($$args{'jpegqual'}) {
                    833:     logger('INFO', "JPEG quality set to '$$args{'jpegqual'}'!");
                    834:     $jpeg_quality = $$args{'jpegqual'};
                    835: }
                    836: 
                    837: # force encoder
                    838: if ($$args{'encoder'}) {
                    839:     logger('INFO', "Using encoder '$$args{'encoder'}'!");
                    840:     $use_encoder = $$args{'encoder'};
1.1       casties   841: }
                    842: 
1.2       casties   843: # Overwrite
                    844: if ($$args{'replace'}) {
                    845:     logger('INFO', "Set to overwrite existing files!");
                    846:     $overwrite = 1;
1.1       casties   847: }
                    848: 
1.2       casties   849: # debug
                    850: if ($$args{'debug'}) {
                    851:     logger('INFO', "Set debug level to $$args{'debug'}!");
                    852:     $debug = $$args{'debug'};
1.1       casties   853: }
                    854: 
1.2       casties   855: # simulate
                    856: if ($$args{'simulate'}) {
                    857:     logger('INFO', "Set to simulate operation only ($$args{'simulate'})!");
                    858:     $simulate = $$args{'simulate'};
1.1       casties   859: }
1.2       casties   860: 
                    861: convert_dir($srcdir, $workdir, $destdir);

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>