Android bitmap保姆级教学

news2024/11/24 13:40:20

1. 认识Bitmap

Bitmap是一个final类,因此不能被继承。Bitmap只有一个构造方法,且该构造方法是没有任何访问权限修饰符修饰,也就是说该构造方法是friendly,但是谷歌称Bitmap的构造方法是private(私有的),感觉有点不严谨。不管怎样,一般情况下,我们不能通过构造方法直接新建一个Bitmap对象。
Bitmap是Android系统中的图像处理中最重要类之一。Bitmap可以获取图像文件信息,对图像进行剪切、旋转、缩放,压缩等操作,并可以以指定格式保存图像文件。

2. 创建Bitmap对象

既然不能直接通过构造方法创建Bitmap,那怎样才能创建Bitmap对象。通常我们可以利用Bitmap的静态方法createBitmap()和BitmapFactory的decode系列静态方法创建Bitmap对象。

  • Bitmap的静态方法createBitmap()
    createBitmap

  • BitmapFactory的decode系列静态方法
    bitmapFactory

2.1. 流——BitmapFactory.decodeStream()

(1) 文件流

FileInputStream fis = new FileInputStream("/sdcard/test.png"); 
Bitmap bitmap=BitmapFactory.decodeStream(fis);

(2) 以ResourceStream的方式代替R文件

Bitmap bitmap=BitmapFactory.decodeStream(
    getClass().getResourceAsStream(/res/drawable/test.png”));

(3) 以文件流+ R文件 的方式

InputStream in = getResources().openRawResource(R.drawable. test );
Bitmap bitmap = BitmapFactory.decodeStream(in);

(4) 图片放在src目录下

String path = "com/xiangmu/test.png"; //图片存放的路径
InputStream in = getClassLoader().getResourceAsStream(path); //得到图片流
Bitmap imageBitmap3 = BitmapFactory.decodeStream(in);

(5) 图片放在 Assets目录

InputStream in = getResources().getAssets().open(fileName);
Bitmap imageBitmap4 = BitmapFactory.decodeStream(in);

2.2. 文件路径——BitmapFactory.decodeFile()

Bitmap imageBitmap = BitmapFactory.decodeFile(path);// (path 是图片的路径,跟目录是/sdcard)

支持的文件格式:

2.3. 资源ID——BitmapFactory.decodeResource()

(1) 以R文件的方式

// 假设 res/drawable下有 test.jpg文件
Bitmap bitmap =BitmapFactory.decodeResource(getResources(), R.drawable.test);

(2) 获取制定packageName的资源文件

ApplicationInfo appInfo = getApplicationInfo();
//得到该图片的id(name 是该图片的名字,"drawable" 是该图片存放的目录,appInfo.packageName是应用程序的包)
int resID = getResources().getIdentifier(fileName, "drawable", appInfo.packageName);
Bitmap imageBitmap2 = BitmapFactory.decodeResource(getResources(), resID);

2.4. 字节数组——BitmapFactory.decodeByteArray()

(1) bmp格式的数组

byte[] bmpBytes = readFileToByteArray(bmpPath);// bmp文件格式
Bitmap bitmap = BitmapFactory.decodeByteArray(bmpBytes, 0, bmpBytes.length);

(2) yuv-nv21/jpg格式的数组

