Last active
February 24, 2020 17:45
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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