Annotation of scaleomat/scaleomat.pl, revision 1.1

1.1     ! casties     1: #!/usr/bin/perl
        !             2: 
        !             3: $| = 1; # unblock IO
        !             4: 
        !             5: $version = "V0.7 (ROC 23.12.2003)";
        !             6: 
        !             7: $debug = 0;
        !             8: $simulate = 0;
        !             9: 
        !            10: $do_descend = 1;
        !            11: 
        !            12: @source_base_dirs = ("/docuserver/images");
        !            13: $dest_base_dir = "/docuserver/scaled/small";
        !            14: $dir_perm = 0775;
        !            15: $file_perm = 0664;
        !            16: 
        !            17: umask 000; # to make shure we can actually use these perms
        !            18: 
        !            19: $dont_overwrite = 1; # don't overwrite already converted files
        !            20: 
        !            21: @imgfile_ext = ("tif", "tiff", "gif", "jpg", "png");
        !            22: 
        !            23: $target_size = 2048; # pixel of longest side
        !            24: $scale_relative = 0; # scale by relative factor instead of destination size
        !            25: $jpeg_quality = 75; # default JPEG compression quality
        !            26: 
        !            27: ##########################################################################
        !            28: # subroutines
        !            29: #
        !            30: 
        !            31: #
        !            32: # checksoft()
        !            33: #
        !            34: # returns if all necessary external programs are installed
        !            35: #
        !            36: sub checksoft {
        !            37: 
        !            38:     my @softdirs = ("/usr/X11R6/bin", "/usr/bin", "/usr/local/bin");
        !            39: 
        !            40:     $identifier = findfile(\@softdirs, "identify")
        !            41:    or die("ABORT: neccessary external program not found: identify");
        !            42:     $jpegloader = findfile(\@softdirs, "jpegtopnm")
        !            43:    or die("ABORT: neccessary external program not found: jpegtopnm");
        !            44:     $tiffloader = findfile(\@softdirs, "tifftopnm")
        !            45:    or die("ABORT: neccessary external program not found: tifftopnm");
        !            46:     $quantizer = findfile(\@softdirs, "pbmtopgm")
        !            47:    or die("ABORT: neccessary external program not found: pbmtopgm");
        !            48:     $scaler = findfile(\@softdirs, "pnmscale")
        !            49:    or die("ABORT: neccessary external program not found: pnmscale");
        !            50:     $jpegwriter = findfile(\@softdirs, "ppmtojpeg")
        !            51:    or die("ABORT: neccessary external program not found: ppmtojpeg");
        !            52:     $pngwriter = findfile(\@softdirs, "pnmtopng")
        !            53:    or die("ABORT: neccessary external program not found: pnmtopng");
        !            54:     $converter = findfile(\@softdirs, "convert")
        !            55:    or die("ABORT: neccessary external program not found: convert");
        !            56: 
        !            57: }
        !            58: 
        !            59: 
        !            60: 
        !            61: #
        !            62: # dprint($message)
        !            63: # 
        !            64: # print if $debug = 1
        !            65: #
        !            66: sub dprint {
        !            67:     my ($msg) = @_;
        !            68: 
        !            69:     if ($debug) {
        !            70:    print "$msg";
        !            71:     }
        !            72: }
        !            73: 
        !            74: 
        !            75: 
        !            76: #
        !            77: # findir(\@basedirs, $subdir)
        !            78: #
        !            79: # check directories in @basedirs+$subdir and return the first existing basedir
        !            80: #
        !            81: sub findir {
        !            82:     my($dirlist, $subdir) = @_;
        !            83: 
        !            84:     foreach my $dir (@$dirlist) {
        !            85:    if (-d "$dir/$subdir") {
        !            86:        return "$dir";
        !            87:    }
        !            88:     }
        !            89:     return;
        !            90: }
        !            91: 
        !            92: #
        !            93: # findfile(\@basedirs, $filename)
        !            94: #
        !            95: # check @basedirs+$filename and return the first existing file
        !            96: #
        !            97: sub findfile {
        !            98:     my($dirlist, $fn) = @_;
        !            99: 
        !           100:     foreach my $dir (@$dirlist) {
        !           101:    if (-f "$dir/$fn") {
        !           102:        return "$dir/$fn";
        !           103:    }
        !           104:     }
        !           105:     return;
        !           106: }
        !           107: 
        !           108: 
        !           109: #
        !           110: # mmkdir($dirname)
        !           111: #
        !           112: # create directory recursively and check permissions
        !           113: #
        !           114: sub mmkdir {
        !           115:     my($dirname) = @_;
        !           116:     my $newdir;
        !           117: 
        !           118:     # does the directory already exist?
        !           119:     if (-d $dir) {
        !           120:    chmod $dir_perm, $dir or do {
        !           121:        print "ERROR: unable to change permission on $dir!\n";
        !           122:        return 0;
        !           123:    };
        !           124:    return 1;
        !           125:     }
        !           126:     # split directory name by levels
        !           127:     my @dirlist = split /\//, $dirname;
        !           128:     my @newlist = ();
        !           129:     my $dir = join("/", @dirlist);
        !           130:     # test backwards which directories exist
        !           131:     while (not -d $dir) {
        !           132:    # move missing elements from the end of @dirlist to @newlist
        !           133:    unshift @newlist, pop @dirlist;
        !           134:    $dir = join("/", @dirlist);
        !           135:     }
        !           136:     # create missing directories level by level
        !           137:     foreach $newdir (@newlist) {
        !           138:    push @dirlist, $newdir;
        !           139:    $dir = join("/", @dirlist);
        !           140:    mkdir "$dir", $dir_perm or do {
        !           141:        print "ERROR: unable to create $dir!\n";
        !           142:        return 0;
        !           143:    }
        !           144:     }
        !           145:     return 1;
        !           146: }
        !           147: 
        !           148: #
        !           149: # dir_ok($dirname)
        !           150: #
        !           151: # check directory name against evil
        !           152: #
        !           153: sub dir_ok {
        !           154:     my($dirname) = @_;
        !           155: 
        !           156:     if ($dirname eq "") {
        !           157:    print "ERROR: DIR mustn't be empty!\n";
        !           158:    return 0;
        !           159:     }
        !           160:     if ($dirname =~ /\.\./) {
        !           161:    print "ERROR: DIR mustn't backref!\n";
        !           162:    return 0;
        !           163:     }
        !           164:     if ($dirname =~ /[|<>]+/) {
        !           165:    print "ERROR: DIR mustn't be special!\n";
        !           166:    return 0;
        !           167:     }
        !           168:     return 1;
        !           169: }
        !           170: 
        !           171: 
        !           172: #
        !           173: # convert_file($filename)
        !           174: #
        !           175: # convert file
        !           176: #
        !           177: sub convert_file {
        !           178:     my($basedir, $filename) = @_;
        !           179:     my $newfn;
        !           180:     my $pictype;
        !           181:     my $picwidth;
        !           182:     my $picheight;
        !           183:     my $scaleopt = 0.3;
        !           184: 
        !           185:     if (not (( -f "$basedir/$filename") && (-r _))) {
        !           186:    print "ERROR: unable to read file '$basedir/$filename'\n;";
        !           187:    return 0;
        !           188:     }
        !           189: 
        !           190:     #
        !           191:     # run ident first to get image type and dimensions
        !           192:     # calculate scaling factor based on destination size or factor
        !           193:     #
        !           194:     if (open(IDENT, "nice -10 $identifier -ping -format '%w %h %m\n' '$basedir/$filename' 2>/dev/null|")) {
        !           195:    my @id = <IDENT>;
        !           196:    my $picinfo = $id[0];
        !           197:    close IDENT;
        !           198:    chomp $picinfo;
        !           199:    dprint "INFO: PIC is $picinfo\n";
        !           200:    if ($picinfo =~ /^(\d+) (\d+) (\w+)$/) {
        !           201:        $picwidth = $1;
        !           202:        $picheight = $2;
        !           203:        $pictype = $3;
        !           204:        if ($scale_relative) {
        !           205:        $scaleopt = $target_size;
        !           206:        } else {
        !           207:        if ($picheight > $picwidth) {
        !           208:            $scaleopt = $target_size / $picheight;
        !           209:            dprint "INFO: PIC is portrait\n";
        !           210:        } else {
        !           211:            $scaleopt = $target_size / $picwidth;
        !           212:            dprint "INFO: PIC is landscape\n";
        !           213:        }
        !           214:        if ($scaleopt >= 1) {
        !           215:            $scaleopt = 1;
        !           216:            dprint "INFO: PIC is already smaller\n";
        !           217:        }
        !           218:        }
        !           219:    }
        !           220:     }
        !           221:     
        !           222:     #
        !           223:     # scale JPEG images to JPEG using netpbm tools
        !           224:     #
        !           225:     if ($pictype eq 'JPEG') {
        !           226:    # convert jpg -> jpg
        !           227:    $newfn = $filename;
        !           228:    $newfn =~ s/\.\w+$/.jpg/;
        !           229:    if (-f "$dest_base_dir/$newfn") {
        !           230:        dprint "INFO  CONV file exists: $newfn\n";
        !           231:        if ($dont_overwrite) {
        !           232:        print "INFO:  File already converted: $newfn\n";
        !           233:        return 1;
        !           234:        }
        !           235:    }
        !           236:    print "INFO: Convert(jpg): $filename -> $newfn\n";
        !           237:    return 1 if ($simulate);
        !           238:    dprint("nice -10 $jpegloader '$basedir/$filename' 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $jpegwriter > '$dest_base_dir/$newfn' 2>/dev/null\n");
        !           239:    if (system("nice -10 $jpegloader '$basedir/$filename' 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $jpegwriter > '$dest_base_dir/$newfn' 2>/dev/null") != 0) {
        !           240:        return 0;
        !           241:    }
        !           242:    chmod $file_perm, "$dest_base_dir/$newfn" or
        !           243:        print "WARNING: unable to set permission on '$dest_base_dir/$newfn'\n";
        !           244:    return 1;
        !           245:     }
        !           246: 
        !           247:     #
        !           248:     # scale TIFF images to JPEG using convert 
        !           249:     # (slower but netpbm doesn't always work)
        !           250:     #
        !           251:     if ($pictype eq 'TIFF') {
        !           252:    # convert tif -> jpg
        !           253:    $newfn = $filename;
        !           254:    $newfn =~ s/\.\w+$/.jpg/;
        !           255:    if (-f "$dest_base_dir/$newfn") {
        !           256:        dprint "INFO:  CONV file exists: $newfn\n";
        !           257:        if ($dont_overwrite) {
        !           258:        print "INFO:  File already converted: $newfn\n";
        !           259:        return 1;
        !           260:        }
        !           261:    }
        !           262:    print "INFO: Convert(tif): $filename -> $newfn\n";
        !           263:    if ($scale_relative) {
        !           264:        my $per_scale = 100 * $scaleopt;
        !           265:        dprint("nice -10 $converter -quality $jpeg_quality -scale $per_scale\% $basedir/$filename $dest_base_dir/$newfn 2>/dev/null\n");
        !           266:        return 1 if ($simulate);
        !           267:        if (system("nice -10 $converter -quality $jpeg_quality -scale $per_scale\% '$basedir/$filename' '$dest_base_dir/$newfn' 2>/dev/null\n") != 0) {
        !           268:        return 0;
        !           269:        }
        !           270:    } else {
        !           271:        dprint("nice -10 $converter -quality $jpeg_quality -scale ${target_size}x${target_size} $basedir/$filename $dest_base_dir/$newfn 2>/dev/null\n");
        !           272:        return 1 if ($simulate);
        !           273:        if (system("nice -10 $converter -quality $jpeg_quality -scale ${target_size}x${target_size} '$basedir/$filename' '$dest_base_dir/$newfn' 2>/dev/null\n") != 0) {
        !           274:        return 0;
        !           275:        }
        !           276:    }
        !           277:    chmod $file_perm, "$dest_base_dir/$newfn" or
        !           278:        print "WARNING: unable to set permission on '$newfn'\n;";
        !           279:    return 1;
        !           280:     }
        !           281: 
        !           282:     #
        !           283:     # convert TIFF to PNG using netpbm tools (not used any more)
        !           284:     #
        !           285:     if ($pictype eq 'TIFF_old') {
        !           286:    # convert tif -> png
        !           287:    $newfn = $filename;
        !           288:    $newfn =~ s/\.\w+$/.png/;
        !           289:    if (-f "$dest_base_dir/$newfn") {
        !           290:        dprint "INFO:  CONV file exists: $newfn\n";
        !           291:        if ($dont_overwrite) {
        !           292:        print "INFO:  File already converted: $newfn\n";
        !           293:        return 1;
        !           294:        }
        !           295:    }
        !           296:    print "INFO: Convert(tif): $filename -> $newfn\n";
        !           297:    return 1 if ($simulate);
        !           298:    dprint("nice -10 $tiffloader $basedir/$filename 2>/dev/null | nice -10 $quantizer 2 2 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $pngwriter > $dest_base_dir/$newfn 2>/dev/null\n");
        !           299:    if (system("nice -10 $tiffloader $basedir/$filename 2>/dev/null | nice -10 $quantizer 2 2 2>/dev/null | nice -10 $scaler $scaleopt 2>/dev/null | nice -10 $pngwriter > $dest_base_dir/$newfn 2>/dev/null") != 0) {
        !           300:        return 0;
        !           301:    }
        !           302:    chmod $file_perm, "$dest_base_dir/$newfn" or
        !           303:        print "WARNING: unable to set permission on '$newfn'\n;";
        !           304:    return 1;
        !           305:     }
        !           306: 
        !           307:     print "WARNING: unknown file type: '$basedir/$filename'\n;";
        !           308:     return 0;
        !           309: }    
        !           310: 
        !           311: 
        !           312: #
        !           313: # walk_convert_dir($dirname)
        !           314: #
        !           315: # Descend recursively through $dirname and work on all files
        !           316: #
        !           317: sub walk_convert_dir {
        !           318:     my($workdir) = @_;
        !           319:     my $errcnt = 0;
        !           320:     my $newfn;
        !           321: 
        !           322:     my $basedir = findir(\@source_base_dirs, $workdir);
        !           323: 
        !           324:     opendir WORKDIR, "$basedir/$workdir" or do {
        !           325:    print "ERROR: Unable to open directory $basedir/$workdir!\n";
        !           326:    return 0;
        !           327:     };
        !           328: 
        !           329:     my @dirlist = readdir(WORKDIR);
        !           330: 
        !           331:     closedir WORKDIR;
        !           332: 
        !           333:     if ($do_descend) {
        !           334:    foreach (sort @dirlist) {
        !           335:        if (/^[.]+$/) {
        !           336:        next;
        !           337:        }
        !           338:        if (-d "$basedir/$workdir/$_") {
        !           339:        walk_convert_dir("$workdir/$_");
        !           340:        }
        !           341:    }
        !           342:     }
        !           343: 
        !           344:     print "INFO:  Working on $workdir\n";
        !           345:     print "INFO:    Reading from $basedir.\n";
        !           346:     print "INFO:    Writing to $dest_base_dir\n";
        !           347: 
        !           348:     if (not ($simulate)) {
        !           349:    mmkdir("$dest_base_dir/$workdir") or do {
        !           350:        print "ERROR: unable to create directory '$dest_base_dir/$workdir'\n;";
        !           351:        $errcnt++;
        !           352:        return 0;
        !           353:    };
        !           354:    if ($dont_overwrite == 0) {
        !           355:        foreach (@imgfile_ext) {
        !           356:        system("rm -f $dest_base_dir/$workdir/*.$_");
        !           357:        }
        !           358:    }
        !           359:     }
        !           360:  
        !           361:     foreach (sort @dirlist) {
        !           362:    if (/^[.]+.*$/) {
        !           363:        next;
        !           364:    }
        !           365:    if (-f "$basedir/$workdir/$_") {
        !           366:        if (convert_file($basedir, "$workdir/$_") == 0) {
        !           367:        $errcnt++;
        !           368:        }
        !           369:    }
        !           370:     }
        !           371: 
        !           372:     if ($errcnt) {
        !           373:    print "INFO:  There were errors converting $workdir!\n";
        !           374:     } else {
        !           375:    print "INFO:  Finished converting $workdir!\n";
        !           376:     }
        !           377: 
        !           378:     return 1;
        !           379: }
        !           380: 
        !           381: 
        !           382: #
        !           383: # convert_dir($from_dir)
        !           384: #
        !           385: # Convert directory "from_dir" and its subdirectories
        !           386: #
        !           387: sub convert_dir {
        !           388:     my ($workdir) = @_;
        !           389: 
        !           390:     print "INFO: ** Converting Scans **\n";
        !           391:     print "INFO: Starting in directory '$workdir'\n";
        !           392:     
        !           393:     dir_ok($workdir) or die("ABORT: Illegal directory name '$workdir'!\n");
        !           394: 
        !           395:     walk_convert_dir($workdir);
        !           396: 
        !           397:     # touch source directory so digilib rescans the thumbnails
        !           398:     #print "DEBUG:/usr/bin/touch $source_base_dirs[0]/$workdir\n";
        !           399:     system("/usr/bin/touch $source_base_dirs[0]/$workdir");
        !           400: 
        !           401:     print "DONE: ** Finished converting scans **\n";
        !           402:     return 1;
        !           403: }
        !           404: 
        !           405: 
        !           406: 
        !           407: 
        !           408: 
        !           409: 
        !           410: ###############################################################
        !           411: ## Main
        !           412: 
        !           413: if ($#ARGV < 0) {
        !           414:     print "Scale-O-Mat $version\n";
        !           415:     print "  use: scaleomat.pl hires-dir dest-base size [quality] [--replace]\n";
        !           416:     print "    - if hires-dir starts with '/' then it's absolute.\n";
        !           417:     print "    - if size starts with 'x' then it's magnification factor.\n";
        !           418:     print "    - quality is JPEG quality (0-100)\n";
        !           419:     print "    - --replace replaces existing files (default=skip).\n";
        !           420:     exit 1;
        !           421: }
        !           422: 
        !           423: # test software installation
        !           424: checksoft;
        !           425: 
        !           426: # parameter 1 is destination dir
        !           427: if ($#ARGV > 0) {
        !           428:     $dest_base_dir = $ARGV[1];
        !           429: }
        !           430: 
        !           431: # parameter 2 is destination size (or factor when starting with "x")
        !           432: if ($#ARGV > 1) {
        !           433:     if ($ARGV[2] =~ /^x([\d.]+)/) {
        !           434:    $scale_relative = 1;
        !           435:    $target_size = $1;
        !           436:    print "INFO: scaling relative by factor $target_size\n";
        !           437:     } else {
        !           438:    $scale_relative = 0;
        !           439:    $target_size = $ARGV[2];
        !           440:    print "INFO: scaling absolute to size $target_size\n";
        !           441:     }
        !           442: }
        !           443: 
        !           444: # optional parameters are JPEG quality or --replace
        !           445: if ($#ARGV > 2) {
        !           446:     for ($i = 3; $i <= $#ARGV; $i++) {
        !           447:    $s = $ARGV[$i];
        !           448:    if ($s eq "--replace") {
        !           449:        print "INFO: set to overwrite existing files!\n";
        !           450:        $dont_overwrite = 0;
        !           451:    } else {
        !           452:        print "INFO: JPEG quality set to '$s'!\n";
        !           453:        $jpeg_quality = $s;
        !           454:    }
        !           455:     }
        !           456: }
        !           457: 
        !           458: # convert all files in the directory
        !           459: my $srcdir = $ARGV[0];
        !           460: if ($srcdir =~ /^\//) {
        !           461:     # if source dir starts with / then ist's absolute
        !           462:     $source_base_dirs[0] = "/";
        !           463: }
        !           464: convert_dir($srcdir);

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