SDWebImage-解码、压缩图像

article/2025/10/8 2:13:07

一、简单介绍

研究了下SDWebImage的源码,借鉴了别人的一些资料,感觉逐渐的明白的一些原理,现在就来记录下。

在我们使用 UIImage 的时候,创建的图片通常不会直接加载到内存,而是在渲染的时候默认在主线程上再进行解码并加载到内存。这就会导致 UIImage 在渲染的时候效率上不是那么高效。为了提高效率所以在SDWebImage中就采取在子线程中进行解码图片。

这里再介绍下为什么创建图像的时候是需要解码的因为一般下载的图片或者是我们手动拖进工程的图片都是PNG 或者JPEG或者是其他格式的图片,这些图片都是经过编码压缩后的图片数据,并不是我们的控件可以直接显示的位图,如果我们直接使用加载渲染图片到手机上的时候,系统默认会在主线程立即进行图片的解码工作,这个过程就是把图片数据解码成可以供给控件直接显示的位图数据,由于这个解码操作比较耗时,并且默认是在主线程进行,所以如果加载过多的图片的话肯定是会发生卡顿现象的。

二、源码分析

首先介绍的是根据data来解码成一个UIImage对象的方法

- (UIImage *)decodedImageWithData:(NSData *)data {if (!data) {return nil;}UIImage *image = [[UIImage alloc] initWithData:data];//如果是MAC端就直接返回image
#if SD_MACreturn image;
#elseif (!image) {return nil;}//不然的话就要去获取数据中图片的方向UIImageOrientation orientation = [[self class] sd_imageOrientationFromImageData:data];//如果图片的方向不是默认向上的话就要去根据其图片信息的方向来重新创建图片if (orientation != UIImageOrientationUp) {image = [[UIImage alloc] initWithCGImage:image.CGImage scale:image.scale orientation:orientation];}return image;
#endif
}

这里再介绍下关于获取图片方向的sd_imageOrientationFromImageData方法,这里面其实就是根据imageData去创建CGImageSourceRef然后去读取其图像的属性

+ (UIImageOrientation)sd_imageOrientationFromImageData:(nonnull NSData *)imageData {UIImageOrientation result = UIImageOrientationUp;//创建从Core Foundation 数据对象中读取的图像源/**参数1:参数2:指定额外创建option字典。我们可以在options字典中包含的键来创建图像源。比如说kCGImageSourceTypeIdentifierHintkCGImageSourceShouldAllowFloatkCGImageSourceShouldCachekCGImageSourceCreateThumbnailFromImageIfAbsentkCGImageSourceCreateThumbnailFromImageAlwayskCGImageSourceThumbnailMaxPixelSizekCGImageSourceCreateThumbnailWithTransform*/CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);if (imageSource) {//调用CGImageSourceCopyPropertiesAtIndex的时候会才去读取图像元数据//返回图像源中指定位置的图像的属性。/**参数1:一个图像的来源参数2:你想要获得的属性的索引。该指数是从零开始的。index参数设置获取第几张图像参数3:可以用来请求其他选项的字典。返回包含与图像相关联的属性的字典。请参见CGImageProperties,以获得可以在字典中使用的属性列表。CGImageProperties引用定义了代表图像I/O框架使用的图像特征的常量。*/CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL);//判断属性存不存在,如果不存在就用默认的UIImageOrientationUp方向if (properties) {//typedef const void *CFTypeRef;CFTypeRef val;NSInteger exifOrientation;//返回与给定键关联的值,这里就是返回方向键值所对应的内容val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation);//如果其存在的话,就去获取if (val) {//将CFNumber对象转换为指定类型的值/**参数1:要检查的CFNumber对象。参数2:指定要返回的数据类型的常量。请参阅CFNumberType以获得可能的值列表。参数3:返回的时候包含数字的值*/CFNumberGetValue(val, kCFNumberNSIntegerType, &exifOrientation);//转换exif中信息的方向到iOS里面的方向result = [SDWebImageCoderHelper imageOrientationFromEXIFOrientation:exifOrientation];} // else - if it's not set it remains at upCFRelease((CFTypeRef) properties);} else {//NSLog(@"NO PROPERTIES, FAIL");}//释放这个图像源CFRelease(imageSource);}//返回结果  return result;
}

