zoukankan      html  css  js  c++  java
  • iOS 2D绘图详解(Quartz 2D)之Bitmap

    什么是Bitmap?

    Bitmap叫做位图,每一个像素点由1-32bit组成。每个像素点包括多个颜色组件和一个Alpha组件(例如:RGBA)。

    iOS中指出如下格式的图片 JPEG, GIF, PNG, TIF, ICO, GMP, XBM,和 CUR。其他格式的图片要给Quartz2D传入图片的数据分布信息。


    数据类型CGImageRef

    在Quartz中,Bitmap的数据由CGImageRef封装。由以下几个函数可以创建CGImageRef对象

    • CGImageCreate - 最灵活,但也是最复杂的一种方式,要传入11个参数,这个方法最后讲解。
    • CGImageSourceCreate-ImageAtIndex-通过已经存在的Image对象来创建
    • CGImageSourceCreate-ThumbnailAtIndex- 和上一个函数类似,不过这个是创建缩略图
    • CGBitmapContextCreateImage - 通过Copy Bitmap Graphics来创建
    • CGImageCreateWith-ImageInRect -通过在某一个矩形内数据来创建

    例子一,在一个bitmap context绘制,并且重新生成一张图片

    先看看一个方法,创建bitmap context-CGBitmapContextCreate
    函数体

    CGContextRef _Nullable CGBitmapContextCreate (
       void * _Nullable data,
       size_t width,
       size_t height,
       size_t bitsPerComponent,
       size_t bytesPerRow,
       CGColorSpaceRef _Nullable space,
       uint32_t bitmapInfo
    );

    参数

    • data 是一个指针,指向存储绘制的bitmap context的实际数据的地址,最少大小为bytesPerRow* height.可以传入null,让quartz自动分配计算
    • width/height bitmap的宽度,高度,以像素为单位
    • bytesPerRow 每一行的byte数目。如果data传入null,这里传入0,则会自动计算
    • 一个component占据多少位。对于32bit的RGBA空间,则是8(8*4=32)。
    • space 颜色空间,一般就是DeviceRGB
    • bitmapInfo,一个常量,指定了是否具有alpha通道,alpha通道的位置,像素点存储的数据类型是float还是Integer等信息。

    其中bitmapInfo可以传入的参数如下,通过名字就能看出来,这里不加注释了

    enum CGImageAlphaInfo {
       kCGImageAlphaNone,
       kCGImageAlphaPremultipliedLast,
       kCGImageAlphaPremultipliedFirst,
       kCGImageAlphaLast,
       kCGImageAlphaFirst,
       kCGImageAlphaNoneSkipLast,
       kCGImageAlphaNoneSkipFirst,
       kCGImageAlphaOnly 
    };

    原图(1280*800)

    效果

    重新绘制成200*100,并在图片中间加上我们自定义的绘制

    代码

        CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
        CGSize targetSize = CGSizeMake(200, 100);
        CGContextRef bitmapContext = CGBitmapContextCreate(NULL,
                                                           targetSize.width,
                                                           targetSize.height,
                                                           8,
                                                           targetSize.width * 4,
                                                           rgb,
                                                        kCGImageAlphaPremultipliedFirst);
        CGRect imageRect;
        imageRect.origin = CGPointMake(0, 0);
        imageRect.size = targetSize;
        UIImage * imageToDraw = [UIImage imageNamed:@"image.jpg"];
        CGContextDrawImage(bitmapContext,imageRect,imageToDraw.CGImage);
        CGContextAddArc(bitmapContext,100,40, 20,M_PI_4, M_PI_2, true);
        CGContextSetLineWidth(bitmapContext, 4.0);
        CGContextStrokePath(bitmapContext);
    
    
        CGImageRef imageRef = CGBitmapContextCreateImage(bitmapContext);
        UIImage * image = [[UIImage alloc] initWithCGImage:imageRef];
    
        CGImageRelease(imageRef);
        CGContextRelease(bitmapContext);
        CGColorSpaceRelease(rgb);
    
        UIImageView * imageView = [[UIImageView alloc] initWithImage:image];
        imageView.center = self.view.center;
        [self.view addSubview:imageView];

    例子二,截取图片的一部分

    效果

    代码

        UIImage * imageToDraw = [UIImage imageNamed:@"image.jpg"];
        CGImageRef partImageRef = CGImageCreateWithImageInRect(imageToDraw.CGImage, CGRectMake(0, 0,300, 200));
        UIImage * partImage = [[UIImage alloc] initWithCGImage:partImageRef];
        UIImageView * imageView = [[UIImageView alloc] initWithImage:partImage];
        imageView.center = self.view.center;
        [self.view addSubview:imageView];

    看看CGImageCreate这个方法

    CGImageRef _Nullable CGImageCreate (
       size_t width,
       size_t height,
       size_t bitsPerComponent,
       size_t bitsPerPixel,
       size_t bytesPerRow,
       CGColorSpaceRef _Nullable space,
       CGBitmapInfo bitmapInfo,
       CGDataProviderRef _Nullable provider,
       const CGFloat * _Nullable decode,
       bool shouldInterpolate,
       CGColorRenderingIntent intent
    );

    参数

    • width/height 图片的像素宽度,高度
    • bitsPerComponent 每个component的占用bit个数,和上文提到的一样
    • bitsPerPixel 每个像素点占用的bit个数。例如32bit RGBA中,就是32
    • bytesPerRow 每一行占用的byte个数
    • colorspace 颜色空间
    • bitmapInfo 和上文提到的那个函数一样
    • provider bitmap的数据源
    • decode 解码array,传入null,则保持原始数据
    • interpolation 是否要像素差值来平滑图像
    • intent 指定了从一个颜色空间map到另一个颜色空间的方式

    UIKit中的Bitmap

    成对使用来创建bitmap context,进行绘制

    UIGraphicsBeginImageContext
    
    UIGraphicsEndImageContext

    通过一下方法来获取当前context就可以绘制了。

    UIGraphicsGetCurrentContext

    然后通过,UIGraphicsGetImageFromCurrentImageContext来生成图片

    例如
    调整图片的大小

    + (UIImage*)imageWithImage:(UIImage*)image
                  scaledToSize:(CGSize)newSize;
    {
        UIGraphicsBeginImageContext( newSize );
        [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
        UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return newImage;
    }

    截屏

       UIWindow * keyWindow = [UIApplication sharedApplication].keyWindow;
        UIGraphicsBeginImageContextWithOptions(keyWindow.bounds.size, NO, [UIScreen mainScreen].scale);
        CGContextRef context = UIGraphicsGetCurrentContext();
        [keyWindow.layer renderInContext:context];
        UIImage * screenShot = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
  • 相关阅读:
    选择排序的C、C++实现
    冒泡排序的C、C++实现
    Node.js使用UDP通讯
    Node.js使用TCP通讯
    栈的C语言实现
    顺序表的C、C++实现
    vim的几种模式&快捷键
    ubuntu安装discourse论坛----结合在apache服务上建立虚拟主机
    Ubuntu下使用mail命令发送邮件
    深入解读EOS源代码之——区块链内核
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/5949014.html
Copyright © 2011-2022 走看看