//data可以是jpg格式的数组
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//yuv格式的byte[]转换成bitmap
public static Bitmap nv21ToBitmap(byte[] nv21, int width, int height) {   
    Bitmap bitmap = null;
    try {
        YuvImage image = new YuvImage(nv21, ImageFormat.NV21, width, height, null);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        image.compressToJpeg(new Rect(0, 0, width, height), 80, stream);
        bitmap = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
        stream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return bitmap;
}

2.5. 从bitmapDrawable获取——bitmapDrawable.getBitmap()

InputStream in = getResources().openRawResource(R.drawable. test );
BitmapDrawable bitmapDrawable = new BitmapDrawable(in);
Bitmap bitmap = bitmapDrawable.getBitmap();

注意: openRawResource可以打开 drawable, sound, 和raw资源,但不能是string和color。

2.6. Bitmap.createBitmap()

(1) RGB888格式的数组

//24位RGB转Bitmap
public static Bitmap rgb888ToBitmap(byte[] data, int width, int height)
{
    byte[] Bits = new byte[data.length * 4]; //RGBA 数组
    // data.length / 3 表示 3位为一组
    for (int i = 0; i < data.length / 3; i++)
    {
        // 原理:24位是有彩色的,所以要复制3位,最后一位Alpha = 0xff;
        Bits[i * 4] = data[i * 3];
        Bits[i * 4 + 1] = data[i * 3 + 1];
        Bits[i * 4 + 2] = data[i * 3 + 2];
        Bits[i * 4 + 3] = -1;
    }
    // Bitmap.Config.ARGB_8888 表示:图像模式为8位
    Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    bmp.copyPixelsFromBuffer(ByteBuffer.wrap(Bits));
    return bmp;
}

//先转成int再转成bitmap,会稍微快几个ms
public static Bitmap rgb888ToBitmap(byte[] data, int width, int height)
    {
        int[] iData = new int[data.length/3]; //RGBA 数组
        // data.length / 3 表示 3位为一组
        for (int i = 0; i < data.length / 3; i++)
        {
            // 原理:24位是有彩色的,所以要复制3位,最后一位Alpha = 0xff;
            iData[i] = (((int)data[i*3]) << 16) + (((int)data[i*3+1]) << 8) + data[i*3+2] + 0xff000000;
        }
        // Bitmap.Config.ARGB_8888 表示:图像模式为8位
        return Bitmap.createBitmap(iData, width, height, Bitmap.Config.ARGB_8888);
    }

(2) 8位灰度数组

public static Bitmap byteToBitmap(byte[] values, int width, int height) {    
    //使用8位来保存图片
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    int[] pixels = new int[width * height];
    for (int i = 0; i < values.length; i++) {
        //关键代码,生成灰度图,灰度图的argb格式就是0xff开头,后面rgb数值全一样,0xff131313
        pixels[i] = values[i] * 256 * 256 + values[i] * 256 + values[i] + 0xFF000000;
    }
    bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
    return bitmap;
}

//方式二:
public static Bitmap byteToBitmap(byte[] data, int width, int height) {
    byte[] Bits = new byte[data.length * 4]; //RGBA 数组
    // 原理:4个字节表示一个灰度,则RGB  = 灰度值,最后一个Alpha = 0xff;
    for (int i = 0; i < data.length; i++) {		
        Bits[i * 4] = Bits[i * 4 + 1] = Bits[i * 4 + 2] = data[i];
        Bits[i * 4 + 3] = -1; //0xff
    }
    // Bitmap.Config.ARGB_8888 表示:图像模式为8位
    Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    bmp.copyPixelsFromBuffer(ByteBuffer.wrap(Bits));
    return bmp;
}

2.7. Bitmap资源回收

if (bitmap!=null&&!bitmap.isRecycle()) {
    bitmap.recycle();  
    bitmap= null;
    system.gc(); 
}

3. Bitmap的颜色配置信息与压缩方式信息

Bitmap中有两个内部枚举类:ConfigCompressFormatConfig是用来设置颜色配置信息的,CompressFormat是用来设置压缩方式的。

config&compressFormat

  • Config
    

    解析:

    • Bitmap.Config.ALPHA_8:颜色信息只由透明度组成,占8位。
    • Bitmap.Config.ARGB_4444:颜色信息由透明度与R(Red),G(Green),B(Blue)四部分组成,每个部分都占4位,总共占16位。
    • Bitmap.Config.ARGB_8888:颜色信息由透明度与R(Red),G(Green),B(Blue)四部分组成,每个部分都占8位,总共占32位。是Bitmap默认的颜色配置信息,也是最占空间的一种配置。
    • Bitmap.Config.RGB_565:颜色信息由R(Red),G(Green),B(Blue)三部分组成,R占5位,G占6位,B占5位,总共占16位。

通常我们优化Bitmap时,当需要做性能优化或者防止OOM(Out Of Memory),我们通常会使用Bitmap.Config.RGB_565这个配置,因为Bitmap.Config.ALPHA_8只有透明度,显示一般图片没有意义,Bitmap.Config.ARGB_4444显示图片不清楚,Bitmap.Config.ARGB_8888占用内存最多。

  • CompressFormat
    

    解析:

    • Bitmap.CompressFormat.JPEG:表示以JPEG压缩算法进行图像压缩,压缩后的格式可以是".jpg"或者".jpeg",是一种有损压缩。
    • Bitmap.CompressFormat.PNG:表示以PNG压缩算法进行图像压缩,压缩后的格式可以是".png",是一种无损压缩。
    • Bitmap.CompressFormat.WEBP:表示以WebP压缩算法进行图像压缩,压缩后的格式可以是".webp",是一种有损压缩,质量相同的情况下,WebP格式图像的体积要比JPEG格式图像小40%。美中不足的是,WebP格式图像的编码时间“比JPEG格式图像长8倍”。

4. Bitmap对图像进行操作

4.1. Bitmap裁剪图像

Bitmap裁剪图像有两种方式:

  • Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height)

根据源Bitmap对象source,创建出source对象裁剪后的图像的Bitmap。x,y分别代表裁剪时,x轴和y轴的第一个像素,width,height分别表示裁剪后的图像的宽度和高度。
注意:x+width要小于等于source的宽度,y+height要小于等于source的高度。

  • Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height,Matrix m, boolean filter)

这个方法只比上面的方法多了mfilter这两个参数,m是一个Matrix(矩阵)对象,可以进行缩放,旋转,移动等动作,filter为true时表示source会被过滤,仅仅当m操作不仅包含移动操作,还包含别的操作时才适用。其实上面的方法本质上就是调用这个方法而已。

public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) {
    return createBitmap(source, x, y, width, height, null, false);
}  

4.2. Bitmap缩放,旋转,移动图像

Bitmap缩放,旋转,移动,倾斜图像其实就是通过Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height,Matrix m, boolean filter)方法实现的,只是在实现这些功能的同时还可以实现图像的裁剪。

// 定义矩阵对象  
Matrix matrix = new Matrix();  
// 缩放图像  
matrix.postScale(0.8f, 0.9f);  
// 按中心点镜像垂直翻转
matrix.postScale(1, -1, x/2, y/2);  
// 按中心点镜像水平翻转
matrix.postScale(-1, 1, x/2, y/2);
// 向左旋转(逆时针旋转)45度,参数为正则向右旋转(顺时针旋转) 
matrix.postRotate(-45);  
// 按中心点顺时针旋转90度 
matrix.postRotate(90, x/2, y/2); 
//移动图像
//matrix.postTranslate(100,80);
Bitmap bitmap = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);    

Matrix的postScalepostRotate方法还有多带两个参数的重载方法postScale(float sx, float sy, float px, float py)postRotate(float degrees, float px, float py),后两个参数pxpy都表示以该点为中心进行操作。
注意:虽然Matrix还可以调用postSkew方法进行倾斜操作,但是却不可以在此时创建Bitmap时使用。

4.3. Bitmap保存图像与释放资源

bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.feng);
File file=new File(getFilesDir(),"lavor.jpg");
if(file.exists()){
    file.delete();
}
try {
    FileOutputStream outputStream=new FileOutputStream(file);
    bitmap.compress(Bitmap.CompressFormat.JPEG,90,outputStream);
    outputStream.flush();
    outputStream.close();
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}
bitmap.recycle();//释放bitmap的资源,这是一个不可逆转的操作

4.4. Bitmap获取rgb格式数组

//从bitmap中获取rgb格式的数组
byte[] getByteFromBitmap(Bitmap bitmap){
    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    int[] pixels = new int[width * height];
    bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    byte[] pixelsBytes = getRgbFromPixels(pixels);
    bitmap.recycle();
    return pixelsBytes;
}
byte[] getRgbFromPixels(int[] vArr) {
    byte[] bytes = new byte[vArr.length*3];
    for (int i = 0;i<vArr.length;i++){
        int accum = vArr[i];
        bytes[i*3] = (byte)((accum>>16) & 0xFF);
        bytes[i*3+1] = (byte)((accum>>8) & 0xFF);
        bytes[i*3+2] = (byte)(accum & 0xFF);
//      bytes[i*4+3] = (byte)((accum>>24) & 0xFF);
    }
    return bytes;
}

5. BitmapFactory通过BitmapFactory.Options对图像进行操作

BitmapFactory是通过BitmapFactory.Options对图像进行操作的,然后将操作后的图像生成Bitmap对象或者将操作后的图像用已经存在的Bitmap保存,当不能用之保存时会返回null
BitmapFactory.Options中常用的字段有:
options

  • inBitmap:如果设置将会将生成的图像内容加载到该Bitmap对象中。
  • inDensity:给Bitmap对象设置的密度,如果inScaled为true(这是默认的),而若inDensityinTargetDensity不匹配,那么就会在Bitmap对象返回前将其缩放到匹配inTargetDensity
  • inDither:是否对图像进行抖动处理,默认值是false。
  • inJustDecodeBounds:如果设置成true,表示获取Bitmap对象信息,但是不将其像素加载到内存,不会真的返回一个Bitmap给你,它仅仅会把它的宽,高取回来给你,这样就不会占用太多的内存,也就不会那么频繁的发生OOM。设置为false,BitmapFactory返回bitmap。
  • inMutable:如果设为true,将返回一个mutable的bitmap,可用于修改BitmapFactory加载而来的bitmap。
  • inPreferredConfig:Bitmap对象颜色配置信息,默认是Bitmap.Config.ARGB_8888
    • ALPHA_8:每个像素用占8位,存储的是图像的透明值,占1个字节;
    • RGB_565:每个像素用占16位,分别为5-R,6-G,5-B通道,占2个字节;
    • ARGB-4444:每个像素占16位,即每个通道用4位表示,占2个字节;
    • ARGB_8888:每个像素占32位,每个通道用8位表示,占4个字节。
  • inSampleSize:获取采样率,设置的值大于1时,图像高、宽分别以2的inSampleSize次方分之一缩小;
    设置的值小于等于1时,图像高、宽不变。用于对图像进行压缩,设置的值为2的整数次幂或者接近2的整数次幂,当次设置为2时,宽和高为都原来的1/2,图像所占空间为原来的1/4。
  • inScaled:设置是否缩放位图。
  • inTargetDensity:绘制到目标Bitmap上的密度。
  • outHeight:Bitmap对象的高度。
  • outWidth:Bitmap对象的宽度。

BitmapFactory.Options的作用:
(1).防止内存溢出;
(2).节省内存开销;
(3).系统更流畅;

6. 使用Bitmap时防止OOM的有效方法

6.1. 高效压缩图片

/**
     * 谷歌推荐使用方法,从资源中加载图像,并高效压缩,有效降低OOM的概率
     * @param res 资源
     * @param resId 图像资源的资源id
     * @param reqWidth 要求图像压缩后的宽度
     * @param reqHeight 要求图像压缩后的高度
     * @return
     */
public Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
                                              int reqWidth, int reqHeight) {
    // 设置inJustDecodeBounds = true ,表示获取图像信息,但是不将图像的像素加入内存
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // 调用方法计算合适的 inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth,reqHeight);

    // inJustDecodeBounds 置为 false 真正开始加载图片
    options.inJustDecodeBounds = false;
    //将options.inPreferredConfig改成Bitmap.Config.RGB_565,
    // 是默认情况Bitmap.Config.ARGB_8888占用内存的一般
    options.inPreferredConfig= Bitmap.Config.RGB_565;
    return BitmapFactory.decodeResource(res, resId, options);
}

