Skip to content

Ecce Signum

Immanentize the Empathy

  • Home
  • About Me
  • Published Works and Literary Matters
  • Indexes
  • Laboratory
  • Notebooks
  • RSS Feed

Month: October 2011

Toys Become Tools

2011-10-06 John Winkelman

Back in March Seth Godin wrote that he was happy that some of the common web technologies appear to be, in the opinion of the cognoscenti, “dead”. Dead, in this case, meaning supplanted by the myriad shiny new toys available to anyone with the appropriate budget and bandwidth. Now that the shine has worn off of “weblogs”, for instance, they can once again be made repositories of information. Useful, instead of cool.

I had never really thought about it, but he is absolutely right. Social media – Facebook, Twitter, and the like – have slurped up the attention bandwidth which once made Movable Type and the like profitable ventures. Your cat photos get posted on Facebook. Other peoples’ cat photos get posted on a Tumblr page. Add captions and upload it to I Can Has Cheezburger, and now everyone can play with your cat. (quick question: do you ever bother to pay attention to who creates individual LOLcats at ICHC?)

Kevin Kelly once said that the older a technology is, the more likely it is to remain useful*. Axes have been around at least as long as Homo sapiens, and levers probably even longer. And while the physical representation of an old-but-useful technology may evolve (c.f. axe -> saw -> chainsaw -> lightsaber), it seldom does away with the need which drove the original discovery. Actually, that may be the only event which would completely kill off a piece of technology – the ultimate solution to the problem which prompted its invention. When there is no longer anything which can be improved by the application of percussive force, the hammer will finally disappear.

* “old” technology is not synonymous with “dead” technology.

Posted in Life comment on Toys Become Tools

Syntax Highlighter Test

2011-10-05 John Winkelman

I just installed the Syntax Highlighter Javascript Library, which makes it easy to display easily-readable source code on websites. As my first test, here is a class I wrote in Actionscript 3 a couple of years ago, when I was deep in a dozen different projects, all built using Notepad++ and the MXMLC command-line compiler. The upshot of that was, no way to “trace” output from the .swf file. So I wrote my own, more or less. Here is the source code:

