<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JellyFilled Studios</title>
	<atom:link href="http://www.jellyfilledstudios.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jellyfilledstudios.com</link>
	<description>iOS Applications</description>
	<lastBuildDate>Thu, 26 Jan 2012 21:09:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Zapp</title>
		<link>http://www.jellyfilledstudios.com/2011/11/23/zapp/</link>
		<comments>http://www.jellyfilledstudios.com/2011/11/23/zapp/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 03:28:11 +0000</pubDate>
		<dc:creator>jellyrob</dc:creator>
				<category><![CDATA[Entertainment]]></category>

		<guid isPermaLink="false">http://www.jellyfilledstudios.com/?p=51</guid>
		<description><![CDATA[Zapp is an app that puts the power of high-voltage electricity at your fingertips. Use your iPhone camera&#8217;s live background and send bolts of lightning to whatever&#8217;s on the screen. The power of the simulated lightning bolts follow your touch as your finger crosses the screen. This app is recommended for Super Hero wannabees, fans ...]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://itunes.apple.com/us/app/zapp/id305571434?mt=8"><img src="http://www.jellyfilledstudios.com/wp-content/uploads/2012/01/App_Store_Badge_EN_0609-300x150.png" alt="" title="App_Store_Badge_EN_0609" width="300" height="150" class="alignnone size-medium wp-image-356" /></a></p>
<p>Zapp is an app that puts the power of high-voltage electricity at your fingertips.</p>
<p>Use your iPhone camera&#8217;s live background and send bolts of lightning to whatever&#8217;s on the screen. The power of the simulated lightning bolts follow your touch as your finger crosses the screen.</p>
<p>This app is recommended for Super Hero wannabees, fans of atmospheric discharge, amateur bolt throwers and addicts of any other apps that are for amusement only.</p>
<p>iTouch users can also use Zapp as it also allows electric charge simulation on photos selected from your photo library.</p>
<p>Fun Tip: Take a snapshot of your iPhone or iTouch desktop by pressing the power button and home button at the same time. This will save a screen shot to your photo library. Then, using the Zapp application, turn on &#8220;stealth mode&#8221; and select the screen shot as a background. Your device will appear to have an electrical short!</p>
<p>Best if held in your own hand to avoid anyone dropping the device in fear of being shocked. This application is for entertainment purposes only. The acting out of any prank, joke, or hoax is strongly discouraged.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jellyfilledstudios.com/2011/11/23/zapp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick Distance</title>
		<link>http://www.jellyfilledstudios.com/2011/11/23/quick-distance/</link>
		<comments>http://www.jellyfilledstudios.com/2011/11/23/quick-distance/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 03:27:41 +0000</pubDate>
		<dc:creator>jellyrob</dc:creator>
				<category><![CDATA[Productivity]]></category>

		<guid isPermaLink="false">http://www.jellyfilledstudios.com/?p=48</guid>
		<description><![CDATA[The QuickDistance IPhone application is a quick and simple way to measure. QuickDistance can: Measure the distance from home plate to the pitchers mound Determine distances from wall to wall Find the distance to any object It&#8217;s a handy replacement for the &#8220;guesstimate&#8221; used for stepping-off distances. The ideal accuracy range for the average person ...]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://itunes.apple.com/us/app/quickdistance/id307921176?mt=8"><img src="http://www.jellyfilledstudios.com/wp-content/uploads/2012/01/App_Store_Badge_EN_0609-300x150.png" alt="" title="App_Store_Badge_EN_0609" width="300" height="150" class="alignnone size-medium wp-image-356" /></a></p>
<p>The QuickDistance IPhone application is a quick and simple way to measure.</p>
<p>QuickDistance can:<br />
Measure the distance from home plate to the pitchers mound<br />
Determine distances from wall to wall<br />
Find the distance to any object</p>
<p>It&#8217;s a handy replacement for the &#8220;guesstimate&#8221; used for stepping-off distances.</p>
<p>The ideal accuracy range for the average person is between 5 feet and 30 feet.</p>
<p>QuickDistance is ideally suited to measuring distances on level ground but also supports a slope adjustment for measurements on an uphill or downhill grade.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jellyfilledstudios.com/2011/11/23/quick-distance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Moon Shot</title>
		<link>http://www.jellyfilledstudios.com/2011/11/23/moon-shot/</link>
		<comments>http://www.jellyfilledstudios.com/2011/11/23/moon-shot/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 03:26:57 +0000</pubDate>
		<dc:creator>jellyrob</dc:creator>
				<category><![CDATA[Entertainment]]></category>

		<guid isPermaLink="false">http://www.jellyfilledstudios.com/?p=44</guid>
		<description><![CDATA[You will love this incredibly realistic simulation of the classic Moon Shot marble game. Moon Shot HD puts a new twist on this old classic. With the touch of two fingers, slide the bars apart and watch the ball as it defies the laws of gravity by moving up hill. Slide the bars back together ...]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://itunes.apple.com/us/app/moonshothd/id380998833?mt=8"><img src="http://www.jellyfilledstudios.com/wp-content/uploads/2012/01/App_Store_Badge_EN_0609-300x150.png" alt="" title="App_Store_Badge_EN_0609" width="300" height="150" class="alignnone size-medium wp-image-356" /></a></p>
<p>You will love this incredibly realistic simulation of the classic Moon Shot marble game. Moon Shot HD puts a new twist on this old classic.</p>
<p>With the touch of two fingers, slide the bars apart and watch the ball as it defies the laws of gravity by moving up hill. Slide the bars back together to give the ball a boost and see who can reach the highest level.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jellyfilledstudios.com/2011/11/23/moon-shot/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Motion Activated Video</title>
		<link>http://www.jellyfilledstudios.com/2011/11/23/motion-activated-video/</link>
		<comments>http://www.jellyfilledstudios.com/2011/11/23/motion-activated-video/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 03:26:00 +0000</pubDate>
		<dc:creator>jellyrob</dc:creator>
				<category><![CDATA[Utilities]]></category>

		<guid isPermaLink="false">http://www.jellyfilledstudios.com/?p=40</guid>
		<description><![CDATA[Motion Activated Audio and Video Recorder works with iPhone and iTouch. Automatically starts audio and video recording when it detects any movement within view of the camera. Recording will continue until about 10 seconds after motion has stopped. A Time stamp is placed on every frame of the video recording. We used it to catch ...]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://itunes.apple.com/us/app/motion-activated-video-recorder/id403864235?mt=8"><img src="http://www.jellyfilledstudios.com/wp-content/uploads/2012/01/App_Store_Badge_EN_0609-300x150.png" alt="" title="App_Store_Badge_EN_0609" width="300" height="150" class="alignnone size-medium wp-image-356" /></a></p>
<p>Motion Activated Audio and Video Recorder works with iPhone and iTouch.</p>
<p>Automatically starts audio and video recording when it detects any movement within view of the camera. Recording will continue until about 10 seconds after motion has stopped. </p>
<p>A Time stamp is placed on every frame of the video recording. </p>
<p>We used it to catch which one of our dogs was stealing treats from the kitchen counter. See the sample video here:</p>
<p><iframe width="500" height="375" src="http://www.youtube.com/embed/_49A6rNi6Cw?fs=1&#038;feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p>All recordings are stored with the application and will automatically delete after 5 days. Clips you want to keep can be combined together and moved to your iOS Photo Library in a video format that can be sync&#8217;d to your computer or shared via SMS.</p>
<p>Run in stealth mode with a clock view or in standard mode with a notice displayed informing anyone within view that audio and video surveillance is active.</p>
<p>Warning: Do not to use this application for any illegal purpose. If not used correctly, covert cameras and audio recording devices may violate the privacy rights of others. This product is for home/personal use and not intended for professional surveillance or spying.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jellyfilledstudios.com/2011/11/23/motion-activated-video/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Live Effects Cam</title>
		<link>http://www.jellyfilledstudios.com/2011/11/23/live-effects-cam/</link>
		<comments>http://www.jellyfilledstudios.com/2011/11/23/live-effects-cam/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 03:25:21 +0000</pubDate>
		<dc:creator>jellyrob</dc:creator>
				<category><![CDATA[Photo & Video]]></category>

		<guid isPermaLink="false">http://www.jellyfilledstudios.com/?p=37</guid>
		<description><![CDATA[Live Effects is an advanced real-time camera application that lets you view fun, crazy and sometimes artistic effects live through your iPhone or camera equipped iTouch. &#8220;What you see is what you get&#8221; when you use the cool effects and overlays in Live Effects to take fun snapshots with your built-in camera. Contort your smile ...]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://itunes.apple.com/us/app/live-effects-cam/id399175661?mt=8"><img src="http://www.jellyfilledstudios.com/wp-content/uploads/2012/01/App_Store_Badge_EN_0609-300x150.png" alt="" title="App_Store_Badge_EN_0609" width="300" height="150" class="alignnone size-medium wp-image-356" /></a></p>
<p>Live Effects is an advanced real-time camera application that lets you view fun, crazy and sometimes artistic effects live through your iPhone or camera equipped iTouch.</p>
<p>&#8220;What you see is what you get&#8221; when you use the cool effects and overlays in Live Effects to take fun snapshots with your built-in camera. Contort your smile with the Shape effects. Add an artistic look with the Pixel Effects. View yourself hanging in an art museum with the Overlay Effects.</p>
<p>When you like what you see, take a snapshot. All snapshots are instantly saved in your iOS Photo Library. </p>
<p>We&#8217;ve developed an advanced implementation of technologies that combine your iOS device camera, pixel mapping and Open/GL to give Live Effects the unique ability to produce stunning image effects in REAL-TIME.</p>
<p>Experiment with all the effects and combinations to transform your look instantly. Then, take a snapshot and send them to your friends, use them as your profile pics or add them to your Address Book. </p>
<h2>Sample Augmented Reality Code</h2>
<p>This is all the code needed to build the foundation of an augmented reality app. This project allows you to implement a normal UIView as your camera layer or an Open/GLES1 view with the camera stream as a texture</p>
<div class="toggle">
<h4 class="toggle_title">GLView.h</h4>
<div class="toggle_content">
<pre class="brush: objc; title: ; toolbar: false; wrap-lines: false; notranslate">
//
//  GLView.h
//  AugCam
//
//  Created by John Carter on 1/26/2012.
//

#define HIRESDEVICE (((int)rintf([[[UIScreen mainScreen] currentMode] size].width/[[UIScreen mainScreen] bounds].size.width )&gt;1))

#import &lt;UIKit/UIKit.h&gt;
#import &lt;OpenGLES/EAGL.h&gt;
#import &lt;OpenGLES/ES1/gl.h&gt;
#import &lt;OpenGLES/ES1/glext.h&gt;
#import &lt;QuartzCore/QuartzCore.h&gt;
#import &lt;OpenGLES/EAGLDrawable.h&gt;

@interface GLView : UIView
	{
@private
	/* The pixel dimensions of the backbuffer */
	GLint backingWidth;
	GLint backingHeight;

	EAGLContext *context;

	/* OpenGL names for the renderbuffer and framebuffers used to render to this view */
	GLuint viewRenderbuffer;
	GLuint viewFramebuffer;
	GLuint depthRenderbuffer;

	/* OpenGL name for the sprite texture */
	GLuint spriteTexture;
	}

@property (readonly) GLint backingWidth;
@property (readonly) GLint backingHeight;
@property (readonly) EAGLContext *context;

- (void) drawView;
+ (UIImage *) snapshot:(GLView *)eaglview;

@end
</pre>
</div>
</div>
<div class="toggle">
<h4 class="toggle_title">GLView.m</h4>
<div class="toggle_content">
<pre class="brush: objc; title: ; toolbar: false; wrap-lines: false; notranslate">
//
//  GLView.m
//  AugCam
//
//  Created by John Carter on 1/26/2012.
//

#define DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) / 180.0 * M_PI)

#import &quot;GLView.h&quot;

// Private Methods
//
@interface GLView()

- (BOOL) createFramebuffer;
- (void) destroyFramebuffer;

@end

@implementation GLView

@synthesize backingWidth;
@synthesize backingHeight;
@synthesize context;

+ (Class) layerClass
	{
	return [CAEAGLLayer class];
	}

- (id)init
	{
	self = [[super init] initWithFrame:CGRectMake(0.0, 0.0, 480.0, 640.0)];		// size of the camera image being captures

	if ( self==nil )
		return self;

	// Set Content Scaling
	//
	if ( HIRESDEVICE )
		{
	 	self.contentScaleFactor = (CGFloat)2.0;
		}

	// Get our backing layer
	//
	CAEAGLLayer *eaglLayer = (CAEAGLLayer*) self.layer;

	// Configure it so that it is opaque, does not retain the contents of the backbuffer when displayed, and uses RGBA8888 color.
	//
	eaglLayer.opaque = YES;

	eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
										[NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking,
										kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
										nil];

	// Create our EAGLContext, and if successful make it current and create our framebuffer.
	//
	context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];

	if(!context || ![EAGLContext setCurrentContext:context] || ![self createFramebuffer])
		{
		[self release];
		return nil;
		}

	// Final View Settings
	//
	[self setOpaque:YES];
	self.multipleTouchEnabled = YES;
	self.backgroundColor = [UIColor clearColor];

	[EAGLContext setCurrentContext:context];

	glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
	glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	GLfloat zNear = 1.0;
	GLfloat zFar = 1000.0;
	GLfloat fieldOfView = 90;		// Lens Angle of View
	GLfloat size = zNear * tanf(DEGREES_TO_RADIANS(fieldOfView) / 2.0);
	CGRect rect = CGRectMake( (CGFloat)0.0, (CGFloat)0.0, backingWidth, backingHeight);

	glFrustumf(-size, size, -size / (rect.size.width / rect.size.height), size / (rect.size.width / rect.size.height), zNear, zFar);

	glViewport(0, 0, backingWidth, backingHeight);

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);
	glEnable(GL_MULTISAMPLE);
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
	glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
	glDisable(GL_ALPHA_TEST);

	// Turn Translucent Textures: OFF
	//
	glDisable(GL_BLEND);

//	// Turn Translucent Textures: ON
//	//
//	glEnable(GL_BLEND);
//	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

	return self;
	}

- (void) drawView
	{
	[context presentRenderbuffer:GL_RENDERBUFFER_OES];
	}

- (BOOL)createFramebuffer
	{
	// Generate IDs for a framebuffer object and a color renderbuffer
	//
	glGenFramebuffersOES(1, &amp;viewFramebuffer);
	glGenRenderbuffersOES(1, &amp;viewRenderbuffer);

	glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
	glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);

	// This call associates the storage for the current render buffer with the EAGLDrawable (our CAEAGLLayer)
	// allowing us to draw into a buffer that will later be rendered to screen whereever the layer is (which corresponds with our view).
	//
	[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];

	glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

	glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &amp;backingWidth);
	glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &amp;backingHeight);

	// If this app uses a depth buffer, we'll create and attach one via another renderbuffer.
	//
	if ( YES )
		{
		glGenRenderbuffersOES(1, &amp;depthRenderbuffer);
		glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
		glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
		glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
		}   

	if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
		{
		NSLog(@&quot;failed to make complete framebuffer object %x&quot;, glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
		return NO;
		}

	return YES;
	}

- (void) destroyFramebuffer
	{
	glDeleteFramebuffersOES(1, &amp;viewFramebuffer);
	viewFramebuffer = 0;

	glDeleteRenderbuffersOES(1, &amp;viewRenderbuffer);
	viewRenderbuffer = 0;

	if(depthRenderbuffer)
		{
		glDeleteRenderbuffersOES(1, &amp;depthRenderbuffer);
		depthRenderbuffer = 0;
		}
	}

+ (UIImage *) snapshot:(GLView *)eaglview
	{
	NSInteger x = 0;
	NSInteger y = 0;
	NSInteger width = [eaglview backingWidth];
	NSInteger height = [eaglview backingHeight];
	NSInteger dataLength = width * height * 4;

	NSUInteger i;
	for ( i=0; i&lt;100; i++ )
		{
		glFlush();
		CFRunLoopRunInMode(kCFRunLoopDefaultMode, (float)1.0/(float)60.0, FALSE);
		}

	GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte));

	// Read pixel data from the framebuffer
	//
	glPixelStorei(GL_PACK_ALIGNMENT, 4);
	glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);

	// Create a CGImage with the pixel data
	// If your OpenGL ES content is opaque, use kCGImageAlphaNoneSkipLast to ignore the alpha channel
	// otherwise, use kCGImageAlphaPremultipliedLast
	//
	CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, data, dataLength, NULL);
	CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
	CGImageRef iref = CGImageCreate(width, height, 8, 32, width * 4, colorspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast, ref, NULL, true, kCGRenderingIntentDefault);

	// OpenGL ES measures data in PIXELS
	// Create a graphics context with the target size measured in POINTS
	//
	NSInteger widthInPoints;
	NSInteger heightInPoints;

	if (NULL != UIGraphicsBeginImageContextWithOptions)
		{
		// On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
		// Set the scale parameter to your OpenGL ES view's contentScaleFactor
		// so that you get a high-resolution snapshot when its value is greater than 1.0
		//
		CGFloat scale = eaglview.contentScaleFactor;
		widthInPoints = width / scale;
		heightInPoints = height / scale;
		UIGraphicsBeginImageContextWithOptions(CGSizeMake(widthInPoints, heightInPoints), NO, scale);
		}
	else
		{
		// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
		//
		widthInPoints = width;
		heightInPoints = height;
		UIGraphicsBeginImageContext(CGSizeMake(widthInPoints, heightInPoints));
		}

	CGContextRef cgcontext = UIGraphicsGetCurrentContext();

	// UIKit coordinate system is upside down to GL/Quartz coordinate system
	// Flip the CGImage by rendering it to the flipped bitmap context
	// The size of the destination area is measured in POINTS
	//
	CGContextSetBlendMode(cgcontext, kCGBlendModeCopy);
	CGContextDrawImage(cgcontext, CGRectMake(0.0, 0.0, widthInPoints, heightInPoints), iref);

	// Retrieve the UIImage from the current context
	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();	// autoreleased image

	UIGraphicsEndImageContext();

	// Clean up
	free(data);
	CFRelease(ref);
	CFRelease(colorspace);
	CGImageRelease(iref);

	return image;
	}

@end
</pre>
</div>
</div>
<div class="toggle">
<h4 class="toggle_title">GLMapper.h</h4>
<div class="toggle_content">
<pre class="brush: objc; title: ; toolbar: false; wrap-lines: false; notranslate">
//
//	GLMapper.h
//  AugCam
//
//  Created by John Carter on 1/26/2012.
//

#import &quot;GLView.h&quot;

@interface GLMapper : NSObject
	{
	// VERTICIES
	//
	GLfloat modelScale;
	int vertexCount;
	GLfloat *vertexData;
	GLfloat *textureData;
	}

@property (readonly) int vertexCount;
@property (readonly) GLfloat *vertexData;
@property (readonly) GLfloat *textureData;

- (void) buildVertexMap:(NSUInteger)buildOptions;
- (void) buildVertexMap:(NSUInteger)buildOptions scale:(GLfloat)scaleOption;
- (void) buildTextureMap:(NSUInteger)buildOptions forOrientation:(UIInterfaceOrientation)toInterfaceOrientation frontCamera:(BOOL)useFrontCamera;

@end
</pre>
</div>
</div>
<div class="toggle">
<h4 class="toggle_title">GLMapper.m</h4>
<div class="toggle_content">
<pre class="brush: objc; title: ; toolbar: false; wrap-lines: false; notranslate">
//
//	GLMapper.m
//  AugCam
//
//  Created by John Carter on 1/26/2012.
//

#import &quot;GLMapper.h&quot;

static CGFloat aspectAdjustment = 1.333;

// FOUR PANELS
//
static int planeDefVertexCount=24;
static const GLfloat planeDef[] =
		{
		-1.0f,	0.0f,	0.0f,
		-1.0f,	1.0f,	0.0f,
		0.0f,	0.0f,	0.0f,	

		0.0f,	0.0f,	0.0f,
		-1.0f,	1.0f,	0.0f,
		0.0f,	1.0f,	0.0f,	

		0.0f,	0.0f,	0.0f,
		0.0f,	1.0f,	0.0f,
		1.0f,	1.0f,	0.0f,	

		0.0f,	0.0f,	0.0f,
		1.0f,	1.0f,	0.0f,
		1.0f,	0.0f,	0.0f,	

		-1.0f,	-1.0f,	0.0f,
		-1.0f,	0.0f,	0.0f,
		0.0f,	0.0f,	0.0f,	

		-1.0f,	-1.0f,	0.0f,
		0.0f,	0.0f,	0.0f,
		0.0f,	-1.0f,	0.0f,	

		0.0f,	-1.0f,	0.0f,
		0.0f,	0.0f,	0.0f,
		1.0f,	-1.0f,	0.0f,	

		1.0f,	-1.0f,	0.0f,
		0.0f,	0.0f,	0.0f,
		1.0f,	0.0f,	0.0f,
		};

@implementation GLMapper

@synthesize vertexCount;
@synthesize vertexData;
@synthesize textureData;

- (void) dealloc
	{
	if ( vertexData != NULL )
		{
		free( vertexData );
		vertexData=NULL;
		}

	if ( textureData != NULL )
		{
		free( textureData );
		textureData=NULL;
		}

	[super dealloc];
	}

- (id) init
	{
	self = [super init];

	vertexCount=0;
	vertexData=NULL;
	textureData=NULL;

	return self;
	}

- (void) buildTextureMap:(NSUInteger)buildOptions forOrientation:(UIInterfaceOrientation)toInterfaceOrientation frontCamera:(BOOL)frontCamera
	{
	int i;
	int textureIndex = 0;
	int vertexIndex = 0;
	GLfloat xMinVertex = FLT_MAX;
	GLfloat yMinVertex = FLT_MAX;
	GLfloat xMaxVertex = -FLT_MAX;
	GLfloat yMaxVertex = -FLT_MAX;

	if ( textureData != NULL )
		{
		free( textureData );
		textureData=NULL;
		}

	textureData = (GLfloat *)malloc(sizeof(GLfloat) * vertexCount * 2);
	memset(textureData, (unsigned int)0, sizeof(GLfloat) * vertexCount * 2);

	for ( i=0; i&lt;vertexCount*3; i+=3 )
		{
		if ( vertexData[i+0] &lt; xMinVertex )
			xMinVertex = vertexData[i+0] ;
		if ( vertexData[i+1] &lt; yMinVertex )
			yMinVertex = vertexData[i+1] ;

		if ( vertexData[i+0] &gt; xMaxVertex )
			xMaxVertex = vertexData[i+0] ;
		if ( vertexData[i+1] &gt; yMaxVertex )
			yMaxVertex = vertexData[i+1] ;
		}

	GLfloat xVertexRange = fabs(xMaxVertex - xMinVertex);
	GLfloat yVertexRange = fabs(yMaxVertex - yMinVertex);

	double vertexPctX;
	double vertexPctY;
	double texturePointX;
	double texturePointY;
	double texturePointXsizeAdjusted;
	double texturePointYsizeAdjusted;

	GLfloat xMinTexture = FLT_MAX;
	GLfloat yMinTexture = FLT_MAX;
	GLfloat xMaxTexture = -FLT_MAX;
	GLfloat yMaxTexture = -FLT_MAX;

	//
	// TEXTURE COORDINATES
	//
	for ( i=0; i&lt;vertexCount; i++ )
		{
		vertexIndex = i*3;
		textureIndex = i*2;

		vertexPctX = (double)((vertexData[vertexIndex+0] - xMinVertex) / xVertexRange);
		vertexPctY = (double)((vertexData[vertexIndex+1] - yMinVertex) / yVertexRange);

		if ( frontCamera )
			{
			texturePointX = (double)1024.0 - (double)vertexPctY * (double)1024.0;
			texturePointY = (double)vertexPctX * (double)1024.0;
			}
		else
			{
			texturePointX = (double)1024.0 - (double)vertexPctY * (double)1024.0;
			texturePointY = (double)1024.0 - (double)vertexPctX * (double)1024.0;
			}

		texturePointXsizeAdjusted = texturePointX * (double)((double)640.0 / (double)1024.0);
		texturePointYsizeAdjusted = texturePointY * (double)((double)480.0 / (double)1024.0) + (double)544.0;

		textureData[textureIndex+0] = (GLfloat)texturePointXsizeAdjusted/1024.0;
		textureData[textureIndex+1] = (GLfloat)texturePointYsizeAdjusted/1024.0;

		if ( textureData[textureIndex+0] &lt; xMinTexture )
			xMinTexture = textureData[textureIndex+0] ;
		if ( textureData[textureIndex+1] &lt; yMinTexture )
			yMinTexture = textureData[textureIndex+1] ;

		if ( textureData[textureIndex+0] &gt; xMaxTexture )
			xMaxTexture = textureData[textureIndex+0] ;
		if ( textureData[textureIndex+1] &gt; yMaxTexture )
			yMaxTexture = textureData[textureIndex+1] ;
		}
	}

- (void) buildVertexMap:(NSUInteger)buildOptions
	{
	[self buildVertexMap:buildOptions scale:(GLfloat)1.0];
	}

- (void) buildVertexMap:(NSUInteger)buildOptions scale:(GLfloat)scaleOption
	{
	int i;
	int vertexIndex = 0;

	if ( vertexData != NULL )
		{
		free( vertexData );
		vertexData=NULL;
		}
	vertexCount=0;

	modelScale = (GLfloat)1.0;

	if ( scaleOption &gt; (GLfloat)0.0 )
		modelScale = scaleOption;

	GLfloat xScale = modelScale;
	GLfloat yScale = modelScale * aspectAdjustment;
	GLfloat zScale = modelScale;

	vertexCount = planeDefVertexCount;

	vertexData = (GLfloat *)malloc( sizeof(GLfloat) * vertexCount * 3 );
	memset( vertexData, (unsigned char)0, sizeof(GLfloat) * vertexCount * 3 );

	for ( i=0; i&lt;vertexCount*3; i+=3 )
		{
		vertexData[vertexIndex+0] = planeDef[i+0] * xScale;
		vertexData[vertexIndex+1] = planeDef[i+1] * yScale;
		vertexData[vertexIndex+2] = planeDef[i+2] * zScale;
		vertexIndex+=3;
		}
	}

@end
</pre>
</div>
</div>
<div class="toggle">
<h4 class="toggle_title">AppDelegate.h</h4>
<div class="toggle_content">
<pre class="brush: objc; title: ; toolbar: false; wrap-lines: false; notranslate">
//
//  SuperBoothAppDelegate.h
//  AugCam
//
//  Created by John Carter on 1/26/2012.
//

#import &lt;UIKit/UIKit.h&gt;
#import &quot;ViewController.h&quot;

@interface AppDelegate : NSObject &lt;UIApplicationDelegate&gt;
	{
	UIWindow *window;
	ViewController *viewController;
	}

@property (nonatomic, retain) IBOutlet UIWindow *window;

@end
</pre>
</div>
</div>
<div class="toggle">
<h4 class="toggle_title">AppDelegate.m</h4>
<div class="toggle_content">
<pre class="brush: objc; title: ; toolbar: false; wrap-lines: false; notranslate">
//
//  SuperBoothAppDelegate.m
//  AugCam
//
//  Created by John Carter on 1/26/2012.
//

#import &quot;AppDelegate.h&quot;

@implementation AppDelegate

@synthesize window;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
	{
	[application setIdleTimerDisabled:YES];

	[application setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];

	[window setBackgroundColor:[UIColor blackColor]];

	viewController = [[ViewController alloc] init];

    [window addSubview:viewController.view];
    [window makeKeyAndVisible];

    return YES;
	}

- (void)applicationWillResignActive:(UIApplication *)application
	{
    /*
     Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
     Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
     */
	}

- (void)applicationDidEnterBackground:(UIApplication *)application
	{
    /*
     Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
     If your application supports background execution, called instead of applicationWillTerminate: when the user quits.
     */
	}

- (void)applicationWillEnterForeground:(UIApplication *)application
	{
    /*
     Called as part of  transition from the background to the inactive state: here you can undo many of the changes made on entering the background.
     */
	}

- (void)applicationDidBecomeActive:(UIApplication *)application
	{
    /*
     Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
     */
	}

- (void)applicationWillTerminate:(UIApplication *)application
	{
    /*
     Called when the application is about to terminate.
     See also applicationDidEnterBackground:.
     */
	}

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
	{
    /*
     Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later.
     */
	}

- (void)dealloc
	{
    [viewController release];
    [window release];
    [super dealloc];
	}

@end
</pre>
</div>
</div>
<div class="toggle">
<h4 class="toggle_title">ViewController.h</h4>
<div class="toggle_content">
<pre class="brush: objc; title: ; toolbar: false; wrap-lines: false; notranslate">
//
//  ViewController.h
//  AugCam
//
//  Created by John Carter on 1/26/2012.
//

enum	{
		VIEWSOURCE_UIIMAGEVIEW = 1,
		VIEWSOURCE_OPENGLVIEW,
		};

enum	{
		CameraDeviceSetting640x480 = 0,
		CameraDeviceSettingHigh = 1,
		CameraDeviceSettingMedium = 2,
		CameraDeviceSettingLow = 3,
		};

#import &lt;UIKit/UIKit.h&gt;
#import &lt;MobileCoreServices/UTCoreTypes.h&gt;
#import &lt;MobileCoreServices/UTType.h&gt;
#import &lt;QuartzCore/QuartzCore.h&gt;
#import &lt;AVFoundation/AVFoundation.h&gt;
#import &lt;CoreGraphics/CoreGraphics.h&gt;
#import &lt;CoreVideo/CoreVideo.h&gt;
#import &lt;CoreMedia/CoreMedia.h&gt;
#import &quot;GLView.h&quot;
#import &quot;GLMapper.h&quot;

@interface ViewController : UIViewController &lt;AVCaptureVideoDataOutputSampleBufferDelegate&gt;
	{
	BOOL ignoreImageStream;

	// Device Information
	//
	int cameraCount;
	int currentCameraDeviceIndex;
	int frontCameraDeviceIndex;
	int backCameraDeviceIndex;
	int cameraImageOrientation;
	UIInterfaceOrientation currentDeviceOrientation;

	// test layers for augmented screen capture
	//
	UIImageView *backingLayer;
	UIImageView *overlayLayer;

	// The primary View for image capture
	// and it's cooresponding view for display
	//
	int currentViewSource;		// 1=cameraView,	2=glView
	UIView *displayView;

	// ViewSettings
	//
	NSUInteger textureMapBuilderCode;
	NSUInteger vertexMapBuilderCode;
	GLfloat vertexMapBuilderScale;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	// Camera Capture, OpenGL and Pixel Manipulation Stuff
	//
	////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	//
	AVCaptureDeviceInput *captureInput;
	AVCaptureVideoDataOutput *captureOutput;
	AVCaptureSession *captureSession;
	AVCaptureVideoPreviewLayer *cameraPreviewLayer;
	NSDictionary* videoSettings;
	NSNumber *pixelFormatCode;
	NSString *pixelFormatKey;
	int cameraDeviceSetting;

	UIImageView *cameraView;
	UIImage *cameraImage;
	UIImage *cameraImage0;
	UIImage *cameraImage1;

	// Open/GL
	//
	GLView *glView;
	EAGLContext *glViewContext;

	// VERTICIES
	//
	GLMapper *glMapper;
	int vertexCount;
	GLfloat *vertexData;
	GLfloat *textureData;

	// CAMERA IMAGE TEXTURE BUFFER
	//
	GLuint cameraTextureTag;
	void *cameraTextureImageBuffer;
	CGRect cameraTextureRect;
	CGContextRef cameraTextureContext;
	CGColorSpaceRef cameraTextureColorSpace;

	// VERTEX BUFFERING
	//
	GLuint vboVertexBuffer;
	GLuint vboTextureBuffer;
	}

@property (readonly) UIImage *cameraImage;
@property (readonly) GLView *glView;
@property (readonly) int cameraImageOrientation;

@end
</pre>
</div>
</div>
<div class="toggle">
<h4 class="toggle_title">ViewController.m</h4>
<div class="toggle_content">
<pre class="brush: objc; title: ; toolbar: false; wrap-lines: false; notranslate">
//
//  ViewController.m
//  AugCam
//
//  Created by John Carter on 1/26/2012.
//

#import &quot;ViewController.h&quot;
#import &quot;ScreenCapture.h&quot;

@interface ViewController()

- (void) performImageCaptureFrom:(CMSampleBufferRef)sampleBuffer;
- (void) activateCameraFeed;
- (void) initOpenGL;
- (void) refreshVBObjects;
- (void) scanForCameraDevices;
- (void) mapGLViewForOrientation:(UIInterfaceOrientation)toInterfaceOrientation;
- (void) swapCameras;
- (void) setViewSource:(int)newViewSource;
- (void) saveDisplayView;
- (void) saveGLView;
- (void) goLive;

@end

@implementation ViewController

@synthesize cameraImage;
@synthesize glView;
@synthesize cameraImageOrientation;

- (void)dealloc
	{
	if ( captureOutput != nil )
		{
		[captureOutput release];
		captureOutput = nil;
		}

	if ( captureInput != nil )
		{
		[captureInput release];
		captureInput = nil;
		}

	if ( glMapper != nil )
		{
		[glMapper release];
		glMapper = nil;
		}

	if ( glView != nil )
		{
		[glView removeFromSuperview];
		[glView release];
		glView = nil;
		}

	if ( cameraView != nil )
		{
		[cameraView removeFromSuperview];
		[cameraView release];
		cameraView = nil;
		}

	if (backingLayer != nil)
		{
		[backingLayer removeFromSuperview];
		[backingLayer release];
		backingLayer=nil;
		}

	if (overlayLayer != nil)
		{
		[overlayLayer removeFromSuperview];
		[overlayLayer release];
		overlayLayer=nil;
		}

	if (displayView != nil)
		{
		[displayView removeFromSuperview];
		[displayView release];
		displayView=nil;
		}

	[super dealloc];
	}

- (id) init
	{
	self = [super init];

	[[self view] setBackgroundColor:[UIColor blackColor]];

	return self;
	}

- (void) viewDidAppear:(BOOL)animated
	{
	[super viewDidAppear:animated];

	[self goLive];
	}

- (void) goLive
	{
	// Disable Processing any Camera Fees for now
	//
	ignoreImageStream = YES;

	// Device Info
	//
	currentDeviceOrientation = UIInterfaceOrientationPortrait;
	currentViewSource = 0;			// or VIEWSOURCE_UIIMAGEVIEW or VIEWSOURCE_OPENGLVIEW

	// Scan for Cameras
	//
	cameraCount = 0;
	frontCameraDeviceIndex = -1;
	backCameraDeviceIndex = -1;

	[self scanForCameraDevices];

	// Turn on the Camera
	//
	[self activateCameraFeed];

	// Init Open/GL
	//
	[self initOpenGL];

	vertexMapBuilderScale = (GLfloat)1.0;
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.0, 0.0, -1.0);

	// testing gl manipulation
	//
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.0, 0.0, -1.5);
	glRotatef( (GLfloat)M_PI, (GLfloat)1.0, (GLfloat)0.0, (GLfloat)0.0 );
	glRotatef( (GLfloat)M_PI, (GLfloat)0.0, (GLfloat)1.0, (GLfloat)0.0 );
	glRotatef( (GLfloat)M_PI, (GLfloat)0.0, (GLfloat)0.0, (GLfloat)1.0 );

	[self mapGLViewForOrientation:UIInterfaceOrientationPortrait];

	// Init the test layers
	//
	backingLayer = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@&quot;backinglayer.png&quot;]];
	overlayLayer = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@&quot;overlaylayer.png&quot;]];

	// Init the Plain Camera
	//
	cameraView = [[UIImageView alloc] initWithFrame:CGRectMake((CGFloat)0.0, (CGFloat)0.0, (CGFloat)480.0, (CGFloat)640.0)];	// size of the camera feed images

	// Init the displayView container and set the transform to scale the 480x640 so it will fit in 320x480 view (becomes 320x427)
	//
	displayView = [[UIImageView alloc] initWithFrame:CGRectMake((CGFloat)0.0, (CGFloat)0.0, (CGFloat)480.0, (CGFloat)640.0)];	// size of the camera feed images
	[displayView setTransform:CGAffineTransformIdentity];
	[displayView setTransform:CGAffineTransformScale([displayView transform], (CGFloat)0.667, (CGFloat)0.667)];
	[displayView setTransform:CGAffineTransformTranslate([displayView transform], (CGFloat)-120, (CGFloat)-173)];
	[self.view addSubview:displayView];

	// Set the default view source (also turns on the image stream)
	//
//	[self setViewSource:VIEWSOURCE_UIIMAGEVIEW];
	[self setViewSource:VIEWSOURCE_OPENGLVIEW];
	}

- (void) setViewSource:(int)newViewSource
	{
	if ( newViewSource==currentViewSource )
		{
		return;
		}

	ignoreImageStream=YES;

	// Pop all the views off the container view
	//
	if ( overlayLayer != nil )
		[overlayLayer removeFromSuperview];

	switch( currentViewSource )
		{
		case VIEWSOURCE_OPENGLVIEW:
			[glView removeFromSuperview];
			break;

		case VIEWSOURCE_UIIMAGEVIEW:
			[cameraView removeFromSuperview];
			break;
		}

	if ( backingLayer != nil )
		[backingLayer removeFromSuperview];

	currentViewSource = newViewSource;

	// Put all the views back in the container view
	//
	if ( backingLayer != nil )
		[displayView addSubview:backingLayer];

	switch( newViewSource )
		{
		case VIEWSOURCE_OPENGLVIEW:
			[displayView addSubview:glView];
			break;

		case VIEWSOURCE_UIIMAGEVIEW:
			[displayView addSubview:cameraView];
			break;
		}

	if ( overlayLayer != nil )
		[displayView addSubview:overlayLayer];

	ignoreImageStream=NO;
	}

//
// This will only automatically change the size of self.view
// it will not change the sizes and locations of subviews
//
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
	{
	return( interfaceOrientation==UIInterfaceOrientationPortrait );
	}

//
// This method releases the 'newimage' because it may change it
// so the references passed can no longer be released by the
// caller of this method
//
- (void) newCameraImageNotification:(CGImageRef)newImage
	{
	if ( newImage == nil )
		return;

	if ( currentViewSource == VIEWSOURCE_UIIMAGEVIEW )
		{
		cameraImage0 = [[UIImage alloc] initWithCGImage:newImage scale:(CGFloat)1.0 orientation:cameraImageOrientation];
		cameraImage = cameraImage0;

		[cameraView setImage:cameraImage];

		if ( cameraImage1 != nil )
			[cameraImage1 release];
		cameraImage1 = cameraImage0;
		}
	else
	if ( currentViewSource == VIEWSOURCE_OPENGLVIEW )
		{
		size_t textureBufferWidth = (size_t)rintf( cameraTextureRect.size.width );
		size_t textureBufferHeight = (size_t)rintf( cameraTextureRect.size.height );

//		memset( cameraTextureImageBuffer, (unsigned char)0, textureBufferWidth * textureBufferHeight * 4 );	// needs to be done to avoid shadowing under transparency

		// Draw the full image into our cameraTextureImageBuffer (which is sized to account for this) even though
		// for texture mapping to work, we will only bind to a 512x512 section of the image
		//
		CGRect extractRect = CGRectMake((CGFloat)0.0, (CGFloat)0.0, (CGFloat)CGImageGetWidth(newImage), (CGFloat)CGImageGetHeight(newImage));
		CGContextDrawImage(cameraTextureContext, extractRect, newImage);
		glBindTexture(GL_TEXTURE_2D, cameraTextureTag);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureBufferWidth, textureBufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, cameraTextureImageBuffer);

		[self refreshVBObjects];
		}

	CGImageRelease(newImage);
	}

- (void) savedSnapShot:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
	{
	if ( error != nil )
		{
		NSLog(@&quot;Error saving snapshot: %@&quot;,
<div class="error">
<div class="message_box_content"></div>
<div class="clearboth"></div>
</div>

 );
		}
	}

- (void) snapShot
	{
	if ( ignoreImageStream )
		return;

	ignoreImageStream = YES;

	if ( currentViewSource==VIEWSOURCE_OPENGLVIEW )
		[self saveGLView];
	else
	if ( currentViewSource==VIEWSOURCE_UIIMAGEVIEW )
		[self saveDisplayView];

	ignoreImageStream = NO;
	}

- (void) saveGLView
	{
	UIImage *photo = [ScreenCapture GLViewToImage:glView];				// returns an autoreleased image

	if ( photo == nil )
		return;

	[photo retain];

	// Replace CAEAGLLayer glView with a UIImageView version of itself
	//
	NSInteger viewIndex = [[displayView subviews] indexOfObject:glView];
	UIImageView *glImageView = [[UIImageView alloc] initWithImage:photo];
	[glView removeFromSuperview];
	[displayView insertSubview:glImageView atIndex:viewIndex];
	[photo release];

	// Take a normal snapshot now
	//
	[self saveDisplayView];

	// Put glView back and release the temporary UIImageView version of it
	//
	[glImageView removeFromSuperview];
	[glImageView release];
	[displayView insertSubview:glView atIndex:viewIndex];
	}

- (void) saveDisplayView
	{
	UIImage *photo = [ScreenCapture UIViewToImage:displayView];			// returns an autoreleased image

	if ( photo == nil )
		return;

	[photo retain];

	UIImageWriteToSavedPhotosAlbum(photo, self, @selector(savedSnapShot:didFinishSavingWithError:contextInfo:), nil);

	[photo release];
	}

- (void) refreshVBObjects
	{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glBindBuffer(GL_ARRAY_BUFFER, vboVertexBuffer);
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_FLOAT, 0, (void *)0);

	glBindBuffer(GL_ARRAY_BUFFER, vboTextureBuffer);
	glEnable(GL_TEXTURE_2D);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glBindTexture(GL_TEXTURE_2D, cameraTextureTag);
	glTexCoordPointer(2, GL_FLOAT, 0, (void *)0);

	glDrawArrays(GL_TRIANGLES, 0, vertexCount);

	[glViewContext presentRenderbuffer:GL_RENDERBUFFER_OES];
	}

- (void) mapGLViewForOrientation:(UIInterfaceOrientation)toInterfaceOrientation
	{
	if ( vboVertexBuffer != 0 )
		{
		glDeleteBuffers( 1, &amp;vboVertexBuffer );
		glDeleteBuffers( 1, &amp;vboTextureBuffer );
		}

	[glMapper buildVertexMap:vertexMapBuilderCode scale:vertexMapBuilderScale];

	[glMapper buildTextureMap:textureMapBuilderCode forOrientation:toInterfaceOrientation frontCamera:(currentCameraDeviceIndex==frontCameraDeviceIndex)];

	vertexCount = [glMapper vertexCount];
	vertexData = [glMapper vertexData];
	textureData = [glMapper textureData];

	glGenBuffers(1, &amp;vboVertexBuffer);
	glBindBuffer(GL_ARRAY_BUFFER, vboVertexBuffer);
	glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*vertexCount*3, vertexData, GL_STATIC_DRAW);

	glGenBuffers(1, &amp;vboTextureBuffer);
	glBindBuffer(GL_ARRAY_BUFFER, vboTextureBuffer);
	glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*vertexCount*2, textureData, GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	}

- (void) initOpenGL
	{
	glView = [[GLView alloc] init];
	glViewContext = [glView context];

	glMapper = [[GLMapper alloc] init];

	//
	// Establish Location of Camera
	//
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.0, 0.0, -1.0);

	cameraTextureRect = CGRectMake( (CGFloat)0.0, (CGFloat)0.0, (CGFloat)1024.0, (CGFloat)1024.0 );

	size_t imageWidth = (size_t)rintf( cameraTextureRect.size.width );
	size_t imageHeight = (size_t)rintf( cameraTextureRect.size.height );

	//
	// To increase performance, the full captured image is copied to this buffer so the
	// size of the buffer needs to match the size of the images (480x640) even though
	// for texture mapping we use a 512x512 section of the date which equates to
	// chopping the final texture mapped image to a 480x546 image.
	//
	// The final 480x546 image still has a ratio of 480x640 so after it is mapped
	// as a 512x512 texture the texture mapping needs to account for the
	// perspective correction
	//
	unsigned int dataSize = 960 * 1280 * 4;

	cameraTextureImageBuffer = malloc( dataSize );
	memset( cameraTextureImageBuffer, (unsigned char)0, dataSize );

	// Create Texture Colorspace
	//
	cameraTextureColorSpace = CGColorSpaceCreateDeviceRGB();

	// Create the texture Context
	cameraTextureContext = CGBitmapContextCreate(cameraTextureImageBuffer, imageWidth, imageHeight, 8, imageWidth*4, cameraTextureColorSpace, kCGImageAlphaPremultipliedLast);

	if ( cameraTextureContext == NULL )
		{
		NSLog(@&quot;error creating texture context&quot;);
		return;
		}

	glGenTextures(1, &amp;cameraTextureTag);
	glBindTexture(GL_TEXTURE_2D, cameraTextureTag);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glEnable(GL_TEXTURE_2D);
	}

- (void) scanForCameraDevices
	{
	cameraCount = 0;
	frontCameraDeviceIndex = -1;
	backCameraDeviceIndex = -1;

	AVCaptureDevice *backCameraDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
	NSArray *deviceList = [AVCaptureDevice devices];
	NSRange cameraSearch;
	NSUInteger i;

	for ( i=0; i&lt;[deviceList count]; i++ )
		{
		AVCaptureDevice *currentDevice = (AVCaptureDevice *)[deviceList objectAtIndex:i];

		//
		// This is the best info so skip string the string searches
		// that follow if we have a match on this
		//
		if ( currentDevice==backCameraDevice )
			{
			backCameraDeviceIndex = i;
			cameraCount++;
			continue;
			}

		cameraSearch = [[currentDevice description] rangeOfString:@&quot;front camera&quot; options:NSCaseInsensitiveSearch];
		if ( frontCameraDeviceIndex&lt;0 &amp;&amp; cameraSearch.location != NSNotFound )
			{
			frontCameraDeviceIndex = i;
			cameraCount++;
			continue;
			}

		cameraSearch = [[currentDevice description] rangeOfString:@&quot;back camera&quot; options:NSCaseInsensitiveSearch];
		if ( backCameraDevice&lt;0 &amp;&amp; cameraSearch.location != NSNotFound )
			{
			backCameraDeviceIndex = i;
			cameraCount++;
			continue;
			}

		cameraSearch = [[currentDevice description] rangeOfString:@&quot;camera&quot; options:NSCaseInsensitiveSearch];
		if ( backCameraDevice&lt;0 &amp;&amp; cameraSearch.location != NSNotFound )
			{
			backCameraDeviceIndex = i;
			cameraCount++;
			continue;
			}
		}
	}

- (void) activateCameraFeed
	{
	videoSettings = nil;

	pixelFormatCode = [[NSNumber alloc] initWithUnsignedInt:(unsigned int)kCVPixelFormatType_32BGRA];
	pixelFormatKey = [[NSString alloc] initWithString:(NSString *)kCVPixelBufferPixelFormatTypeKey];
	videoSettings = [[NSDictionary alloc] initWithObjectsAndKeys:pixelFormatCode, pixelFormatKey, nil]; 

	dispatch_queue_t queue = dispatch_queue_create(&quot;com.jellyfilledstudios.ImageCaptureQueue&quot;, NULL);

	captureOutput = [[AVCaptureVideoDataOutput alloc] init];
	[captureOutput setAlwaysDiscardsLateVideoFrames:YES];
	[captureOutput setSampleBufferDelegate:self queue:queue];
	[captureOutput setVideoSettings:videoSettings];

	dispatch_release(queue);

	AVCaptureDevice *selectedCamera;

	currentCameraDeviceIndex = -1;

	// default to front facing camera
	//
	if ( YES )
		{
		currentCameraDeviceIndex = frontCameraDeviceIndex;
		cameraImageOrientation = UIImageOrientationLeftMirrored;
		}
	else
		{
		currentCameraDeviceIndex = backCameraDeviceIndex;
		cameraImageOrientation = UIImageOrientationRight;
		}

	if ( currentCameraDeviceIndex &lt; 0 )
		selectedCamera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
	else
		selectedCamera = [[AVCaptureDevice devices] objectAtIndex:(NSUInteger)currentCameraDeviceIndex];

	captureInput = [AVCaptureDeviceInput deviceInputWithDevice:selectedCamera error:nil];

	if ( [selectedCamera lockForConfiguration:nil] )
		{
		if ( [selectedCamera isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure] )
			{
			[selectedCamera setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
			}

		if ( [selectedCamera isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance] )
			{
			[selectedCamera setWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance];
			}

		if ( [selectedCamera isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus] )
			{
			[selectedCamera setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
			}

		if ( [selectedCamera isTorchModeSupported:AVCaptureTorchModeAuto] )
			{
			[selectedCamera setTorchMode:AVCaptureTorchModeOff];	// AVCaptureTorchModeOn turns the &quot;torch&quot; light ON
			}

		if ( [selectedCamera isFlashModeSupported:AVCaptureFlashModeAuto] )
			{
			[selectedCamera setFlashMode:AVCaptureFlashModeAuto];	// AVCaptureFlashModeAuto
			}

		[selectedCamera unlockForConfiguration];
		}

	captureSession = [[AVCaptureSession alloc] init];
	[captureSession beginConfiguration];

	if ( [selectedCamera supportsAVCaptureSessionPreset:AVCaptureSessionPreset640x480])
		{
		cameraDeviceSetting = CameraDeviceSetting640x480;
		[captureSession setSessionPreset:AVCaptureSessionPreset640x480];	// AVCaptureSessionPresetHigh or AVCaptureSessionPreset640x480
		}
	else
	if ( [selectedCamera supportsAVCaptureSessionPreset:AVCaptureSessionPresetHigh] )
		{
		cameraDeviceSetting = CameraDeviceSettingHigh;
		[captureSession setSessionPreset:AVCaptureSessionPresetHigh];	// AVCaptureSessionPresetHigh or AVCaptureSessionPreset640x480
		}
	else
	if ( [selectedCamera supportsAVCaptureSessionPreset:AVCaptureSessionPresetMedium] )
		{
		cameraDeviceSetting = CameraDeviceSettingMedium;
		[captureSession setSessionPreset:AVCaptureSessionPresetMedium];	// AVCaptureSessionPresetHigh or AVCaptureSessionPreset640x480
		}
	else
	if ( [selectedCamera supportsAVCaptureSessionPreset:AVCaptureSessionPresetLow] )
		{
		cameraDeviceSetting = CameraDeviceSettingLow;
		[captureSession setSessionPreset:AVCaptureSessionPresetLow];	// AVCaptureSessionPresetHigh or AVCaptureSessionPreset640x480
		}	

	[captureSession addInput:captureInput];
	[captureSession addOutput:captureOutput];
	[captureSession commitConfiguration];

	[captureSession startRunning];
	}

- (void)cameraSwapAnimation:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
	{
	}

- (void) swapCameras
	{
	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDuration:0.75];
	[UIView setAnimationCurve:UIViewAnimationCurveLinear];
	[UIView setAnimationDelegate:self];
	[UIView setAnimationDidStopSelector:@selector(cameraSwapAnimation:finished:context:)];
	[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:[self view] cache:YES];
	[UIView commitAnimations];

	[captureSession stopRunning];
	[captureSession beginConfiguration];
	[captureSession removeInput:captureInput];

	if ( currentCameraDeviceIndex==frontCameraDeviceIndex )
		{
		currentCameraDeviceIndex = backCameraDeviceIndex;
		cameraImageOrientation = UIImageOrientationRight;
		}
	else
		{
		currentCameraDeviceIndex = frontCameraDeviceIndex;
		cameraImageOrientation = UIImageOrientationLeftMirrored;
		}

	//
	// Re-map the Open/GL to account for imageOrientation change
	//
	[self mapGLViewForOrientation:UIInterfaceOrientationPortrait];

	// Start the Camera
	//
	AVCaptureDevice *selectedCamera = [[AVCaptureDevice devices] objectAtIndex:(NSUInteger)currentCameraDeviceIndex];

	captureInput = [AVCaptureDeviceInput deviceInputWithDevice:selectedCamera error:nil];

	if ( [selectedCamera lockForConfiguration:nil] )
		{
		if ( [selectedCamera isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure] )
			{
			[selectedCamera setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
			}

		if ( [selectedCamera isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance] )
			{
			[selectedCamera setWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance];
			}

		if ( [selectedCamera isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus] )
			{
			[selectedCamera setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
			}

		if ( [selectedCamera isTorchModeSupported:AVCaptureTorchModeAuto] )
			{
			[selectedCamera setTorchMode:AVCaptureTorchModeOff];	// AVCaptureTorchModeOn turns the &quot;torch&quot; light ON
			}

		if ( [selectedCamera isFlashModeSupported:AVCaptureFlashModeAuto] )
			{
			[selectedCamera setFlashMode:AVCaptureFlashModeAuto];	// AVCaptureFlashModeAuto
			}

		[selectedCamera unlockForConfiguration];
		}

	if ( [selectedCamera supportsAVCaptureSessionPreset:AVCaptureSessionPreset640x480])
		{
		cameraDeviceSetting = CameraDeviceSetting640x480;
		[captureSession setSessionPreset:AVCaptureSessionPreset640x480];	// AVCaptureSessionPresetHigh or AVCaptureSessionPreset640x480
		}
	else
	if ( [selectedCamera supportsAVCaptureSessionPreset:AVCaptureSessionPresetHigh] )
		{
		cameraDeviceSetting = CameraDeviceSettingHigh;
		[captureSession setSessionPreset:AVCaptureSessionPresetHigh];	// AVCaptureSessionPresetHigh or AVCaptureSessionPreset640x480
		}
	else
	if ( [selectedCamera supportsAVCaptureSessionPreset:AVCaptureSessionPresetMedium] )
		{
		cameraDeviceSetting = CameraDeviceSettingMedium;
		[captureSession setSessionPreset:AVCaptureSessionPresetMedium];	// AVCaptureSessionPresetHigh or AVCaptureSessionPreset640x480
		}
	else
	if ( [selectedCamera supportsAVCaptureSessionPreset:AVCaptureSessionPresetLow] )
		{
		cameraDeviceSetting = CameraDeviceSettingLow;
		[captureSession setSessionPreset:AVCaptureSessionPresetLow];	// AVCaptureSessionPresetHigh or AVCaptureSessionPreset640x480
		}	

	[captureSession addInput:captureInput];
	[captureSession commitConfiguration];

	[captureSession startRunning];
	}

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
	{
	if ( ignoreImageStream )
		return;
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	[self performImageCaptureFrom:sampleBuffer];
	[pool drain];
	} 

- (void) performImageCaptureFrom:(CMSampleBufferRef)sampleBuffer
	{
	CVImageBufferRef imageBuffer;

	if ( CMSampleBufferGetNumSamples(sampleBuffer) != 1 )
	 	return;
	if ( !CMSampleBufferIsValid(sampleBuffer) )
	 	return;
	if ( !CMSampleBufferDataIsReady(sampleBuffer) )
	 	return;

	imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 

	if ( CVPixelBufferGetPixelFormatType(imageBuffer) != kCVPixelFormatType_32BGRA )
	 	return;

	CVPixelBufferLockBaseAddress(imageBuffer,0); 

	uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
	size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
	size_t width = CVPixelBufferGetWidth(imageBuffer);
	size_t height = CVPixelBufferGetHeight(imageBuffer); 

	CGImageRef newImage = nil;

	if ( cameraDeviceSetting == CameraDeviceSetting640x480 )
		{
		CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
		CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
		newImage = CGBitmapContextCreateImage(newContext);
		CGColorSpaceRelease( colorSpace );
		CGContextRelease(newContext);
		}
	else
		{
		uint8_t *tempAddress = malloc( 640 * 4 * 480 );
		memcpy( tempAddress, baseAddress, bytesPerRow * height );
		baseAddress = tempAddress;
		CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
		CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace,  kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);
		newImage = CGBitmapContextCreateImage(newContext);
		CGContextRelease(newContext);
		newContext = CGBitmapContextCreate(baseAddress, 640, 480, 8, 640*4, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
		CGContextScaleCTM( newContext, (CGFloat)640/(CGFloat)width, (CGFloat)480/(CGFloat)height );
		CGContextDrawImage(newContext, CGRectMake(0,0,640,480), newImage);
		CGImageRelease(newImage);
		newImage = CGBitmapContextCreateImage(newContext);
		CGColorSpaceRelease( colorSpace );
		CGContextRelease(newContext);
		free( tempAddress );
		}

	if ( newImage != nil )
		{
		[self performSelectorOnMainThread:@selector(newCameraImageNotification:) withObject:(id)newImage waitUntilDone:YES];
		}

	CVPixelBufferUnlockBaseAddress(imageBuffer,0);
	}

static BOOL processingTouchEvent = NO;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
	{
	if ( processingTouchEvent )
		return;
	processingTouchEvent = YES;

	[self snapShot];
	[self swapCameras];

	processingTouchEvent = NO;
	}

@end
</pre>
</div>
</div>
<div class="toggle">
<h4 class="toggle_title">ScreenCapture.h</h4>
<div class="toggle_content">
<pre class="brush: objc; title: ; toolbar: false; wrap-lines: false; notranslate">
//
//  ScreenCapture.h
//  AugCam
//
//  Created by John Carter on 1/26/2012.
//

#import &quot;GLView.h&quot;

@interface ScreenCapture : NSObject
	{
	}

+ (UIImage *) UIViewToImage:(UIView *)view;
+ (UIImage *) GLViewToImage:(GLView *)glView;

@end
</pre>
</div>
</div>
<div class="toggle">
<h4 class="toggle_title">ScreenCapture.m</h4>
<div class="toggle_content">
<pre class="brush: objc; title: ; toolbar: false; wrap-lines: false; notranslate">
//
//  ScreenCapture.m
//  AugCam
//
//  Created by John Carter on 1/26/2012.
//

#import &quot;ScreenCapture.h&quot;

#import &lt;QuartzCore/CABase.h&gt;
#import &lt;QuartzCore/CATransform3D.h&gt;
#import &lt;QuartzCore/CALayer.h&gt;
#import &lt;QuartzCore/CAScrollLayer.h&gt;

#import &lt;OpenGLES/EAGL.h&gt;
#import &lt;OpenGLES/ES1/gl.h&gt;
#import &lt;OpenGLES/ES1/glext.h&gt;
#import &lt;QuartzCore/QuartzCore.h&gt;
#import &lt;OpenGLES/EAGLDrawable.h&gt;

@implementation ScreenCapture

+ (UIImage *) GLViewToImage:(GLView *)glView
	{
	UIImage *glImage = [GLView snapshot:glView];							// returns an autoreleased image

	return glImage;
	}

+ (UIImage *) UIViewToImage:(UIView *)view
	{
	// Create a graphics context with the target size
	// On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
	// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext

	// camera image size extended to screen ratio so it captures the entire screen
	//
	CGSize imageSize = CGSizeMake( (CGFloat)480.0, (CGFloat)720.0 );

	if (NULL != UIGraphicsBeginImageContextWithOptions)
		UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
	else
		UIGraphicsBeginImageContext(imageSize);

	CGContextRef context = UIGraphicsGetCurrentContext();

	// Start with the view...
	//
	CGContextSaveGState(context);
	CGContextTranslateCTM(context, [view center].x, [view center].y);
	CGContextConcatCTM(context, [view transform]);
	CGContextTranslateCTM(context,-[view bounds].size.width * [[view layer] anchorPoint].x,-[view bounds].size.height * [[view layer] anchorPoint].y);
	[[view layer] renderInContext:context];
	CGContextRestoreGState(context);

	// ...then repeat for every subview from back to front
	//
	for (UIView *subView in [view subviews])
		{
		if ( [subView respondsToSelector:@selector(screen)] )
			if ( [(UIWindow *)subView screen] == [UIScreen mainScreen] )
				continue;

		CGContextSaveGState(context);
		CGContextTranslateCTM(context, [subView center].x, [subView center].y);
		CGContextConcatCTM(context, [subView transform]);
		CGContextTranslateCTM(context,-[subView bounds].size.width * [[subView layer] anchorPoint].x,-[subView bounds].size.height * [[subView layer] anchorPoint].y);
		[[subView layer] renderInContext:context];
		CGContextRestoreGState(context);
		}

	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();	// autoreleased image

	UIGraphicsEndImageContext();

	return image;
	}

@end
</pre>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.jellyfilledstudios.com/2011/11/23/live-effects-cam/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Light Mirror</title>
		<link>http://www.jellyfilledstudios.com/2011/11/23/light-mirror/</link>
		<comments>http://www.jellyfilledstudios.com/2011/11/23/light-mirror/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 03:24:43 +0000</pubDate>
		<dc:creator>jellyrob</dc:creator>
				<category><![CDATA[Utilities]]></category>

		<guid isPermaLink="false">http://www.jellyfilledstudios.com/?p=34</guid>
		<description><![CDATA[A simple little app that adds a light frame on screen so you can use the front facing camera as a lighted mirror in a dark or dimly lighted room]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://itunes.apple.com/us/app/light-mirror/id396466213?mt=8"><img src="http://www.jellyfilledstudios.com/wp-content/uploads/2012/01/App_Store_Badge_EN_0609-300x150.png" alt="" title="App_Store_Badge_EN_0609" width="300" height="150" class="alignnone size-medium wp-image-356" /></a></p>
<p>A simple little app that adds a light frame on screen so you can use the front facing camera as a lighted mirror in a dark or dimly lighted room</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jellyfilledstudios.com/2011/11/23/light-mirror/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iSpeak and Spell</title>
		<link>http://www.jellyfilledstudios.com/2011/11/23/ispeak-and-spell/</link>
		<comments>http://www.jellyfilledstudios.com/2011/11/23/ispeak-and-spell/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 03:24:11 +0000</pubDate>
		<dc:creator>jellyrob</dc:creator>
				<category><![CDATA[Entertainment]]></category>

		<guid isPermaLink="false">http://www.jellyfilledstudios.com/?p=31</guid>
		<description><![CDATA[New in Version 3.0: ★ Added a “Phonetic Spelling” option to each word in the word list. This allows you to enter an optional spelling of the word in a way that the computer voice can pronounce it more clearly.  ★ Added a “Usage Phrase” option to each word in the word list. When a ...]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://itunes.apple.com/us/app/ispeak-and-spell/id334249715?mt=8"><img src="http://www.jellyfilledstudios.com/wp-content/uploads/2012/01/App_Store_Badge_EN_0609-300x150.png" alt="" title="App_Store_Badge_EN_0609" width="300" height="150" class="alignnone size-medium wp-image-356" /></a></p>
<p>New in Version 3.0:</p>
<p>★ Added a “Phonetic Spelling” option to each word in the word list. This allows you to enter an optional spelling of the word in a way that the computer voice can pronounce it more clearly. <br />
★ Added a “Usage Phrase” option to each word in the word list. When a Usage Phrase is present, iSpeak and Spell will announce the spelling word and then follow it with “AS IN&#8230;” and then it will speak the Usage Phrase. This feature is especially funny to use when you use Urban Dictionary to create your spelling words and examples. <br />
★ Added high resolution support for iPhone 4 devices <br />
★ Improved the appearance of the information and configuration dialogs.<br />
 ★ Added new controls for adjusting the talking speed of the computer voice. </p>
<p>iSpeak and Spell</p>
<p>A multilingual text-to-speech application styled to emulate the original Speak &#038; Spell.</p>
<p>Enjoy hours of fun listening to iSpeak and Spell use voices and dialects from around the world to read aloud anything you type.</p>
<p>iSpeak and Spell lets you enter your own list of words (simulating the “expansion modules” of the original) or you can use it with the over 200 words built right inside.</p>
<p>Custom list of words also includes: <br />
★ Phonetic Spelling option for each word in the word list. This allows you to enter an optional spelling of the word in a way that the computer voice can pronounce it more clearly. <br />
★ Usage Phrase option for each word in the word list. When a Usage Phrase is present, iSpeak and Spell will announce the spelling word and then follow it with “AS IN&#8230;” and then it will speak the Usage Phrase. This feature is especially funny to use when you use Urban Dictionary to create your spelling words and examples.</p>
<p>iSpeak and Spell will announce the words you&#8217;ve chosen and will incorporate those words into the same fun and challenging activities the original icon of the early 80&#8242;s offered.</p>
<p>iSpeak and Spell presents all of the word challenge games in rounds of 10 words each. Before and after each round, you are in “Free Play Mode” where you can type anything you want and listen to iSpeak and Spell say it.</p>
<p>After each round of word challenges, iSpeak and Spell reports your results and then uses that information as it creates new word lists for each new round.</p>
<p>iSpeak and Spell will detect which words seem to be giving you the most trouble and will repeat those intermittently through each round.</p>
<p>A useful learning tool that’s fun and entertaining.</p>
<p>iSpeak and Spell will speak in any of the following dialects:</p>
<p>English (US)<br />
English (UK)<br />
English (Lancashire)<br />
English (Scottish)<br />
English (West Indies)<br />
English (West Midlands)<br />
Spanish<br />
Spanish (Latin American)<br />
Czech<br />
Danish<br />
German<br />
Finnish<br />
French<br />
French (Belgium)<br />
Hungarian<br />
Icelandic<br />
Italian<br />
Latin<br />
Norwegian<br />
Polish<br />
Portuguese (Brazil)<br />
Portuguese (Portugal)<br />
Romanian<br />
Slovak<br />
Swedish<br />
Turkish</p>
<p>** Note that because iSpeak and Spell is retro-styled for the nostalgic at heart, it does not support international keyboard characters. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.jellyfilledstudios.com/2011/11/23/ispeak-and-spell/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Bug Vision</title>
		<link>http://www.jellyfilledstudios.com/2011/11/23/bug-vision/</link>
		<comments>http://www.jellyfilledstudios.com/2011/11/23/bug-vision/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 03:23:31 +0000</pubDate>
		<dc:creator>jellyrob</dc:creator>
				<category><![CDATA[Entertainment]]></category>

		<guid isPermaLink="false">http://www.jellyfilledstudios.com/?p=28</guid>
		<description><![CDATA[Bug Vision is an advanced real-time camera application that lets you view fun, crazy and sometimes artistic effects live through your iPhone or camera equipped iTouch. &#8220;What you see is what you get&#8221; when you use the cool effects and overlays in Bug Vision to take fun snapshots with your built-in camera. Contort your smile ...]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://itunes.apple.com/us/app/bug-vision/id403622440?mt=8"><img src="http://www.jellyfilledstudios.com/wp-content/uploads/2012/01/App_Store_Badge_EN_0609-300x150.png" alt="" title="App_Store_Badge_EN_0609" width="300" height="150" class="alignnone size-medium wp-image-356" /></a></p>
<p>Bug Vision is an advanced real-time camera application that lets you view fun, crazy and sometimes artistic effects live through your iPhone or camera equipped iTouch.</p>
<p>&#8220;What you see is what you get&#8221; when you use the cool effects and overlays in Bug Vision to take fun snapshots with your built-in camera. Contort your smile with the Shape effects. Add an artistic look with the Pixel Effects. View yourself hanging in an art museum with the Overlay Effects.</p>
<p>When you like what you see, take a snapshot. All snapshots are instantly saved in your iOS Photo Library. </p>
<p>We&#8217;ve developed an advanced implementation of technologies that combine your iOS device camera, pixel mapping and Open/GL to give Bug Vision the unique ability to produce stunning image effects in REAL-TIME.</p>
<p>Experiment with all the effects and combinations to transform your look instantly. Then, take a snapshot and send them to your friends, use them as your profile pics or add them to your Address Book. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.jellyfilledstudios.com/2011/11/23/bug-vision/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazing Dice</title>
		<link>http://www.jellyfilledstudios.com/2011/11/23/amazing-dice/</link>
		<comments>http://www.jellyfilledstudios.com/2011/11/23/amazing-dice/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 03:22:54 +0000</pubDate>
		<dc:creator>jellyrob</dc:creator>
				<category><![CDATA[Entertainment]]></category>

		<guid isPermaLink="false">http://www.jellyfilledstudios.com/?p=25</guid>
		<description><![CDATA[The touch interaction and reality of this 4D world is all so amazingly real, you will instantly see where Amazing Dice got it&#8217;s name. Enjoy any of the hundreds of dice games at your finger tips with these Amazing Dice. Any game that can be played with 1 to 6 dice, can be enjoyed even ...]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://itunes.apple.com/us/app/amazing-dice/id384343313?mt=8"><img src="http://www.jellyfilledstudios.com/wp-content/uploads/2012/01/App_Store_Badge_EN_0609-300x150.png" alt="" title="App_Store_Badge_EN_0609" width="300" height="150" class="alignnone size-medium wp-image-356" /></a></p>
<p>The touch interaction and reality of this 4D world is all so amazingly real, you will instantly see where Amazing Dice got it&#8217;s name.</p>
<p>Enjoy any of the hundreds of dice games at your finger tips with these Amazing Dice. Any game that can be played with 1 to 6 dice, can be enjoyed even more with Amazing Dice.</p>
<p>With the touch of your fingers you can roll the dice from the cup and push the dice around on the table.</p>
<p>Use two fingers to rotate and pan the play room or three fingers to tilt the room in any direction. The touch interaction inside the simulated game room is so accurate it makes the entire game seem so real.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jellyfilledstudios.com/2011/11/23/amazing-dice/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OmniCalc</title>
		<link>http://www.jellyfilledstudios.com/2011/11/23/omnicalc/</link>
		<comments>http://www.jellyfilledstudios.com/2011/11/23/omnicalc/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 03:08:08 +0000</pubDate>
		<dc:creator>jellyrob</dc:creator>
				<category><![CDATA[Utilities]]></category>

		<guid isPermaLink="false">http://www.jellyfilledstudios.com/?p=20</guid>
		<description><![CDATA[OmniCalc The friendliest calculator on the planet. You can change anything you enter and get instant results just like a spreadsheet. Getting one number wrong in a series of operations doesn&#8217;t mean starting over anymore. Customize the look with 12 different keyboard layouts, 19 color schemes, 3 button styles and 16 numeric fonts. Scroll through ...]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://itunes.apple.com/us/app/omnicalc/id363882488?mt=8"><img src="http://www.jellyfilledstudios.com/wp-content/uploads/2012/01/App_Store_Badge_EN_0609-300x150.png" alt="" title="App_Store_Badge_EN_0609" width="300" height="150" class="alignnone size-medium wp-image-356" /></a></p>
<h2>OmniCalc</h2>
<p>The friendliest calculator on the planet. You can change anything you enter and get instant results just like a spreadsheet. Getting one number wrong in a series of operations doesn&#8217;t mean starting over anymore.</p>
<p>Customize the look with 12 different keyboard layouts, 19 color schemes, 3 button styles and 16 numeric fonts.</p>
<p>Scroll through operations to add, edit or delete entries in your calculation with realtime results like a spreadsheet.</p>
<h3>Key Features:</h3>
<ul class="list4 list_color_red">
<li>Multiple calculators in one:</li>
</ul>
<div style="margin-top:-16px; margin-bottom:-16px;">
<ul>
<ul class="list1 list_color_red">
<li>Standard Calculator Functions</li>
<li>Scientific Calculator Functions</li>
<li>Statistical Calculator Functions</li>
<li>Date Math Calculator Functions</li>
</ul>
</ul>
</div>
<ul class="list4 list_color_red">
<li>Rotate the iPhone/iTouch/iPad to instantly swap between 4 instant calculators.</li>
<li>6 different calculator styles to choose from:</li>
</ul>
<div style="margin-top:-16px; margin-bottom:-16px;">
<ul>
<ul class="list1 list_color_red">
<li>Super Easy</li>
<li>Easy</li>
<li>Scientific (Right)</li>
<li>Scientific (Left)</li>
<li>Easy (Long View)</li>
<li>Easy (Big Button)</li>
</ul>
</ul>
</div>
<ul class="list4 list_color_red">
<li>Detailed documentation built in <a href="http://www.jellyfilledstudios.com/apps/omnicalc-help" target="_blank">(view here)</a></li>
<li>Annotate a series of operations to turn your formula into a powerful spreadsheet style form.</li>
<li>Save formulas or operation history in your own math library.</li>
<li>Date Math is automatically detected in normal operations. Add or subtract dates from each other, add or subtract a number from any date.</li>
<li>3 Button styles</li>
<li>16 different display fonts</li>
<li>25 different color schemes</li>
</ul>
<h3>Examples: <span style="font-size:70%;">(click images to enlarge)</span></h3>
<p><a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/img_0008/' title='IMG_0008'><img width="640" height="960" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IMG_0008.png" class="attachment-full" alt="IMG_0008" title="IMG_0008" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/img_0010/' title='IMG_0010'><img width="640" height="960" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IMG_0010.png" class="attachment-full" alt="IMG_0010" title="IMG_0010" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/img_0019/' title='IMG_0019'><img width="640" height="960" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IMG_0019.png" class="attachment-full" alt="IMG_0019" title="IMG_0019" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/img_0036/' title='IMG_0036'><img width="768" height="1024" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IMG_0036.png" class="attachment-full" alt="IMG_0036" title="IMG_0036" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/img_0055/' title='IMG_0055'><img width="768" height="1024" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IMG_0055.png" class="attachment-full" alt="IMG_0055" title="IMG_0055" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/img_0392/' title='IMG_0392'><img width="320" height="480" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IMG_0392.png" class="attachment-full" alt="IMG_0392" title="IMG_0392" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/img_0396/' title='IMG_0396'><img width="480" height="320" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IMG_0396.png" class="attachment-full" alt="IMG_0396" title="IMG_0396" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/img_0399/' title='IMG_0399'><img width="320" height="480" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IMG_0399.png" class="attachment-full" alt="IMG_0399" title="IMG_0399" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/img_0383/' title='IMG_0383'><img width="320" height="480" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IMG_0383.png" class="attachment-full" alt="IMG_0383" title="IMG_0383" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/img_0384/' title='IMG_0384'><img width="320" height="480" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IMG_0384.png" class="attachment-full" alt="IMG_0384" title="IMG_0384" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/img_0382/' title='IMG_0382'><img width="320" height="480" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IMG_0382.png" class="attachment-full" alt="IMG_0382" title="IMG_0382" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/ipad-omnicalc-image-1/' title='IPAD OmniCalc Image 1'><img width="768" height="1024" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IPAD-OmniCalc-Image-1.png" class="attachment-full" alt="IPAD OmniCalc Image 1" title="IPAD OmniCalc Image 1" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/ipad-omnicalc-image-2/' title='IPAD OmniCalc Image 2'><img width="768" height="1024" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IPAD-OmniCalc-Image-2.png" class="attachment-full" alt="IPAD OmniCalc Image 2" title="IPAD OmniCalc Image 2" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/ipad-omnicalc-image-3/' title='IPAD OmniCalc Image 3'><img width="768" height="1024" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IPAD-OmniCalc-Image-3.png" class="attachment-full" alt="IPAD OmniCalc Image 3" title="IPAD OmniCalc Image 3" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/ipad-omnicalc-image-4/' title='IPAD OmniCalc Image 4'><img width="768" height="1024" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IPAD-OmniCalc-Image-4.png" class="attachment-full" alt="IPAD OmniCalc Image 4" title="IPAD OmniCalc Image 4" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/ipad-omnicalc-image-5/' title='IPAD OmniCalc Image 5'><img width="768" height="1024" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/IPAD-OmniCalc-Image-5.png" class="attachment-full" alt="IPAD OmniCalc Image 5" title="IPAD OmniCalc Image 5" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/omnicalc-image-1/' title='OmniCalc Image 1'><img width="320" height="480" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/OmniCalc-Image-1.png" class="attachment-full" alt="OmniCalc Image 1" title="OmniCalc Image 1" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/omnicalc-image-2/' title='OmniCalc Image 2'><img width="320" height="480" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/OmniCalc-Image-2.png" class="attachment-full" alt="OmniCalc Image 2" title="OmniCalc Image 2" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/omnicalc-image-3/' title='OmniCalc Image 3'><img width="320" height="480" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/OmniCalc-Image-3.png" class="attachment-full" alt="OmniCalc Image 3" title="OmniCalc Image 3" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/omnicalc-image-4/' title='OmniCalc Image 4'><img width="320" height="480" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/OmniCalc-Image-4.png" class="attachment-full" alt="OmniCalc Image 4" title="OmniCalc Image 4" /></a><br />
<a href='http://www.jellyfilledstudios.com/2011/11/23/omnicalc/omnicalc-image-5/' title='OmniCalc Image 5'><img width="320" height="480" src="http://www.jellyfilledstudios.com/wp-content/uploads/2011/11/OmniCalc-Image-5.png" class="attachment-full" alt="OmniCalc Image 5" title="OmniCalc Image 5" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.jellyfilledstudios.com/2011/11/23/omnicalc/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

