iOS开发iOS开发基础知识

UIImage

2017-04-24  本文已影响2763人  阿斯兰iOS

官方文档点蓝色文字:UIImageCIImageCGImage

这篇文章是对官方文档的学习笔记,不是翻译,对文档抽象的地方加了解释和示例,对啰嗦的地方删掉。前面是概念讲解,后面是 API 讲解。重要的概念有图片拉伸、动态图、图片方向、模板图片等。

先对比3个概念 UIImage、CImage、CGImage:


<p>


Overview

图片定义:An object that manages image data in your app. An image object may contain a single image or a sequence of images you intend to use in an animation.

图片用途之一:Draw an image directly into a view or other graphics context.

虽然支持所有类型图片,但是建议使用PNG和JPEG。这两种类型都优化过,性能更好。尤其PNG是无损格式,墙裂推荐使用。


<p>

Creating Image Objects

注意图片是否在bundle中、是否缓存图片、图片的使用频率:

  • Use the imageNamed:inBundle:compatibleWithTraitCollection: method (or the imageNamed: method) to create an image from an image asset or image file located in your app’s main bundle (or some other known bundle). Because these methods cache the image data automatically, they are especially recommended for images that you use frequently.
  • Use the imageWithContentsOfFile: or initWithContentsOfFile: method to create an image object where the initial data is not in a bundle. These methods load the image data from disk each time, so you should not use them to load the same image repeatedly.
  • Use the animatedImageWithImages:duration: and animatedImageNamed:duration: methods to create a single UIImage object comprised of multiple sequential images. Install the resulting image in a UIImageView object to create animations in your interface.

imageNamed:方法加载<u>在bundle中</u>的图片,缓存到内存中,适合频繁使用的图片。imageWithContentsOfFile:方法每次都从沙盒中加载图片,适合使用频率低的图片。animatedImageWithImages:duration:方法创建一个由多张图片构成的图片,用于UIImageView播放动画。

UIImage类的其他方法允许你从Core Graphics images or image data创建图片和动画。UIKit提供 UIGraphicsGetImageFromCurrentImageContext 方法从当前的context中获取你绘制的图片。

注意,image对象是不可变的,属性在图片创建之后就不能修改了。这也意味着,它是线程安全的。

使用Image assets管理图片是最简易的,它可以添加多个image set ,每个set包含用于不同系统版本、环境(compact or regular)和缩放比例的图片。

除了从disk加载图片,也可以使用UIImagePickerController从摄像头或者照片库获取图片,但这需要用户授权。


<p>

Defining a Stretchable Image

使用resizableImageWithCapInsets: 或者 resizableImageWithCapInsets:resizingMode:方法创建可拉伸图片,参数insets分割图片为2~9个部分。如图1所示,4个方向非零的inset把图片分割为9个部分。

Figure 1 Using insets to define stretchable regions

inset定义了4个方形盖子,top、left、bottom、right,被盖子盖住的部分不被拉伸。top、bottom保证在垂直方向不被拉伸,left、right保证在水平方向不被拉伸。图2的4个角落是不会被拉伸的,每个箭头表示该区域允许被拉伸的方向。

Each inset defines the potion of the image that does not stretch in the given dimension. The regions inside an image’s top and bottom insets maintain a fixed height, and the areas inside the left and right insets maintain a fixed width. Figure 2 shows how each part of a nine-part image stretches as the image itself is stretched to fill the available space. The corners of the image do not change size because they are inside both a horizontal and vertical inset.

Figure 2 Stretchable portions of a nine-part image


<p>

Comparing Images

从相同的图片缓存数据创建的两个图片对象也可能是不同的。唯一可靠的办法是使用isEqual:方法比较。

正确的和错误的比较方式:

// Load the same image twice.
UIImage* image1 = [UIImage imageNamed:@"MyImage"];
UIImage* image2 = [UIImage imageNamed:@"MyImage"];
 
// The image objects may be different, but the contents are still equal
if ([image1 isEqual:image2]) {
   // Correct. This technique compares the image data correctly.
}
 
if (image1 == image2) {
   // Incorrect! Direct object comparisons may not work.
}


<p>

Accessing the Image Data

CGImageCIImage 属性分别是 Core Graphics 和 Core Image 的图片数据。也可以使用 UIImagePNGRepresentationUIImageJPEGRepresentation 函数生成一个包含 PNG 或 JPEG 格式图片数据的 NSData 对象。