package {
	import flash.display.DisplayObjectContainer;
	import flash.display.Stage;
	import flash.display.Sprite;
	import flash.events.TimerEvent;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.utils.Timer;
	public class InfoPanel extends Sprite {
		private var dragBar:Sprite;
		private var closeButton:Sprite;
		private var clearButton:Sprite;
		private var resizeButton:Sprite;
		private var outputWindow:TextField;
		private var timer:Timer;
		private var base:DisplayObjectContainer;
		private var isDragging:Boolean = false;
		private var isResizing:Boolean = false;
		private var dragMouseOffX:Number = 0;
		private var dragMouseOffY:Number = 0;
		private var resizeMouseOffX:Number = 0;
		private var resizeMouseOffY:Number = 0;
		private var w:Number = 0;
		private var h:Number = 0;
		private var bgc:Number;
		private var fgc:Number;
		private var outputFormat:TextFormat = new TextFormat("Courier New",11,0x33ff33,false,false,false,null,null,"left");
		public function InfoPanel($base:DisplayObjectContainer,$w:Number = 150,$h:Number = 100,$bgc:Number=0x000000,$fgc:Number=0x66ff66):void {
			base = $base;
			w = $w;
			h = $h;
			bgc = $bgc;
			fgc = $fgc;
			outputFormat.color = fgc;
			graphics.lineStyle(0,0x666666,1);
			graphics.beginFill(bgc,1);
			graphics.drawRect(0,0,w,h);
			graphics.endFill();
			dragBar = new Sprite();
			dragBar.graphics.beginFill(0x666666,1);
			dragBar.graphics.drawRect(0,0,w,10);
			dragBar.graphics.endFill();
			dragBar.buttonMode = true;
			dragBar.useHandCursor = true;
			dragBar.addEventListener(MouseEvent.MOUSE_DOWN,onDragMouseDown);
			dragBar.addEventListener(MouseEvent.MOUSE_UP,onDragMouseUp);
			dragBar.x = 0;
			dragBar.y = 0;
			addChild(dragBar);
			
			
			clearButton = new Sprite();
			clearButton.graphics.lineStyle(0,0xcccccc,1)
			clearButton.graphics.beginFill(0x666666,1);
			clearButton.graphics.drawCircle(0,0,3);
			clearButton.graphics.endFill();
			clearButton.x = w-15;
			clearButton.y = 5;
			clearButton.buttonMode = true;
			clearButton.useHandCursor = true;
			clearButton.addEventListener(MouseEvent.CLICK,onClearButtonClicked);
			addChild(clearButton);
			
			
			closeButton = new Sprite();
			closeButton.graphics.beginFill(0xcccccc,1);
			closeButton.graphics.drawCircle(0,0,3);
			closeButton.graphics.endFill();
			closeButton.x = w-5;
			closeButton.y = 5;
			closeButton.buttonMode = true;
			closeButton.useHandCursor = true;
			closeButton.addEventListener(MouseEvent.CLICK,onCloseButtonClicked);
			addChild(closeButton);
			resizeButton = new Sprite();
			resizeButton.graphics.beginFill(0xcccccc,1);
			resizeButton.graphics.drawRect(0,0,6,6);
			resizeButton.graphics.endFill();
			resizeButton.x = w-6;
			resizeButton.y = h-6;
			resizeButton.buttonMode = true;
			resizeButton.useHandCursor = true;
			resizeButton.addEventListener(MouseEvent.MOUSE_DOWN,onResizeMouseDown);
			resizeButton.addEventListener(MouseEvent.MOUSE_UP,onResizeMouseUp);
			addChild(resizeButton);

			outputWindow = new TextField();
			outputWindow.width = w-10;
			outputWindow.height = h-20;
			outputWindow.x = 5;
			outputWindow.y = 15;
			outputWindow.selectable = true;
			outputWindow.wordWrap = true;
			outputWindow.multiline = true;
			outputWindow.text = "STATS";
			outputWindow.setTextFormat(outputFormat);
			outputWindow.defaultTextFormat = outputFormat;
			
			addChild(outputWindow);
			timer = new Timer(25);
			timer.addEventListener(TimerEvent.TIMER,onTimer);
		}
		
		private function onTimer(e:TimerEvent):void {
			if(isDragging==true) dragMe();
			if(isResizing==true) resizeMe();
			e.updateAfterEvent();
		}
		private function onDragMouseDown(e:MouseEvent):void {
			e.stopPropagation();
			dragMouseOffX = e.target.mouseX;
			dragMouseOffY = e.target.mouseY;
			startMe();
			isDragging = true;
		}
		private function onDragMouseUp(e:MouseEvent):void {
			isDragging = false;
			stopMe();
			base.addChild(this);
		}
		private function onResizeMouseDown(e:MouseEvent):void {
			e.stopPropagation();
			resizeMouseOffX = e.target.mouseX;
			resizeMouseOffY = e.target.mouseY;
			startMe();
			isResizing = true;
		}
		private function onResizeMouseUp(e:MouseEvent):void {
			isResizing = false;
			stopMe();
		}
		private function onCloseButtonClicked(e:MouseEvent):void {
			e.stopPropagation();
			hideMe();
		}
		private function onClearButtonClicked(e:MouseEvent):void {
			outputWindow.text = "";
		}
		private function startMe():void {
			timer.start();
		}
		private function stopMe():void {
			timer.stop();
		}
		public function showMe():void {
			base.addChild(this);
		}
		public function hideMe():void {
			base.removeChild(this);
		}
		private function dragMe():void {
			x = stage.mouseX - dragMouseOffX;
			y = stage.mouseY - dragMouseOffY;
		}
		private function resizeMe():void {
			w = mouseX + 6 - resizeMouseOffX;
			h = mouseY + 6 - resizeMouseOffY;
			graphics.clear();
			graphics.lineStyle(0,0x666666,1);
			graphics.beginFill(bgc,1);
			graphics.drawRect(0,0,w,h);
			graphics.endFill();
			dragBar.graphics.clear();
			dragBar.graphics.beginFill(0x666666,1);
			dragBar.graphics.drawRect(0,0,w,10);
			dragBar.graphics.endFill();
			outputWindow.width = w - 10;
			outputWindow.height = h - 20;
			resizeButton.x = w - 6;
			resizeButton.y = h - 6
			clearButton.x = w - 15;
			closeButton.x = w - 5;
		}
		public function update($s:*,$r:Boolean = false):void {
			if($r==true) {
				outputWindow.text = $s.toString();
			} else {
				outputWindow.appendText("\n"+$s.toString());
			}
			outputWindow.scrollV = outputWindow.maxScrollV;
			base.addChild(this);
		}
	}
}

And it is called like this:

var info:InfoPanel = new InfoPanel(this);
info.update("hello world");

After being created the InfoPanel can be positioned just like any other DisplayObject. It accepts up to five arguments, in this order:

parent:DisplayObjectContainer, width:Number, height:Number, backgroundColor:Number,textColor:Number

Of them, only the parent argument is required; the rest will revert to default values if left empty. The parent item must be a DisplayObjectContainer, such as the Stage, or a MovieClip or Sprite.

Once created, the InfoPanel can be moved, resized, cleared and closed with the mouse.

To update the content, use the following method call:

info.update("a string");

This will append a line break, then the string. To clear the info panel when updating it, use the method call as follows:

info.update("a string",true);

Be careful; once the content of the InfoPanel starts measuring in the many thousands of characters, updating it may start to bog down the Flash player, slowing down whatever else you are running.

Posted in ProgrammingTagged Flash comment on Syntax Highlighter Test

More Thoughts About PhotoFly

2011-10-04 John Winkelman

Off and on over the past several weeks I have wandered around town with my camera looking for likely subjects to turn into 3d digital representations of themselves. My success rate is about .5, and is mostly made up of tree trunks and patches of gravel. Small objects, and objects in a light box, have not worked at all. I don’t know if this is a fundamental flaw with PhotoFly, an artifact of PhotoFly being in beta, or if I just don’t get it. I suspect (and hope) it is a mix of the latter two.

But enough of that. Of my successes, I have created animations of the best ones and posted them on YouTube.

 

This is the first animation I created. PhotoFly makes this quite easy, with a well-thought-out timeline-based animation tool. The gaps in the scene are places where the camera could not see the environment from where I took the photos. While beautiful, there are not a lot of vantage points at the koi pond.

 

This tree trunk is the second successful scene. The photos are from my parent’s house in Springport. I believe I took around 20 photos. Notice the gaps in the grass around the highest-resolution parts of the lawn. This is where PhotoFly couldn’t quite figure out how to stitch parts of the scene together, because grass is too uniform a color and texture for the software to sort out.

 

This one is my favorite so far. the overpass is a block from my house. I was wandering around with my camera when I noticed an extraordinary piece of graffiti on the concrete embankment. I took a few photos, then began wandering up and down the tracks, and up into the nooks and crannies of the overpass, trying to get everything from every angle. Mostly, I succeeded. The bridge is quite new, and nowhere near as post-apocalyptic in real life as it appears in the animation. This is my only successful attempts at modelling a hollow structure.

I went back a couple of weeks later, intending to model the entire overpass, including the railroad track leading into it. Unfortunately, the regularity, the sameness of the man-made parts of the scene confounded PhotoFly, and of the hundred or so photos I took, PhotoFly only managed to incorporate about 20 into the final scene, which looked like someone had printed a photo of the bridge onto a wad of silly putty, then twisted it up and thrown it against a wall. I suspect that a more judicious use of angles when taking photos would make a future attempt more successful.

 

In my opinion, this is the most successful of all of my PhotoFly experiments, simply because this is the one with the least amount of distortion. The photos which went into this scene are from the Lake Michigan shoreline, just north of Oval Beach in Saugatuck, Michigan. There was enough light, and enough varied texture, that the software created this scene in one go. I didn’t need to define any points or re-stitch any of the photos. It just worked.

 

This is the most recent one. A goose-neck gourd, on a foot stool in my back yard. I would call it a qualified success. The yard looks great! The gourd, other than the neck, looks pretty good. The footstool – the man-made, smooth, texture-less object – is warped and distorted, and has been melded with the background. This one probably suffered a little from the bright sunlight. The gourd is smooth and shiny, and some of its color patterns were obscured by reflections.

The three things PhotoFly seems to have the most difficulty with are reflections, lack of context, and sharply contrasting light sources. The pattern recognition part of PhotoFly can’t (at present) distinguish between a pattern and a reflection of a pattern. This makes sense; it tries to find and reproduce patterns. If two parts of a photo have the same pattern, it is difficult to decide which part goes where, without a lot of other contextual information.

