2012-11-30
关于Cocoa
2012-12-12 星期三
图像编程相关:
*iOS Drawing Concepts
High-quality graphics are an important part ofyour app’s user interface. Providing high-quality graphics not only makes yourapp look good, but it also makes your app look like a natural extension to therest of the system. iOS provides two primary paths for creating high-qualitygraphics in your system: OpenGL or native rendering using Quartz, CoreAnimation, and UIKit. This document describes native rendering. (To learn aboutOpenGL drawing, see OpenGL ES Programming Guide foriOS.)
Quartz is the main drawing interface, providingsupport for path-based drawing, anti-aliased rendering, gradient fill patterns,images, colors, coordinate-space transformations, and PDF document creation,display, and parsing. UIKit provides Objective-C wrappers for line art, Quartzimages, and color manipulations. Core Animation provides the underlying supportfor animating changes in many UIKit view properties andcan also be used to implement custom animations.
This chapter provides an overview of the drawingprocess for iOS apps, along with specific drawing techniques for each of thesupported drawing technologies. You will also find tips and guidance on how tooptimize your drawing code for the iOS platform.
Important: Notall UIKit classes are thread safe. Be sure to check the documentation beforeperforming drawing-related operations on threads other than your app’s main thread.
摘要:ios提供两种主要的图形渲染方式:opengl和使用Quartz, Core Animation以及使用UIKit,
Quartz是主要的绘制接口,提供基于路径绘制,反锯齿,渐进色填充,图像,颜色,坐标空间变换以及pdf 文档创建,显示,解析。
UIKit使用objective-c对线,Quartz图像,颜色操作进行封装。
Core Animation为对UIKit 视图属性的动画修改及 自定义动画 提供了底层支持。
The UIKit Graphics System
IniOS, all drawing to the screen—regardless of whether it involves OpenGL,Quartz, UIKit, or Core Animation—occurs within the confines of an instance ofthe UIView
class or a subclassthereof. Views definethe portion of the screen in which drawing occurs. If you use system-providedviews, this drawing is handled for you automatically. If you define customviews, however, you must provide the drawing code yourself. If you use Quartz,Core Animation, and UIKit to draw, you use the drawing concepts described inthe following sections.
在ios中,不管那种类型的绘制,所有展现在屏幕上得都需要UIView或其子类上。
Inaddition to drawing directly to the screen, UIKit also allows you to draw intooffscreen bitmap and PDF graphics contexts. When you draw in an offscreencontext, you are not drawing in a view, which means that concepts such as theview drawing cycle do not apply (unless you then obtain that image and draw itin an image view or similar).
除了直接绘制在屏幕上以外,UIKit 也允许你绘制在 offscreen bitmap 和 PDF图形上下文 中。
There are several actions that can trigger a view update:
*Movingor removing another view that was partially obscuring your view
* Making a previouslyhidden view visible again by setting Its hidden property to NO
* Scrolling a viewoff of the screen and then back onto the screen
*Explicitly callingthe setNeedsDisplay or setNeedsDisplayInRect: method of yourview
Eachof the drawing frameworks of iOS establishes a default coordinate system basedon the current graphics context. In iOS, there are two main types of coordinatesystems:
· Anupper-left-origin coordinate system (ULO), in which the origin of drawingoperations is at the upper-left corner of the drawing area, with positivevalues extending downward and to the right.The default coordinate system used by the UIKit and Core Animationframeworks is ULO-based.
· Alower-left-origin coordinate system (LLO), in which the origin of drawingoperations is at the lower-left corner of the drawing area, with positivevalues extending upward and to the right.Thedefault coordinate system used by Core Graphics framework is LLO-based.
·
Points Versus Pixels
In iOS there is a distinction between thecoordinates you specify in your drawing code and the pixels of the underlyingdevice. When using native drawing technologies such as Quartz, UIKit, and CoreAnimation, the drawing coordinate space and the view’s coordinate space areboth logical coordinate spaces,with distances measured in points. These logicalcoordinate systems are decoupled from the device coordinate space used by thesystem frameworks to manage the pixels onscreen.
点 vs 像素
在ios中,用code进行绘制与设备基于像素所描绘的坐标是又区别的,当使用像Quartz,UIKit,Core Animation原始绘制技术,绘制的坐标空间及view的坐标空间都是逻辑坐标空间,它是用点为单位来描述距离。逻辑坐标系统是对系统框架用于基于屏幕像素设备坐标空间 的一种解耦。
The system automatically maps points in the view’scoordinate space to pixels in the device coordinate space, but this mapping isnot always one-to-one. This behavior leads to an important fact that you shouldalways remember:
· One point does not necessarilycorrespond to one physical pixel.
系统会自动将 逻辑坐标空间的点 映射成 设备坐标空间的像素,但是这种映射不总是1:1,所以你需要知道:
一个点并不总对应一个物理像素。
IniOS, the UIScreen, UIView, UIImage, and CALayer classes provideproperties to obtain (and, in some cases, set) a scale factor thatdescribes the relationship between points and pixels for that particularobject.
在IOS中,UIScreen, UIView, UIImage, CALayer类都提供了一个对特定对象获取点,像素关系的描述属性,叫缩放因子(scale factor)。
Obtaining Graphics Contexts
Most of the time, graphics contexts are configuredfor you. Each view object automatically creates a graphics context so that yourcode can start drawing immediately as soon as your custom drawRect:
method iscalled. As part of this configuration, the underlying UIView
class createsa graphics context (a CGContextRef
opaque type)for the current drawing environment.
If you want to draw somewhere other than your view(for example, to capture a series of drawing operations in a PDF or bitmapfile), or if you need to call Core Graphics functions that require a contextobject, you must take additional steps to obtain a graphics context object. Thesections below explain how.
For more information about graphics contexts,modifying the graphics state information, and using graphics contexts to createcustom content, see Quartz 2D Programming Guide.For a list of functions used in conjunction with graphics contexts, see CGContext Reference, CGBitmapContext Reference,and CGPDFContext Reference.
获取图形上下文
如果你想绘制一些东西但是又不在你的view上面,或者,如果你需要调用 Core Graphicfunction,它需要一个上下文对象,你就必须要采用其他一些步骤来获取 图像上下文对象,以下部分介绍了你该如何做。
关于图像上下文,修改图像状态信息 及使用 图像上下文创建自定义上下文, 请参见 Quartz 2D Programming Guide.相应的函数可以参见 CGContext Reference,CGBitmapContext Referenceand CGPDFContext Reference.
Drawing to the Screen
Ifyou use Core Graphics functions to draw to a view, either in the drawRect:
method or elsewhere, you’llneed a graphics context for drawing. (The first parameter of many of thesefunctions must be a CGContextRef
object.) You can call thefunction UIGraphicsGetCurrentContext
to get an explicit versionof the same graphics context that’s made implicit indrawRect:
. Because it’sthe same graphics context, the drawing functions should also make reference toa ULO default coordinate system.
If you want to use Core Graphics functionsto draw in a UIKit view, you should use the ULO coordinate system of UIKit fordrawing operations. Alternatively, you can apply a flip transform to the CTMand then draw an object in the UIKit view using Core Graphics native LLOcoordinate system. “Flippingthe Default Coordinate System” discusses flip transformsin detail.
The UIGraphicsGetCurrentContext
function always returnsthe graphics context currently in effect. For example, if you create a PDFcontext and then callUIGraphicsGetCurrentContext
, you’d receivethat PDF context. You must use the graphics context returned by UIGraphicsGetCurrentContext
if you use Core Graphicsfunctions to draw to a view.
Note: The UIPrintPageRenderer
class declares severalmethods for drawing printable content. In a manner similar to drawRect:
, UIKit installs animplicit graphics context for implementations of these methods. This graphicscontext establishes a ULO default coordinate system.
屏幕绘制
如果你使用 Core Graphics functions 来对view 进行绘制,你可以使用drawRect: 方法或其他, 对于绘制,你总是需要一个 图像上下文(对于所有这类函数的第一个参数一定是 CGContextRef 对象),使用UIGraphicsGetCurrentContext来明确获取一个同样图形上下文,而使用drawRect:方法是隐式获取一个同样图像上下文。由于是同样图形上下文,绘制函数也应该是参考ULO默认坐标系统。
UIKit使用的是ULO坐标系统。
CoreGraphic Function使用的是LLO 坐标系统。
Drawing to Bitmap Contexts and PDF Contexts
UIKit provides functions for rendering images in abitmap graphics context and for generating PDF content by drawing in a PDFgraphics context. Both of these approaches require that you first call afunction that creates a graphics context—a bitmap context or a PDF context,respectively. The returned object serves as the current (and implicit) graphicscontext for subsequent drawing and state-setting calls. When you finish drawingin the context, you call another function to close the context.
绘制位图上下文及PDF上下文
UIKit提供图像上下文 及 pdf图像上下文 的渲染函数,两种方法都需要首次调用一个函数来创建图像上下文。返回值即为当前图像上下文,用于后续的绘制及状态设置,一旦完成绘制,需要调用另外一个函数来关闭上下文。
Colorand Color Spaces
iOSsupports the full range of color spaces available in Quartz; however, most appsshould need only the RGB color space. Because iOS is designed to run onembedded hardware and display graphics onscreen, the RGB color space is themost appropriate one to use.
The UIColor
object providesconvenience methods for specifying color values using RGB, HSB, and grayscalevalues. When creating colors in this way, you never need to specify the colorspace. It is determined for you automatically by the UIColor
object.
Youcan also use the CGContextSetRGBStrokeColor
and CGContextSetRGBFillColor
functions in the CoreGraphics framework to create and set colors. Although the Core Graphics framework includessupport for creating colors using other color spaces, and for creating customcolor spaces, using those colors in your drawing code is not recommended. Yourdrawing code should always use RGB colors.
IO在Quartz里面提供了所有可用范围的颜色空间,UIColor来完成。
Drawing with Quartz andUIKit
Quartz is the general name for the native drawingtechnology in iOS. The Core Graphics framework isat the heart of Quartz, and is the primary interface you use for drawingcontent. This framework provides data types and functions for manipulating thefollowing:
· Graphics contexts
· Paths
· Images and bitmaps
· Transparency layers
· Colors, pattern colors, and colorspaces
· Gradients and shadings
· Fonts
· PDF content
使用Quartz和UIKit进行绘制
Quartz是ios中原始绘制技术的简称, Core Graphics framework 是Quartz的核心,并且也是用于绘制上下文的主要接口,以下是框架提供的数据类型及操作的函数。
UIKit是建立在Quartz基本特性之上的,并且提供了一系列图形相关操作的类。
Configuring the Graphics Context
Beforecalling your drawRect:
method, theview object creates a graphics context and sets it as the current context. Thiscontext exists only for the lifetime of the drawRect:
call. You canretrieve a pointer to this graphics context by calling the UIGraphicsGetCurrentContext
function. Thisfunction returns a reference to a CGContextRef
type, whichyou pass to Core Graphics functions to modify the current graphics state. Table 1-1 lists the main functions you use toset different aspects of the graphics state. For a complete list of functions,see CGContext Reference.This table also lists UIKit alternatives where they exist.
The graphics context contains a stack of savedgraphics states. When Quartz creates a graphics context, the stack is empty.Using the CGContextSaveGState
functionpushes a copy of the current graphics state onto the stack. Thereafter,modifications you make to the graphics state affect subsequent drawingoperations but do not affect the copy stored on the stack. When you are donemaking modifications, you can return to the previous graphics state by poppingthe saved state off the top of the stack using the CGContextRestoreGState
function.Pushing and popping graphics states in this manner is a fast way to return to aprevious state and eliminates the need to undo each state change individually.It is also the only way to restore some aspects of the state, such as theclipping path, back to their original settings.
Forgeneral information about graphics contexts and using them to configure thedrawing environment, see “Graphics Contexts” in Quartz 2D Programming Guide.
配置图形上下文
在调用drawRect:方法之前,view 对象要创建 图形上下文 并将其座位当前上下文,这个上下文生命期仅存在与drawRect:方法调用期间内。你可以通过调用UIGraphicsGetCurrentContext 函数来获取图形上下文指针,这个函数会返回一个 CGConttextRef 类型的引用,通过将其传递给 Core Graphics function 去修改当前图像状态。
图形上下文包含了以保存图形状态的栈数据,当Quartz创建图形上下文时,该栈是空的,使用CGContextSaveGState函数会将当前图形状态的一个拷贝压入栈中,之后,在后续绘制操作中对这个图形状态的修改不会影响放置在栈中的拷贝,所以当你修改完成以后,可以通过使用 CGContextRestoreGState函数弹出栈顶信息来返回置先前的状态。
Applying Core AnimationEffects
Core Animation is an Objective-C framework that providesinfrastructure for creating fluid, real-time animations quickly and easily.Core Animation is not a drawing technology itself, in the sense that it doesnot provide primitive routines for creating shapes, images, or other types ofcontent. Instead, it is a technology for manipulating and displaying contentthat you created using other technologies.
Most apps can benefit from using Core Animation insome form in iOS. Animations provide feedback to the user about what ishappening. For example, when the user navigates through the Settings app,screens slide in and out of view based on whether the user is navigatingfurther down the preferences hierarchy or back up to the root node. This kindof feedback is important and provides contextual information for the user. Italso enhances the visual style of an app.
Inmost cases, you may be able to reap the benefits of Core Animation with verylittle effort. For example, several properties ofthe UIView
class(including the view’s frame, center, color, and opacity—among others) can beconfigured to trigger animations when their values change. You have to do somework to let UIKit know that you want these animations performed, but theanimations themselves are created and run automatically for you. Forinformation about how to trigger the built-in view animations, see “Animating Views” in UIView Class Reference.
When you go beyond the basic animations, you mustinteract more directly with Core Animation classes and methods. The followingsections provide information about Core Animation and show you how to work withits classes and methods to create typical animations in iOS. For additionalinformation about Core Animation and how to use it, see Core Animation Programming Guide.
应用Core Animation 效果
Core Animation是objective-c 框架,该框架提供了创建实时动画。CoreAnmiation本身不是一种绘制技术,也就是说不提供原始的创建图形,图像或其他类型的方法,其实,他是一种使用其他技术为让你创建的内容进行操作,显示的技术。
AboutLayers
Thekey technology in Core Animation is the layer object. Layers are lightweightobjects that are similar in nature to views, but that areactually model objectsthat encapsulate geometry,timing, and visual properties for the content you want to display.The content itself is provided in one of three ways:
· You can assigna CGImageRef
to the contents
property of the layer object.
· You can assigna delegate to the layer and let the delegate handle the drawing.
· You cansubclass CALayer
and override oneof the display methods.
Whenyou manipulate a layer object’s properties, what you are actually manipulatingis the model-level data that determines how the associated content should bedisplayed. The actual rendering of that content is handled separately from yourcode and is heavily optimized to ensure it is fast. All you must do is set thelayer content, configure the animation properties, and then let Core Animationtake over.
Formore information about layers and how they are used, see Core Animation Programming Guide.
关于层:
Core Animation关键技术就在于layer object.Layers时一个轻量级的对象,类似于views,但是实际上他是一个模型对象,封装了几何,定时器及显示对象上下文的可视属性,上下文本身由以下三种方式之一来提供:
。你可以将CGImageRef分配给层对象的contents属性。
。给层添加一个代理并让代理来处理绘制。
。子类化CALayer并且重载一个显示方法。
当你操作层级对象属性时,你实际操作的其实是一个模型级别的数据,该数据决定你如何将关联的上下文进行显示,实际对上下文的渲染处理与你的code是分离的这样可以保证优化时可以足够快,所有你能做的就是 设置层上下文,配置动画属性, 以及之后让 Core Animation 接管。
TheQuartz 2D API is part of the Core Graphics framework, so you may see Quartzreferred to as Core Graphics or, simply, CG.
Quartz2d API是CoreGraphics framework的一部分,因此你可以参照Core Graphics来了解Quartz.
*Graphics Contexts
Drawing to a View GraphicsContext in iOS
To draw to the screen in an iOS application, youset up a UIView
object andimplement its drawRect:
method toperform drawing. The view’s drawRect:
methodis called when the view is visible onscreen and its contents need updating.Before calling your custom drawRect:
method, theview object automatically configures its drawing environment so that your codecan start drawing immediately. As part of this configuration, the UIView
object createsa graphics context (a CGContextRef
opaque type)for the current drawing environment. You obtain this graphics context in your drawRect:
method bycalling the UIKit function UIGraphicsGetCurrentContext
.
Thedefault coordinate system used throughout UIKit is different from thecoordinate system used by Quartz. In UIKit, the origin is in the upper-leftcorner, with the positive-y value pointing downward. The UIView
objectmodifies the CTM of the Quartz graphics context to match the UIKit conventionsby translating the origin to the upper left corner of the view and invertingthe y-axis by multiplying it by -1
.For more information on modified-coordinate systems and the implications inyour own drawing code, see “Quartz 2DCoordinate Systems.”
UIView
objectsare described in detail in View Programming Guide for iOS.
在ios中绘制可视图像上下文:
绘制屏幕需要UIView对象并实现drawRect:方法,当view需要显示在屏幕上同时它的内容需要更新是,view的drawRect方法会被调用,view对象会自动配置他的绘制环境,方便需要时进行绘制。作为配置的一部分,UIView 对象为当前绘制环境创建一个上下文,你可以在drawRect:方法中通过调用UIKit函数UIGraphicsGetCurrentContext函数来获取这个图形上下文。
Creating a Window GraphicsContext in Mac OS X
When drawing in Mac OS X, you need to create awindow graphics context that’s appropriate for the framework you are using. TheQuartz 2D API itself provides no functions to obtain a windows graphicscontext. Instead, you use the Cocoa framework to obtain a context for a windowcreated in Cocoa.
You obtain a Quartz graphics context from withinthe drawRect:
routine of aCocoa application using the following line of code:
CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort]; |
在 Mac OS X创建一个 window graphics context
当在Mac OS X进行绘制时,你需要创建一个窗口图形上下文应用于你当前使用的框架。Quartz 2D API 本省并没有函数来获取windows graphicscontext,相反,你需要使用cocoa 框架来获取已创建的窗口上下文。(Cocoa时Next Step开发的,所以函数以NS为前缀)
Creating a Bitmap GraphicsContext
A bitmap graphics context accepts a pointer to amemory buffer that contains storage space for the bitmap. When you paint intothe bitmap graphics context, the buffer is updated. After you release thegraphics context, you have a fully updated bitmap in the pixel format youspecify.
Note: Bitmapgraphics contexts are sometimes used for drawing offscreen. Before you decideto use a bitmap graphics context for this purpose, see “CoreGraphics Layer Drawing.” CGLayerobjects (CGLayerRef
)are optimized for offscreen drawing because, whenever possible, Quartz cacheslayers on the video card.
iOS Note: iOSapplications should use the function UIGraphicsBeginImageContextWithOptions
instead ofusing the low-level Quartz functions described here. If your applicationcreates an offscreen bitmap using Quartz, the coordinate system used by bitmapgraphics context is the default Quartz coordinate system. In contrast, if yourapplication creates an image context by calling the function UIGraphicsBeginImageContextWithOptions
,UIKit applies the same transformation to the context’s coordinate system as itdoes to a UIView
object’sgraphics context. This allows your application to use the same drawing code foreither without having to worry about different coordinate systems. Althoughyour application can manually adjust the coordinate transformation matrix toachieve the correct results, in practice, there is no performance benefit todoing so.
You use the function CGBitmapContextCreate to create abitmap graphics context. This function takes the following parameters:
· data
. Supply a pointer to the destinationin memory where you want the drawing rendered. The size of this memory blockshould be at least (bytesPerRow
*height
) bytes.
· width
. Specify the width, in pixels, of thebitmap.
· height
. Specify the height, in pixels, ofthe bitmap.
· bitsPerComponent
.Specify the number of bits to use for each component of a pixel in memory. Forexample, for a 32-bit pixel format and an RGB color space, you would specify avalue of 8 bits per component. See “SupportedPixel Formats.”
· bytesPerRow
. Specify the number of bytes of memoryto use per row of the bitmap.
Tip: When you create a bitmap graphics context, you’ll get the best performance ifyou make sure the data and bytesPerRow
are 16-bytealigned.
提示:当要创建位图图形上下文时,如果能确保数据 bytesPerRow的数据时16字节对齐的话,将会或得比较好的性能。
· colorspace
.The color space to use for the bitmap context. You can provide a Gray, RGB,CMYK, or NULL color space when you create a bitmap graphics context. Fordetailed information on color spaces and color management principles, see ColorManagement Overview. For information on creating and using colorspaces in Quartz, see “Color andColor Spaces.” Forinformation about supported color spaces, see “ColorSpaces and Bitmap Layout” inthe“BitmapImages and Image Masks” chapter.
· bitmapInfo
.Bitmap layout information, expressed as a CGBitmapInfo
constant, thatspecifies whether the bitmap should contain an alpha component, the relativelocation of the alpha component (if there is one) in a pixel, whether the alphacomponent is premultiplied, and whether the color components are integer orfloating-point values. For detailed information on what these constants are,when each is used, and Quartz-supported pixel formats for bitmap graphicscontexts and images, see “ColorSpaces and Bitmap Layout” inthe “BitmapImages and Image Masks” chapter.
*Core Graphics Layer Drawing
How Layer Drawing Works
A layer, represented by the CGLayerRef
data type, isengineered for optimal performance. When possible, Quartz caches a CGLayerobject using a mechanism appropriate to the type of Quartz graphics context itis associated with. For example, a graphics context associated with a videocard might cache the layer on the video card, which makes drawing the contentthat’s in a layer much faster than rendering a similar image that’s constructedfrom a bitmap graphics context. For this reason a layer is typically a betterchoice for offscreen drawing than a bitmap graphics context is.
AllQuartz drawing functions draw to a graphics context. The graphics contextprovides an abstraction of the destination, freeing you from the details of thedestination, such as its resolution. You work in user space, and Quartzperforms the necessary transformations to render the drawing correctly to thedestination. When you use a CGLayer object for drawing, you also draw to agraphics context. Figure 12-1 illustratesthe necessary steps for layer drawing.
Alllayer drawing starts with a graphics context from which you create a CGLayerobject using the function CGLayerCreateWithContext
.The graphics context used to create a CGLayer object is typically a windowgraphics context. Quartz creates a layer so that it has all the characteristicsof the graphics context—its resolution, color space, and graphics state settings.You can provide a size for the layer if you don’t want to use the size of thegraphics context. In Figure 12-2, the left side shows the graphics contextused to create the layer. The gray portion of the box on the right side,labeled CGLayer object, represents the newly created layer.
Beforeyou can draw to the layer, you must obtain the graphics context that’sassociated with the layer by calling the function CGLayerGetContext
.This graphics context is the same flavor as the graphics context used to createthe layer. As long as the graphics context used to create the layer is a windowgraphics context, then the CGLayer graphics context is cached to the GPU if atall possible. The white portion of the box on the right side of Figure 12-2representsthe newly created layer graphics context.
Youdraw to the layer’s graphics context just as you would draw to any graphicscontext, passing the layer’s graphic context to the drawing function. Figure 12-2 shows a leaf shape drawn to the layercontext.
When you are ready to use the contents of thelayer, you can call the functions CGContextDrawLayerInRect
or CGContextDrawLayerAtPoint
,to draw the layer into a graphics context. Typically you would draw to the samegraphics context that you used to create the layer object, but you are notrequired to. You can draw the layer to any graphics context, keeping in mindthat layer drawing has the characteristics of the graphics context used tocreate the layer object, which could impose certain constraints (performance orresolution, for example). For example, a layer associated with the screen maybe cached in video hardware. If the destination context is a printing or PDFcontext, it may need to be fetched from the graphics hardware to memory,resulting in poor performance.
Figure 12-2 shows thecontents of the layer—the leaf—drawn repeatedly to the graphics context used tocreate the layer object. You can reuse the drawing that’s in a layer as manytimes as you’d like before releasing the CGLayer object.
Tip: Use transparency layers when you want to composite parts of a drawing toachieve such effects as shadowing a group of objects. (See “TransparencyLayers.”) Use CGLayer objects when you want to drawoffscreen or when you need to repeatedly draw the same thing.