这里再介绍的介绍下imageOrientationFromEXIFOrientation的方法,这个方法就是转换一个EXIF信息中图像方向到iOS中的方向说白了就是从NSInteger转换为UIImageOrientationUp这样的枚举值。

// Convert an EXIF image orientation to an iOS one.
+ (UIImageOrientation)imageOrientationFromEXIFOrientation:(NSInteger)exifOrientation {// CGImagePropertyOrientation is available on iOS 8 above. Currently kept for compatibilityUIImageOrientation imageOrientation = UIImageOrientationUp;switch (exifOrientation) {case 1:imageOrientation = UIImageOrientationUp;break;case 3:imageOrientation = UIImageOrientationDown;break;case 8:imageOrientation = UIImageOrientationLeft;break;case 6:imageOrientation = UIImageOrientationRight;break;case 2:imageOrientation = UIImageOrientationUpMirrored;break;case 4:imageOrientation = UIImageOrientationDownMirrored;break;case 5:imageOrientation = UIImageOrientationLeftMirrored;break;case 7:imageOrientation = UIImageOrientationRightMirrored;break;default:break;}return imageOrientation;
}

接下来开始讲下解码图像,在这里面其实刚开始先判断能不能解码图片,这个方法是这样的

+ (BOOL)shouldDecodeImage:(nullable UIImage *)image {// Prevent "CGBitmapContextCreateImage: invalid context 0x0" error//如果图片都为空,那肯定返回的是NOif (image == nil) {return NO;}//不能编码动画图片// do not decode animated imagesif (image.images != nil) {return NO;}CGImageRef imageRef = image.CGImage;BOOL hasAlpha = SDCGImageRefContainsAlpha(imageRef);//不支持解码含有透明度的图片// do not decode images with alphaif (hasAlpha) {return NO;}return YES;
}

回到这个方法,其实主要的过程就是CGBitmapContextCreate创建一个位图上下文→CGContextDrawImage绘制原始位图到上下文→CGBitmapContextCreateImage创建解码后的新位图。

- (nullable UIImage *)sd_decompressedImageWithImage:(nullable UIImage *)image {if (![[self class] shouldDecodeImage:image]) {return image;}// autorelease the bitmap context and all vars to help system to free memory when there are memory warning.// on iOS7, do not forget to call [[SDImageCache sharedImageCache] clearMemory];//新建自动释放池,将bitmap context和临时变量都添加到池中在方法末尾自动释放以防止内存警告@autoreleasepool{//获取传入的UIImage对应的CGImageRef(位图)CGImageRef imageRef = image.CGImage;//获取彩色空间CGColorSpaceRef colorspaceRef = [[self class] colorSpaceForImageRef:imageRef];//获取高和宽size_t width = CGImageGetWidth(imageRef);size_t height = CGImageGetHeight(imageRef);// kCGImageAlphaNone is not supported in CGBitmapContextCreate.// Since the original image here has no alpha info, use kCGImageAlphaNoneSkipLast// to create bitmap graphics contexts without alpha info.//初始化bitmap graphics context 上下文/*参数1:指向要呈现绘图的内存中目标的指针。这个内存块的大小至少应该是(bytesPerRow*height)字节。如果希望此函数为位图分配内存,则传递NULL。这将使您不必管理自己的内存,从而减少内存泄漏问题。参数2:所需宽度,以像素为单位参数3:所需高度参数4:用于内存中一个像素的每个组件的比特数参数5:位图中每一行使用的内存字节数。如果数据参数为NULL,传递值为0,则会自动计算值。参数6:颜色空间参数7:指定位图是否应该包含一个alpha通道、alpha通道在一个像素中的相对位置,以及关于像素组件是浮点数还是整数值的信息。指定alpha通道信息的常量使用CGImageAlphaInfo类型声明,可以安全地传递给该参数。您还可以传递与CGBitmapInfo类型相关联的其他常量。例如,如何指定颜色空间、每个像素的位元、每个像素的位元以及位图信息,请参阅图形上下文。*///kCGBitmapByteOrderDefault 是默认模式,对于iPhone 来说,采用的是小端模式CGContextRef context = CGBitmapContextCreate(NULL,width,height,kBitsPerComponent,0,colorspaceRef,kCGBitmapByteOrderDefault|kCGImageAlphaNoneSkipLast);//如果上下文为NULL,就返回imageif (context == NULL) {return image;}// Draw the image into the context and retrieve the new bitmap image without alpha/**这里创建的contexts是没有透明因素的。在UI渲染的时候,实际上是把多个图层按像素叠加计算的过程,需要对每一个像素进行 RGBA 的叠加计算。当某个 layer 的是不透明的,也就是 opaque 为 YES 时,GPU 可以直接忽略掉其下方的图层,这就减少了很多工作量。这也是调用 CGBitmapContextCreate 时 bitmapInfo 参数设置为忽略掉 alpha 通道的原因。而且这里主要针对的就是解码图片成位图*///将CGImageRef对象画到上面生成的上下文中,且将alpha通道移除CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);//使用上下文创建位图CGImageRef imageRefWithoutAlpha = CGBitmapContextCreateImage(context);//从位图创建UIImage对象,返回含有指定的方向和scale的图片UIImage *imageWithoutAlpha = [[UIImage alloc] initWithCGImage:imageRefWithoutAlpha scale:image.scale orientation:image.imageOrientation];//释放CG对象CGContextRelease(context);CGImageRelease(imageRefWithoutAlpha);return imageWithoutAlpha;}
}

