图片的二次采样

1.为什么要进行图片的二次采样?

主要是避免OOM。假设客户端需要加载一张图片,图片尺寸为3000*3000(单位/像素),那么计算一下,如果客户端想显示原图,按一个像素四个字节算,
3000 * 3000 * 4 / 1024 / 1024 = 34 M,想想看客户端一个应用程序的运行内存就十几M,你一下显示一个30多M的图片,直接crash了。

2.怎么解决?

这里就需要对图片进行二次采样。
原理:
BitmapFactory内部的图片解码,形成Bitmap是通过底层C/C++来实现的,有专门的图片界面库,可以通过参数来获取图片的尺寸,以及设置针对颜色加载的采样比率,采样比率就是把多个像素采样成一个像素,图片自然就变小了,最终传递给Java级别的对象,内存就变小了,图片也就变小了。

步骤:
第一步:在加载网络、文件的图片时,进行图片的解码BitmapFactory.decode(),只进行图片的尺寸获取,不进行实际的Bitmap创建,因此,第一次解码,不会占用太多的内存,可以获取图片的宽和高;

第二步:根据图片真实的宽高,以及客户端希望图片加载后的尺寸,进行一个计算,形成一种图片解码时缩小采样的一个数值,这个数值,可以直接运用在BitmapFactory上,加载到内存的Bitmap,就是变小的,内存是小图片的内容,不是原始图片的内存;

3.参数说明

3.1BitmapFactory中的Options说明
1)成员变量作为配置信息传给解码器
2)变量分为两部分:in开头的、out开头的
3)In开头的:用于个解码器传递参数
4)Out开头的:用于从解码器获取结果

3.2inSampleSize 采样比率
1)最好是2的幂,因为这种C语言解码效率最高
2)采样比率有一个官方的算法:以对角线的方式进行缩放比率的计算

/**
     * 计算图片二次采样的采样率,使用获取图片宽高之后的Options作为第一个参数
     * @param options
     * @param reqWidth
     * @param reqHeight
     * @return
     *
     * --by Google
     */
    private static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        //只有当请求的宽度、高度 > 0时,进行缩放
        //否则,图片不进行缩放
        if(reqHeight > 0 && reqWidth > 0){
            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;
                }
            }
        }
        return inSampleSize;
    }

这里写图片描述

4.使用:

注释很详细了,不细说

 /**
     * 获取二次采样图片
     * @param data
     * @param requestWidth
     * @param requestHeight
     * @return
     */
    public static Bitmap getDownDimensionBitmap(byte[] data, int requestWidth, int requestHeight){
        Bitmap bitmap = null;
        if(data != null){
            //按照原始的图片尺寸,进行Bitmap的生存
            //按照Bitmap生成,是按照图片的原始宽高,进行生成,并且每一个像素占用4个字节 ARGB
//                ret = BitmapFactory.decodeByteArray(data, 0, data.length);

            //采用二次采样(缩小图片尺寸的方式)
            //1.步骤1 获取原始图片的宽高信息,用于进行采样的计算

            //1.1创建Options ,给BitmapFactory的内部解码器设置参数
            BitmapFactory.Options options = new BitmapFactory.Options();
            //1.2设置inJustDecodeBounds 来控制解码器,只会进行图片宽高的获取,不会获取图片
            //不占用内存,当使用这个参数,代表BitmapFactory.decodexxx()不会返回bitmap
            options.inJustDecodeBounds = true;

            //解码,使用options参数 设置解码方式
            BitmapFactory.decodeByteArray(data, 0, data.length, options);

            //2.步骤2 根据图片的真实尺寸,与当前需要显示的尺寸,进行计算,生成采样率

            //2.1
            //int picW = options.outWidth;
            //int picH = options.outHeight;

            //2.2准备 显示在手机上 256x128 128x64
            //尺寸是根据程序需要来设置的

//                int reqW = 256;
//                int reqH = 128;

            //2.3计算 设置 图片采样率
            options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight);//宽度的1/32  高度的1/32

            //2.4开放 解码,实际生成Bitmap
            options.inJustDecodeBounds = false;

            //2.4.1 Bitmap.Config的说明
            //要求解码器对于每一个采样的像素,使用RGB_565 存储方式
            //一个像素,占用两个字节,比ARGB_8888笑了一半
            //如果解码器不能使用指定配置,就自动使用ARGB_8888
            options.inPreferredConfig = Bitmap.Config.RGB_565;

            //2.4.2是一个过时的设置,可以及时清除内存
            options.inPurgeable = true;

            //2.5使用设置采样的参数,来进行 解码,获取bitmap
            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
        }
        return bitmap;
}

