Showing posts with label Programs. Show all posts
Showing posts with label Programs. Show all posts

Tuesday, October 30, 2012

Sleep in Windows

Many of us are aware that there is no sleep in Windows. For those of us who don't want Cygwin or something similar, I wrote this stupid little script just now.

#!/usr/bin/env python2 from time import sleep from sys import argv, stderr, exit try: duration = int(argv[1]) if duration <= 0: raise ValueError sleep(duration) except (IndexError, ValueError): print >>stderr, 'Usage: %s duration' % argv[0]

It's not significant, but I am not amused by the lack of such a command in Windows.

Wednesday, October 24, 2012

tmpchrome

After my dissatisfaction with incognito mode in Chromium, I ended up writing this script, which I call 'tmpchrome' (despite it using Chromium).

My main issue is how all pages share a single incognito session; I'd rather have more control over how sessions are shared.

#!/usr/bin/env python2 from subprocess import Popen from sys import exit, argv from traceback import print_exc from os import rmdir from os.path import isdir from shutil import rmtree from tempfile import mkdtemp profile = mkdtemp() returncode = 1 p = None try: print 'Profile:', profile p = Popen(['chromium', '--user-data-dir=%s' % profile] + argv[1:]) p.wait() returncode = p.returncode except: if p is not None: p.kill() p.wait() returncode = p.returncode finally: try: rmtree(profile) if isdir(profile): rmdir(profile) except Exception: print_exc() finally: exit(returncode)

It isn't perfect, but is good enough for me.

Sunday, September 23, 2012

Wikipedia Graphs

Back when I was a college student with too much free time, I decided to make a set of scripts to operate on a Wikipedia database dump, which would create a directed graph of all of the inter-page links. Here are some results:

Anyone with an interest in 'wikidiving' would appreciate this sort of thing.

Thursday, January 19, 2012

flatten3.py

I recently updated flatten.py to strip out pngcrush and use argparse:

#!/usr/bin/env python2 from sys import argv, stderr, exit from subprocess import Popen from argparse import ArgumentParser, ArgumentError from copy import copy from os import remove from os import close as os_close from re import compile as re_compile from os.path import join, isfile, exists from tempfile import mkstemp filext = re_compile('^(.+)\.(.+)$') filext_png = re_compile('\.png$') img_type = ['Bilevel', 'Grayscale', 'GrayscaleMatte', 'Palette', 'PaletteMatte', 'TrueColor', 'TrueColorMatte', 'ColorSeparate', 'ColorSeparationMatte', 'Optimize'] img_cspace = ['CMY', 'CMYK', 'Gray', 'HSB', 'HSL', 'HWB', 'Lab', 'Log', 'OHTA', 'Rec601Luma', 'Rec601YCbCr', 'Rec709Luma', 'Rec709YCbCr', 'RGB', 'sRGB', 'Transparent', 'XYZ', 'YCbCr', 'YCC', 'YIQ', 'YPbPr', 'YUV'] parser = ArgumentParser(usage = 'Usage: %(prog)s [ options ] input [ output ]') parser.add_argument('-s', '--size', dest = 'size', default = None, help = 'The output size; passed directly to ImageMagick') parser.add_argument('-n', '--no-clobber', dest = 'clobber', default = True, action = 'store_false', help = 'Don\'t overwrite the target file') parser.add_argument('-X', '--lossy-reduction', dest = 'lossy_reduction', default = True, action = 'store_false', help = 'Don\'t allow OptiPNG to perform lossy optimizations') parser.add_argument('-f', '--filter', dest = 'filter', default = 'Catrom', help = 'The filter to resize with if necessary') parser.add_argument('-b', '--background', dest = 'background', default = 'white', help = 'The background when flattening') parser.add_argument('-F', '--no-flatten', dest = 'flatten', default = True, action = 'store_false', help = 'Don\'t flatten the output') parser.add_argument('-t', '--type', dest = 'type', choices = img_type + img_cspace, default = None, help = 'The type of the output image: analogous to both -type and -colorspace in ImageMagick') parser.add_argument('-d', '--depth', dest = 'depth', choices = (1, 2, 4, 8, 16), type = int, default = None, help = 'The depth of the output image') parser.add_argument('-p', '--pre-color', dest = 'precolor', default = False, action = 'store_true', help = 'Change bit-depth/colorspace prior to scaling if applicable') parser.add_argument('input', help = 'Input file') parser.add_argument('output', nargs = '?', help = 'Destination file; will default to ${input}_small.png') args = parser.parse_args() if isfile(args.input): pngout = False if args.output: output = args.output if filext_png.search(output): pngout = True else: m = filext.search(args.input) if not m is None: output = '%s_small.%s' % (m.group(1), m.group(2)) if m.group(2) == 'png': pngout = True else: output = '%s_small.png' % args.input pngout = True if not args.clobber and exists(output): print >>stderr, 'Output file exists:', output exit(2) # ACTUAL PROCESSING pargs = ['convert', args.input] if args.precolor: if args.flatten: pargs += ['-background', args.background, '-flatten', '+matte'] if not args.size is None: pargs += ['-filter', args.filter, '-resize', args.size] if not args.type is None: if args.type in img_type: pargs += ['-type', args.type] if not args.depth is None: pargs += ['-depth', str(args.depth)] elif args.type in img_cspace: pargs += ['-colorspace', args.type] if not args.depth is None: pargs += ['-depth', str(args.depth)] if not args.precolor: if args.flatten: pargs += ['-background', args.background, '-flatten', '+matte'] if not args.size is None: pargs += ['-filter', args.filter, '-resize', args.size] if pngout: # Run convert pargs.append('png:' + output) try: Popen(pargs).wait() except KeyboardInterrupt: if isfile(output): remove(output) exit(1) # Run optipng try: optipng = ['optipng', '-o9'] if not args.lossy_reduction: optipng.append('-nx') optipng.append(output) Popen(optipng).wait() except KeyboardInterrupt: if isfile(output): remove(output) else: pargs.append(output) Popen(pargs).wait() # END else: print >>stderr, 'No such file:', args.input exit(2)

Monday, March 15, 2010

flatten2.py

After reading about OptiPNG, I decided to add it into the mix of flatten.py. Since it doesn't support reducing bit depths of grayscale images, I have the script run pngcrush first and then OptiPNG.

Since the last post about flatten, I've made a few other changes as well, such as passing -bit_depth to pngcrush when a bit depth is provided. Since I use this script to compress images for my webcomic, that's an important change.

flatten.py

#!/usr/bin/python
from sys import argv, stderr, exit
from subprocess import Popen
from optparse import OptionParser, OptionValueError
from copy import copy
from os import remove
from os import close as os_close
from re import compile as re_compile
from os.path import join, isfile
from tempfile import mkstemp


size = re_compile('^(.+)x(.+)$')

def check_size(option, opt_str, value, parser):
m = size.search(value)
if m:
parser.values.size = m.group(1), m.group(2)
else:
raise OptionValueError('Invalid size: %s' % value)

filext = re_compile('^(.+)\.(.+)$')
filext_png = re_compile('\.png$')

img_type = ['Bilevel', 'Grayscale', 'GrayscaleMatte', 'Palette', 'PaletteMatte', 'TrueColor', 'TrueColorMatte', 'ColorSeparate', 'ColorSeparationMatte', 'Optimize']
img_cspace = ['CMY', 'CMYK', 'Gray', 'HSB', 'HSL', 'HWB', 'Lab', 'Log', 'OHTA', 'Rec601Luma', 'Rec601YCbCr', 'Rec709Luma', 'Rec709YCbCr', 'RGB', 'sRGB', 'Transparent', 'XYZ', 'YCbCr', 'YCC', 'YIQ', 'YPbPr', 'YUV']
pngcrush = ['pngcrush', '-rem', 'gAMA', '-rem', 'cHRM', '-rem', 'iCCP', '-rem', 'sRGB']