<p>

Symbols


Loading and Caching Images


<p>

+ (UIImage *)imageNamed:(NSString *)name 
               inBundle:(NSBundle *)bundle 
compatibleWithTraitCollection:(UITraitCollection *)traitCollection;
size class


<p>

+ (UIImage *)imageNamed:(NSString *)name;


<p>


Creating and Initializing Image Objects


<p>

+ (UIImage *)imageWithContentsOfFile:(NSString *)path;

// demo
NSString *path = [[NSBundle mainBundle]pathForResource:@"demo" ofType:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:path];


<p>

+ (UIImage *)imageWithData:(NSData *)data;

// demo
NSString *path = [[NSBundle mainBundle]pathForResource:@"demo" ofType:@"png"];
NSData *data = [NSData dataWithContentsOfFile:path];
UIImage *image = [UIImage imageWithData:data]; 


<p>

+ (UIImage *)imageWithData:(NSData *)data 
                     scale:(CGFloat)scale;

// demo
// 以为是放大十倍,结果是缩小了十倍。但是image.cgImage大小不变
image = [UIImage imageWithData:data scale:10]; // po image.size: (width = 64, height = 38.6)
image = [UIImage imageWithData:data scale:1]; //  po image.size: (width = 640, height = 386)


<p>

+ (UIImage *)imageWithCGImage:(CGImageRef)cgImage;

+ (UIImage *)imageWithCGImage:(CGImageRef)cgImage 
                        scale:(CGFloat)scale 
                  orientation:(UIImageOrientation)orientation;


// demo
UIImage *image = [UIImage imageNamed:@"demo"];
// 图片截取
CGImageRef cgImage = CGImageCreateWithImageInRect(image.CGImage,CGRectMake(0, 0, 1000, 1000)); 
image = [UIImage imageWithCGImage:cgImage];
// UIImageOrientationUpMirrored 是图片向上并水平翻转
image = [UIImage imageWithCGImage:cgImage scale:1 orientation:UIImageOrientationUpMirrored];
CGImageRelease(cgImage); // 释放内存
图片方向


<p>

+ (UIImage *)imageWithCIImage:(CIImage *)ciImage;

+ (UIImage *)imageWithCIImage:(CIImage *)ciImage 
                        scale:(CGFloat)scale 
                  orientation:(UIImageOrientation)orientation;


// demo
// 创建滤镜和CIImage
CIImage *ciImage = [CIImage imageWithData:data];
CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"]; // 创建滤镜
ciImage = [filter outputImage]; // 滤镜处理后输出图像

image = [UIImage imageWithCIImage:ciImage];
image = [UIImage imageWithCIImage:ciImage scale:1 orientation:UIImageOrientationUpMirrored];


<p>


Creating Specialized Image Objects


<p>

+ (UIImage *)animatedImageNamed:(NSString *)name 
                       duration:(NSTimeInterval)duration;


<p>

+ (UIImage *)animatedImageWithImages:(NSArray<UIImage *> *)images 
                            duration:(NSTimeInterval)duration;


<p>

+ (UIImage *)animatedResizableImageNamed:(NSString *)name 
                               capInsets:(UIEdgeInsets)capInsets 
                                duration:(NSTimeInterval)duration;


<p>

+ (UIImage *)animatedResizableImageNamed:(NSString *)name 
                               capInsets:(UIEdgeInsets)capInsets 
                            resizingMode:(UIImageResizingMode)resizingMode 
                                duration:(NSTimeInterval)duration;


<p>

- (UIImage *)imageFlippedForRightToLeftLayoutDirection;

</br>

- (UIImage *)imageWithRenderingMode:(UIImageRenderingMode)renderingMode;

