iOS UImage 与 RGB 裸数据的相互转换
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. 总的来说,这个和我们之前的那一套原理是一样的,应该说这样是更新式的做法,推荐的做法。
参考
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 裸数据的相互转换的更多相关文章
- iOS 直播-获取音频(视频)数据
iOS 直播-获取音频(视频)数据 // // ViewController.m // capture-test // // Created by caoxu on 16/6/3. // Copyri ...
- iOS开发之JSON格式数据的生成与解析
本文将从四个方面对IOS开发中JSON格式数据的生成与解析进行讲解: 一.JSON是什么? 二.我们为什么要用JSON格式的数据? 三.如何生成JSON格式的数据? 四.如何解析JSON格式的数据? ...
- iOS五种本地缓存数据方式
iOS五种本地缓存数据方式 iOS本地缓存数据方式有五种:前言 1.直接写文件方式:可以存储的对象有NSString.NSArray.NSDictionary.NSData.NSNumber,数据 ...
- 关于iOS去除数组中重复数据的几种方法
关于iOS去除数组中重复数据的几种方法 在工作工程中我们不必要会遇到,在数组中有重复数据的时候,如何去除重复的数据呢? 第一种:利用NSDictionary的AllKeys(AllValues)方 ...
- iOS中使用RSA对数据进行加密解密
RSA算法是一种非对称加密算法,常被用于加密数据传输.如果配合上数字摘要算法, 也可以用于文件签名. 本文将讨论如何在iOS中使用RSA传输加密数据. 本文环境 mac os openssl-1.0. ...
- RGB图像数据字符叠加,图像压缩(ijl库),YUV转RGB
jackyhwei 发布于 2010-01-01 12:02 点击:3218次 来自:CSDN.NET 一些非常有用的图像格式转换及使用的源代码,包括RGB图像数据字符叠加,图像压缩(ijl库),Y ...
- vc/mfc获取rgb图像数据后动态显示及保存图片的方法
vc/mfc获取rgb图像数据后动态显示及保存图片的方法 该情况可用于视频通信中获取的位图数据回放显示或显示摄像头捕获的本地图像 第一种方法 #include<vfw.h> 加载 vfw3 ...
- iOS开发网络篇—JSON数据的解析
iOS开发网络篇—JSON数据的解析 iOS开发网络篇—JSON介绍 一.什么是JSON JSON是一种轻量级的数据格式,一般用于数据交互 服务器返回给客户端的数据,一般都是JSON格式或者XML格式 ...
- Linux Bash 脚本:自己定义延迟代码块(裸数据保存方案)
结合 alias 和 read 使用方法.能够保存一些将要延迟执行的脚本,或者裸数据(字符串不被扩展)到一个变量中.以备后用. $ alias BEGIN='read -d "" ...
随机推荐
- Centos6.4三种更改hostname的方法之间的对比
首先,利用hostname命令查看一下当前主机的主机名,在终端输入hostname,会发现显示的是完整的主机名称(主机名.域名),其中主机名与进入终端后:登录名@主机名,显示的一致,如下图所示: 其次 ...
- python通过getopt模块获取执行命令参数
python脚本和shell脚本一样可以获取命令行的参数,根据不同的参数,执行不同的逻辑处理. 通常我们可以通过getopt模块获得不同的执行命令和参数. 下面我通过新建一个test.py的脚本解释下 ...
- Mac搭建cocos2dx+Android studio开发环境以及AnySDK的集成
配置环境: mac osx 10.12.6 cocos2dx 3.14 Android studio 2.3 目标: 在mac上配置cocos Android开发环境,接入AnySDK 配置: 1.安 ...
- 重构仿vue社区代码
半年前根据vue社区提供的开放api制作的vue社区,功能大部分和原vue社区一样,还一些功能没做完,项目是半年前做的,已经过了半年,当时因为公司一个项目打算要vue来重构,提取小试牛刀做了个dom试 ...
- JavaScript for in的缺陷
for in 语句用来列举对象的属性(成员),如下 1 2 3 4 5 6 7 var obj = { name:"jack", getName:function(){ ...
- 【Java学习笔记之二十】final关键字在Java继承中的用法小结
谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法. ...
- UESTC 1584 Washi与Sonochi的约定【树状数组裸题+排序】
题目链接:UESTC 1584 Washi与Sonochi的约定 题意:在二维平面上,某个点的ranked被定义为x坐标不大于其x坐标,且y坐标不大于其y坐标的怪物的数量.(不含其自身),要求输出n行 ...
- [51nod1502]苹果曼和纸
苹果曼有很大的一张纸.这张纸的形状是1×n的长方形.你的任务是帮助苹果曼来折叠这一张纸.有一些操作,这些操作有如下两个种形式: 1. 把这张纸在第pi个位置对折.经过对折后,左边的1×pi部分会盖到右 ...
- BZOJ2282: [Sdoi2011]消防
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2282 答案一定是在直径上的一段,然后答案一定不会小于不在直径上的点到直径的距离(要是可以的话那 ...
- HDU-5157Harry and magic string
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5157 先从后往前插点,在构造回文树时,让cnt[i]+=cnt[fail[i]],然后维护一个后缀和a. ...