Cocos2dx在IOS平台中将截屏保存到到手机相册
来源:互联网 发布:网络棋牌游戏 编辑:程序博客网 时间:2024/04/29 06:18
最近使用Cocos2dx 2.2.3进行IOS游戏开发,碰到了关于截屏路径的一个问题,cocos2dx本身自带了截屏的功能,代码如下:
CCSize size = CCDirector::sharedDirector()->getWinSize(); CCRenderTexture* renderTexture = CCRenderTexture::create(size.width, size.height); CCScene* curScene = CCDirector::sharedDirector()->getRunningScene(); renderTexture->begin(); curScene->visit(); renderTexture->end(); renderTexture->saveToFile("curScene.png", kCCImageFormatPNG);
但是saveToFile()函数在IOS下面默认保存的路径是应用程序的Document目录,用户无法在自己的相册中进行查看,并且IOS下的权限控制很严格,想要访问相册的目录估计是无法在游戏内部进行了,于是在上网搜索半天无果之后,只好通过C++和OC混合编译,调用IOS的API来进行。苦于没有IOS开发基础,上网搜索了一段OC代码:
-(UIImage *) glToUIImage { NSInteger myDataLength = 1024 * 768 * 4; // allocate array and read pixels into it. GLubyte *buffer = (GLubyte *) malloc(myDataLength); glReadPixels(0, 0, 1024, 768, GL_RGBA, GL_UNSIGNED_BYTE, buffer); // gl renders "upside down" so swap top to bottom into new array. // there's gotta be a better way, but this works. GLubyte *buffer2 = (GLubyte *) malloc(myDataLength); for(int y = 0; y <768; y++) { for(int x = 0; x <1024 * 4; x++) { buffer2[(767 - y) * 1024 * 4 + x] = buffer[y * 4 * 1024 + x]; } } // make data provider with data. CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL); // prep the ingredients int bitsPerComponent = 8; int bitsPerPixel = 32; int bytesPerRow = 4 * 1024; CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; // make the cgimage CGImageRef imageRef = CGImageCreate(1024, 768, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); // then make the uiimage from that UIImage *myImage = [UIImage imageWithCGImage:imageRef]; return myImage; UIImageWriteToSavedPhotosAlbum(myImage, self, nil, nil);}
这段代码通过glReadPixels来读取屏幕的像素值,然后转换为UIImage对象,最后通过UIImageWriteToSavedPhotosAlbum()保存到相册中间,只需要稍稍修改一下屏幕的尺寸能使用。在OC和C++混编的时候还有一些小问题要注意,就是在C++中包含OC头文件的时候不能直接包含:
#include "ScreenShot.h"
这样会报错,必须加上预编译的处理:
#ifdef __OBJC__#include "ScreenShot.h"#endif
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) [ScreenShot saveImage];#else
到了这里我以为大功告成了,但是试验之后发现在模拟器中完美截屏,真机测试的时候却发现截图全是黑的,所有像素都是0。谷歌一番之后,找到了问题所在,stackoverflow上的原问题,glReadPixels读取的是缓冲区中的内容,而在ios6.0之后,系统会将已经显示过的内容从缓冲区中清空,而在游戏中调用glReadPixels时屏幕的内容可能已经显示过了,这是Cocos2dx内部的机制,我们无法更改,导致无法正确截图。
仔细思考一下,其实我们调用OC代码的部分也只有保存到相册的那一部分而已,至于截图,完全可以用Cocos2dx自带的功能,所以只要能获取renderTexture的像素信息,再在OC部分中转换为UIImage保存即可,由此诞生了最终版本:
//C++部分的代码 CCSize size = CCDirector::sharedDirector()->getWinSize(); CCRenderTexture* renderTexture = CCRenderTexture::create(size.width, size.height); CCScene* curScene = CCDirector::sharedDirector()->getRunningScene(); renderTexture->begin(); curScene->visit(); renderTexture->end(); CCImage* image = renderTexture->newCCImage();#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) [ScreenShot saveImage:image->getData() width:image->getWidth() height:image->getHeight()];#else renderTexture->saveToFile("curScene.png", kCCImageFormatPNG);#endif
//OC部分的代码@interface ScreenShot : NSObject+(void) saveImage: (GLubyte*)imageData width: (int)width height:(int)height;@end@implementation ScreenShot+(void) saveImage: (GLubyte*)imageData width: (int)width height:(int)height{ NSInteger myDataLength = width * height * 4; // make data provider with data. CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, imageData, myDataLength, NULL); // prep the ingredients int bitsPerComponent = 8; int bitsPerPixel = 32; int bytesPerRow = 4 * width; CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; // make the cgimage CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); // then make the uiimage from that UIImage *myImage = [UIImage imageWithCGImage:imageRef]; UIImageWriteToSavedPhotosAlbum(myImage, nil, nil, nil);}@end
通过renderTexture->newCCImage()->getData()获取unsigned char* 像素数据,然后再saveImage函数中转换为UIImage对象最后保存,由此实现在IOS平台中将截图保存到相册的功能。
- Cocos2dx在IOS平台中将截屏保存到到手机相册
- cocos2dx截屏保存到手机内存卡
- iOS 任意页面摇一摇并截屏保存到相册
- 在手机相册(ios设备相册)中创建相册
- Android中将图片从相册取出且获取到图片在手机中的地址
- 42.截屏保存到相册
- iOS 生成带 logo 的二维码,区域截屏保存至相册(小功能二连发 (一))
- cocos2dx-lua ios系统访问系统相册
- 在unity中将图片保存在移动平台下(Android和IOS)
- iOS中将图片保存到自定义相册中
- Cocos2dx IOS平台相关代码
- cocos2dx 跨平台iOS 求助
- cocos2dx 截取屏幕保存至手机相册中
- iOS 访问手机相册以及从相册获取相片
- iOS访问手机自带的相册
- ios将Image保存到手机相册
- iOS 手机相册英文字母的设定
- 在手机相册中保存图片失败
- 【BZOJ】【P3117】【NOI1999】【内存分配】【题解】
- CentOS 6.5 PYPI本地源制作
- Bug无法启动
- c++的小摘要
- 1.2虚拟机的基本操作
- Cocos2dx在IOS平台中将截屏保存到到手机相册
- 控制台 - 网络管理之华为交换机 S系列端口限速
- ASP.NET Web API已支持OData v4.0,WCF不会
- hdu4362 dp + 单调队列优化
- 二:4、yum install varnish
- watch dog不起作用的问题
- 信号量与PV操作
- GRUB2 添加WINDOWS7启动项
- hdu2586How far away ?