// demo
  UIImage *myImage = [UIImage imageNamed:@"myImageFile.png"];
  myImage = [myImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
设置 renderingMode


<p>

- (UIImage *)imageWithAlignmentRectInsets:(UIEdgeInsets)alignmentInsets;


  // demo
  // 图片阴影在右下方,大小是20*20,所以要往右下平移
  UIEdgeInsets rInsets = UIEdgeInsetsMake(0, 0, 20, 20);
  image = [image imageWithAlignmentRectInsets:rInsets]; // 只对自动布局有效,代码布局无效
alignment rectInsets


<p>

- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets;


<p>

- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets 
                            resizingMode:(UIImageResizingMode)resizingMode;


    // demo
    // 拉伸图片的不同区域
    float bottom = image.size.height / 2;
    float top   =  image.size.height / 2;
    // 上,左,下,右
    UIEdgeInsets capInsets2 = UIEdgeInsetsMake(0, 0, bottom, 0); // 底部绿色区域在垂直方向上不被拉伸
    UIEdgeInsets capInsets3 = UIEdgeInsetsMake(top, 0, 0, 0); // 顶部蓝色区域在垂直方向上不被拉伸
    // 变形模式是拉伸
    UIImage *image2 = [image resizableImageWithCapInsets:capInsets2 resizingMode:UIImageResizingModeStretch];
    UIImage *image3 = [image resizableImageWithCapInsets:capInsets3 resizingMode:UIImageResizingModeStretch];

拉伸图片


<p>


Image Attributes


<p>


<p>


Drawing Images


<p>

这里涉及到 Core Graphics, 有几篇文章写的不错:


<p>

- (void)drawAtPoint:(CGPoint)point;


<p>

- (void)drawAtPoint:(CGPoint)point 
          blendMode:(CGBlendMode)blendMode 
              alpha:(CGFloat)alpha;



<p>

- (void)drawInRect:(CGRect)rect;


<p>

- (void)drawInRect:(CGRect)rect 
         blendMode:(CGBlendMode)blendMode 
             alpha:(CGFloat)alpha;



<p>

- (void)drawAsPatternInRect:(CGRect)rect;



<p>


Constants


<p>

// UIImageOrientation
typedef NS_ENUM(NSInteger, UIImageOrientation) {
    UIImageOrientationUp,            // default orientation
    UIImageOrientationDown,          // 180 deg rotation
    UIImageOrientationLeft,          // 90 deg CCW
    UIImageOrientationRight,         // 90 deg CW
    UIImageOrientationUpMirrored,    // as above but image mirrored along other axis. horizontal flip
    UIImageOrientationDownMirrored,  // horizontal flip
    UIImageOrientationLeftMirrored,  // vertical flip
    UIImageOrientationRightMirrored, // vertical flip
};


// demo
    image = [UIImage imageNamed:@"R.jpg"];
    UIImageOrientation orientation = UIImageOrientationUp;
    orientation = UIImageOrientationLeft;
    orientation = UIImageOrientationRight;
    orientation = UIImageOrientationDown;
    orientation = UIImageOrientationUpMirrored;
    orientation = UIImageOrientationLeftMirrored; // 先左右翻转再左转90°!
    orientation = UIImageOrientationRightMirrored;
    orientation = UIImageOrientationDownMirrored;
    image = [UIImage imageWithCGImage:image.CGImage scale:1 orientation:orientation];


图片旋转.png


<p>

// UIImageResizingMode
typedef NS_ENUM(NSInteger, UIImageResizingMode) {
    UIImageResizingModeTile,
    UIImageResizingModeStretch,
};


// demo
    image = [UIImage imageNamed:@"R.jpg"];
    UIImageResizingMode mode = UIImageResizingModeStretch; // 拉伸
    mode = UIImageResizingModeTile; // 平铺
    // 创建可变图片。当 imageView 大于 image 时,可能会拉伸或者平铺 image。
    image = [image resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:mode]; 

图1 平铺和拉伸 图2 contentMode 的影响


<p>

// UIImage​Rendering​Mode
typedef NS_ENUM(NSInteger, UIImageRenderingMode) {
    UIImageRenderingModeAutomatic,          // Use the default rendering mode for the context where the image is used
    UIImageRenderingModeAlwaysOriginal,     // Always draw the original image, without treating it as a template
    UIImageRenderingModeAlwaysTemplate,     // Always draw the image as a template image, ignoring its color information
} NS_ENUM_AVAILABLE_IOS(7_0);


// demo
  UIImage *myImage = [UIImage imageNamed:@"myImageFile.png"];
  myImage = [myImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];


<p>


Instance Properties


<p>

@property(nonatomic, readonly) UIGraphicsImageRendererFormat *imageRendererFormat;


<p>


Instance Methods


<p>

- (CGImageRef)CGImage;


<p>

- (UIImage *)imageWithHorizontallyFlippedOrientation;


<p>

上一篇下一篇

猜你喜欢

热点阅读