Here is a clean 512 pixel-tall icon for Tex-Edit Plus, the venerable script-able text editing application for OSX. Click on it, then right-click on the graphic to "save image as" a png with alpha locally.
Tuesday, January 13, 2015
Saturday, November 29, 2014
Tuesday, March 11, 2014
Smile as R.A.D.
Rapid Application (ish) Development Using Smile
Back in the day, when I was a burgeoning AppleScript experimenter (at some point I became a “developer”, but it was a bumpy road), FaceSpan was the Rapid Application Development Environment I loved. It was fast and easy and powerful. Those days are gone. FaceSpan was dropped by its developer and by its rescuer-developer. XCode AppleScript Application Development became the de facto AppleScript development platform beyond the Script Editor (and indeed, it is very powerful). Other players (Hypercard, Supercard, Ultracard, MegaUltraCard [okay, I made a couple of those up] Runtime Revolution, QuicKeys [oh, man, did I have fun with that one], RealBasic/Studio, FutureBasic) fell by the wayside, for various reasons (although a few of them still have a following, at least, or some measure of commercial success).
I’d like to put in a good word for what seems to be a somewhat overlooked diamond-well-out-of-the-rough: Smile.
Why Smile?
Smile is known (at least) as a sophisticated AppleScript Script Editor developed by Satimage (satimage.fr), a french company whose software products SmileLab and Smile have been around since, oh, I don’t know, the Pleistocene perhaps.
Brass Tacks.
I admit it. Attempts to adopt AppleScript/Cocoa App Development have met with some success and some frustration. It’s not the fault of Apple (um ... no, it’s not. Wait ... no, it’s not). It’s because I spread myself very thin across many disciplines, of which software development is a very thin and spackled emulsion indeed. I have to re-learn. I have to dig up old snippets of code and manuals. I have to troll websites like the wonderful stackoverflow.com.
In short, I miss the direct and, dare I say it, intuitive flow of FaceSpan.
I’ve used Smile to create interface-rich dialogs (or even super simple dialogs, like the one which is a simple progress bar that can be used to offer feedback for my more complex or time-consuming scripts).
One of these dialogs, which I call ScanButton,
was originally just a button to activate the scanimage binary (http://www.sane-project.org/sane-frontends.html), but which soon (soon? yeah, soon) became a fairly sophisticated interface to scan, including previewing and pre-scan cropping.
I made this because I bought a scanner on craigslist which probably fell off a truck, was twenty bucks, and was lacking in consistent OSX-friendly software, especially for doing batches of scan sequences (among other things, I do traditional animation, you see). So I wrote my own, and utilized Smile’s dialog development.
My latest endeavor came about because I was messing around with ffmpeg (www.ffmpeg.org) to do fast conversions of movies (quicktime, windows media, avi, mpeg) for a job I was working on. Long story short (am I still typing?), I decided that I wanted to give the company I was working for a GUI-enhanced script to help with their approvals and deliveries. I wanted to do it quickly. I wanted it to be fun (yes, I find Smile “fun”).
Somewhere in the annals of Smile documentation there is a feature that allows you to wrap a scripted Smile dialog into its own app. Man, I can’t tell you how many times I tried to use that feature and had it blow up. It seemed buggy and unreliable. Whether or not it is buggy and unreliable is not the purpose of this article. But when developing this movie-converter dialog, I thought, why not just have the company download and install Smile, give them the dialog file (which is basically a double-clickable plugin) and have them use that? Is it possible, I wondered, to modify Smile so that the dialog acts just like a stand-alone-type thing? Basically, yes. AppleScript is at the heart of Smile; it’s one of the most beautifully complete AppleScript-powered applications out there. All you have to do is add some code into your dialog’s on prepare, on deactivated, and on delete handlers (and, if you like, add an additional handler, as I did), and you can make the dialog the main attraction and limit the user’s control over Smile (but if they want to do more Smile-y things, they can open Smile by itself and go to town).
The Code Snippets
on prepare theDialog
set prepared to true
modifySmileUI(theDialog)
end prepare
to modifySmileUI(thisMainDialog)
set menuKillList to {2, 4, 5, 9, 10, 11}
repeat with m in menuKillList
set visible of menu m to false
end repeat
--then get rid of specific items:
set visible of menu item "Clear Console" of menu 3 to false
set visible of menu item "Compare" of menu 3 to false
set visible of menu item "Output to Console" of menu 3 to false
set visible of menu item "Edit Mode" of menu 3 to false
set visible of menu item 18 of menu 3 to false--menu item "Go to line…"
set visible of menu item 19 of menu 3 to false--menu item ""
set visible of menu item "Find definition" of menu 3 to false
set visible of menu item "Enter selection" of menu 3 to false
set visible of menu item "Smile dictionary" of menu 1 to false
--set visible of menu item "Preferences..." of menu 1 to false--not accessible
close (every window whose name is not (name of thisMainDialog))
end modifySmileUI
on deactivated
thisDlg
--keeps Prefs from being opened :
--DANGER! Do NOT close the Prefs window; this will crash Smile in a bad way.
if ("Preferences" is in (name of windows)) then
set visible of window "Preferences" to false
set index of window "MovieForge" to 1 --hmm.
end if
end deactivated
on delete theDialog
continue delete theDialog
quit
end delete
The AppleScript code above represents everything I use to make my dialog feel more like a stand-alone. I comment out the “modifySmileUI(theDialog)” line in the first handler until the dialog is ready to be delivered. I also comment out the “quit” line in the last handler until the dialog is ready to ship. When the dialog is complete, I un-comment out these lines and the dialog is ready to be double-clicked by users who have no interest in the inner-workings of the dialog or Smile. They just want an interface to use for their workflow-enhancing pleasure.
What It Does.
Handler #1, on prepare, is what the dialog does as it is creating itself. When the modifySmileUI line “goes live” (gets un-commented), it calls the modifySmileUI handler which turns off all unnecessary menus and menu items in Smile, so that only the “Smile”, “Edit” and “Help” menus are visible.
The on deactivated handler, called when another window opens in front of the dialog, has some rather hack-y code that prevents (more or less) Smile’s Preferences from being opened. The idea here is that Smile’s Preference’s are accessible when using Smile, but not when using my dialog. As you can read in the comment, my first attempts at this, which actually sent a close window event to the Preferences window, caused Smile to crash hard, so I dispensed with this idea and used the “set visible to false” technique, which isn’t ideal (the interface is a little confusing for a split-second, and afterward, the main dialog floats in a sort of frontmost-but-not-frontmost limbo until you click on it), but it works.
Finally, the last handler, on delete, handles what happens when you close the dialog by quitting Smile completely, so that quitting the dialog quits the whole shebang, and no one is the wiser.
© 2014 Christopher R Green
Monday, January 13, 2014
Delicious Flag Animation
Mmmmmm. Delicious flag action. Made in Cheetah3D and After Effects, with help from the friendly Element3D plugin.
Oh. You want to see it move. Fine.
Oh. You want to see it move. Fine.
Friday, November 29, 2013
awk 'BEGIN { cntr = 0 } /repeating string/ { cntr++ ;OFS=""; print "repeating newString", cntr } !/repeating string/ { print $0 }' thisfile.txt>modified-thisfile.txt
This bash script "one-liner" searches for occurrences of "repeating string" in a file and for each occurrence, replaces the string with "repeating newString" and adds a number (cntr) to that new string, so that the output file (modified-thisfile.txt) has "repeating newString1", "repeating newString2", etc., where the original strings were. I used this to modify material assignments in (3D) obj files (in which the original string in question was "usemtl default").
The problem was that I needed to make the materials assigned to each 3D object unique. These obj files were exported from Cheetah3D, and were to be used with the Element3D plugin in After Effects, which uses separate and unique material assignments to separate objects/polygons.
The OFS part ensures that the number is printed directly after the string, instead of, by default, with a space before it.
This bash script "one-liner" searches for occurrences of "repeating string" in a file and for each occurrence, replaces the string with "repeating newString" and adds a number (cntr) to that new string, so that the output file (modified-thisfile.txt) has "repeating newString1", "repeating newString2", etc., where the original strings were. I used this to modify material assignments in (3D) obj files (in which the original string in question was "usemtl default").
The problem was that I needed to make the materials assigned to each 3D object unique. These obj files were exported from Cheetah3D, and were to be used with the Element3D plugin in After Effects, which uses separate and unique material assignments to separate objects/polygons.
The OFS part ensures that the number is printed directly after the string, instead of, by default, with a space before it.
Saturday, April 20, 2013
Python Script for getting pixel color on screen in OSX
This post on stackoverflow: http://stackoverflow.com/questions/12978846/python-get-screen-pixel-value-in-os-x, and this blog post: http://neverfear.org/blog/view/156/OS_X_Screen_capture_from_Python_PyObjC describe a pixel-color-grabbing method using python on OSX. Here is a simplified version, which takes command line arguments and is made to only capture a 1x1 pixel region (this makes it faster for just this functionality) (btw, I shall do my best to get this to format correctly for copying and pasting):
#!/usr/bin/python
import struct
import operator
import Quartz.CoreGraphics as CG
import sys, getopt
def main():
args = getopt.getopt(sys.argv[1:], '')
twoArgs = len(args[1]) == 2
#print args[1]
#error correction here to check for [correct] arguments
if twoArgs:
argx = args[1][0]
argy = args[1][1]
try:
global x
x = int(argx)
global y
y = int(argy)
except ValueError:
print "Error! Enter two integers as arguments."
#print x
#print y
else:
sp = ScreenPixel()
sp.capture()
print sp.pixel(0, 0)
else:
print "Error! Script requires two integers as arguments."
class ScreenPixel(object):
"""Captures the screen using CoreGraphics, and provides access to
the pixel values.
[crg:]
... pass two arguments to script (no comma, no nuthin', a la:
./thisScript.py 112 767
"""
def capture(self):
"""see original version for capturing full screen
(and lots of other stuff)
"""
region = CG.CGRectMake(x, y, 1, 1)
# Create screenshot as CGImage
image = CG.CGWindowListCreateImage(
region,
CG.kCGWindowListOptionOnScreenOnly,
CG.kCGNullWindowID,
CG.kCGWindowImageDefault)
# Intermediate step, get pixel data as CGDataProvider
prov = CG.CGImageGetDataProvider(image)
# Copy data out of CGDataProvider, becomes string of bytes
self._data = CG.CGDataProviderCopyData(prov)
# Get width/height of image
self.width = CG.CGImageGetWidth(image)
self.height = CG.CGImageGetHeight(image)
def pixel(self, x, y):
"""Get pixel value at given (x,y) screen coordinates
Must call capture first.
"""
# Pixel data is unsigned char (8bit unsigned integer),
# and there are four (blue,green,red,alpha)
data_format = "BBBB"
# Calculate offset, based on
# http://www.markj.net/iphone-uiimage-pixel-color/
# [crg]: removed this -- unnecessary step, just using zero
#offset = 4 * ((self.width*int(round(y))) + int(round(x)))
# Unpack data from string into Python'y integers
b, g, r, a = struct.unpack_from(data_format, self._data, offset=0)
# Return BGRA as RGBA
return (r, g, b)
#can (used to) return alpha, too, but in this context, unnecessary
if __name__ == '__main__':
main()
Monday, March 19, 2012
Sometimes it is amazing how upgrading to a new version can make a problem just magically go away. It also helps to make a useful mistake along the way.
I work with three 3D camera trackers: PHoePro (The Pixel Farm), SynthEyes (Andersson Technologies), and Camera Tracker for After Effects (The Foundry). Just started a new project that involved some deceptively simple green screen elements. The lens used for shooting these objects, however (a fairly long one [75mm]) was the kind that you can shift into different positions so as to offset the perspective. Doing camera or object tracks with footage shot with such a lens can be a little tricky, especially with a long lens.
On-set in a supervisory capacity, I was tempted to upset the whole arrangement by asking to shoot with a different (that is, not-shift-able) lens. But I am loathe to do too much of that kind of thing, mostly because they had already decided that the look of the objects was "right". I'm more likely to ask for slight adjustments to the shoot that take maybe 2 minutes, and save hours (or days, hopefully) in post. In this case, the good folks at AutoFuss were good enough to humor me and use a longer lens than the one they started with (but still shifted), and utilize on the rig some very high tech additions which I had brought with me: marked up clothes pins (they look sort of like little "Egyptian Mau"s).
The lens was to get more of the rig in the shot; the clothespins were quickly clamped onto the rig (away from the important object) to make it more "track-able". We were shooting with the Red One, so there was plenty of resolution to allow for this. The first tests I did showed that I was going to have problems. All attempts at tracking either flat-out failed or created bad cameras that were infected with "inverted perspective" -- where the software "sees" a detail moving across the screen and interprets that movement as being background when it should be foreground, or vice versa. This can happen when background details are fuzzy and jump around and appear to be moving "faster" (if they weren't jumping, they wouldn't be moving faster, you see), so the algorithms determine that such movement must be closer to camera. This doesn't happen often, but it happens. Inverted perspective can also happen when the perspective is so compressed, as with a very long lens, that the software gets fooled, and chooses a screwy "solution" (like in this case, half the move is correct, then the solve camera decides to make a 180 as it were and starts moving in the opposite direction, even though the original camera continues along the "same" path).
Anyway, the shifted lens was complicating things, and probably adding to the perspective problems. When I first saw the camera and lens set-up, I suspected this might lead to weirdness, so just in case, when they were about to wrap, I had them shoot a couple of reference frames of the lens in its shifted and "unshifted" positions.
So fast forward to the next day, when all the footage was in, and I was playing around like crazy trying to get my trackers to work. I didn't have too much faith in PFHoePro, although it happens to give the best results when it works, and I have done some pretty nutty things to footage to get it to work in PFHoePro when it seemed like there was no way such an "auto-pilot" tool would handle less-than-ideal footage. SynthEyes seemed like the best bet, but I figured I'd still have to pull some tricks out of my bag to get it to behave. One of the things I tried was simply rotating the footage -90 degrees. Interestingly, the tracker behaved differently, but still failed.
Many hours later, I had tried a number of things, but felt I needed to come up with something really wacky. Then, after a lot of playing around and meditating, I thought "hey, I just got paid; let's upgrade SynthEyes" (I was still using the '08 version).
After upgrading to the newer '11 version, my intention was to first plug in the original footage to see how it would do. But this wasn't what I did. I accidentally plugged in the rotated-only version and was amazed to see a perfect track. When I eventually realized my "mistake" of using the rotated footage, I thought, oh, I'll just plug in the original non-rotated footage. But guess what? FAIL. Inverted perspective.
So it seems that SynthEyes understands rotations around the Y axis better than the Z (given X=left-right, Y=up-down, Z=backward-forward). Go figure.
I work with three 3D camera trackers: PHoePro (The Pixel Farm), SynthEyes (Andersson Technologies), and Camera Tracker for After Effects (The Foundry). Just started a new project that involved some deceptively simple green screen elements. The lens used for shooting these objects, however (a fairly long one [75mm]) was the kind that you can shift into different positions so as to offset the perspective. Doing camera or object tracks with footage shot with such a lens can be a little tricky, especially with a long lens.
On-set in a supervisory capacity, I was tempted to upset the whole arrangement by asking to shoot with a different (that is, not-shift-able) lens. But I am loathe to do too much of that kind of thing, mostly because they had already decided that the look of the objects was "right". I'm more likely to ask for slight adjustments to the shoot that take maybe 2 minutes, and save hours (or days, hopefully) in post. In this case, the good folks at AutoFuss were good enough to humor me and use a longer lens than the one they started with (but still shifted), and utilize on the rig some very high tech additions which I had brought with me: marked up clothes pins (they look sort of like little "Egyptian Mau"s).
The lens was to get more of the rig in the shot; the clothespins were quickly clamped onto the rig (away from the important object) to make it more "track-able". We were shooting with the Red One, so there was plenty of resolution to allow for this. The first tests I did showed that I was going to have problems. All attempts at tracking either flat-out failed or created bad cameras that were infected with "inverted perspective" -- where the software "sees" a detail moving across the screen and interprets that movement as being background when it should be foreground, or vice versa. This can happen when background details are fuzzy and jump around and appear to be moving "faster" (if they weren't jumping, they wouldn't be moving faster, you see), so the algorithms determine that such movement must be closer to camera. This doesn't happen often, but it happens. Inverted perspective can also happen when the perspective is so compressed, as with a very long lens, that the software gets fooled, and chooses a screwy "solution" (like in this case, half the move is correct, then the solve camera decides to make a 180 as it were and starts moving in the opposite direction, even though the original camera continues along the "same" path).
Anyway, the shifted lens was complicating things, and probably adding to the perspective problems. When I first saw the camera and lens set-up, I suspected this might lead to weirdness, so just in case, when they were about to wrap, I had them shoot a couple of reference frames of the lens in its shifted and "unshifted" positions.
So fast forward to the next day, when all the footage was in, and I was playing around like crazy trying to get my trackers to work. I didn't have too much faith in PFHoePro, although it happens to give the best results when it works, and I have done some pretty nutty things to footage to get it to work in PFHoePro when it seemed like there was no way such an "auto-pilot" tool would handle less-than-ideal footage. SynthEyes seemed like the best bet, but I figured I'd still have to pull some tricks out of my bag to get it to behave. One of the things I tried was simply rotating the footage -90 degrees. Interestingly, the tracker behaved differently, but still failed.
Many hours later, I had tried a number of things, but felt I needed to come up with something really wacky. Then, after a lot of playing around and meditating, I thought "hey, I just got paid; let's upgrade SynthEyes" (I was still using the '08 version).
After upgrading to the newer '11 version, my intention was to first plug in the original footage to see how it would do. But this wasn't what I did. I accidentally plugged in the rotated-only version and was amazed to see a perfect track. When I eventually realized my "mistake" of using the rotated footage, I thought, oh, I'll just plug in the original non-rotated footage. But guess what? FAIL. Inverted perspective.
So it seems that SynthEyes understands rotations around the Y axis better than the Z (given X=left-right, Y=up-down, Z=backward-forward). Go figure.
Subscribe to:
Posts (Atom)