源码下载

### 回答1: QCustomPlot 是一个基于Qt框架的图表绘制库,可以用于实现各种静态和动态的数据可视化。QCustomPlot的二次开发指的是在QCustomPlot的基础上进行定制化的开发,以满足特定的需求。 QCustomPlot提供了丰富的功能和灵活的接口,可以轻松地绘制各种类型的图表,如曲线图、柱状图、散点图等。它还支持自定义图表的外观和交互行为,包括调整坐标轴、添加标题和子标题、设置图表背景、绘制网格线等。 QCustomPlot的二次开发可以通过以下几个方面来实现。首先,可以根据项目要求自定义图表的外观,如修改颜色、线型和符号的样式,以及添加背景图片和阴影效果。其次,可以添加交互功能,如鼠标悬停提示、数据选择和缩放等,以提供更好的用户体验。 此外,QCustomPlot还支持动态更新图表,可以实时显示数据的变化情况。在二次开发中,可以利用这个功能实现实时数据的监控和展示。例如,在工业控制系统中,可以通过QCustomPlot将传感器数据可视化,实时呈现设备状态和变化趋势。 QCustomPlot还可以与Qt中的其他模块和类进行整合,以实现更复杂的功能。例如,可以使用Qt的网络模块从远程服务器获取数据,然后通过QCustomPlot进行绘制和展示。 综上所述,QCustomPlot的二次开发可以根据具体需求来增加、修改和定制图表的功能和外观,以实现更多样化和个性化的数据可视化效果。 ### 回答2: QCustomPlot是一个开源的Qt绘图库,它提供了一系列的绘图工具和功能,包括曲线绘制、图表绘制、坐标系设置等。在QCustomPlot中进行二次开发,可以根据自己的需求进行定制和扩展,增加特定的功能和样式。 QCustomPlot的二次开发可以从以下几个方面入手: 1. 数据源:可以通过二次开发,将不同的数据源与QCustomPlot结合起来。比如,可以从数据库、网络或其他文件中读取数据,并进行绘图展示。也可以通过实时数据更新的方式,将实时数据显示在曲线或图表上。 2. 绘图样式:QCustomPlot提供了一些默认的样式,但二次开发可以通过自定义样式来增加个性化的图表展示。可以调整线条的颜色、粗细、曲线的类型,修改图表的背景、坐标轴的标签、刻度等。 3. 交互功能:可以通过二次开发,添加一些交互式的功能。例如,可以实现放大缩小、平移、拖拽等操作,以便用户在绘图上进行交互。也可以添加工具栏、菜单等界面元素,提供更多的操作选项。 4. 数据处理:可以通过二次开发,在QCustomPlot上进行数据处理和分析。例如,可以对绘图数据进行滤波、平滑、峰值检测等操作,以便更好地展示和分析数据。 5. 导出和保存:可以通过二次开发,增加数据导出和保存的功能。可以将绘制的图表保存为图片,或者导出数据为文件,以方便用户进行后续的处理和使用。 通过以上的二次开发,可以根据具体需求定制化QCustomPlot,使其更加符合自己的项目要求。需要注意的是,在二次开发过程中,需要具备Qt和绘图相关的知识和经验,以便更好地理解和使用QCustomPlot库。 ### 回答3: QCustomPlot是一个非常强大的开源绘图库,可以用于绘制二维图形和图表。通过二次开发,我们可以根据自己的需求对其进行定制和扩展。 QCustomPlot的二次开发可以包括以下几个方面的内容: 1. 绘图定制:通过修改绘图函数、调整绘图参数等方式,可以实现各种各样的绘图效果。例如,可以改变线条颜色、线型、点的形状,添加背景图像或标签等。 2. 数据处理:可以通过二次开发,对绘图数据进行处理和分析。例如,可以实现数据滤波、数据采样、数据拟合等功能,从而在绘图时展示更加准确和精细的数据。 3. 交互功能:可以通过二次开发,添加交互式的功能,使用户能够与绘图进行互动。例如,可以添加鼠标拖动、缩放、平移等功能,使用户可以自由浏览和操作图形。 4. 扩展功能:QCustomPlot还可以通过二次开发,集成其他相关功能。例如,可以与其他界面库结合,实现更加丰富的用户界面;也可以与数据存储库结合,实现数据的保存和读取功能等。 总之,QCustomPlot的二次开发可以根据具体需求进行定制和扩展,从而实现更加个性化和强大的绘图功能。无论是改变绘图样式、处理数据、添加交互功能,还是集成其他功能,QCustomPlot都可以通过二次开发来实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值