iOS UImage 与 RGB 裸数据的相互转换

Touch the data of image in iOS

Get data from a image

较简单,根据已有的 image 的属性,创建 CGBitmapContext, 这个 context 是带有直接访问的指针的。然后将 Image 绘制到这个 context, 得到裸数据。

Code:

    CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(srcImg.CGImage);
CGColorSpaceRef colorRef = CGColorSpaceCreateDeviceRGB(); float width = srcImg.size.width;
float height = srcImg.size.height; // Get source image data
uint8_t *imageData = (uint8_t *) malloc(width * height * 4); CGContextRef imageContext = CGBitmapContextCreate(imageData,
width, height,
8, static_cast<size_t>(width * 4),
colorRef, alphaInfo); CGContextDrawImage(imageContext, CGRectMake(0, 0, width, height), srcImg.CGImage);
CGContextRelease(imageContext);
CGColorSpaceRelease(colorRef);

拿到指针就可以操作数据了。

需要注意的地方:alphaInfo, 通常我处理的图像都是带有透明度的,但是 RGBA 和 ARGB 都有遇到过,所以需要看清楚这个信息是哪一种,列举如下:

typedef CF_ENUM(uint32_t, CGImageAlphaInfo) {
kCGImageAlphaNone, /* For example, RGB. */
kCGImageAlphaPremultipliedLast, /* For example, premultiplied RGBA */
kCGImageAlphaPremultipliedFirst, /* For example, premultiplied ARGB */
kCGImageAlphaLast, /* For example, non-premultiplied RGBA */
kCGImageAlphaFirst, /* For example, non-premultiplied ARGB */
kCGImageAlphaNoneSkipLast, /* For example, RBGX. */
kCGImageAlphaNoneSkipFirst, /* For example, XRGB. */
kCGImageAlphaOnly /* No color data, alpha data only */
};

一般来说我们的工程都会打开一个png图片压缩的选项,所以我们拿到的 image 一般来说是 premultiplied 的,也就是说,RGB的值已经是和alpha值相乘的结果了,在 OpenGL 纹理操作的时候要注意。

Create a image from raw data

1) Create BitmapContext and get image from it

	size_t bitsPerComponent = 8;
size_t bitsPerPixel = 32;
size_t bytesPerRow = static_cast<size_t>(4 * outWidth);
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); // set the alpha mode RGBA
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast; ////
// This method is much simple and without coordinate flip
// You can use this method either
// but the UIGraphicsBeginImageContext() is much more modern.
//// CGContextRef cgBitmapCtx = CGBitmapContextCreate(outData,
static_cast<size_t>(outWidth),
static_cast<size_t>(outHeight),
bitsPerComponent,
bytesPerRow,
colorSpaceRef,
bitmapInfo); CGImageRef cgImg = CGBitmapContextCreateImage(cgBitmapCtx); UIImage *retImg = [UIImage imageWithCGImage:cgImg]; CGContextRelease(cgBitmapCtx);
CGColorSpaceRelease(colorSpaceRef);
free(outData);

主要方法就是 CGBitmapContextCreate 直接将数据地址 outData 作为初始化参数提供,这样这个 context 就是带有正确数据的了,然后就直接获得 CGImage 了。

2) CGDataProvider --> CGImage --> UIImage

这个方法的思路就是直接使用 CGImageCreate() 函数直接创建 CGImage.

    size_t bitsPerComponent = 8;
size_t bitsPerPixel = 32;
size_t bytesPerRow = static_cast<size_t>(4 * outWidth);
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); // set the alpha mode RGBA
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, outData, outDataLength, NULL); CGImageRef imageRef = CGImageCreate(outWidth, outHeight,
bitsPerComponent, bitsPerPixel, bytesPerRow,
colorSpaceRef, bitmapInfo, provider,
NULL, NO, renderingIntent); UIImage *retImage1 = [UIImage imageWithCGImage:imageRef];

创建 provider 的时候无需回调函数,故直接提供 NULL.

创建 CGImage 時需要提供详细的配置参数,其中部分参数和创建 CGBitmapContext 相同,额外需要提供的就是默认参数以及不需要使用的特性比如 decode array 等等。得到 CGImageRef 后可以直接得到 UIImage 对象,但是我发现我的同事写了如下一段代码:

    UIGraphicsBeginImageContext(outSize);
// the same: UIGraphicsBeginImageContextWithOptions(outSize, NO, 1.0f); CGContextRef cgCtx = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(cgCtx, kCGBlendModeCopy); CGContextDrawImage(cgCtx, CGRectMake(0.0, 0.0, outWidth, outHeight), imageRef); UIImage *retImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();

这段代码的功能是:创建CGContext 然后将 CGimage 绘制到当前的 Context 上面,再得到 UIImage.

基本可以认为是 [UIImage imageWithCGImage:imageRef] 我的不知道为什么同事这样写,可能是这个方法是有什么坑的,我暂时没有遇到。所以我将这段代码先记下来,留着以后用。

关于 UIGraphicsBeginImageContext() 方法,apple 的介绍如下:

iOS Note: iOS applications should use the function UIGraphicsBeginImageContextWithOptions instead of using the low-level Quartz functions described here. If your application creates an offscreen bitmap using Quartz, the coordinate system used by bitmap graphics context is the default Quartz coordinate system. In contrast, if your application creates an image context by calling the function UIGraphicsBeginImageContextWithOptions, UIKit applies the same transformation to the context’s coordinate system as it does to a UIView object’s graphics context. This allows your application to use the same drawing code for either without having to worry about different coordinate systems. Although your application can manually adjust the coordinate transformation matrix to achieve the correct results, in practice, there is no performance benefit to doing so.

