Skip to content

Instantly share code, notes, and snippets.

@zwetan
Last active August 29, 2015 14:21
Show Gist options
  • Save zwetan/350955576b98551dfed1 to your computer and use it in GitHub Desktop.
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
#!/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