下面再介绍下关于SDWebImage中的图片压缩的算法,其实简单来说就是将图像矩阵按照规则分割成小型子矩阵进行压缩,然后插值拼接,而且这个算法也是借鉴苹果的,官方Demo链接:https://developer.apple.com/library/content/samplecode/LargeImageDownsizing/Introduction/Intro.html  关于这个算法,苹果的定义就是此代码示例演示了一种支持在有限的内存环境中显示超大图像的方法,方法是将磁盘上的大图像转换为内存中较小的图像。这在原始图像太大而无法按照要显示的要求放入内存的情况下很有用 我目前也只能理解个大概,还有些细节方面还没想到,它是怎么进行优化的,代码都有注释。现在先简单的介绍下回用到的宏吧。

// 每个像素占4个字节大小 共32位
static const size_t kBytesPerPixel = 4;
//每个通道由8位组成
static const size_t kBitsPerComponent = 8;/** Defines the maximum size in MB of the decoded image when the flag `SDWebImageScaleDownLargeImages` is set* Suggested value for iPad1 and iPhone 3GS: 60.* Suggested value for iPad2 and iPhone 4: 120.* Suggested value for iPhone 3G and iPod 2 and earlier devices: 30.该参数用于设置内存占用的最大字节数。默认为60MB,下面给出了一些旧设备的参考数值。如果图片大小大于该值,则将图片以该数值为目标进行压缩。*/
static const CGFloat kDestImageSizeMB = 60.0f;/** Defines the maximum size in MB of a tile used to decode image when the flag `SDWebImageScaleDownLargeImages` is set* Suggested value for iPad1 and iPhone 3GS: 20.* Suggested value for iPad2 and iPhone 4: 40.* Suggested value for iPhone 3G and iPod 2 and earlier devices: 10.设置压缩时对于源图像使用到的*块*的最大字节数。原图方块的大小,这个方块将会被用来分割原图,默认设置为20M。*/
static const CGFloat kSourceImageTileSizeMB = 20.0f;
//1M有多少字节
static const CGFloat kBytesPerMB = 1024.0f * 1024.0f;
//1M有多少像素 262144个像素
static const CGFloat kPixelsPerMB = kBytesPerMB / kBytesPerPixel;
//目标总像素kDestImageSizeMB为60MB
static const CGFloat kDestTotalPixels = kDestImageSizeMB * kPixelsPerMB;
//目标图像的像素点个数
static const CGFloat kTileTotalPixels = kSourceImageTileSizeMB * kPixelsPerMB;
//目标重叠像素大小
static const CGFloat kDestSeemOverlap = 2.0f;   // the numbers of pixels to overlap the seems where tiles meet.