// 计算 BitmapFactpry 的 inSimpleSize的值的方法
public int calculateInSampleSize(BitmapFactory.Options options, 
                                 int reqWidth, int reqHeight) {
    if (reqWidth == 0 || reqHeight == 0) {
        return 1;
    }

    // 获取图片原生的宽和高
    final int height = options.outHeight;
    final int width = options.outWidth;
    Log.d(TAG, "origin, w= " + width + " h=" + height);
    int inSampleSize = 1;

    // 如果原生的宽高大于请求的宽高,那么将原生的宽和高都置为原来的一半
    if (height > reqHeight || width > reqWidth) {
        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // 主要计算逻辑
        // Calculate the largest inSampleSize value that is a power of 2 and
        // keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) >= reqHeight 
               && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    Log.d(TAG, "sampleSize:" + inSampleSize);
    return inSampleSize;
}  

6.2. 使用缓存

常用的缓存有内存缓存LruCache和磁盘缓存DiskLruCache

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/589132.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】this 指针的概念

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、缘起 2、this 指针的用途 2.1、用途 1 2.1.1 解法 1 2.1.2 解法 2 2.2、用途 2 2.3、用途 3 3、总结 1、缘起 我…

网络编程_TCP/IP四层协议分层

网络编程_TCP/IP四层协议分层 1. OSI七层协议模型 (open system interconnection)与TCP/IP四层协议分层2. 协议封装3. TCP 协议头部4.三次握手5.滑动窗口正常情况丢包情况 6.四次挥手 1. OSI七层协议模型 (open system interconnection)与TCP/IP四层协议分层 OSI七层协议模型 (…

珞珈一号夜间灯光数据校正流程

一、前言 随着珞珈一号夜间灯光数据的发射,其高分辨率等优异性能,可以为我国相关部门监测国内和全球宏观经济运行情况,为政府决策提供客观依据,珞珈一号理想情况下荷在15天内完成绘制全球夜光影像,提供我国或者全球GDP指数、碳排放指数、城市住房空置率指数等专题产品。 …

larvael dcat-admin 表单设置自定义样式

表单有些不是自己想要的样式想要覆写或者增加 可以如下 public function form() {​​​​​​​$this->column(6, function () {$this->dateRange(order_created_at.start, order_created_at.end)->label(下单时间)->setLabelClass([input-group]) // 设置样式-&…

盘点几个实现VLAN间路由的好方法

在真实的网络中&#xff0c;常常需要跨VLAN通信。 许多网络工作者通常选择一些方法来实现不同VLAN中的主机之间的相互访问&#xff0c;如单臂路由。 然而&#xff0c;由于单臂路由技术的一些限制&#xff0c;如带宽和转发效率&#xff0c;这种技术是很少使用。 三层交换机在…

SpringBoot 集成WebSocket详解

感谢参考文章的博主&#xff0c;关于WebSocket概述和使用写的都很详细&#xff0c;这里结合自己的理解&#xff0c;整理了一下。 一、WebSocket概述 1、WebSocket简介 WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器…

一文详解 Sa-Token 中的 SaSession 对象

Sa-Token 是一个轻量级 java 权限认证框架&#xff0c;主要解决登录认证、权限认证、单点登录、OAuth2、微服务网关鉴权 等一系列权限相关问题。 Gitee 开源地址&#xff1a;https://gitee.com/dromara/sa-token 本文将详细介绍 Sa-Token 中的不同 SaSession 对象的区别&#x…

由jar包冲突导致的logback日志不输出

一、前言 最近升级一个老项目&#xff0c;发面日志没有按照预期的生成。 1、resource下面有logback配置但没有生成日志 检查resource目录下&#xff0c;发现有logback.xml配置&#xff0c;但部署在服务器的项目没有按配置生成日志。于是启动本地tomcat发现日志按logback配置…

【创造一个源点去建图】【有等级限制的dijkstra(采用多次dijk方法处理)】昂贵的聘礼

昂贵的聘礼 题意分析 原题链接 题意分析 本题需要注意&#xff1a; 等级限制比较复杂&#xff0c;可以最后考虑本题说 由 B物品 可以换 A物品&#xff0c;想到了B节点可以走到A节点&#xff0c;所以构建图由于我们是要买一个点再开始换的&#xff0c;所以我们可以构建一个源点…

bird 2023 比赛总结

1. 引言 &#x1f4cc; 参加这场比赛的时间&#xff0c;应该是还剩一个月不到了&#xff0c;本来没啥想法&#xff0c;因为在忙一些其它的比赛或者是工作和个人上的烦心事&#xff0c;不过在看过了赛题分析后&#xff0c;整体给我感观是一道挺有意思的学习赛&#xff0c;不仅仅…

ESP32-CAM开发板 使用 sqlite3 数据库存储数据记录

忘记过去&#xff0c;超越自己 ❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-05-29 ❤️❤️ 本篇更新记录 2023-05-29 ❤️&#x1f389; 欢迎关注 &#x1f50e;点赞 &#x1f44d;收藏 ⭐️留言&#x1f4dd;&#x1f64…

Python - Pycharm 配置 autopep8 并设置快捷键

什么是 PEP8 官方&#xff1a;PEP 8 – Style Guide for Python Code | peps.python.org 中文翻译博客&#xff1a;https://www.cnblogs.com/ajianbeyourself/p/4377933.html PEP8 是 Python 官方推出的一套编码的规范&#xff0c;只要代码不符合它的规范&#xff0c;就会有…

iOS unable to find utility “pngcrush“, not a developer tool or in PATH

0x00 奇怪的Bug 很奇怪&#xff0c;还很蛋疼 T_T 前一秒还能 Build 成功&#xff0c;运行 后一秒直接 GG sh -c /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -sdk /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/S…

Win10系统更新时不小心中断了无法启动怎么办?

Win10系统更新时不小心中断了无法启动怎么办&#xff1f;有用户使用的Win10系统电脑在进行系统更新的时候&#xff0c;被自己误触了电脑导致更新进程中断了。那么遇到这样的情况我们怎么去进行问题的解决呢&#xff1f;接下来我们一起来看看以下的解决方法吧。 准备工作&#x…

flink写mysql报错Could not retrieve transation read-only status server

事务隔离级别前提下还是报错 SET GLOBAL tx_isolationREAD-COMMITTED; show global variables like wait timeout; 发现mysql是8小时。如果flnk超过8小时没有发送数据&#xff0c;invoke将会导致 mysql主动断开连接&#xff0c;而java侧并无感知。 解决问题&#xff0c;在使…

Benewake(北醒) TFmini-i-485/TF02-i-485/TF03-485 雷达Modbus协议在Python Tkinter模块上实现功能配置的GUI设计

目录 实验目的测试环境Python库需求Benewake(北醒) TF雷达接线示意图库安装说明例程运行展示 实验目的 实现485接口系列雷达Modbus协议在Python下Tkinter模块实现功能配置的GUI设计。 本例程主要功能如下&#xff1a; 1.设备连接&#xff08;已知雷达设备的波特率和站号&#…

C++11 auto类型推导

1.类型推导 C11引入了auto 和 decltype 关键字实现类型推导&#xff0c;通过这两个关键字不仅能方便地获取复杂的类型&#xff0c;而且还能简化书写&#xff0c;提高编码效率。 auto 类型推导的语法和规则 在之前的 C 版本中&#xff0c;auto 关键字用来指明变量的存储类型…

SSL/TLS协议核心原理解析与实战

什么是SSL/TLS SSL&#xff08;secure sockets layer&#xff0c;安全套接层&#xff09;安全传输技术。TCP是传输层的协议&#xff0c;但是它是明文传输的&#xff0c;是不安全的。SSL的诞生给TCP加了一层保险&#xff0c;为TCP通信提供安全及数据完整性保护。TLS只是SSL的升…

软件测试银行金融项目如何测?看看资深测试老鸟的总结,一篇足够...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 自动化测试&#x…

如何获取ios打包证书

要获取ios证书&#xff0c;需要去苹果开发者中心注册苹果开发者账号&#xff0c;百度苹果开发者中心即可进入苹果开发者中心官网。 假如你还从来没注册过苹果开发者&#xff0c;你可以参考下面这篇文章先注册成为苹果开发者&#xff0c;必须要有苹果开发者账号才能生成ios打包…