main.py
from PyObjCTools import AppHelper
import CIBevelView
import SampleCIView
import objc; objc.setVerbose(True)
AppHelper.runEventLoop()
Translation into python of and ADC example of the same name.
from Cocoa import *
from Quartz import *
from SampleCIView import SampleCIView
from math import sin
import objc
NUM_POINTS=4
class CIBevelView (SampleCIView):
currentPoint = objc.ivar(type=objc._C_INT)
points = objc.ivar()
angleTime = objc.ivar(type=objc._C_FLT)
lineImage = objc.ivar()
twirlFilter = objc.ivar()
heightFieldFilter = objc.ivar()
shadedFilter = objc.ivar()
def initWithFrame_(self, frameRect):
self = super(CIBevelView, self).initWithFrame_(frameRect)
if self is None:
return None
self.points = [ None ] * NUM_POINTS
self.points[0] = CGPointMake(0.5 * frameRect.size.width, frameRect.size.height - 100.0)
self.points[1] = CGPointMake(150.0, 100.0)
self.points[2] = CGPointMake(frameRect.size.width - 150.0, 100.0)
self.points[3] = CGPointMake(0.7*self.points[0].x + 0.3*self.points[2].x, 0.7*self.points[0].y + 0.3*self.points[2].y)
url = NSURL.fileURLWithPath_(
NSBundle.mainBundle().pathForResource_ofType_("lightball", "tiff"))
self.lightball = CIImage.imageWithContentsOfURL_(url)
self.heightFieldFilter = CIFilter.filterWithName_("CIHeightFieldFromMask")
self.heightFieldFilter.setDefaults()
self.heightFieldFilter.setValue_forKey_(15.0, "inputRadius")
self.twirlFilter = CIFilter.filterWithName_("CITwirlDistortion")
self.twirlFilter.setDefaults()
self.twirlFilter.setValue_forKey_(
CIVector.vectorWithX_Y_(
0.5*frameRect.size.width,
0.5*frameRect.size.height),
"inputCenter")
self.twirlFilter.setValue_forKey_(300.0, "inputRadius")
self.twirlFilter.setValue_forKey_(0.0, "inputAngle")
self.shadedFilter = CIFilter.filterWithName_("CIShadedMaterial")
self.shadedFilter.setDefaults()
self.shadedFilter.setValue_forKey_(self.lightball, "inputShadingImage")
self.shadedFilter.setValue_forKey_(20.0, "inputScale")
# 1/30 second should give us decent animation
NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(
1.0/30.0, self, 'changeTwirlAngle:', None, True)
return self
def changeTwirlAngle_(self, timer):
self.angleTime += timer.timeInterval()
self.twirlFilter.setValue_forKey_(
-0.2 * sin(self.angleTime*5.0), 'inputAngle')
self.updateImage()
def mouseDragged_(self, event):
loc = self.convertPoint_fromView_(event.locationInWindow(), None)
self.points[self.currentPoint].x = loc.x
self.points[self.currentPoint].y = loc.y
self.lineImage = None
# normally we'd want this, but the timer will cause us to
# redisplay anyway
#self.setNeedsDisplay_(True)
def mouseDown_(self, event):
d = 1e4
loc = self.convertPoint_fromView_(event.locationInWindow(), None)
for i in range(NUM_POINTS):
x = self.points[i].x - loc.x
y = self.points[i].y - loc.y
t = x*x + y*y
if t < d:
self.currentPoint = i
d = t
self.mouseDragged_(event)
def updateImage(self):
context = NSGraphicsContext.currentContext().CIContext()
if self.lineImage is None:
bounds = self.bounds()
layer = context.createCGLayerWithSize_info_(
CGSizeMake(NSWidth(bounds), NSHeight(bounds)), None)
cg = CGLayerGetContext(layer)
CGContextSetRGBStrokeColor(cg, 1,1,1,1)
CGContextSetLineCap(cg, kCGLineCapRound)
CGContextSetLineWidth(cg, 60.0)
CGContextMoveToPoint(cg, self.points[0].x, self.points[0].y)
for i in range(1, NUM_POINTS):
CGContextAddLineToPoint(cg, self.points[i].x, self.points[i].y)
CGContextStrokePath(cg)
self.lineImage = CIImage.alloc().initWithCGLayer_(layer)
self.heightFieldFilter.setValue_forKey_(self.lineImage, "inputImage")
self.twirlFilter.setValue_forKey_(
self.heightFieldFilter.valueForKey_("outputImage"),
"inputImage")
self.shadedFilter.setValue_forKey_(
self.twirlFilter.valueForKey_("outputImage"),
"inputImage")
self.setImage_(self.shadedFilter.valueForKey_("outputImage"))
"""
SampleCIView - simple OpenGL based CoreImage view
"""
from Cocoa import *
from Quartz import *
import CGL
from OpenGL.GL import *
# XXX: this may or may not be a bug in the OpenGL bindings
from OpenGL.GL.APPLE.transform_hint import *
import objc
# The default pixel format
_pf = None
class SampleCIView (NSOpenGLView):
_context = objc.ivar()
_image = objc.ivar()
_lastBounds = objc.ivar(type=NSRect.__typestr__)
@classmethod
def defaultPixelFormat(self):
global _pf
if _pf is None:
# Making sure the context's pixel format doesn't have a recovery
# renderer is important - otherwise CoreImage may not be able to
# create deeper context's that share textures with this one.
attr = ( NSOpenGLPFAAccelerated,
NSOpenGLPFANoRecovery, NSOpenGLPFAColorSize, 32 )
_pf = NSOpenGLPixelFormat.alloc().initWithAttributes_(attr)
return _pf
def image(self):
return self._image
def setImage_dirtyRect_(self, image, r):
if self._image is not image:
self._image = image
if CGRectIsInfinite(r):
self.setNeedsDisplay_(True)
else:
self.setNeedsDisplayInRect_(r)
def setImage_(self, image):
self.setImage_dirtyRect_(image, CGRectInfinite)
def prepareOpenGL(self):
parm = 1
# Enable beam-synced updates.
self.openGLContext().setValues_forParameter_(
(parm,), NSOpenGLCPSwapInterval)
# Make sure that everything we don't need is disabled. Some of these
# are enabled by default and can slow down rendering.
glDisable(GL_ALPHA_TEST)
glDisable(GL_DEPTH_TEST)
glDisable(GL_SCISSOR_TEST)
glDisable(GL_BLEND)
glDisable(GL_DITHER)
glDisable(GL_CULL_FACE)
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)
glDepthMask(GL_FALSE)
glStencilMask(0)
glClearColor(0.0, 0.0, 0.0, 0.0)
glHint (GL_TRANSFORM_HINT_APPLE, GL_FASTEST)
def viewBoundsDidChange_(self, bounds):
# For subclasses.
pass
def updateMatrices(self):
r = self.bounds()
if r != self._lastBounds:
self.openGLContext().update()
# Install an orthographic projection matrix (no perspective)
# with the origin in the bottom left and one unit equal to one
# device pixel.
glViewport(0, 0, r.size.width, r.size.height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, r.size.width, 0, r.size.height, -1, 1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
self._lastBounds = r
self.viewBoundsDidChange_(r)
def drawRect_(self, r):
self.openGLContext().makeCurrentContext()
# Allocate a CoreImage rendering context using the view's OpenGL
# context as its destination if none already exists.
if self._context is None:
pf = self.pixelFormat()
if pf is None:
pf = type(self).defaultPixelFormat()
self._context=CIContext.contextWithCGLContext_pixelFormat_options_(
CGL.CGLGetCurrentContext(), pf.CGLPixelFormatObj(), None)
ir = CGRectIntegral(r)
if NSGraphicsContext.currentContextDrawingToScreen():
self.updateMatrices()
# Clear the specified subrect of the OpenGL surface then
# render the image into the view. Use the GL scissor test to
# clip to * the subrect. Ask CoreImage to generate an extra
# pixel in case * it has to interpolate (allow for hardware
# inaccuracies)
rr = CGRectIntersection (CGRectInset(ir, -1.0, -1.0),
self._lastBounds)
glScissor(ir.origin.x, ir.origin.y, ir.size.width, ir.size.height)
glEnable(GL_SCISSOR_TEST)
glClear(GL_COLOR_BUFFER_BIT)
if self.respondsToSelector_('drawRect:inCIContext:'):
self.drawRect_inCIContext_(rr, self._context)
elif self._image is not None:
self._context.drawImage_atPoint_fromRect_(
self._image, rr.origin, rr)
glDisable(GL_SCISSOR_TEST)
# Flush the OpenGL command stream. If the view is double
# buffered this should be replaced by [[self openGLContext]
# flushBuffer].
glFlush ()
else:
# Printing the view contents. Render using CG, not OpenGL.
if self.respondsToSelector_('drawRect:inCIContext:'):
self.drawRect_inCIContext_(ir, self._context)
elif self._image is not None:
cgImage = self._context.createCGImage_fromRect_(
self._image, ir)
if cgImage is not None:
CGContextDrawImage(
NSGraphicsContext.currentContext().graphicsPort(),
ir, cgImage)
from PyObjCTools import AppHelper
import CIBevelView
import SampleCIView
import objc; objc.setVerbose(True)
AppHelper.runEventLoop()
"""
Script for building the example.
Usage:
python setup.py py2app
"""
from distutils.core import setup
import py2app
setup(
name='CIBevelSample',
app=["main.py"],
data_files=["English.lproj", 'lightball.tiff']
)