
当用到二进制传输的时候,一定会用bytebuffer这个类,它是buffer接口的子类。
ByteBuffer byteBuffer = ByteBufferallocate(6);
虽然使用allocate方法创建的缓冲区并不是一次性地分配内存空间,但我们可以从用户地角度将一个缓冲区想象成一个长度为capacity的数组。当缓冲区创建后,和数组一样,缓冲区的大小(capacity值)将无法改变,也无法访问缓冲区外的数据
既然缓冲区和数组类似,那么缓冲区也应该象数组一样可以标识当前的位置。缓冲区的position方法为我们提供了这个功能。position方法有两种重载形式,它们的定义如下:
public final int position()
public final Buffer position(int newPosition)
第一个重载形式用来获取缓冲区的当前位置。在创建缓冲区后,position的初始值是0,也就是缓冲区第一个元素的位置。当从缓冲区读取一个元素后,position的值加1我们从这一点可以看出,position方法返回的位置就是当前可以读取的元素的位置。position的取值范围从0到capacity – 1如果position的值等于capacity,说明缓冲区当前已经没有数据可读了。
在大多数情况下不需要直接控制缓冲区的位置。缓冲区类提供的用于读写数据的方法可以自动地设置缓冲区的当前位置。在缓冲区类中,get和put方法用于读写缓冲区中的数据。 每当put方法向缓冲区写入一个数据后,缓冲区的当前位置都会加1如果缓冲区的当前位置已经等于capacity,调用put方法就会抛出一个javanioBufferOverflowException异常。在缓冲区未初赋值的区域将被0填充。使用get方法可以得到缓冲区当前位置的数据,并使缓冲区的当前位置加1和put方法一样,[/color]在缓冲区当前位置等于capacity时使用get方法也会抛出javanioBufferOverflowException异常
可以使用position方法将当前位置移到缓冲区的任何位置。缓冲区除了position和capacity外,还提供了一个标识limit来限制缓冲区可访问的范围。[color=red]在初始状态下,缓冲区的limit和capacity值相同。但limit和capacity的区别是limit可以通过limit方法进行设置,而capacity在创建缓冲区时就已经指定了,并且不能改变。limit还可以表示缓冲区中实际的数据量
while(byteBufferhasRemaining()) // 枚举byteBuffer中的数据,常用判断
byteBufferflip(); // 将limit设为position即2,然后将position设置为 0
Protocol Buffer是Google出品的一种轻量高效的结构化数据存储格式
可以直接使用 brew install swift-protobuf 安装
也可以按如下步骤配置:
> 之前网上搜索到很多的方法,但是会出问题,这里分享下! -(UIImage )cvsamplebufferrefToimage:(CVImageBufferRef)imageBuffer{ CVPixelBufferLockBaseAddress(imageBuffer, 0); void baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); size_t width = CVPixelBufferGetWidth(imageBuffer); size_t height = CVPixelBufferGetHeight(imageBuffer); size_t bufferSize = CVPixelBufferGetDataSize(imageBuffer); size_t bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, 0); // Create a device-dependent gray color space CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); // Create a bitmap graphics context with the sample buffer data CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGImageAlphaNone); // Create a Quartz image from the pixel data in the bitmap graphics context CGImageRef quartzImage = CGBitmapContextCreateImage(context); // Free up the context and color space CGContextRelease(context); CGColorSpaceRelease(colorSpace); // Create an image object from the Quartz image UIImage image = [UIImage imageWithCGImage:quartzImage]; return image; } 前些天,程序出现了一个bug:数据莫名的丢失。由于业务复杂,折腾了好久才解决,在网上也没有找的答案, 故,记下来。 例如 本着不修改第三方库的原则,项目中使用了 YYModel。添加了个分类 GPBMessage (YYModel) 在 Json 转Model 时过滤掉has , _count 先这样解决了问题。
在iOS开发中, (UIImage) 是我们在开发中,占用手机 内存 比较大的对象,如果在运行过程中,内存占用过大,对 电池寿命 会造成影响,如果超过了 内存占用的最大值 ,会造成App的 crash 。这篇文章从 的加载 原理和 SDWebImage 的源码实现的角度来介绍加载。
在iOS中使用 UIImage 和 UIImageView 来记载,他俩遵守经典的 MVC 架构, UIImage 相当于 Model , UIImageView 相当于 View :
UIImage 负责 加载 , UIImageView 负责 渲染 。
的渲染流程分为 3个阶段 : 加载(Load),解码(Decoder)和渲染(Render)
在每个阶段都会有相对应的 缓冲区 : 数据缓冲区(DataBuffer),图像缓冲区(imageBuffer)和帧缓冲区(framebuffer) 。
我们以加载一个的尺寸为: 2048 px 1536 px ,在磁盘上的大小为: 590kb 的为例,来分析前两个阶段的缓冲区。
DataBuffer 只是一种包含 一系列字节 的缓冲区。通常以某些 元数据 开头, 元数据 描述了存储在数据缓冲区中的图像大小,包含图形数据本身, 图像数据以某种形式编码 如 JPEG压缩或PNG,这意味着, 该字节并不直接描述图像中像素的任何内容 。此时的 DataBuffer 大小为 590kb 。
在 SDWebImage 中,加载完成后,在 sd_imageFormatForImageData 的方法中,是通过 DataBuffer 的 第一个字节 来判断的格式的。
在 加载 完后,需要将 Data Buffer 的 JPEG,PNG或其他编码的数据 ,转换为 每个像素 的 图像信息 ,这个过程,称为 Decoder(解码) ,将 像素信息 存放在 ImageBuffer 。
占用的内存大小与 图像的尺寸有关 ,与它的 文件大小无关 ,在iOS SRGB 显示格式中 (4byte空间显示一个像素) ,如果解析所有的像素,需要 2048 px 1536 px 4 byte/px = 10MB 的空间,此时的 ImageBuffer 的大小为 10MB 。
在 ImageBuffer 解析完后,提交给 frameBuffer 进行渲染显示。
总的来说,加载过程和消耗的内存如下图所示:
在 Xcode 工程中,当push新页面的时候,只加载一个。
加载前内存值:
加载后内存值:
大多数情况下,我们并不需要如此高精度的显示,占用了这么多的内存,能否减少加载时占用的内存值呢
在苹果官方文档中,建议我们使用 向下采样(Downsampleing) 的技术,来加载,减少 ImageBuffer 的大小。
方法如下:
我们来测试一下:
加载之前时是 13M ,加载之后是 17M ,效果是很明显的,节省了大约 5M 的内存空间。
在对进行压缩时,我们应首选向下采样技术 。
在 SDWebIamge 中,一共有3种类型的解码器: SDImageIOCoder, SDImageGIFCoder, SDImageAPNGCoder ,根据 DataBuffer 的编码类型,使用相对应的编码器。
在 -(UIImage )decodedImageWithData:(NSData )data 方法中,配置解码参数,开始进行解码 *** 作。
在 + (UIImage )createFrameAtIndex:(NSUInteger)index source:(CGImageSourceRef)source scale:(CGFloat)scale preserveAspectRatio:(BOOL)preserveAspectRatio thumbnailSize:(CGSize)thumbnailSize options:(NSDictionary )options 中,完成图像解码
在 iOS中,渲染格式有4种
正确的思路是: 不选择渲染格式,让渲染格式选择你 。
使用 UIGraphicsImageRender 来替换 UIGraphicsBeginImageContextWithOptions ,前者在 iOS12 以后,会自动选择渲染格式,后者默认都会选择 SRGB Format 。
此时,系统为自动选择 Alpha 8 Format 格式,内容空间占用,将会减少 75% 。
在需要绘制带有子视图的View时,不使用 draw(rect:) 方法,使用 系统的View属性 或者 添加子视图 的方式,将绘制工作交给系统来处理。
背景色直接通过 UIViewbackgroundColor 设置,而非使用 draw(rect:)
我们在开发中,一般会对进行 子线程异步加载 ,在后台进行 解码和下采样 。在列表中,有时会加载很多,此时应该注意 线程爆炸 问题。
当我们要求 系统去做比CPU能够做的工作更多的工作时 就会发生这种情况,比如我们要显示 8张 ,但我们只有 两个CPU ,就不能一次完成所有这些工作,无法在不存在的CPU上进行并行处理, 为了避免向一个全局队列中异步的分配任务时发生死锁 , GCD 将创建新线程来捕捉我们要求它所做的工作,然后CPU将花费大量时间,在这些 线程 之间进行 切换 ,尝试在所有工作上取得我们要求 *** 作系统为我们做的 渐进式进展 ,在这些线程之间 不停切换 ,实际上是相当大的开销,现在 不是简单地将工作分派到全局异步队列之一 ,而是 创建一个串行队列 ,在预取的方法中,异步的将工作分派到该队列,它的确意味着单个图像的加载,可能要比以前晚才能开始取得进展,但CPU将花费更少的时间,在它可以做的小任务之间来回切换。
在 SDWebImage 中,解码的队列 _coderQueuemaxConcurrentOperationCount = 1 就是一个串行队列。这样就很好的解决了 多异步解码 时, 线程爆炸 问题。
以上就是关于ios中有没有类似buffer的缓冲区域全部的内容,包括:ios中有没有类似buffer的缓冲区域、iOS ProtocolBuffer环境配置与使用、iOS硬解后获取的CVImageBufferRef转uiimage等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)