上面所述的 low-level Quartz function 就是我们上面用的 CGBitmapContextCreate 这一类方法。所以用这个新的方法直接就将 创建好的 bitmapContext 绑定到当前状态。仍然调用 CGContextDrawImage() 函数,将 CGImage 绘制到指定的 context 上面。然后再获取 UIImage. 总的来说,这个和我们之前的那一套原理是一样的,应该说这样是更新式的做法,推荐的做法。

参考

Quartz 2D Programming Guide

How do I create a CGImage with RGB data?

Converting RGB data into a bitmap in Objective-C++ Cocoa

CGImage to UIImage doesn't work

iOS UImage 与 RGB 裸数据的相互转换的更多相关文章

  1. iOS 直播-获取音频(视频)数据

    iOS 直播-获取音频(视频)数据 // // ViewController.m // capture-test // // Created by caoxu on 16/6/3. // Copyri ...

  2. iOS开发之JSON格式数据的生成与解析

    本文将从四个方面对IOS开发中JSON格式数据的生成与解析进行讲解: 一.JSON是什么? 二.我们为什么要用JSON格式的数据? 三.如何生成JSON格式的数据? 四.如何解析JSON格式的数据? ...

  3. iOS五种本地缓存数据方式

    iOS五种本地缓存数据方式   iOS本地缓存数据方式有五种:前言 1.直接写文件方式:可以存储的对象有NSString.NSArray.NSDictionary.NSData.NSNumber,数据 ...

  4. 关于iOS去除数组中重复数据的几种方法

    关于iOS去除数组中重复数据的几种方法   在工作工程中我们不必要会遇到,在数组中有重复数据的时候,如何去除重复的数据呢? 第一种:利用NSDictionary的AllKeys(AllValues)方 ...

  5. iOS中使用RSA对数据进行加密解密

    RSA算法是一种非对称加密算法,常被用于加密数据传输.如果配合上数字摘要算法, 也可以用于文件签名. 本文将讨论如何在iOS中使用RSA传输加密数据. 本文环境 mac os openssl-1.0. ...

  6. RGB图像数据字符叠加,图像压缩(ijl库),YUV转RGB

    jackyhwei 发布于 2010-01-01 12:02 点击:3218次  来自:CSDN.NET 一些非常有用的图像格式转换及使用的源代码,包括RGB图像数据字符叠加,图像压缩(ijl库),Y ...

  7. vc/mfc获取rgb图像数据后动态显示及保存图片的方法

    vc/mfc获取rgb图像数据后动态显示及保存图片的方法 该情况可用于视频通信中获取的位图数据回放显示或显示摄像头捕获的本地图像 第一种方法 #include<vfw.h> 加载 vfw3 ...

  8. iOS开发网络篇—JSON数据的解析

    iOS开发网络篇—JSON数据的解析 iOS开发网络篇—JSON介绍 一.什么是JSON JSON是一种轻量级的数据格式,一般用于数据交互 服务器返回给客户端的数据,一般都是JSON格式或者XML格式 ...

  9. Linux Bash 脚本:自己定义延迟代码块(裸数据保存方案)

    结合 alias 和 read 使用方法.能够保存一些将要延迟执行的脚本,或者裸数据(字符串不被扩展)到一个变量中.以备后用. $ alias BEGIN='read -d "" ...

随机推荐

  1. 【最大流ISAP】洛谷P3376模板题

    题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行 ...

  2. OpenCV2.4.9 Qt5.3.1 开发环境配置错误原因与解决方案

    问题原因与解决办法 A.配置完成后,示例程序无法正常显示图片且程序无法运行 出现原因:环境变量未正确配置 解决办法:检查环境变量,添加缺失的环境变量 B.出"未定义的引用..."类 ...

  3. Django-常用模板标签及过滤器

    常用模板标签及过滤器 标签和过滤器完整介绍 https://docs.djangoproject.com/en/1.11/ref/templates/builtins/ 模板的组成 HTML代码+ 逻 ...

  4. 【干货】分享几个写 demo 的思路

    好久没有动笔,最近发现了一个新的写 demo 的思路,仔细一想,自己仿佛积累了不少写 demo 的思路和想法,总结一下,抛砖引玉. 本文所说 demo 主要分以下三种: 本地 demo 外链 demo ...

  5. LVS三种模式分析(超详细)

    1.DR模式:(Direct Routing)直接路由模式 DR模式的网络拓扑: DR模式的工作过程: 1.当一个client发送一个WEB请求到VIP,LVS服务器根据VIP选择对应的real-se ...

  6. 成功破解邻居的Wifi密码

    // 这是一篇导入进来的旧博客,可能有时效性问题. 默认配置的路由器,8位以下密码,黑客几分钟就可以破解.以前用自己的路由器做过实验,这次真正实践成功.环境:Kali Linux工具集:aircrac ...

  7. 在mac下使用终端命令通过ssh协议连接远程linux系统,代替windows的putty

    指令:ssh username@server.address.com 事例:wangmingdeMacBook-Pro:~ xxxxxxxxxx$ ssh root@XXXX.net The auth ...

  8. Inception服务的安装以及使用Python 3 实现MySQL的审计

    Inception服务的安装以及使用Python实现MySQL的审计 Bison是Inception服务所依赖的包之一,但是某些Linux版本已安装的Bison,或者是通过yum安装的Bison,通常 ...

  9. Codeforces Round #328 (Div. 2)_A. PawnChess

    A. PawnChess time limit per test 1 second memory limit per test 256 megabytes input standard input o ...

  10. css3滤镜Filter使用

    Filter主要用于图片,SVG等元素上,其默认值是none,有以下10个filter-function值可选: grayscale(灰度)效果类似于PS中的去色或者黑白 blur(模糊)效果类似于P ...