关于算法的描述,位图其实简单可以描述为是由像素组成的矩阵,所以下面其实就是把图像当做一个矩阵(或多个矩阵的组合)来进行处理的。

- (nullable UIImage *)sd_decompressedAndScaledDownImageWithImage:(nullable UIImage *)image {//1、判断图片是否支持解码if (![[self class] shouldDecodeImage:image]) {return image;}//2、判断图片是否支持缩小也就是压缩,总像素要大于15728640才能压缩,也就是kDestTotalPixels的大小if (![[self class] shouldScaleDownImage:image]) {return [self sd_decompressedImageWithImage:image];}//声明压缩目标用的上下文CGContextRef destContext;// autorelease the bitmap context and all vars to help system to free memory when there are memory warning.// on iOS7, do not forget to call [[SDImageCache sharedImageCache] clearMemory];@autoreleasepool {//3. 获取源图像位图CGImageRef sourceImageRef = image.CGImage;//4. 源图像尺寸,存储在CGSize结构体中CGSize sourceResolution = CGSizeZero;sourceResolution.width = CGImageGetWidth(sourceImageRef);sourceResolution.height = CGImageGetHeight(sourceImageRef);//5. 计算源图像总的像素点个数float sourceTotalPixels = sourceResolution.width * sourceResolution.height;// Determine the scale ratio to apply to the input image// that results in an output image of the defined size.// see kDestImageSizeMB, and how it relates to destTotalPixels.//6. 获取原图像和目标图像的比例(以像素点个数为基准),这里是以60MB的像素点为标准了 60MB的总像素要除以原文件的总像素小于1的float imageScale = kDestTotalPixels / sourceTotalPixels;//7. 使用imagescale计算目标图像的宽高,所以我目标图像的目标就是到60MBCGSize destResolution = CGSizeZero;destResolution.width = (int)(sourceResolution.width*imageScale);destResolution.height = (int)(sourceResolution.height*imageScale);//8. 进行图像绘制前的准备工作// current color spaceCGColorSpaceRef colorspaceRef = [[self class] colorSpaceForImageRef:sourceImageRef];// kCGImageAlphaNone is not supported in CGBitmapContextCreate.// Since the original image here has no alpha info, use kCGImageAlphaNoneSkipLast// to create bitmap graphics contexts without alpha info.//创建位图上下文destContext = CGBitmapContextCreate(NULL,destResolution.width,destResolution.height,kBitsPerComponent,0,colorspaceRef,kCGBitmapByteOrderDefault|kCGImageAlphaNoneSkipLast);if (destContext == NULL) {return image;}/*9. 设置图像插值的质量为高,设置图形上下文的插值质量水平CGContextSetInterpolationQuality允许上下文以各种保真度水平内插像素。在这种情况下,kCGInterpolationHigh通过最佳结果*/CGContextSetInterpolationQuality(destContext, kCGInterpolationHigh);//现在定义矩形的大小,用于增量位块从输入图像到输出图像。// Now define the size of the rectangle to be used for the// incremental blits from the input image to the output image.//由于iOS从磁盘检索图像数据的方式,我们使用源图像宽度与源图像的宽度相等// we use a source tile width equal to the width of the source// image due to the way that iOS retrieves image data from disk./*iOS必须在全宽度的“波段”中从磁盘上解码图像,即使当前的图形上下文被剪切到band内的一个subrect中。因此,我们充分利用了所有的像素数据,这些数据是由解码操作产生的,通过将我们的平铺大小与输入图像的宽度匹配。*/// iOS must decode an image from disk in full width 'bands', even// if current graphics context is clipped to a subrect within that// band. Therefore we fully utilize all of the pixel data that results// from a decoding opertion by achnoring our tile size to the full// width of the input image.//10. 定义一个称为*块*的增量矩形(incremental blits,即矩形大小在每一次迭代后都不断增长/减小)用于计算从源图像到目标图像的输出。CGRect sourceTile = CGRectZero;//源块的宽度等于源图像的宽度,宽度要保持一定sourceTile.size.width = sourceResolution.width;//  块的高度是动态的,我们前面指定了源tile的值,也就是kTileTotalPixels目标图像的像素点个数 根据宽度计算动态的高度// The source tile height is dynamic. Since we specified the size// of the source tile in MB, see how many rows of pixels high it// can be given the input image width.sourceTile.size.height = (int)(kTileTotalPixels / sourceTile.size.width );// *块*的起始x值总是为0sourceTile.origin.x = 0.0f;//输出的tile与输入的tile比例相同,但图像按比例缩放。图像按比例缩放就要用到插值运算了// The output tile is the same proportions as the input tile, but// scaled to image scale.//同样的方式初始化目标图像的块CGRect destTile;//宽度 = 目标图像的宽度destTile.size.width = destResolution.width;//高度 = 源图像块的高度 * 缩放比例destTile.size.height = sourceTile.size.height * imageScale;destTile.origin.x = 0.0f;// The source seem overlap is proportionate to the destination seem overlap.// this is the amount of pixels to overlap each tile as we assemble the ouput image.//11、计算源图像与压缩后目标图像重叠的像素大小。这里就是按照sourceResolution.height和destResolution.height进行相比float sourceSeemOverlap = (int)((kDestSeemOverlap/destResolution.height)*sourceResolution.height);CGImageRef sourceTileImageRef;//计算组装输出图像所需的读/写操作数// calculate the number of read/write operations required to assemble the// output image.//源图像的高度除以分割源图像的方块的高度得出源图像被分割成多少个方块并赋值给 iterations,再做取余运算取得分割的最大的整数int iterations = (int)( sourceResolution.height / sourceTile.size.height );//12、如果tile height不均匀地分割图像高度,则添加另一个迭代来解释剩余的像素。// If tile height doesn't divide the image height evenly, add another iteration// to account for the remaining pixels.int remainder = (int)sourceResolution.height % (int)sourceTile.size.height;if(remainder) {iterations++;}// Add seem overlaps to the tiles, but save the original tile height for y coordinate calculations.//定义一个 float 变量 sourceTitleHeightMinusOverlap 存放那个用来分割源图像,大小为 20 MB 的方块的高度。float sourceTileHeightMinusOverlap = sourceTile.size.height;//用于切割源图像大小为 20 MB 的方块的高度加上源图像与源图像分割方块的像素重叠数sourceTile.size.height += sourceSeemOverlap;//destTile.size.height = sourceTile.size.height * imageScale;//目标图像的分割方块的高度加上 kDestSeemOverlap(像素重叠数赋值为 2)destTile.size.height += kDestSeemOverlap;//13、进行for 循环,y 从0开始,到小于源图像被分割的块数for( int y = 0; y < iterations; ++y ) {@autoreleasepool {//sourceTile 和 destTile 都是宽度和高度固定的,x 值为 0,只有 y  值随着循环的 y  值在变化,sourceTile 的 y 值在递增,destTile 的 y 值在递减,只有最最后一次循环中,如果有余数那么size就会发生变化,这是因为最后一次中去取源图像的高度其实//sourceTileHeightMinusOverlap = sourceTile.size.height;sourceTile.origin.y = y * sourceTileHeightMinusOverlap + sourceSeemOverlap;destTile.origin.y = destResolution.height - (( y + 1 ) * sourceTileHeightMinusOverlap * imageScale + kDestSeemOverlap);/*14、在用到在一张图片中截取某一部分图片中,用到CGImageRef类中的CGImageCreateWithImageInRect函数然后循环的从源图像的 sourceImageRef 根据大小为 20 MB 的分割块的不同 CGRect 的矩形区域内获取 sourceTileImageRef,这里sourceTile的高度是根据kTileTotalPixels / sourceTile.size.width*/sourceTileImageRef = CGImageCreateWithImageInRect(sourceImageRef, sourceTile);//计算剩余的像素,所采用的方法if( y == iterations - 1 && remainder ) {//destTile.size.height = sourceTile.size.height * imageScale;float dify = destTile.size.height;destTile.size.height = CGImageGetHeight( sourceTileImageRef ) * imageScale;dify -= destTile.size.height;destTile.origin.y += dify;}//15、绘制图像到图形上下文指定的destTile范围中CGContextDrawImage( destContext, destTile, sourceTileImageRef );CGImageRelease( sourceTileImageRef );}}CGImageRef destImageRef = CGBitmapContextCreateImage(destContext);CGContextRelease(destContext);if (destImageRef == NULL) {return image;}//16、输出图像UIImage *destImage = [[UIImage alloc] initWithCGImage:destImageRef scale:image.scale orientation:image.imageOrientation];CGImageRelease(destImageRef);if (destImage == nil) {return image;}return destImage;}
}

