求助,使用cgcontextdrawpathImage内存迅速上升问题

最近在做一个相册类的应用,但是在内存方面一直出现这一些问题,原因就是有着大量图片显示和存取,这里整理一下查到的资料,列举一下造成内存警告的潜在原因
1.imageName创建UIimage的时候实际上只是在Bundle内查找到文件名,然后把文件名返回,并没有对文件惊醒读取和解码,当UIImage第一次显示在屏幕的时候解码方法才会被调用,并且会保存到一个全局缓存当中,且APP第一次退出或者受到内存警告的时候才会被清空。!!!
2.imageWithData同样也不能避免缓存
3.如何避免缓存,把图片用 CGContextDrawImage() 绘制到画布上,然后把画布的数据取出来当作图片。
4.cell重用问题,老生常谈,要注意的就是footer header的复用,
- (nullable __kindof UITableViewHeaderFooterView *)dequeueReusableHeaderFooterViewWithIdentifier:(NSString *)identifier
究其原因,一方面是相片本身大小,iphone相机返回的照片都在2M左右,而每个app如果内存超过20M就会爆出内存警告,解决办法,压缩图片大小:
UIImageJPEGRepresentation(image1, kCompressionQuality)
阅读(...) 评论()IOS&View以及内存位图的坐标_shindow_新浪博客
IOS&View以及内存位图的坐标
一。UIView的CGContextRef
当创建一个View,并把其添加了试图的子View时,画一条线:效果如图1-1:
1-1
​坐标没有旋转,正常。文本如下图1-2所示:
1-2
很明显文本还是倒立的。
因此对于View的CGContextRef来说,坐标是以左上角为起点,而文本倒立,坐标也是按左上角计算的。​
​但是有一个函数很奇怪CGContextDrawImage,源图如图1-3所示:
1-3
​如果拷贝到屏幕上,屏幕没有旋转坐标的话则应直接拷贝,而按上面我们解释的UIView的CGContextRef的坐标应按左上角。可是拷贝到屏幕上效果图如图1-4所示:
1-4
​为了进一步验证到底是生成的UIImage坐标变化了还是调用CGContextDrawImage使得坐标变化了,因此把UIImage写成一张图片,最后验证了UIImage生成的图片还是和原始图片一致,所以可以确定CGContextDrawImage有问题。
二。内存位图的CGContextRef​
把一张带有直线(0,0)到(200,200)的图片加载内存位图中,并在内存位图上绘制一条(0,0)到(100,200)的线段,然后保存成图片,效果图(图片)如图1-5所示:
1-5
可以看出在内存位图上绘制内容时,它是以左下角为坐标(0,0)的,然后拷贝到屏幕上,经过了CGContextDrawImage又转成左上角了,看起来貌似就对了。
接着试一下文本,绘制文本在内存位图中,保存成图片效果图如下1-6:
1-6
​可以看到内存位图中的文本是正的,并且坐标是按左下角。那么可以想象,如果拷贝到屏幕上,那必然文本坐标是按左上角,但是文本也跟着倒转了。
所以根据以上情况可以总结如下,一般指定一个位置(x,y)要么是按左上角要么是按左下角。UIView和创建的内存的CGContextRef刚好属于这两种情况,前面一个属于坐标按左上角,内存位图则按左下角,而UIView的文本则是倒转的,而内存位图的文本则没有倒转。
故你想达到在内存位图中绘制的内容正确的拷贝到屏幕上,则需要
1.内存位图文本倒转,UIView的文本倒转即可。
(解释:内存位图文本本身是没有倒转的,并且坐标是左下角,所以通过CGContextDrawImage既可以到达文本与坐标全部转正的效果,而UIView的文本本身倒转,则还需要修改UIView的文本坐标,但是还是有个问题,因为在内存位图中绘制的内容都是倒转的,所以我加载一张图片在内存位图中,那么里面绘制的内容倒转,所以这种方法如果加载了图片,最终会使得图片倒转)。
​2.内存位图坐标倒转,UIView的坐标倒转,UIView的文本倒转
(解释:内存位图坐标倒转了及是正的,那么这样加载的图片就不会有第一种情况,而CGContextDrawImage本身会有个倒转,所以还需要把UIView的坐标倒转,拷贝才会成功,但这样就是的之后使用的UIView的坐标有问题了,因为是倒转了的)
通过以上充分说明了,这尼玛真蛋疼。​
博客等级:
博客积分:0
博客访问:20,925
关注人气:0
荣誉徽章:5464人阅读
iOS Quartz 2D(9)
首先看看网上关于Quartz 2D的一段话:
Quartz&2D 绘制模型定义了两种独立的坐标空间:用户空间(用于表现文档页)和设备空间(用于表现设备的本地分辨率)。用户坐标空间用浮点数表示坐标,与设备空间的像素分辨率没有关系。当我们需要一个点或者显示文档时,&Quartz会将用户空间坐标系统映射到设备空间坐标系统。
下面说下自己的个人见解和分析:
由于坐标空间分为用户空间和设备空间两种,所以坐标系也分为两种。一种是CGContext绘图时的坐标系,以左下角为原点,y正轴向上,x正轴向右。另一种是设备空间的坐标系,以左上角为原点,y正轴向下,x正轴向右。
其中用户空间有一个绘图上下文,可以将其想象成一张画布。如果要在当前上下文中画图片,就要使用CGContextDrawImage方法,先看看直接使用该方法的情况:
- (void)drawRect:(CGRect)rect
CGContextRef context = UIGraphicsGetCurrentContext();
UIImage *image = [UIImage imageNamed:@&addText.png&];
CGRect rect1 = CGRectMake(100.0, 100.0, 100.0, 100.0);
CGContextDrawImage(context, rect1, [image CGImage]);
drawImage(context, [image CGImage], rect1);
原来的图片为:
运行结果如下:
每个方格为100 * 100的规格。也就是image的位置是(100, 100, 100, 100),但是图片反过来了。如何在上下文中绘图,才能正确地映射到设备空间中?需要先做一些变换:
- (void)drawRect:(CGRect)rect
CGContextRef context = UIGraphicsGetCurrentContext();
UIImage *image = [UIImage imageNamed:@&addText.png&];
CGRect rect1 = CGRectMake(100.0, 100.0, 100.0, 100.0);
CGContextDrawImage(context, rect1, [image CGImage]);
drawImage(context, [image CGImage], rect1);
void drawImage(CGContextRef context, CGImageRef image , CGRect rect){
CGContextSaveGState(context);
CGContextTranslateCTM(context, rect.origin.x, rect.origin.y);
CGContextTranslateCTM(context, 0, rect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, -rect.origin.x, -rect.origin.y);
CGContextDrawImage(context, rect, image);
CGContextRestoreGState(context);
运行结果为:
之后来分析一下变化过程,先看看用户空间到设备空间的变换:
再来看看以上代码变换的详细过程,假设要在设备空间的(a, b, c, d)位置画一个矩形。
1.原来的画布
2.平移画布:CGContextTranslateCTM(context, rect.origin.x,
rect.origin.y)
3.平移画布:CGContextTranslateCTM(context,0, rect.size.height);
4.翻转画布:CGContextScaleCTM(context,1.0,
5.平移画布:CGContextTranslateCTM(context, -rect.origin.x, -rect.origin.y);
在画布上参照画布的坐标系(蓝色的坐标系)的(a, b, c, d)位置绘图:CGContextDrawImage(context, rect, image);
6.将用户空间中的图像映射到设备空间中
其中画布就是一个绘图上下文,绘图操作的结果在这里展现。用户空间有一个属于自己的坐标系,画布有一个独立于用户空间的坐标系,设备空间也有自己的坐标系,其中画布的坐标系是可变的,例如平移,翻转等,另外两个是固定的。
在进行上下文变换时,画布的位置是变化的,注意画布的坐标系翻转后,往(-c, -d)方向作平移,是相对自己的坐标系做平移的(即蓝色的坐标系),而不是原来黑色标识的用户空间坐标系。
同样地,在画布上画图时就是根据画布自己的坐标系在上面画图。
在画布上画好图后,将图像从用户空间映射到设备空间时,参照的坐标系是用户空间坐标系和设备空间坐标系。
在创建PDF文档时,PDF上下文和输出的PDF文档的坐标系是一致的。
以上部分参考了:
代码参考了:
以上经过Demo的测试和分析,分析过程的图是自己做的,纯属个人的一些见解。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:795633次
积分:9151
积分:9151
排名:第1707名
原创:172篇
转载:66篇
评论:98条
(8)(1)(1)(4)(7)(25)(7)(17)(13)(22)(32)(7)(18)(36)(16)(9)(13)(2)(1)在 iOS 中与 CGContextRef 的内存泄漏
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.
我有一套需要图像存储在 UIImageView 中,修改的它的内容将复制到一个新的映像为不同的 UIImageView 的代码。问题是这段代码当我分析项目时总是接收来自我的编译器的内存警告。我试图以各种方式在执行这段代码,我总是最终接受一种不同的内存警告。从编译器输出说"对 'CGBitMapContextCreateImage' 函数的调用返回 + 1 保留计数的核心基础对象",而这会导致要保留计数为 + 1 的图像对象。如果我 autorelease 图像对象,编译器有警告到多次调用 autorelease 和图像对象最初有保留计数为 0 的记忆力。
这两个编译器警告是不是矛盾吗?如何解决此代码以确保没有内存泄漏发生?
-(UIImage *) makeImageLight{
UIImage * image = self.masterImage.
NSUInteger width = image.size.
NSUInteger height = image.size.
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = width * bytesPerP
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bmContext = CGBitmapContextCreate(NULL, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(bmContext, (CGRect){.origin.x = 0.0f, .origin.y = 0.0f, .size.width = width, .size.height = height}, image.CGImage);
UInt8* data = (UInt8*)CGBitmapContextGetData(bmContext);
for (size_t i = 0; i & CGBitmapContextGetWidth(bmContext); i++)
for (size_t j = 0; j & CGBitmapContextGetHeight(bmContext); j++)
int pixel = j * CGBitmapContextGetWidth(bmContext) +
pixel = pixel * 4;
UInt8 red = data[pixel + 1];
// If you need this info, enable it
UInt8 green = data[pixel + 2]; // If you need this info, enable it
UInt8 blue = data[pixel + 3];
// If you need this info, enable it
red = ((255 - red) * .3) +
green = ((255 - green) * .3) +
data[pixel + 1] =
data[pixel + 2] =
data[pixel + 3] =
// memory warning occurs in the following line:
image = [UIImage imageWithCGImage:CGBitmapContextCreateImage(bmContext)];
CGContextRelease(bmContext);
别管,我通过添加以下代码,以释放从上下文中创建的 CGImage 固定它:
CGImageRef imageRef = CGBitmapContextCreateImage(bmContext);
image = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
解决方法 1:
您使用 CGBitmapContextCreateImage() 创建 CGImage,但你还没释放那 CGImage
您需要拆分 UIImage 创建行,如下所示:
CGImageRef cgimage = CGBitmapContextCreateImage(bmContext);
image = [UIImage imageWithCGImage:cgimage];
CGImageRelease(cgimage);}

我要回帖

更多关于 怎么在企业内迅速上升 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信