Core Graphics
Core Graphics Tutorial Part 1: Getting Started
There are three fundamentals to know about paths:
- A path can be stroked and filled.
- A stroke outlines the path in the current stroke color.
- A fill will fill up a closed path with the current fill color.
- Never call draw(_:) directly. If your view is not being updated, then call setNeedsDisplay() on the view.
setNeedsDisplay() does not itself call draw(_:), but it flags the view as ‘dirty’, triggering a redraw using draw(_:) on the next screen update cycle. Even if you call setNeedsDisplay() five times in the same method you’ll only ever actually call draw(_:) once.
- @IBDesignable — Live Rendering — change code then storyboard rendering
-
@IBInspectable is an attribute you can add to a property that makes it readable by Interface Builder.
Core Graphics Tutorial Part 2: Gradients and Contexts
Drawing a Gradient — CGGradient
Transform Context & fill bezierPath
Core Graphics Tutorial Part 3: Patterns and Playgrounds
UIGraphicsBeginImageContextWithOptions()
UIColor(patternImage: image).setFill()
Quartz 2D Programming Guide
一、Overview of Quartz 2D
- The Page
drawing order is important.
- Drawing Destinations: The Graphics Context
you can draw the same image to a different device simply by providing a different graphics context to the same sequence of Quartz drawing routines.
- bitmap graphics context
- PDF graphics context
- Quartz 2D Opaque Data Types
CGLayerRef — for repeated drawing (such as for backgrounds or patterns) and for offscreen drawing.
- Graphics States
CGContextSaveGState + CGContextRestoreGState
the current path is not considered part of the graphics state
Parameters |
---|
Current transformation matrix (CTM) |
Clipping area |
Line: width, join, cap, dash, miter limit |
Accuracy of curve estimation (flatness) |
Anti-aliasing setting |
Color: fill and stroke settings |
Alpha value (transparency) |
Rendering intent |
Color space: fill and stroke settings |
Text: font, font size, character spacing, text drawing mode |
Blend mode |
-
Quartz 2D Coordinate Systems
In particular, patterns and shadows, which are not affected by the CTM, are adjusted separately so that their conventions match UIKit’s coordinate system. -
Memory Management: Object Ownership
Rules:
-
If you create or copy an object, you own it, and therefore you must release it. That is, in general, if you obtain an object from a function with the words “Create” or “Copy” in its name, you must release the object when you’re done with it. Otherwise, a memory leak results.
-
If you obtain an object from a function that does not contain the words “Create” or “Copy” in its name, you do not own a reference to the object, and you must not release it. The object will be released by its owner at some point in the future.
-
If you do not own an object and you need to keep it around, you must retain it and release it when you’re done with it. You use the Quartz 2D functions specific to an object to retain and release that object. For example, if you receive a reference to a CGColorspace object, you use the functions CGColorSpaceRetain and CGColorSpaceRelease to retain and release the object as needed. You can also use the Core Foundation functions CFRetain and CFRelease, but you must be careful not to pass NULL to these functions.
二、Graphics Contexts
-
用CG的原因:只是用图片或是图层效果不能轻易地绘制出矢量图形。
-
Core Graphics绘制 - 如果对视图实现了-drawRect:方法,或者CALayerDelegate的-drawLayer:inContext:方法,那么在绘制任何东西之前都会产生一个巨大的性能开销。为了支持对图层内容的任意绘制,Core Animation必须创建一个内存中等大小的寄宿图片。然后一旦绘制结束之后,必须把图片数据通过IPC传到渲染服务器。在此基础上,Core Graphics绘制就会变得十分缓慢,所以在一个对性能十分挑剔的场景下这样做十分不好。
- Drawing to a View Graphics Context in iOS
UIView - drawRect: — The UIView object modifies the CTM of the Quartz graphics context to match the UIKit conventions
- Creating a Window Graphics Context in Mac OS X
- Creating a PDF Graphics Context
- Creating a Bitmap Graphics Context
UIGraphicsBeginImageContextWithOptions
CGBitmapContextCreate() — all params
Tip: When you create a bitmap graphics context, you’ll get the best performance if you make sure the data and bytesPerRow are 16-byte aligned.
The constant kCGImageAlphaPremultipliedLast indicates that the alpha component is stored in the last byte of each pixel and that the color components have already been multiplied by this alpha value.
三、Paths
- Path Creation and Path Painting
fill + stroke
- The Building Blocks
Lines — CGContextMoveToPoint + CGContextAddLineToPoint + CGContextAddLines
Arcs — CGContextAddArc + CGContextAddArcToPoint
cubic Bézier curve — CGContextAddCurveToPoint
quadratic Bézier curve — CGContextAddQuadCurveToPoint
Ellipses — CGContextAddEllipseInRect
Rectangles — CGContextAddRect + CGContextAddRects
- Creating a Path
Before you begin a new path, call the function CGContextBeginPath
Quartz provides two data types for creating reusable paths — CGPathRef and CGMutablePathRef — CGPathCreateMutable
- CGPathCreateMutable, which replacesCGContextBeginPath
- CGPathMoveToPoint, which replaces CGContextMoveToPoint
- CGPathAddLineToPoint, which replaces CGContextAddLineToPoint
- CGPathAddCurveToPoint, which replaces CGContextAddCurveToPoint
- CGPathAddEllipseInRect, which replaces CGContextAddEllipseInRect
- CGPathAddArc, which replaces CGContextAddArc
- CGPathAddRect, which replaces CGContextAddRect
- CGPathCloseSubpath, which replaces CGContextClosePath
CGContextAddPath + CGContextReplacePathWithStrokedPath
- Painting a Path
<1> Parameters That Affect Stroking
Parameter | Function to set parameter value |
---|---|
Line width | CGContextSetLineWidth |
Line join | CGContextSetLineJoin |
Line cap | CGContextSetLineCap |
Miter limit | CGContextSetMiterLimit |
Line dash pattern | CGContextSetLineDash |
Stroke color space | CGContextSetStrokeColorSpace |
Stroke color | CGContextSetStrokeColorCGContextSetStrokeColorWithColor |
Stroke pattern | CGContextSetStrokePattern |
<2> Functions for Stroking a Path
Function |
---|
CGContextStrokePath |
CGContextStrokeRect |
CGContextStrokeRectWithWidth |
CGContextStrokeEllipseInRect |
CGContextStrokeLineSegments |
CGContextDrawPath |
<3> Filling a Path
i. the nonzero winding number rule — left->right+1, right->left-1
ii. even-odd rule — odd-painted, even-not painted
Function | Description |
---|---|
CGContextEOFillPath | Fills the current path using the even-odd rule |
CGContextFillPath | Fills the current path using the nonzero winding number rule |
CGContextFillRect | Fills the area that fits inside the specified rectangle |
CGContextFillRects | Fills the areas that fits inside the specified rectangles |
CGContextFillEllipseInRect | Fills an ellipse that fits inside the specified rectangle |
CGContextDrawPath | Fills the current path if you pass kCGPathFill (nonzero winding number rule) or kCGPathEOFill (even-odd rule). Fills and strokes the current path if you pass kCGPathFillStroke or kCGPathEOFillStroke |
<4> Setting Blend Modes
CGContextSetBlendMode |
---|
kCGBlendModeNormal |
kCGBlendModeMultiply |
kCGBlendModeScreen |
kCGBlendModeOverlay |
kCGBlendModeDarken |
kCGBlendModeLighten |
- Clipping to a Path
Clip Path |
---|
CGContextClip |
CGContextEOClip |
CGContextClipToRect |
CGContextClipToRects |
CGContextClipToMask |
四、Color and Color Spaces
- About Color and Color Spaces
- The Alpha Value
- Creating Color Spaces
Creating Device-Independent Color Spaces |
---|
CGColorSpaceCreateLab |
CGColorSpaceCreateICCBased |
CGColorSpaceCreateCalibratedRGB |
CGColorSpaceCreateCalibratedGray |
Creating Generic Color Spaces |
---|
kCGColorSpaceGenericGray |
kCGColorSpaceGenericRGB |
kCGColorSpaceGenericCMYK |
Creating Device Color Spaces |
---|
CGColorSpaceCreateDeviceGray |
CGColorSpaceCreateDeviceRGB |
CGColorSpaceCreateDeviceCMYK |
Creating Indexed and Pattern Color Spaces |
---|
CGColorSpaceCreateIndexed |
CGColorSpaceCreatePattern |
Setting and Creating Colors |
---|
CGContextSetFillColorSpace |
CGContextSetStrokeColorSpace |
CGContextSetStrokeColorWithColor |
CGContextSetFillColorWithColor |
CGColorCreate |
- Setting Rendering Intent
CGContextSetRenderingIntent |
---|
kCGRenderingIntentDefault |
kCGRenderingIntentAbsoluteColorimetric |
kCGRenderingIntentRelativeColorimetric |
kCGRenderingIntentPerceptual |
kCGRenderingIntentSaturation |
五、Transforms
- About Quartz Transformation Functions
- Modifying the Current Transformation Matrix
Modifying CTM |
---|
CGContextDrawImage |
CGContextTranslateCTM |
CGContextRotateCTM |
CGContextScaleCTM |
CGContextConcatCTM |
#include <math.h>
static inline double radians (double degrees) {return degrees * M_PI/180;}
- Creating Affine Transforms
Function |
---|
CGAffineTransformMakeTranslation |
CGAffineTransformTranslate |
CGAffineTransformMakeRotation |
CGAffineTransformRotate |
CGAffineTransformMakeScale |
CGAffineTransformScale |
Function |
---|
CGAffineTransformInvert |
CGPointApplyAffineTransform |
CGSizeApplyAffineTransform |
CGRectApplyAffineTransform |
-
Evaluating Affine Transforms
CGAffineTransformEqualToTransform
CGAffineTransformIsIdentity -
Getting the User to Device Space Transform
CGContextGetUserSpaceToDeviceSpaceTransform |
---|
CGContextConvertPointToDeviceSpace & CGContextConvertPointToUserSpace |
CGContextConvertSizeToDeviceSpace & CGContextConvertSizeToUserSpace |
CGContextConvertRectToDeviceSpace & CGContextConvertRectToUserSpace |
-
The Math Behind the Matrices
六、Patterns
-
The Anatomy of a Pattern
-
Colored Patterns and Stencil (Uncolored) Patterns
Colored patterns have inherent colors associated with them, but Stencil (Uncolored) Patterns not.
as part of the pattern cell creation process + as part of the pattern drawing process. -
Tiling
-
How Patterns Work
CGContextSetFillColor + CGContextFillRect
CGContextSetFillPattern + CGContextFillRect
<1> Saves the graphics state.
<2> Translates the current transformation matrix to the origin of the pattern cell.
<3> Concatenates the CTM with the pattern matrix.
<4> Clips to the bounding rectangle of the pattern cell.
<5> Calls your drawing callback to draw the pattern cell.
<6> Restores the graphics state.
- Painting Colored Patterns
<1> Write a Callback Function That Draws a Colored Pattern Cell
— typedef void (*CGPatternDrawPatternCallback) (void *info, CGContextRef context);
<2> Set Up the Colored Pattern Color Space
— CGColorSpaceCreatePattern + CGContextSetFillColorSpace
<3> Set Up the Anatomy of the Colored Pattern
— CGPatternRef CGPatternCreate ( void *info, …)
<4> Specify the Colored Pattern as a Fill or Stroke Pattern
— CGContextSetFillPattern + CGContextSetStrokePattern
<5> Draw With the Colored Pattern
— CGContextSetFillPattern (myContext, myPattern, &alpha);
-
Painting Stencil Patterns
七、Shadows
-
How Shadows Work
CGContextSetShadow + CGContextSetShadowWithColor - Shadow Drawing Conventions Vary Based on the Context
-
Painting with Shadows
八、Gradients
- CGShadingRef and CGGradientRef
-
Axial and Radial Gradient Examples
-
A Comparison of CGShading and CGGradient Objects
<1> CGShading
CGFunctionRef(for computing colors in the gradient) -> CGShadingRef -> CGContextDrawShading
<2> CGGradient — subset of CGShading
<3>
CGGradient | CGShading |
---|---|
Can use the same object to draw axial and radial gradients | Need to create separate objects for axial and radial gradients |
Set the geometry of the gradient at drawing time | Set the geometry of the gradient at object creation time |
Quartz calculates the colors for each point in the gradient | You must supply a callback function that calculates the colors for each point in the gradient |
Easy to define more than two locations and colors | Need to design your callback to use more than two locations and colors, so it takes a bit more work on your part |
-
Extending Color Beyond the End of a Gradient
-
Using a CGGradient Object
<1> CGGradient
<2> CGContextDrawLinearGradient or CGContextDrawRadialGradient -
*Using a CGShading Object
<1> CGShadingCreateAxial or CGShadingCreateRadial
九、Transparency Layers
— The resulting composite is treated as a single object. Ex: shadow
-
How Transparency Layers Work
CGContextBeginTransparencyLayer
CGContextEndTransparencyLayer -
Painting to a Transparency Layer
十、Data Management in Quartz 2D
- Moving Data into Quartz 2D
- CGImageSourceRef(preferred way)
<1> CGImageSourceCreateImageAtIndex, CGImageSourceCreateThumbnailAtIndex, or CGImageSourceCreateIncremental.
<2> CGImageSourceUpdateData or CGImageSourceUpdateDataProvider.
<3> CGImageSourceGetCount , CGImageSourceCopyProperties, and CGImageSourceCopyTypeIdentifiers.
- CGDataProviderRef
<1> CGImageCreate, CGImageCreateWithPNGDataProvider, or CGImageCreateWithJPEGDataProvider.
<2> CGPDFDocumentCreateWithProvider.
<3> CGImageSourceUpdateDataProvider
- Moving Data out of Quartz 2D
- CGImageDestinationRef(preferred way)
<1> CGImageDestinationAddImage or CGImageDestinationAddImageFromSource.
<2> CGImageDestinationSetProperties.
<3> CGImageDestinationCopyTypeIdentifiers or CGImageDestinationGetTypeID.
<1> CGPDFContextCreate.
<2> CGImageDestinationCreateWithDataConsumer
-
Moving Data Between Quartz 2D and Core Image in Mac OS X
十一、Core Graphics Layer Drawing
<1> High-quality offscreen rendering of drawing that you plan to reuse.
<2> Repeated drawing.
<3> Buffering
- How Layer Drawing Works
CGLayerCreateWithContext + CGLayerGetContext
CGContextDrawLayerInRect or CGContextDrawLayerAtPoint
- Drawing with a Layer
<1> Create a CGLayer Object Initialized with an Existing Graphics Context
<2> Get a Graphics Context for the Layer
<3> Draw to the CGLayer Graphics Context
<4> Draw the Layer to the Destination Graphics Context
-
Example: Using Multiple CGLayer Objects to Draw a Flag
十二、Text
十三、Todolist
Bitmap Images and Image Masks
Swift Functional Programming Tutorial
Briefly put, functional programming is a programming paradigm that emphasizes calculations via mathematical-style functions, immutability and expressiveness, and minimizes the use of variables and state.
- .filter — 遍历所有,用colure过滤
func isEven(number: Int) -> Bool {
return number % 2 == 0
}
evens = Array(1...10).filter(isEven)
var evens = Array(1...10).filter { (number) in number % 2 == 0 }
evens = Array(1...10).filter { $0 % 2 == 0 }
func myFilter<T>(source: [T], predicate:(T) -> Bool) -> [T] {
var result = [T]()
for i in source {
if predicate(i) {
result.append(i)
}
}
return result
}
- .reduce — reduce function, which takes a set of inputs and generates a single output.
— 遍历所有,item+initValue,下次遍历
evenSum = Array(1...10)
.filter { (number) in number % 2 == 0 }
.reduce(0) { (total, number) in total + number }
let maxNumber = Array(1...10)
.reduce(0) { (total, number) in max(total, number) }
let numbers = Array(1...10)
.reduce("numbers: ") {(total, number) in total + "\(number) "}
extension Array {
func myReduce<T, U>(seed:U, combiner:(U, T) -> U) -> U {
var current = seed
for item in self {
current = combiner(current, item as T)
}
return current
}
}
.map — 遍历所有,
func buildIndex(words: [String]) -> [Entry] {
let letters = words.map {
(word) -> Character in
Character(word.substringToIndex(advance(word.startIndex, 1)
).uppercaseString)
}
println(letters)
return [Entry]()
}
func distinct<T: Equatable>(source: [T]) -> [T] {
var unique = [T]()
for item in source {
if !contains(unique, item) {
unique.append(item)
}
}
return unique
}
func buildIndex(words: [String]) -> [Entry] {
let letters = words.map {
(word) -> Character in
Character(word.substringToIndex(advance(word.startIndex, 1)
).uppercaseString)
}
let distinctLetters = distinct(letters)
return distinctLetters.map {
(letter) -> Entry in
return (letter, words.filter {
(word) -> Bool in
Character(word.substringToIndex(advance(word.startIndex, 1)
).uppercaseString) == letter
})
}
}
func buildIndex(words: [String]) -> [Entry] {
func firstLetter(str: String) -> Character {
return Character(str.substringToIndex(
advance(str.startIndex, 1)).uppercaseString)
}
let letters = words.map {
(word) -> Character in
firstLetter(word)
}
let distinctLetters = distinct(letters)
return distinctLetters.map {
(letter) -> Entry in
return (letter, words.filter {
(word) -> Bool in
firstLetter(word) == letter
})
}
}
func buildIndex(words: [String]) -> [Entry] {
func firstLetter(str: String) -> Character {
return Character(str.substringToIndex(
advance(str.startIndex, 1)).uppercaseString)
}
return distinct(words.map(firstLetter))
.map {
(letter) -> Entry in
return (letter, words.filter {
(word) -> Bool in
firstLetter(word) == letter
})
}
}
You should strive for immutability; immutable types are easier to test and aid concurrency.
Training
Tempalte -> Learning Algorithm -> Model
Vision — Object Tracking
Core ML
Model -> get -> from open source
Drag -> instantiate
let flowerModel = Flower Classifier()
if let prediction = try? flowerModel.prediction(flowerImage: image) {
return prediction.flowerType
}
网友评论