parser = OptionParser(usage = 'Usage: %prog [ options ] input [ output ]')
parser.add_option('-s', '--size', dest = 'size', type = 'string', action = 'callback', callback = check_size, default = None, help = 'The output size: WIDTHxHEIGHT')
parser.add_option('-n', '--no-clobber', dest = 'clobber', default = True, action = 'store_false', help = 'The output size: WIDTHxHEIGHT')
parser.add_option('-f', '--filter', dest = 'filter', default = 'Catrom', help = 'The filter to resize with if necessary.')
parser.add_option('-b', '--background', dest = 'background', default = 'white', help = 'The background when flattening.')
parser.add_option('-F', '--no-flatten', dest = 'flatten', default = True, action = 'store_false', help = 'Don\'t flatten the output.')
parser.add_option('-t', '--type', dest = 'type', type = 'string', default = None, help = 'The type of the output image: analogous to both -type and -colorspace in ImageMagick')
parser.add_option('-d', '--depth', dest = 'depth', type = 'int', default = None, help = 'The depth of the output image.')

options, args = parser.parse_args()
if len(args):
input = args.pop(0)
if isfile(input):
output = None
pngout = False
if len(args):
output = args.pop(0)
if filext_png.search(output):
pngout = True
else:
m = filext.search(input)
if not m is None:
output = '%s_small.%s' % (m.group(1), m.group(2))
if m.group(2) == 'png':
pngout = True
else:
output = '%s_small.png' % input
pngout = True
if not options.clobber and isfile(output):
print >>stderr, 'Output file exists:', output
exit(2)
# ACTUAL PROCESSING
args = ['convert', input]

if not options.type is None:
if options.type in img_type:
args += ['-type', options.type]
if not options.depth is None:
args += ['-depth', str(options.depth)]
elif options.type in img_cspace:
args += ['-colorspace', options.type]
if not options.depth is None:
args += ['-depth', str(options.depth)]
if options.flatten:
args += ['-background', options.background, '-flatten', '+matte']
if not options.size is None:
args += ['-filter', options.filter, '-resize', '%sx%s' % options.size]


if pngout:
# Run convert
fd, tmpfile = mkstemp()
os_close(fd)
args.append('png:' + tmpfile)
Popen(args).communicate()
# Run pngcrush
args = copy(pngcrush)
if not options.depth is None:
args += ['-bit_depth', str(options.depth)]
args += [tmpfile, output]
Popen(args).communicate()
remove(tmpfile)
# Run optipng
Popen(['optipng', '-o9', output]).communicate()
else:
args.append(output)
Popen(args).communicate()
# END
else:
print >>stderr, 'No such file:', input
exit(2)
else:
parser.print_help()
exit(1)

The runtime options are the same as flatten.py.

Sunday, January 31, 2010

Grok

A friend of mine wrote a Python script to replace Ack (which is much faster than grep) and the resulting script turned out to be significantly faster than it. I decided then to write my own rough equivalent, called 'grok' (name from another similar program):

grok.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pcre.h>
#include <dirent.h>
#include <limits.h>
#define BLOCK_SIZE 1024
#define OFFSET_COUNT 1
struct {
char * bytes;
off_t length;
} blocks = {NULL, 0};


int search(const char * path, pcre * re) {
FILE * input = fopen(path, "r");
off_t n = 1;
int ovector[OFFSET_COUNT];
int rc;
char first_match = 1;
if(!input) {
perror(path);
return 1;
}
if(!blocks.bytes && !blocks.length) {
// Initialize blocks on first time
blocks.bytes = malloc(BLOCK_SIZE);
memset(blocks.bytes, '\0', BLOCK_SIZE);
blocks.length = BLOCK_SIZE;
}
// Search
while(!feof(input)) {
// Read a line
blocks.bytes[blocks.length - 2] = '\0'; // [blocks.length - 1] will always be '\0' due to fgets() behavior
fgets(blocks.bytes, blocks.length, input);
//printf("%lu/%lu; %d\n", strlen(blocks.bytes), blocks.length, blocks.bytes[blocks.length - 2]);
while(!feof(input) && blocks.bytes[blocks.length - 2] && blocks.bytes[blocks.length - 2] != '\n') {
// Expand blocks as necessary
blocks.length += BLOCK_SIZE;
blocks.bytes = realloc(blocks.bytes, blocks.length);
blocks.bytes[blocks.length - 2] = '\0';
fgets(blocks.bytes + strlen(blocks.bytes), BLOCK_SIZE + 1, input);
//printf("%lu/%lu; %d\n", strlen(blocks.bytes), blocks.length, blocks.bytes[blocks.length - 2]);
}
if(!(feof(input) && !*blocks.bytes)) {
n++;
rc = pcre_exec(re, NULL, blocks.bytes, strlen(blocks.bytes), 0, 0, ovector, OFFSET_COUNT);
if(rc < 0) {
switch(rc) {
case PCRE_ERROR_NOMATCH:
break;
case PCRE_ERROR_BADUTF8:
fprintf(stderr, "Bad UTF-8 at line %lu in %s\nSkipping file (try running with -U option to disable Unicode).\n", n, path);
fclose(input);
return 1;
break;
default:
fprintf(stderr, "Error: %d\n", rc);
break;
}
blocks.bytes[0] = '\0';
continue;
}
if(first_match) {
first_match = 0;
printf("%s:\n", path);
}
printf("%6lu:%s", n, blocks.bytes);
blocks.bytes[0] = '\0';
}
}
// Cleanup
fclose(input);
return 0;
}

int recursive_search(const char * path, pcre * re) {
DIR * dirinfo;
struct dirent * file;
struct stat info;
char fullpath[PATH_MAX], * filepart;
if(!stat(path, &info)) {
if(S_ISREG(info.st_mode)) {
// Regular files
if(search(path, re) == -1)
return -1;
}
else if(S_ISDIR(info.st_mode)) {
// Directories
strcpy(fullpath, path);
strcat(fullpath, "/");
filepart = fullpath + strlen(fullpath);
dirinfo = opendir(path);
while((file = readdir(dirinfo)) != NULL) {
if(*file->d_name != '.') {
strcpy(filepart, file->d_name);
if(recursive_search(fullpath, re) == -1)
return -1;
}
}
closedir(dirinfo);
}
}
else
perror(path);
return 0;
}


int main(int argc, const char * argv[]) {
// Defaults
const char * default_dirs[] = {"."};
const char * progname = *argv;
// General Variables
const char ** dirs;
int erroroffset;
int options = PCRE_UTF8;
off_t i, dirs_length;
const char * error;
pcre * re;
// Initialization
argc--; argv++;
// Parse flags
while(argc && (*argv)[0] == '-' && (*argv)[1] != '-') {
switch((*argv)[1]) {
case 'i':
options |= PCRE_CASELESS;
case 'U':
options &= ~PCRE_UTF8;
case '\0': break;
default:
fprintf(stderr, "Invalid option: %s", *argv);
return -1;
break;
}
argc--; argv++;
}
// Parse arguments
if(argc) {
re = pcre_compile(*argv, options, &error, &erroroffset, NULL);
if(argc > 1) {
dirs = argv + 1;
dirs_length = argc - 1;
}
else {
dirs = default_dirs;
dirs_length = 1;
}
}
else {
fprintf(stderr, "Usage: %s [ -i ] [ -u ] expr [ path1 .. pathN ]\n", progname);
return 1;
}
if(!re) {
fprintf(stderr, "PCRE compilation error at offset %d: %s\n", erroroffset, error);
return 2;
}
// Recursive search
for(i = 0; i < dirs_length; i++) {
if(recursive_search(dirs[i], re) == -1) {
fputs("Ran out of memory.", stderr);
return 128;
}
}
// Cleanup
if(blocks.bytes && blocks.length) {
free(blocks.bytes);
blocks.bytes = NULL;
blocks.length = 0;
}
pcre_free(re);
return 0;
}

As it turns out, my program is able to run twice as fast as his on a given directory tree (small to large).