Last active
August 29, 2015 14:21
-
-
Save zwetan/350955576b98551dfed1 to your computer and use it in GitHub Desktop.
build a simple command line tool with as3shebang : a pdf to png converter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/as3shebang -- | |
import C.errno.*; // errno CError | |
import C.stdlib.*; // exit EXIT_SUCCESS EXIT_FAILURE system | |
import C.stdio.*; // remove | |
import C.unistd.*; // access F_OK | |
import C.sys.stat.*; | |
import shell.*; | |
/** | |
* which - locate a program file in the user's path | |
* | |
* The which utility takes a command name and searches the path | |
* for each executable file that would be run had this | |
* command actually been invoked. | |
* | |
* @param name program name to look for. | |
* @param all if <code>true</code> list all instances of executables found. | |
* @return the full path of the program or the empty string if not found. | |
*/ | |
var which:Function = function( name:String, all:Boolean = false ):String | |
{ | |
var PATH:String = getenv( "PATH" ); | |
if( PATH == "" ) { return ""; } | |
var paths:Array = PATH.split( ":" ); | |
paths.push( "." ); | |
var is_there:Function = function( candidate:String ):Boolean | |
{ | |
var fin:* = new status(); | |
/* Note: | |
getlogin() != "root" | |
should be | |
getuid() != 0 | |
*/ | |
if( (access( candidate, X_OK ) == 0) && | |
(stat( candidate, fin ) == 0) && | |
S_ISREG( fin.st_mode ) && | |
( (getlogin() != "root") || | |
((fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0) ) ) | |
{ | |
return true; | |
} | |
return false; | |
} | |
var found:String = ""; | |
var i:uint; | |
var len:uint = paths.length; | |
var candidate:String; | |
for( i = 0; i < len; i++ ) | |
{ | |
candidate = paths[i] + "/" + name; | |
if( is_there( candidate ) ) | |
{ | |
if( all ) | |
{ | |
found += (found == "" ? "": " ") + candidate; | |
} | |
else | |
{ | |
return candidate; | |
} | |
} | |
} | |
return found; | |
} | |
var usage:String = ""; | |
usage += "usage: pdf2png [-L] [-R] filename\n"; | |
usage += " -h display the help\n"; | |
usage += " -L rotate Left\n"; | |
usage += " -R rotate Right\n"; | |
usage += " -big high quality and big file size (default)\n"; | |
usage += " -small less quality and small file size\n"; | |
usage += " -nobg no background (keep transparency)\n"; | |
usage += " -noflat do not flatten\n"; | |
usage += " filename the pdf file to convert\n"; | |
var help:String = ""; | |
help += "Convert PDF files to PNG files using Image Magick.\n"; | |
help += "\n"; | |
help += "By default, a white background is added and the\n"; | |
help += "image is flattened, with a high quality setting.\n"; | |
help += "\n"; | |
help += "For multiple pages PDF, the tool generate one\n"; | |
help += "continuous image, you will have to use the -noflat\n"; | |
help += "option to avoid having the pages merged on top of another.\n"; | |
help += "\n"; | |
help += "If you do want to preserve PDF transparency you need to\n"; | |
help += "use the -nobg and the -noflat options together.\n"; | |
var i:uint; | |
var len:uint = Program.argv.length; | |
if( len == 0 ) | |
{ | |
trace( "arg missing <filename>" ); | |
trace( usage ); | |
exit( EXIT_FAILURE ); | |
} | |
// default options | |
var showhelp:Boolean = false; // show help | |
var density:uint = 300; // big quality | |
var resize:uint = 50; // big quality | |
var rotation:int = 0; // no rotation | |
var background:Boolean = true; // add a white background | |
var flatten:Boolean = true; // flatten the image | |
var filename:String = ""; | |
var arg_error:Boolean = false; | |
var arg_L:Boolean = false; | |
var arg_R:Boolean = false; | |
var arg_big:Boolean = false; | |
var arg_small:Boolean = false; | |
var arg_err_msg:String = ""; | |
var arg_err_messages:Object = {}; | |
arg_err_messages[ "rot_L" ] = "rotation already set with -L"; | |
arg_err_messages[ "rot_R" ] = "rotation already set with -R"; | |
arg_err_messages[ "qual_big" ] = "quality already set with -big"; | |
arg_err_messages[ "qual_small" ] = "quality already set with -small"; | |
var loop:Boolean = true; | |
var arg:String; | |
for( i = 0; (i < len) && loop; i++ ) | |
{ | |
arg = Program.argv[i]; | |
//trace( "arg = [" + arg + "]" ); | |
switch( arg ) | |
{ | |
case "-h": | |
showhelp = true; | |
loop = false; | |
break; | |
case "-L": | |
if( arg_R ) | |
{ | |
arg_error = true; | |
arg_err_msg = arg_err_messages[ "rot_R" ]; | |
loop = false; | |
continue; | |
} | |
rotation = -1; | |
arg_L = true; | |
break; | |
case "-R": | |
if( arg_L ) | |
{ | |
arg_error = true; | |
arg_err_msg = arg_err_messages[ "rot_L" ]; | |
loop = false; | |
continue; | |
} | |
rotation = 1; | |
arg_R = true; | |
break; | |
case "-big": | |
if( arg_small ) | |
{ | |
arg_error = true; | |
arg_err_msg = arg_err_messages[ "qual_small" ]; | |
loop = false; | |
continue; | |
} | |
density = 300; | |
resize = 50; | |
arg_big = true; | |
break; | |
case "-small": | |
if( arg_big ) | |
{ | |
arg_error = true; | |
arg_err_msg = arg_err_messages[ "qual_big" ]; | |
loop = false; | |
continue; | |
} | |
density = 150; | |
resize = 25; | |
arg_small = true; | |
break; | |
case "-nobg": | |
background = false; | |
break; | |
case "-noflat": | |
flatten = false; | |
break; | |
default: | |
filename = arg; | |
} | |
} | |
if( showhelp ) | |
{ | |
trace( "pdf2png" ); | |
trace( "=======" ); | |
trace( help ); | |
trace( usage ); | |
exit( EXIT_SUCCESS ); | |
} | |
if( arg_error ) | |
{ | |
trace( "arg error: " + arg_err_msg ); | |
trace( usage ); | |
exit( EXIT_FAILURE ); | |
} | |
if( filename == "" ) | |
{ | |
trace( "<filename> is empty" ); | |
trace( usage ); | |
exit( EXIT_FAILURE ); | |
} | |
if( access( filename, F_OK ) != 0 ) | |
{ | |
trace( "filename \"" + filename + "\" does not exists" ); | |
trace( usage ); | |
exit( EXIT_FAILURE ); | |
} | |
var convert:String = which( "convert" ); | |
if( convert == "" ) | |
{ | |
trace( "could not find image magick 'convert' command line tool" ); | |
exit( EXIT_FAILURE ); | |
} | |
//trace( "convert = " + convert ); | |
var rotate:int = rotation * 90; | |
var filename_tmppng:String = filename.replace( /(.*)\.pdf$/, "$1_tmp.png" ); | |
var filename_png:String = filename.replace( /(.*)\.pdf$/, "$1.png" ); | |
//trace( "filename_png = " + filename_png ); | |
var cmd_png:String = convert + " -density " + density; | |
if( background ) | |
{ | |
if( flatten ) | |
{ | |
cmd_png += " -background white"; // you need to flatten to apply the background, merge multiple pages PDF on top of another | |
} | |
else | |
{ | |
cmd_png += " -alpha off"; //alternative: ignore the alpha, it will work with multiple pages PDF | |
} | |
} | |
if( flatten ) | |
{ | |
cmd_png += " -flatten"; | |
} | |
cmd_png += " " + filename + " -resize " + resize + "% -append " + filename_tmppng; | |
var cmd_rot:String = convert + " " + filename_tmppng + " -rotate " + rotate + " " + filename_png; | |
var conv_png:int = system( cmd_png ); | |
if( conv_png != 0 ) | |
{ | |
trace( "could not convert file to PNG" ); | |
trace( new CError( "", errno ) ); | |
exit( EXIT_FAILURE ); | |
} | |
var conv_rot:int = system( cmd_rot ); | |
if( conv_rot != 0 ) | |
{ | |
trace( "could not rotate PNG file" ); | |
trace( new CError( "", errno ) ); | |
exit( EXIT_FAILURE ); | |
} | |
var rm_tmp:int = remove( filename_tmppng ); | |
if( rm_tmp != 0 ) | |
{ | |
trace( "Could not delete temporary file \"" + filename_tmppng + "\"" ); | |
trace( new CError( "", errno ) ); | |
exit( EXIT_FAILURE ); | |
} | |
exit( EXIT_SUCCESS ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment