Skip to content

Instantly share code, notes, and snippets.

@andreberg
Last active February 24, 2020 17:45
Show Gist options
  • Save andreberg/5962004 to your computer and use it in GitHub Desktop.
Save andreberg/5962004 to your computer and use it in GitHub Desktop.
[PyObjC CoreGraphics API Example] Shows how to use the functional API of the CoreGraphics framework through PyObjC and Python 2.7. #pyobjc #python #coregraphics #quartz #macos #examples
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#
# pyobjc_coregraphics_example1.py
# PyObjC Scripts
#
# Created by André Berg on 2013-07-09.
# Copyright 2013 Berg Media. All rights reserved.
#
# Example script that shows how to use
# the functional API of the CoreGraphics
# framework through PyObjC and Python 2.7
#
import math
import os
import operator
from subprocess import Popen, PIPE
import Quartz
from Quartz.CoreGraphics import *
from Cocoa import *
WIDTH = 256
HEIGHT = 256
BITDEPTH = 8
# Doesn't seem like these are translated and defined by the PyObjC bridge
# somewhere, so define them here. For reference, see:
# http://developer.apple.com/library/ios/#documentation/graphicsimaging/conceptual/ImageIOGuide/imageio_basics/ikpg_basics.html
kUTTypeImage = "public.image"
kUTTypePNG = "public.png"
kUTTypeJPEG = "public.jpeg"
kUTTypeJPEG2000 = "public.jpeg-2000"
kUTTypeTIFF = "public.tiff"
kUTTypePICT = "com.apple.pict"
kUTTypeGIF = "com.compuserve.gif"
def MakeImage(width, height, bitdepth):
c = CGBitmapContextCreate(None, width, height, BITDEPTH, width * 4, CGColorSpaceCreateDeviceRGB(), 1)
CGContextSetRGBStrokeColor(c, 1, 0, 0, 1)
CGContextSetRGBFillColor(c, 1, 1, 0, 0.5)
CGContextSetLineJoin(c, kCGLineJoinBevel)
CGContextSetLineWidth(c, 8)
x0 = (32.5, 32.5)
size = (191, 191)
rect = CGRect(x0, size)
CGContextAddRect(c, rect)
CGContextSetLineWidth(c, 6)
CGContextMoveToPoint(c, *x0)
x1 = map(operator.add, x0, size)
CGContextAddLineToPoint(c, *x1)
CGContextDrawPath(c, kCGPathFillStroke)
CGContextTranslateCTM(c, 128, 128)
CGContextRotateCTM(c, math.radians(90))
CGContextTranslateCTM(c, -128, -128)
CGContextSetRGBStrokeColor(c, 0, 0, 0, 1)
CGContextSetRGBFillColor(c, 1, 1, 1, 0.8)
CGContextSelectFont(c, "Helvetica", 36, kCGEncodingMacRoman)
CGContextSetTextPosition(c, 32, 118)
CGContextSetTextDrawingMode(c, kCGTextFillStroke)
CGContextSetShadow(c, NSMakePoint(0, -10), 20)
CGContextShowText(c, "Hello world!", 3)
cgimg = CGBitmapContextCreateImage(c)
nsimg = NSImage.alloc().initWithCGImage_size_(cgimg, NSMakeSize(width, height))
#CFRelease(cgimg)
#nsimg.release()
return nsimg
def CGWriteToFile(image, path, format):
url = NSURL.fileURLWithPath_(path)
destination = CGImageDestinationCreateWithURL(url, format, 1, None)
CGImageDestinationAddImage(destination, image, None)
if not CGImageDestinationFinalize(destination):
NSLog("Failed to write image to %s", path)
#CFRelease(destination)
def NSImageWriteToFile(image, path, format):
''' Write image representation as data to an image file.
``format`` can be one of the file type constants, i.e. ``NSPNGFileType``.
'''
imgRep = image.representations().objectAtIndex_(0)
image.lockFocus()
rect = NSMakeRect(0.0, 0.0, image.size().width, image.size().height)
imgRep = NSBitmapImageRep.alloc().initWithFocusedViewRect_(rect)
image.unlockFocus()
data = imgRep.representationUsingType_properties_(format, None)
data.writeToFile_atomically_(path, False)
#CFRelease(imgRep)
def system(cmd, args=None):
'''
Convenience function for firing off commands to
the system console. Used instead of `subprocess.call`_
so that shell variables will be expanded properly.
Not the same as `os.system`_ as here it captures
returns ``stdout`` and ``stderr`` in a tuple in
Python 2.5 and lower or a ``namedtuple`` in 2.6
and higher. So you can use ``result[0]`` in the
first case and ``result.out`` in the second.
:param cmd: a console command line
:type cmd: ``string``
:param args: a list of arguments that
will be expanded in cmd
starting with ``$0``
:type args: ``list``
:return: ``tuple`` or ``namedtuple``
'''
if args is None:
fullcmd = cmd
else:
args = ["'{}'".format(s.replace(r'\\', r'\\\\')
.replace("'", r"\'")) for s in args]
fullcmd = "%s %s" % (cmd, ' '.join(args))
out, err = Popen(fullcmd, stdout=PIPE, shell=True).communicate()
system.out = out
system.err = err
try:
from collections import namedtuple
StdStreams = namedtuple('StdStreams', ['out', 'err'])
return StdStreams(out=out, err=err)
except ImportError:
return (out, err)
if __name__ == '__main__':
image = MakeImage(WIDTH, HEIGHT, BITDEPTH)
NSImageWriteToFile(image, 'out.jpg', NSJPEGFileType)
NSImageWriteToFile(image, 'out.png', NSPNGFileType)
NSImageWriteToFile(image, 'out.tiff', NSTIFFFileType)
system('open', args=[os.path.realpath('out.tiff')])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment