Annotation of scaleomat/scaleomat.pl, revision 1.7

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

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