压缩过程简单流程


参考文章:SDWebImage源码解读_之SDWebImageDecoder

               SDWebImage源码解析之编解码

               SDWebImage源码解析(三)——SDWebImage图片解码/压缩模块


http://chatgpt.dhexx.cn/article/3Ae69rMT.shtml

相关文章

sdwebimage 加载webp图片

sdwebimage加载 webp / git 配置宏 - (void)setUpCusPhoto {_scrollView [UIScrollView new];_scrollView.frame self.view.bounds;[self.view addSubview:_scrollView];//webpUIImageView *view [[UIImageView alloc] init];view.frame CGRectMake(10, 100, 320, 200);NS…

SDWebImage 5.0简介

一、 SDWebImage原理简介 1.结构 (设计思路借鉴&#xff1a;提供多种接口&#xff0c;到底层调用到同一个方法&#xff0c;减少调用方对可选参数的传递) UIImageViewWebCache和UIButtonWebCache直接为表层的 UIKit框架提供接口, SDWebImageManger&#xff08;SDWebImageManager…

SDWebImage的主流程

SDWebImage提供了UIImageView的分类来实现从网络端下载数据并缓存到内存和磁盘。非常的流行,现在就主流程分析下. 主要的学习链接 &#xff1a;SDWebImage源码解读 - 简书 SDWebImage有如下特点&#xff1a; 提供了UIImageView和UIButton的分类。以支持加载网络图片并缓存…

SDWebImage的缓存策略

SDWebImage 相信对大多数开发者来说&#xff0c;都是一个不陌生的名字。它除了帮助我们读取网络图片&#xff0c;还会处理这些图片的缓存。它的缓存机制到底是什么样的呢&#xff0c;让我给跟大家唠叨唠叨&#xff0c;希望你能有收获。 基本结构 闲言少叙&#xff0c;咱们这就…

SDWebImage源码解析

这段时间研究了一下SDWebImage源码&#xff0c;因个人能力有限&#xff0c;如有不对的地方&#xff0c;请指出或留言&#xff0c;谢谢&#xff01; SDWebImage是一个开源的第三方库&#xff0c;它提供了UIImageView的一个分类&#xff0c;以支持从远程服务器下载并缓存图片的功…

【iOS】SDWebImage

文章目录 SDWebImage日常使用一些主要功能获取图片缓存 缓存机制独立的异步图像下载独立的异步图像缓存 图片加载全过程 源码分析架构图结构SDWebImageManager1. SDWebImageOptions2. SDWebImageManagerDelegate SDWebImageCompatSDWebImageCompat.hSDWebImageCompat.m sd_imag…

开源框架:SDWebImage

引言: SDWebImage是我搞iOS以来少数佩服的框架,膜拜一下作者.真的写的非常棒! 这套开源框架还是蛮重要的, 涉及到异步加载图片源和自动缓存. 我们如果能够熟练使用其API 就可以实现很多复杂的需求了. 作者依旧在更新,目前3.0 版本已经非常强大! 简化了更多的API接口.加强了…

iOS 第三方框架-SDWebImage解读

在iOS的图片加载框架中&#xff0c;SDWebImage可谓是占据大半壁江山。它支持从网络中下载且缓存图片&#xff0c;并设置图片到对应的UIImageView控件或者UIButton控件。在项目中使用SDWebImage来管理图片加载相关操作可以极大地提高开发效率&#xff0c;让我们更加专注于业务逻…

iOS——SDWebImage解读

前言 在iOS的图片加载框架中&#xff0c;SDWebImage占据了大半壁江山。它提供了UIImageView的一个分类&#xff0c;支持从网络中下载且缓存图片&#xff0c;并设置图片到对应的UIImageView控件或者UIButton控件。在项目中使用SDWebImage来管理图片加载相关操作可以极大地提高开…

SDWebImage异步加载图片及缓存的管理与清理

一、SDWebImage介绍 1、在项目的开发过程中&#xff0c;我们经常会用到异步加载图片的功能&#xff0c;先从网络上异步下载图片&#xff0c;然后通过UIImageView显示在屏幕上。这是一个经常使用的功能&#xff0c;基本上所有的联网应用程序都要用到的功能&#xff0c;现在GitH…

iOS SDWebImage详细介绍

在iOS的图片加载框架中&#xff0c;SDWebImage使用频率非常高。它支持从网络中下载且缓存图片&#xff0c;并设置图片到对应的UIImageView控件或者UIButton控件。在项目中使用SDWebImage来管理图片加载相关操作可以极大地提高开发效率&#xff0c;让我们更加专注于业务逻辑实现…

JNA入门

1&#xff0c;什么是JNA&#xff1f; JNA全称Java Native Access&#xff0c;是一个建立在JNI技术之上的Java开源框架。 2&#xff0c;JNA有什么用&#xff1f; Java开发过程中&#xff0c;有时候会需要和C&#xff0c;C等交互&#xff0c;JNA相当于中间的适配器 3&#xf…

JNA —— Java调用C/C++动态库

工作所需&#xff0c;要使用Java调用c/c的动态库&#xff0c;实现Java程序使用动态库中的函数。 搜索了一番&#xff0c;常用的有JNI、JNA方法。 JNI&#xff08;Java Native Interface&#xff09; JNI定义了一种公用的语法&#xff0c;当Java和c/c都遵循这样的语法时就可以互…

关于JAVA中的JNA

1、jna是什么 jna是java native access的简称&#xff0c;用他可以调用C、C代码&#xff0c;特别是windows中强大的库文件&#xff08;dll&#xff0c;在linux下是so文件&#xff09;&#xff0c;这样java就可以操控底层的一些东西&#xff0c;比如调用加密机、智能卡之类的 2、…

JNA与JNI谁更受青睐呢

JNA(Java Native Access)框架是一个开源的Java框架&#xff0c;是SUN公司主导开发的&#xff0c;建立在经典的JNI的基础之上的一个框架。非常强大、易用。其中JNA是对JNI的封装&#xff0c;能让java使用者更好的使用本地的动态库 一、JNA与JNI的比较 JNI: JNI允许Java代码和其…

JNA实战系列:第一个简单的JNA开发程序

文章目录 第一个简单的JNA的开发程序一、引入依赖包二、创建一个接口&#xff0c;继承Libary类三、在Java中使用dll中封装的方法总结:JNA中调用C、CDLL或者.so库中的函数的步骤总结:思考 第一个简单的JNA的开发程序 假如有一个helloworld.h和一个helloworld.dll文件&#xff0…

Java通过JNA调用so库 Linux环境

记录一下自己的JNA调研成果&#xff0c;需求是公司同事用C写了一个红外测温SDK&#xff0c;编译成so文件后提供给客户使用。客户需要一个Linux环境用Java调用so库的一个demo&#xff0c;刚好就我一个懂点Java&#xff0c;所有有了这次调研。 因为JNA相关资料实在太少&#xff…

JNI便捷开发框架JNA框架之入门(一)

一、JNA介绍 JNA(Java Native Access)框架是一个开源的Java框架&#xff0c;是SUN公司主导开发的&#xff0c;建立在经典的JNI的基础之上的一个框架。它提供一组Java工具类用于在运行期动态访问系统本地共享类库而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中…

JNA简介

2019独角兽企业重金招聘Python工程师标准>>> JNA JNA&#xff08;Java Native Access &#xff09;提供一组Java工具类用于在运行期动态访问系统本地库&#xff08;native library&#xff1a;如Window的dll&#xff09;而不需要编写任何Native/JNI代码。开发人员只…

JNA的概念

1. JNA简单介绍 先说JNI(Java Native Interface)吧&#xff0c;有过不同语言间通信经历的一般都知道&#xff0c;它允许Java代码和其他语言&#xff08;尤其C/C&#xff09;写的代码进行交互&#xff0c;只要遵守调用约定即可。首先看下JNI调用C/C的过程&#xff0c;注意写程序…