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 "" ...
随机推荐
- 老版VC++线程池
在一般的设计中,当需要一个线程时,就创建一个,但是当线程过多时可能会影响系统的整体效率,这个性能的下降主要体现在:当线程过多时在线程间来回切换需要花费时间,而频繁的创建和销毁线程也需要花费额外的机器指 ...
- 云服务器 远程mysql 无法连接
问题:mysql不管是用免安装版的,还是用直接安装的,还是用phpStudy直接发布的mysql服务.都只能用localhost登录,不能用服务器的ip进行远程访问 遇到这个问题.按照网上大家介绍的方 ...
- IntelliJ IDEA 教程(1)
过完年,新的学习阶段又开始了.星爷的电影票还没还,国民岳父(韩寒)的礼钱也没送,王老板说再立一个小目标,马老板说我不在乎钱...学习还得继续. IntelliJ Idea 简称IDEA,是java语言 ...
- d3 画地图终极自适应大小方案
d3,v4以前用d3画地图的时候,为了让地图差不多正好画在容器的上下左右正中间,不得不慢慢的这样调: const projection = d3.geoMercator() .center([108. ...
- Java多线程与并发编程学习
一.线程三大特性 多线程有三大特性,原子性.可见性.有序性 1.1 什么是原子性 即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行.一个很经典的例子就是银行账户转账 ...
- 微信app支付(android端+java后台)
本文讲解使用微信支付接口完成在android开发的原生态app中完成微信支付功能, 文章具体讲解了前端android如何集成微信支付功能以及后台如何组装前端需要支付信息, 话不多话, 具体看文章内容吧 ...
- 2016广东工业大学新生杯决赛网络同步赛暨全国新生邀请赛 题解&源码
Problem A: pigofzhou的巧克力棒 Description 众所周知,pigofzhou有许多妹子.有一天,pigofzhou得到了一根巧克力棒,他想把这根巧克力棒分给他的妹子们.具体 ...
- UVA 1030 - Image Is Everything【模拟+思维+迭代更新】
题目链接:uva 1030 - Image Is Everything 题目大意:有一个最大为n*n*n的立方体的一个不规整立体,由若干个1*1*1的小正方体构成(每一个小正方体被涂成不同的颜色),给 ...
- [bzoj2157]旅游 (lct)
这个应该也算裸的模板题吧..主要是边权的问题,对于每条边u->v,我们可以新建一个节点代替他,把边的信息弄到新的点上,就变成u->x->v了... 当然了这样的话要防止u和v这些没用 ...
- 使用Redis和jackson操作json中遇到的坑
前言(可以略过) 最近在开发一个智能电表的管理系统,与常规的面向业务的系统不同.智能电表特点是每30分钟会向服务器发一次请求,报道自己目前的电表情况.然后服务器根据电表情况统计此电表的电量使用情况,包 ...