Which is why PhotoFly doesn’t work well with, for instance, something in a light box. The thing itself may have astonishing detail, but without detailed surroundings to give it a location in space, PhotoFly can’t (again, at present) determine angles, curves, relative distances, and the like. This is one case where having a light source which is the same strength, everywhere at once, is actually a detriment.

With brightly contrasting light, say, a plain-colored object in full afternoon sunlight, PhotoFly doesn’t necessarily recognize that the shady side of an object is attached to the sunny side of the object. If the object has a rich texture, lots of additional information which the software can use to create context, this is not such a problem, but a photo of e.g. a large rock, partially silhouetted against the sky, doesn’t work so well.

Having figured these issues out, it is simple to come up with successful PhotoFly scenes. If I discover a workaround to any of the above issues, I will post it here and at the AutoDesk Labs forums.

Posted in PhotographyTagged photogrammetry comment on More Thoughts About PhotoFly

Technical Notes On the New Site

2011-10-03 John Winkelman

For the most part, putting this site together went smoothly. Sure copy-and-pasting 700+ blog entries was a bit of a chore, as was going through every post to find which ones had digital assets which needed to be re-hosted. Tiresome, but not difficult.

In every previous version of this site, if I had a Flash movie which I wanted to show off, I would either post it in-line in the blog, or put it on its own page and link to it, or only show a teaser image on the front page and embed the animation in the full post. For this site I wanted something new. You’ve all seen light boxes – you click on a thumbnail photo, and a translucent overlay appears over the site, and the relevant content appears therein. I decided to go with one of those.

There are myriad ways to create a lightbox. All involve Javascript and CSS, and most of them are good at what they do. I decided to go with ShadowBox.js because it supports all kind of content; not just Flash and/or images. I ran it through a few static page tests, and it had everything I needed.

Getting it hooked up in Drupal Gardens (“DG”) was a little more challenging. Since DG users don’t have access to modify the actual templates of the site, using external code files can be a little challenging. The DG help files recommend creating a block in the header and copy-and-pasting the javascript into a plain text file, and embedding it directly in the HTML for a page. This is what I have done in the past, but having just uploaded over a hundred Flash movies and photos to the content area of the site, I decided to try something new.

It turns out that you can upload any kind of content you want to the content/media area of DG. You might need to make changes in the configuration area of your site to allow for the upload of e.g. a .js or .swf file, but it can be easily done. There is one thing to note: Nothing loaded into this area is processed on the server. If you upload a .php file, it will be served as plain text, NOT processed through Drupal/PHP. Fortunately, for Javascript, I don’t need it to be processed. Plain text is just fine.

Accessing the Javascript is easy; everything uploaded to the media library on DG is in the /sites/mysite.drupalgardens.com/files/ directory. To access it, I created a block which contains a <script> tag, which links to the new files at /sites/mysite.drupalgardens.com/files/shadowbox.js. Everything worked on the first try.

More technical notes to follow, as I figure out how to do more things in Drupal.

Posted in Programming comment on Technical Notes On the New Site

Some Photos of Hot Peppers

2011-10-01 John Winkelman

The pepper season is winding down, so I grabbed the brightest and healthiest of the most recent harvest and took a few photos in my light box. Clicking any of the images will take you to Flickr, where you can see the rest of the photos in the set.

Belgian Carrot Pepper

Cherry Bomb Pepper

Habanero Pepper

Cayenne Pepper

Posted in PhotographyTagged food, gardening comment on Some Photos of Hot Peppers

Posts navigation

Newer posts

Personal website of
John Winkelman

John Winkelman in closeup

Archives

Categories

Posts By Month

October 2011
S M T W T F S
 1
2345678
9101112131415
16171819202122
23242526272829
3031  
« Sep   Nov »

Links of Note

Reading, Writing
Tor.com
Locus Online
The Believer
File 770
IWSG

Watching, Listening
Writing Excuses Podcast
Our Opinions Are Correct
The Naropa Poetics Audio Archive

News, Politics, Economics
Naked Capitalism
Crooked Timber

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

© 2025 Ecce Signum

Proudly powered by WordPress | Theme: x-blog by wpthemespace.com