Annotation of scaleomat/scaleomat.pl, revision 1.5

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: 
1.5     ! casties   133: #
        !           134: # $p = cleanpath($path, $startslash).  
        !           135: #
        !           136: # returns a pathname with trailing and starting slash removed (if
        !           137: # $startslash is true the starting slash is not removed)
        !           138: #
1.4       casties   139: sub cleanpath {
                    140:     my ($path, $startslash) = @_;
                    141: 
                    142:     if ($path =~ /^(\/)*(.*?)\/*$/) {
                    143:    if ($startslash) {
                    144:        return $1 . $2;
                    145:    } else {
                    146:        return $2;
                    147:    }
                    148:     }
                    149:     return $path;
                    150: }
                    151: 
1.1       casties   152: #
1.2       casties   153: # ($basename, $extension) = splitfn($filename)
                    154: #
                    155: # split filename into base and (lowercase) extension
                    156: #
                    157: sub splitfn {
                    158:     my ($filepath) = @_;
                    159:     if ($filepath =~ /^(.*)\.(\w+)$/) {
                    160:    return ($1, lc($2));
                    161:     }
                    162:     return;
                    163: }
                    164: 
                    165: 
                    166: #
1.1       casties   167: # mmkdir($dirname)
                    168: #
                    169: # create directory recursively and check permissions
                    170: #
                    171: sub mmkdir {
                    172:     my($dirname) = @_;
                    173:     my $newdir;
                    174: 
                    175:     # does the directory already exist?
1.2       casties   176:     if (-d $dirname) {
                    177:    chmod $dir_perm, $dirname or do {
1.4       casties   178:        logger('WARNING', "unable to change permission on $dirname!");
1.1       casties   179:    };
                    180:    return 1;
                    181:     }
                    182:     # split directory name by levels
                    183:     my @dirlist = split /\//, $dirname;
                    184:     my @newlist = ();
                    185:     my $dir = join("/", @dirlist);
                    186:     # test backwards which directories exist
                    187:     while (not -d $dir) {
1.2       casties   188:    last unless ($dir);
1.1       casties   189:    # move missing elements from the end of @dirlist to @newlist
                    190:    unshift @newlist, pop @dirlist;
                    191:    $dir = join("/", @dirlist);
                    192:     }
                    193:     # create missing directories level by level
                    194:     foreach $newdir (@newlist) {
                    195:    push @dirlist, $newdir;
                    196:    $dir = join("/", @dirlist);
                    197:    mkdir "$dir", $dir_perm or do {
1.2       casties   198:        logger('ERROR', "unable to create $dir!");
1.1       casties   199:        return 0;
                    200:    }
                    201:     }
                    202:     return 1;
                    203: }
                    204: 
                    205: #
1.2       casties   206: # ($type, $width, $height) = identify($filepath)
                    207: #
                    208: sub identify {
                    209:     my ($filepath) = @_;
1.4       casties   210:     my $pictype = "";
                    211:     my $picwidth = 0;
                    212:     my $picheight = 0;
1.2       casties   213:     my $bitdepth = 0;
                    214:     # use quickident first
                    215:     $pictype = quickident($filepath);
                    216:     # optimize tiff identification
                    217:     if (($pictype)&&($pictype eq 'TIFF')) {
                    218:    logger('DEBUG', "running tiffinfo $tiffinfo");
                    219:    if (open(IDENT, "nice -10 $tiffinfo '$filepath' 2>/dev/null |")) {
                    220:        while (<IDENT>) {
                    221:        chomp;
                    222:        if (/Image Width:\s*(\d+)\s*Image Length:\s*(\d+)/) {
1.4       casties   223:            $picwidth = $1 if ($1 > $picwidth);
                    224:            $picheight = $2 if ($2 > $picheight);
1.2       casties   225:            next;
                    226:        }
                    227:        if (/Bits\/Sample:\s*(\d+)/) {
1.4       casties   228:            $bitdepth = $1 if ($1 > $bitdepth);
1.2       casties   229:            next;
                    230:        }
                    231:        }
                    232:        if ($picwidth) {
1.4       casties   233:        logger('DEBUG', "TIFF $picwidth x $picheight");
1.2       casties   234:        return ($pictype, $picwidth, $picheight, $bitdepth);
                    235:        }
                    236:    }
                    237:     }
                    238:     # run ident to get image type and dimensions
                    239:     logger('DEBUG', "running identifier $identifier");
                    240:     if (open(IDENT, "nice -10 $identifier -ping -format '%w %h %m\n' '$filepath' 2>/dev/null |")) {
                    241:    my @id = <IDENT>;
                    242:    my $picinfo = $id[0];
                    243:    close IDENT;
                    244:    chomp $picinfo;
                    245:    logger('DEBUG', "PIC is '$picinfo'");
                    246:    if ($picinfo =~ /^(\d+) (\d+) (\w+)$/) {
                    247:        $picwidth = $1;
                    248:        $picheight = $2;
                    249:        $pictype = $3;
                    250:    }
                    251:     } else {
                    252:    logger('DEBUG', "unable to identify $filepath!");
                    253:     }
                    254:     return ($pictype, $picwidth, $picheight, $bitdepth);
                    255: }
                    256: 
                    257: #
                    258: # $type = quickident($filepath);
                    259: #
                    260: sub quickident {
                    261:     my ($filepath) = @_;
                    262:     logger('DEBUG', "running quickident");
                    263:     # look at file extension
                    264:     my ($filebase, $fileext) = splitfn($filepath);
                    265:     if ($fileext) {
                    266:    return $img_type_ext{$fileext};
                    267:     }
                    268:     return;
                    269: }
                    270: 
                    271: 
                    272: #
                    273: # $error = scale_jpeg(\$args);
                    274: #
                    275: # scale JPEG images to JPEG using netpbm tools
1.1       casties   276: #
1.2       casties   277: # args needed: $srcdir, $filename, $destdir, 
                    278: #              $scalesize, $scale_rel, $picwidth, $picheight
1.1       casties   279: #
1.2       casties   280: sub scale_jpeg {
                    281:     my ($args) = @_;
                    282: 
                    283:     my $srcdir = $$args{'srcdir'};
                    284:     my $filename = $$args{'filename'};
                    285:     my $destdir = $$args{'destdir'};
                    286:     my $scalesize = $$args{'scalesize'};
                    287:     my $scale_rel = $$args{'scale_rel'};
                    288:     my $scaleopt;
                    289: 
                    290:     # convert jpg -> jpg
                    291:     my ($basename, $fileext) = splitfn($filename);
                    292:     my $newfn = $basename . ".jpg";
                    293:     logger('INFO', "Convert(jpg): $filename -> $newfn");
                    294:     return 1 if ($simulate);
                    295: 
                    296:     if ($scale_rel) {
                    297:    # scale relative -- no size needed, only scaling factor
                    298:    $scaleopt = $scalesize;
                    299:     } else {
                    300:    # scale to size -- size needed
                    301:    my $pictype = $$args{'pictype'};
                    302:    my $picwidth = $$args{'picwidth'};
                    303:    my $picheight = $$args{'picheight'};
                    304:    if (! $picwidth) {
                    305:        ($pictype, $picwidth, $picheight) = identify("$srcdir/$filename");
                    306:        if ((! $pictype)||($picwidth == 0)||($picheight == 0)) {
                    307:        logger('ERROR', "unable to identify $srcdir/$filename!");
                    308:        return 1;
                    309:        }
                    310:    }
                    311:    if ($picheight > $picwidth) {
                    312:        $scaleopt = $scalesize / $picheight;
                    313:        logger('DEBUG', "PIC is portrait");
                    314:    } else {
                    315:        $scaleopt = $scalesize / $picwidth;
                    316:        logger('DEBUG', "PIC is landscape");
                    317:    }
                    318:    if ($scaleopt >= 1) {
                    319:        $scaleopt = 1;
                    320:        logger('DEBUG', "PIC is already smaller");
                    321:    }
                    322:     }
1.1       casties   323: 
1.2       casties   324:     if (!$scaleopt) {
                    325:    logger('ERROR', "unable to calculate scaling options!");
                    326:    return 1;
1.1       casties   327:     }
1.2       casties   328: 
                    329:     # convert
                    330:     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");
                    331:     return 0 if ($simulate);
                    332:     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) {
                    333:    logger('ERROR', "error converting '$srcdir/$filename'!");
                    334:    unlink "$destdir/$newfn";
                    335:    return 1;
1.1       casties   336:     }
1.2       casties   337: 
                    338:     # change permissions
                    339:     chmod $file_perm, "$destdir/$newfn" or
                    340:    logger('WARNING', "unable to set permission on '$destdir/$newfn'");
                    341: 
                    342:     if (! -s "$destdir/$newfn") {
                    343:    # file broken (size 0)
                    344:    logger('ERROR', "created file '$destdir/$newfn' broken -- will be removed!");
                    345:    unlink "$destdir/$newfn";
                    346:    return 1;
1.1       casties   347:     }
1.2       casties   348:     return 0;
1.1       casties   349: }
                    350: 
                    351: 
                    352: #
1.2       casties   353: # $error = scale_tiff_jpeg2(\$args);
                    354: #
                    355: # scale TIFF images to JPEG using ImageMagick convert
1.1       casties   356: #
1.2       casties   357: # args needed: $srcdir, $filename, $destdir, 
                    358: #              $scalesize, $scale_rel, $picwidth, $picheight
1.1       casties   359: #
1.2       casties   360: sub scale_tiff_jpeg2 {
                    361:     my ($args) = @_;
                    362: 
                    363:     my $srcdir = $$args{'srcdir'};
                    364:     my $filename = $$args{'filename'};
                    365:     my $destdir = $$args{'destdir'};
                    366:     my $scalesize = $$args{'scalesize'};
                    367:     my $scale_rel = $$args{'scale_rel'};
                    368:     my $scaleopt;
                    369: 
                    370:     my ($basename, $fileext) = splitfn($filename);
                    371:     my $newfn = $basename . ".jpg";
                    372:     logger('INFO', "Convert(tiff2): $filename -> $newfn");
                    373:     return 1 if ($simulate);
                    374: 
                    375:     if ($scale_rel) {
                    376:    # scale relative -- no size needed, only scaling factor
                    377:    $scaleopt = $scalesize;
                    378:     } else {
                    379:    # scale to size -- size needed
                    380:    my $pictype = $$args{'pictype'};
                    381:    my $picwidth = $$args{'picwidth'};
                    382:    my $picheight = $$args{'picheight'};
                    383:    if (! $picwidth) {
                    384:        ($pictype, $picwidth, $picheight) = identify("$srcdir/$filename");
                    385:        if ((! $pictype)||($picwidth == 0)||($picheight == 0)) {
                    386:        logger('ERROR', "unable to identify $srcdir/$filename!");
                    387:        return 1;
                    388:        }
                    389:    }
                    390:    if ($picheight > $picwidth) {
                    391:        $scaleopt = $scalesize / $picheight;
                    392:        logger('DEBUG', "PIC is portrait");
                    393:    } else {
                    394:        $scaleopt = $scalesize / $picwidth;
                    395:        logger('DEBUG', "PIC is landscape");
                    396:    }
                    397:    if ($scaleopt >= 1) {
                    398:        $scaleopt = 1;
                    399:        logger('DEBUG', "PIC is already smaller");
                    400:    }
                    401:     }
1.1       casties   402: 
1.2       casties   403:     if (!$scaleopt) {
                    404:    logger('ERROR', "unable to calculate scaling options!");
                    405:    return 1;
1.1       casties   406:     }
                    407: 
1.2       casties   408:     if ($scale_rel) {
                    409:    my $per_scale = 100 * $scaleopt;
                    410:    logger('DEBUG', "nice -10 $converter -quality $jpeg_quality -scale $per_scale\% '$srcdir/$filename' '$destdir/$newfn' 2>/dev/null");
                    411:    return 0 if ($simulate);
                    412:    if (system("nice -10 $converter -quality $jpeg_quality -scale $per_scale\% '$srcdir/$filename' '$destdir/$newfn' 2>/dev/null\n") != 0) {
                    413:        logger('ERROR', "error converting '$srcdir/$filename'!");
                    414:        return 1;
                    415:    }
                    416:     } else {
                    417:    logger('DEBUG', "nice -10 $converter -quality $jpeg_quality -scale ${scalesize}x${scalesize} '$srcdir/$filename' '$destdir/$newfn' 2>/dev/null");
                    418:    return 0 if ($simulate);
                    419:    if (system("nice -10 $converter -quality $jpeg_quality -scale ${scalesize}x${scalesize} '$srcdir/$filename' '$destdir/$newfn' 2>/dev/null\n") != 0) {
                    420:        logger('ERROR', "error converting '$srcdir/$filename'!");
                    421:        return 1;
1.1       casties   422:    }
                    423:     }
1.2       casties   424: 
                    425:     # change permissions
                    426:     chmod $file_perm, "$destdir/$newfn" or
                    427:    logger('WARNING', "unable to set permission on '$destdir/$newfn'");
                    428: 
                    429:     if (! -s "$destdir/$newfn") {
                    430:    # file broken (size 0)
                    431:    logger('ERROR', "created file '$destdir/$newfn' broken -- will be removed!");
                    432:    unlink "$destdir/$newfn";
                    433:    return 1;
                    434:     }
                    435:     return 0;
                    436: }
                    437: 
                    438: 
                    439: #
                    440: # $error = scale_tiff_jpeg(\$args);
                    441: #
                    442: # scale TIFF images to JPEG using netpbm tools
                    443: #
                    444: # args needed: $srcdir, $filename, $destdir, 
                    445: #              $scalesize, $scale_rel, $picwidth, $picheight
                    446: #
                    447: sub scale_tiff_jpeg {
                    448:     my ($args) = @_;
                    449: 
                    450:     my $srcdir = $$args{'srcdir'};
                    451:     my $filename = $$args{'filename'};
                    452:     my $destdir = $$args{'destdir'};
                    453:     my $scalesize = $$args{'scalesize'};
                    454:     my $scale_rel = $$args{'scale_rel'};
                    455:     my $scaleopt;
                    456: 
                    457:     # convert jpg -> jpg
                    458:     my ($basename, $fileext) = splitfn($filename);
                    459:     my $newfn = $basename . ".jpg";
                    460:     logger('INFO', "Convert(tiff1): $filename -> $newfn");
                    461:     return 1 if ($simulate);
                    462: 
                    463:     if ($scale_rel) {
                    464:    # scale relative -- no size needed, only scaling factor
                    465:    $scaleopt = $scalesize;
                    466:     } else {
                    467:    # scale to size -- size needed
                    468:    my $pictype = $$args{'pictype'};
                    469:    my $picwidth = $$args{'picwidth'};
                    470:    my $picheight = $$args{'picheight'};
                    471:    if (! $picwidth) {
                    472:        ($pictype, $picwidth, $picheight) = identify("$srcdir/$filename");
                    473:        if ((! $pictype)||($picwidth == 0)||($picheight == 0)) {
                    474:        logger('ERROR', "unable to identify $srcdir/$filename!");
1.1       casties   475:        return 1;
                    476:        }
                    477:    }
1.2       casties   478:    if ($picheight > $picwidth) {
                    479:        $scaleopt = $scalesize / $picheight;
                    480:        logger('DEBUG', "PIC is portrait");
                    481:    } else {
                    482:        $scaleopt = $scalesize / $picwidth;
                    483:        logger('DEBUG', "PIC is landscape");
                    484:    }
                    485:    if ($scaleopt >= 1) {
                    486:        $scaleopt = 1;
                    487:        logger('DEBUG', "PIC is already smaller");
1.1       casties   488:    }
1.2       casties   489:     }
                    490: 
                    491:     if (!$scaleopt) {
                    492:    logger('ERROR', "unable to calculate scaling options!");
1.1       casties   493:    return 1;
                    494:     }
                    495: 
1.2       casties   496:     # convert
                    497:     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");
                    498:     return 0 if ($simulate);
                    499:     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) {
                    500:    logger('ERROR', "error converting '$srcdir/$filename'!");
                    501:    unlink "$destdir/$newfn";
                    502:    return 1;
                    503:     }
                    504: 
                    505:     # change permissions
                    506:     chmod $file_perm, "$destdir/$newfn" or
                    507:    logger('WARNING', "unable to set permission on '$destdir/$newfn'");
                    508: 
                    509:     if (! -s "$destdir/$newfn") {
                    510:    # file broken (size 0)
                    511:    logger('ERROR', "created file '$destdir/$newfn' broken -- will be removed!");
                    512:    unlink "$destdir/$newfn";
                    513:    return 1;
                    514:     }
                    515:     return 0;
                    516: }
                    517: 
                    518: 
                    519: 
                    520: #
                    521: # $error = scale_tiff_png(\$args);
                    522: #
                    523: # scale TIFF images to PNG using netpbm tools
                    524: #
                    525: # args needed: $srcdir, $filename, $destdir, 
                    526: #              $scalesize, $scale_rel, $picwidth, $picheight
                    527: #
                    528: sub scale_tiff_png {
                    529:     my ($args) = @_;
                    530: 
                    531:     my $srcdir = $$args{'srcdir'};
                    532:     my $filename = $$args{'filename'};
                    533:     my $destdir = $$args{'destdir'};
                    534:     my $scalesize = $$args{'scalesize'};
                    535:     my $bitdepth = $$args{'bitdepth'};
                    536:     my $scale_rel = $$args{'scale_rel'};
                    537:     my $scaleopt;
                    538: 
                    539:     # convert jpg -> jpg
                    540:     my ($basename, $fileext) = splitfn($filename);
                    541:     my $newfn = $basename . ".png";
                    542:     logger('INFO', "Convert(tiff3): $filename -> $newfn");
                    543: 
                    544:     if ($scale_rel) {
                    545:    # scale relative -- no size needed, only scaling factor
                    546:    $scaleopt = $scalesize;
                    547:     } else {
                    548:    # scale to size -- size needed
                    549:    my $pictype = $$args{'pictype'};
                    550:    my $picwidth = $$args{'picwidth'};
                    551:    my $picheight = $$args{'picheight'};
                    552:    if (! $picwidth) {
                    553:        ($pictype, $picwidth, $picheight, $bitdepth) = identify("$srcdir/$filename");
                    554:        if ((! $pictype)||($picwidth == 0)||($picheight == 0)) {
                    555:        logger('ERROR', "unable to identify $srcdir/$filename!");
1.1       casties   556:        return 1;
                    557:        }
                    558:    }
1.2       casties   559:    if ($picheight > $picwidth) {
                    560:        $scaleopt = $scalesize / $picheight;
                    561:        logger('DEBUG', "PIC is portrait");
1.1       casties   562:    } else {
1.2       casties   563:        $scaleopt = $scalesize / $picwidth;
                    564:        logger('DEBUG', "PIC is landscape");
                    565:    }
                    566:    if ($scaleopt >= 1) {
                    567:        $scaleopt = 1;
                    568:        logger('DEBUG', "PIC is already smaller");
1.1       casties   569:    }
1.2       casties   570:     }
                    571: 
                    572:     if (!$scaleopt) {
                    573:    logger('ERROR', "unable to calculate scaling options!");
1.1       casties   574:    return 1;
                    575:     }
                    576: 
1.2       casties   577:     # convert
                    578:     my $cmd = "nice -10 $tiffloader \'$srcdir/$filename\' 2>/dev/null ";
                    579:     if ($bitdepth == 1) {
                    580:    # antialiasing bilevel images
                    581:    $cmd .= "| nice -10 $quantizer 2 2 2>/dev/null ";
                    582:     }
                    583:     $cmd .= "| nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $pngwriter > '$destdir/$newfn' 2>/dev/null";
                    584:     logger('DEBUG', "$cmd");
                    585:     return 0 if ($simulate);
                    586:     if (system($cmd) != 0) {
                    587:    logger('ERROR', "error converting '$srcdir/$filename'!");
                    588:    unlink "$destdir/$newfn";
                    589:    return 1;
                    590:     }
                    591: 
                    592:     # change permissions
                    593:     chmod $file_perm, "$destdir/$newfn" or
                    594:    logger('WARNING', "unable to set permission on '$destdir/$newfn'");
                    595: 
                    596:     if (! -s "$destdir/$newfn") {
                    597:    # file broken (size 0)
                    598:    logger('ERROR', "created file '$destdir/$newfn' broken -- will be removed!");
                    599:    unlink "$destdir/$newfn";
                    600:    return 1;
                    601:     }
                    602:     return 0;
                    603: }
                    604: 
                    605: 
                    606: #
                    607: # $error = convert_file($srcdir, $filename, $destdir);
                    608: #
                    609: # convert file
                    610: #
                    611: sub convert_file {
                    612:     my($srcdir, $filename, $destdir) = @_;
                    613:     my $filebase;
                    614:     my $fileext;
                    615:     my $newfn;
                    616:     my $pictype;
                    617:     my $picwidth;
                    618:     my $picheight;
                    619:     my $bitdepth;
                    620:     my $error = 0;
                    621:  
                    622:     logger('DEBUG', "convert_file ($srcdir, $filename, $destdir)");
                    623: 
                    624:     if (not (( -f "$srcdir/$filename") && (-r _))) {
                    625:    logger('ERROR', "unable to read file '$srcdir/$filename'");
                    626:    return 1;
                    627:     }
                    628: 
                    629:     # get base name and extension
                    630:     if ($filename =~ /^(.*)\.(\w+)$/) {
                    631:    $filebase = $1;
                    632:    $fileext = $2;
                    633:     }
                    634: 
1.1       casties   635:     #
1.2       casties   636:     # quick check if target image exists
1.1       casties   637:     #
1.2       casties   638:     $pictype = quickident("$srcdir/$filename");
                    639:     if ($pictype) {
                    640:    my $newext = $target_ext_type{$pictype};
                    641:    if ($newext) {
                    642:        $newfn = $filebase . ".$newext";
                    643:        # check if file exists
                    644:        if (-f "$destdir/$newfn") {
                    645:        logger('DEBUG', "CONV file exists: $newfn");
                    646:        if (! $overwrite) {
                    647:            logger('INFO', "File already converted: $newfn");
                    648:            return 0;
                    649:        }
1.1       casties   650:        }
1.2       casties   651:    } else {
                    652:        logger('DEBUG', "target extension for $pictype unknown!");
1.1       casties   653:    }
1.2       casties   654:     } else {
                    655:    # quick ident failed -- do it slowly
                    656: 
                    657:    ($pictype, $picwidth, $picheight, $bitdepth) = identify("$srcdir/$filename");
                    658:    if ((! $pictype)||($picwidth == 0)||($picheight == 0)) {
                    659:        logger('WARNING', "unknown file type '$srcdir/$filename'");
1.1       casties   660:        return 0;
                    661:    }
                    662:     }
                    663: 
1.2       casties   664:     # collect arguments for the conversion
                    665:     my %args;
                    666:     $args{'srcdir'} = $srcdir;
                    667:     $args{'destdir'} = $destdir;
                    668:     $args{'filename'} = $filename;
                    669:     $args{'pictype'} = $pictype;
                    670:     $args{'picwidth'} = $picwidth;
                    671:     $args{'picheight'} = $picheight;
                    672:     $args{'bitdepth'} = $bitdepth;
                    673:     $args{'srcdir'} = $srcdir;
                    674:     $args{'scalesize'} = $scalesize;
                    675:     $args{'scale_rel'} = $scale_relative;
                    676: 
                    677:     # decide conversion based on image type and encoding preferences
                    678:     if ($pictype eq 'JPEG') {
                    679:    $args{'jpeg_qual'} = $jpeg_quality;
                    680:    #default encoder
                    681:    $error = scale_jpeg(\%args);
                    682:     } elsif ($pictype eq 'TIFF') {
                    683:    if ($use_encoder) {
                    684:        # use specific encoder
                    685:        if ($use_encoder eq 'tiff_jpeg') {
                    686:        $error = scale_tiff_jpeg(\%args);
                    687:        } elsif ($use_encoder eq 'tiff_jpeg2') {
                    688:        $error = scale_tiff_jpeg2(\%args);
                    689:        } elsif ($use_encoder eq 'tiff_png') {
                    690:        $error = scale_tiff_png(\%args);
                    691:        }
                    692:    } else {
                    693:        # default
                    694:        $error = scale_tiff_jpeg(\%args);
                    695:    }
                    696:     } else {
                    697:    logger('WARNING', "unknown file type: $pictype ($srcdir/$filename)");
                    698:     }
                    699:     return $error;
                    700: }
1.1       casties   701: 
                    702: 
                    703: #
                    704: # walk_convert_dir($dirname)
                    705: #
                    706: # Descend recursively through $dirname and work on all files
                    707: #
                    708: sub walk_convert_dir {
1.2       casties   709:     my($srcdir, $workdir, $destdir) = @_;
1.1       casties   710:     my $errcnt = 0;
                    711:     my $newfn;
                    712: 
1.2       casties   713:     opendir WORKDIR, "$srcdir/$workdir" or do {
                    714:    logger('ERROR', "Unable to open directory $srcdir/$workdir!");
1.1       casties   715:    return 0;
                    716:     };
                    717: 
                    718:     my @dirlist = readdir(WORKDIR);
                    719: 
                    720:     closedir WORKDIR;
                    721: 
                    722:     if ($do_descend) {
                    723:    foreach (sort @dirlist) {
1.2       casties   724:        next if (/^[.]+$/);
                    725:        next if ($junk_files{$_});
                    726:        if (-d "$srcdir/$workdir/$_") {
                    727:        walk_convert_dir($srcdir, "$workdir/$_", $destdir);
1.1       casties   728:        }
                    729:    }
                    730:     }
                    731: 
1.2       casties   732:     logger('INFO', "Working on $workdir");
                    733:     logger('INFO', "Reading from $srcdir/$workdir.");
                    734:     logger('INFO', "Writing to $destdir/$workdir");
1.1       casties   735: 
1.2       casties   736:     # create destination directory
1.1       casties   737:     if (not ($simulate)) {
1.2       casties   738:    mmkdir("$destdir/$workdir") or do {
                    739:        logger("ERROR", "unable to create directory '$destdir/$workdir'");
1.1       casties   740:        $errcnt++;
                    741:        return 0;
                    742:    };
                    743:     }
1.2       casties   744: 
1.1       casties   745:     foreach (sort @dirlist) {
1.2       casties   746:    # skip dot-directories
1.1       casties   747:    if (/^[.]+.*$/) {
                    748:        next;
                    749:    }
1.2       casties   750:    if (-f "$srcdir/$workdir/$_") {
                    751:        $errcnt += convert_file("$srcdir/$workdir", "$_", "$destdir/$workdir");
1.1       casties   752:    }
                    753:     }
                    754: 
                    755:     if ($errcnt) {
1.2       casties   756:    logger('INFO', "There were $errcnt errors converting '$workdir'!");
1.1       casties   757:     } else {
1.2       casties   758:    logger('INFO', "Finished converting $workdir!");
1.1       casties   759:     }
                    760: 
                    761:     return 1;
                    762: }
                    763: 
                    764: 
                    765: #
                    766: # convert_dir($from_dir)
                    767: #
                    768: # Convert directory "from_dir" and its subdirectories
                    769: #
                    770: sub convert_dir {
1.2       casties   771:     my ($srcdir, $workdir, $destdir) = @_;
1.1       casties   772: 
1.2       casties   773:     logger('INFO', "** Converting Scans **");
                    774:     logger('INFO', "Starting in directory '$srcdir/$workdir'");
1.1       casties   775:     
1.2       casties   776:     walk_convert_dir($srcdir, $workdir, $destdir);
1.1       casties   777: 
                    778:     # touch source directory so digilib rescans the thumbnails
1.2       casties   779:     #logger('DEBUG', "/usr/bin/touch $source_base_dirs[0]/$workdir");
                    780:     system("/usr/bin/touch '$srcdir/$workdir'");
1.1       casties   781: 
1.2       casties   782:     logger('DONE', "** Finished converting scans **");
1.1       casties   783:     return 1;
                    784: }
                    785: 
                    786: 
                    787: 
                    788: 
                    789: 
                    790: 
                    791: ###############################################################
                    792: ## Main
                    793: 
1.2       casties   794: if ($#ARGV < 3) {
1.1       casties   795:     print "Scale-O-Mat $version\n";
1.2       casties   796:     print "  use: scaleomat.pl -src=src-base -dest=dest-base -dir=workdir [...]\n";
                    797:     print "    reads from scr-base/workdir and writes to dest-base/workdir\n";
                    798:     print "    -scaleto=destination size\n";
                    799:     print "    -scaleby=magnification factor.\n";
                    800:     print "    -jpegqual=JPEG quality (0-100)\n";
                    801:     print "    -replace=yes replaces existing files (default=skip).\n";
                    802:     print "    -encoder=tiff_png|tiff_jpeg|tiff_jpeg2\n";
1.1       casties   803:     exit 1;
                    804: }
                    805: 
                    806: # test software installation
1.2       casties   807: checksoft();
                    808: 
                    809: # read command line parameters
                    810: my $args = parseargs();
                    811: 
                    812: # source dir
1.4       casties   813: my $srcdir = cleanpath($$args{'src'}, 1);
1.1       casties   814: 
1.2       casties   815: # destination dir
1.4       casties   816: my $destdir = cleanpath($$args{'dest'}, 1);
1.2       casties   817: 
                    818: # working dir
1.4       casties   819: my $workdir = cleanpath($$args{'dir'});
1.2       casties   820: 
                    821: # destination size
                    822: if ($$args{'scaleby'}) {
                    823:     $scale_relative = 1;
                    824:     $scalesize = $$args{'scaleby'};
                    825:     logger('INFO', "Scaling relative by factor $scalesize");
                    826: }
                    827: if ($$args{'scaleto'}) {
                    828:     $scale_relative = 0;
                    829:     $scalesize = $$args{'scaleto'};
                    830:     logger('INFO', "Scaling absolute to size $scalesize");
                    831: }
                    832: 
                    833: # JPEG quality
                    834: if ($$args{'jpegqual'}) {
                    835:     logger('INFO', "JPEG quality set to '$$args{'jpegqual'}'!");
                    836:     $jpeg_quality = $$args{'jpegqual'};
                    837: }
                    838: 
                    839: # force encoder
                    840: if ($$args{'encoder'}) {
                    841:     logger('INFO', "Using encoder '$$args{'encoder'}'!");
                    842:     $use_encoder = $$args{'encoder'};
1.1       casties   843: }
                    844: 
1.2       casties   845: # Overwrite
                    846: if ($$args{'replace'}) {
                    847:     logger('INFO', "Set to overwrite existing files!");
                    848:     $overwrite = 1;
1.1       casties   849: }
                    850: 
1.2       casties   851: # debug
                    852: if ($$args{'debug'}) {
                    853:     logger('INFO', "Set debug level to $$args{'debug'}!");
                    854:     $debug = $$args{'debug'};
1.1       casties   855: }
                    856: 
1.2       casties   857: # simulate
                    858: if ($$args{'simulate'}) {
                    859:     logger('INFO', "Set to simulate operation only ($$args{'simulate'})!");
                    860:     $simulate = $$args{'simulate'};
1.1       casties   861: }
1.2       casties   862: 
                    863: convert_dir($srcdir, $workdir, $destdir);

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