鸿蒙应用开发之媒体(图像)

一、基本概念

  • 图像解码

    图像解码就是不同的存档格式图片(如JPEGPNG等)解码为无压缩的位图格式,以方便在应用或者系统中进行相应的处理。

  • PixelMap

    PixelMap是图像解码后无压缩的位图格式,用于图像显示或者进一步的处理。

  • 渐进式解码

    渐进式解码是在无法一次性提供完整图像文件数据的场景下,随着图像文件数据的逐步增加,通过多次增量解码逐步完成图像解码的模式。

  • 预乘

    预乘时,RGB各通道的值被替换为原始值乘以Alpha通道不透明的比例(0~1)后的值,方便后期直接合成叠加;不预乘指RGB各通道的数值是图像的原始值,与Alpha通道的值无关。

  • 图像编码

    图像编码就是将无压缩的位图格式,编码成不同格式的存档格式图片(JPEGPNG等),以方便在应用或者系统中进行相应的处理。

约束与限制

  • 为及时释放本地资源,建议在图像解码的ImageSource对象、位图图像PixelMap对象或图像编码的ImagePacker对象使用完成后,主动调用release()方法

二、图像解码

图像解码就是将所支持格式的存档图片解码成统一的PixelMap图像,用于后续图像显示或其他处理,比如旋转、缩放、裁剪等。当前支持格式包括JPEGPNGGIFHEIFWebPBMP

图像解码主要用到ImageSource,其常用接口如下

接口名描述
create(String pathName, SourceOptions opts)从图像文件路径创建图像数据源。
create(InputStream is, SourceOptions opts)从输入流创建图像数据源。
create(byte[] data, SourceOptions opts)从字节数组创建图像源。
create(byte[] data, int offset, int length, SourceOptions opts)从字节数组指定范围创建图像源。
create(File file, SourceOptions opts)从文件对象创建图像数据源。
create(FileDescriptor fd, SourceOptions opts)从文件描述符创建图像数据源。
createIncrementalSource(SourceOptions opts)创建渐进式图像数据源。
createIncrementalSource(IncrementalSourceOptions opts)创建渐进式图像数据源,支持设置渐进式数据更新模式。
createPixelmap(DecodingOptions opts)从图像数据源解码并创建PixelMap图像。
createPixelmap(int index, DecodingOptions opts)从图像数据源解码并创建PixelMap图像,如果图像数据源支持多张图片的话,支持指定图像索引。
updateData(byte[] data, boolean isFinal)更新渐进式图像源数据。
updateData(byte[] data, int offset, int length, boolean isFinal)更新渐进式图像源数据,支持设置输入数据的有效数据范围。
getImageInfo()获取图像基本信息。
getImageInfo(int index)根据特定的索引获取图像基本信息。
getSourceInfo()获取图像源信息。
release()释放对象关联的本地资源。

普通开发

开发流程如下

/**
 * @description 普通模式解码
 * @author PengHuAnZhi
 * @date 2021/1/17 13:23
 */
private void testNormalImgDecode() {
    /**
     *1、
     *   创建图像数据源ImageSource对象,可以通过SourceOptions指定数据源的格式信息,此格式信息仅为给解码器的提示,正确提供能帮助提高
     *   解码效率,如果不设置或设置不正确,会自动检测正确的图像格式。不使用该选项时,可以将create接口传入的SourceOptions设置为null。
     */
    ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
    srcOpts.formatHint = "image/png";
    String pathName = "/path/to/image.png";
    ImageSource imageSource = ImageSource.create(pathName, srcOpts);
    //也可以设置为空
    ImageSource imageSourceNoOptions = ImageSource.create(pathName, null);
    /**
     * 2、
     * 设置解码参数,解码获取PixelMap图像对象,解码过程中同时支持图像处理操作。设置desiredRegion支持按矩形区域裁剪,如果设置为全0,则不
     * 进行裁剪。设置desiredSize支持按尺寸缩放,如果设置为全0,则不进行缩放。设置rotateDegrees支持旋转角度,以图像中心点顺时针旋转。如果只
     * 需要解码原始图像,不使用该选项时,可将给createPixelMap传入的DecodingOptions 设置为null。
     */
    // 普通解码叠加旋转、缩放、裁剪
    ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
    decodingOpts.desiredSize = new Size(100, 2000);
    decodingOpts.desiredRegion = new Rect(0, 0, 100, 100);
    decodingOpts.rotateDegrees = 90;
    PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);
    //3、普通解码
    PixelMap pixelMapNoOptions = imageSource.createPixelmap(null);
    //4、解码完成获取到PixelMap对象后,可以进行后续处理,比如渲染显示等。
    //这里直接让一个image控件显示
    mTestImg.setPixelMap(pixelMapNoOptions);
}

渐进式解码

/**
 * @description 渐进模式解码
 * @author PengHuAnZhi
 * @date 2021/1/17 13:34
 */
private void testGradualImgDecode() {
    /**
     * 1、
     * 创建渐进式图像数据源ImageSource对象,可以通过SourceOptions指定数据源的格式信息,此格式信息仅为提示,如
     * 果填写不正确,会自动检测正确的图像格式,使用IncrementalSourceOptions指定图像数据的更新方式为渐进式更新。
     */
    ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
    srcOpts.formatHint = "image/jpeg";
    ImageSource.IncrementalSourceOptions incOpts = new ImageSource.IncrementalSourceOptions();
    incOpts.opts = srcOpts;
    incOpts.mode = ImageSource.UpdateMode.INCREMENTAL_DATA;
    ImageSource imageSource = ImageSource.createIncrementalSource(incOpts);
    //2、渐进式更新数据,在未获取到全部图像时,支持先更新部分数据来尝试解码,更新数据时设置isFinal为false,当获取到全部数据后,最后一次更新数据时设置isFinal为true,表示数据更新完毕。设置解码参数同普通解码。
    // 获取到一定的数据时尝试解码,这里的第一个参数数据字节数组只是为了显示而模拟的,真实情况不是这样
    imageSource.updateData(new byte[2048], 0, 20, false);
    ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
    PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);
    mTestImg.setPixelMap(pixelMap);
    // 更新数据再次解码,重复调用直到数据全部更新完成
    imageSource.updateData(new byte[2048], 0, 20, false);
    PixelMap pixelMapNext = imageSource.createPixelmap(decodingOpts);
    mTestImg.setPixelMap(pixelMapNext);
    // 3、数据全部更新完成时需要传入isFinal为true
    imageSource.updateData(new byte[2048], 0, 20, true);
    PixelMap pixelMapFinal = imageSource.createPixelmap(decodingOpts);
    //4、解码完成获取到PixelMap对象后,可以进行后续处理,比如渲染显示等。   
    mTestImg.setPixelMap(pixelMapFinal);
}

三、图像编码

图像编码就是将PixelMap图像编码成不同存档格式图片,用于后续其他处理,比如保存、传输等。当前仅支持JPEG格式。

图像编码主要使用ImagePacker,其主要接口如下

接口名描述
create()创建图像打包器实例。
initializePacking(byte[] data, PackingOptions opts)初始化打包任务,将字节数组设置为打包后输出目的。
initializePacking(byte[] data, int offset, PackingOptions opts)初始化打包任务,将带偏移量的字节数组设置为打包后输出目的。
initializePacking(OutputStream outputStream, PackingOptions opts)初始化打包任务,将输出流设置为打包后输出目的。
addImage(PixelMap pixelmap)将PixelMap对象添加到图像打包器中。
addImage(ImageSource source)将图像数据源ImageSource中图像添加到图像打包器中。
addImage(ImageSource source, int index)将图像数据源ImageSource中指定图像添加到图像打包器中。
finalizePacking()完成图像打包任务。
release()释放对象关联的本地资源。

开发流程如下

/**
 * @description 图像编码
 * @author PengHuAnZhi
 * @date 2021/1/17 13:45
 */
private void testImgEncode() {
    //1、创建图像编码ImagePacker对象。
    ImagePacker imagePacker = ImagePacker.create();
    //2、设置编码输出流和编码参数。设置format为编码的图像格式,当前支持jpeg格式。设置quality为图像质量,范围从0-100,100为最佳质量。
    FileOutputStream outputStream = null;
    try {
        outputStream = new FileOutputStream("/path/to/packed.file");
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
    packingOptions.format = "image/jpeg";
    packingOptions.quality = 90;
    boolean result = imagePacker.initializePacking(outputStream, packingOptions);
    //这里开始是纯为了构造一个pixel而写的,无实际意义
    ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
    srcOpts.formatHint = "image/png";
    String pathName = "/path/to/image.png";
    ImageSource imageSource = ImageSource.create(pathName, srcOpts);
    ImageSource imageSourceNoOptions = ImageSource.create(pathName, null);
   
    ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
    decodingOpts.desiredSize = new Size(100, 2000);
    decodingOpts.desiredRegion = new Rect(0, 0, 100, 100);
    decodingOpts.rotateDegrees = 90;
    //结束,创建了一个pixelMap
    PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);
    result = imagePacker.addImage(pixelMap);
    long dataSize = imagePacker.finalizePacking();
    //5、编码输出完成后,可以进行后续处理,比如保存、传输等。
}

四、位图

位图操作就是指对PixelMap图像进行相关的操作,比如创建、查询信息、读写像素数据等。

位图操作类PixelMap主要接口如下

接口名描述
create(InitializationOptions opts)根据图像大小、像素格式、alpha类型等初始化选项创建PixelMap。
create(int[] colors, InitializationOptions opts)根据图像大小、像素格式、alpha类型等初始化选项,以像素颜色数组为数据源创建PixelMap。
create(int[] colors, int offset, int stride, InitializationOptions opts)根据图像大小、像素格式、alpha类型等初始化选项,以像素颜色数组、起始偏移量、行像素大小描述的数据源创建PixelMap。
create(PixelMap source, InitializationOptions opts)根据图像大小、像素格式、alpha类型等初始化选项,以源PixelMap为数据源创建PixelMap。
create(PixelMap source, Rect srcRegion, InitializationOptions opts)根据图像大小、像素格式、alpha类型等初始化选项,以源PixelMap、源裁剪区域描述的数据源创建PixelMap。
getBytesNumberPerRow()获取每行像素数据占用的字节数。
getPixelBytesCapacity()获取存储Pixelmap像素数据的内存容量。
isEditable()判断PixelMap是否允许修改。
isSameImage(PixelMap other)判断两个图像是否相同,包括ImageInfo属性信息和像素数据。
readPixel(Position pos)读取指定位置像素的颜色值,返回的颜色格式为PixelFormat.ARGB_8888。
readPixels(int[] pixels, int offset, int stride, Rect region)读取指定区域像素的颜色值,输出到以起始偏移量、行像素大小描述的像素数组,返回的颜色格式为PixelFormat.ARGB_8888。
readPixels(Buffer dst)读取像素的颜色值到缓冲区,返回的数据是PixelMap中像素数据的原样拷贝,即返回的颜色数据格式与PixelMap中像素格式一致。
resetConfig(Size size, PixelFormat pixelFormat)重置PixelMap的大小和像素格式配置,但不会改变原有的像素数据也不会重新分配像素数据的内存,重置后图像数据的字节数不能超过PixelMap的内存容量。
setAlphaType(AlphaType alphaType)设置PixelMap的Alpha类型。
writePixel(Position pos, int color)向指定位置像素写入颜色值,写入颜色格式为PixelFormat.ARGB_8888。
writePixels(int[] pixels, int offset, int stride, Rect region)将像素颜色数组、起始偏移量、行像素的个数描述的源像素数据写入PixelMap的指定区域,写入颜色格式为PixelFormat.ARGB_8888。
writePixels(Buffer src)将缓冲区描述的源像素数据写入PixelMap,写入的数据将原样覆盖PixelMap中的像素数据,即写入数据的颜色格式应与PixelMap的配置兼容。
writePixels(int color)将所有像素都填充为指定的颜色值,写入颜色格式为 PixelFormat.ARGB_8888。
getPixelBytesNumber()获取全部像素数据包含的字节数。
setBaseDensity(int baseDensity)设置PixelMap的基础像素密度值。
getBaseDensity()获取PixelMap的基础像素密度值。
setUseMipmap(boolean useMipmap)设置PixelMap渲染是否使用mipmap。
useMipmap()获取PixelMap渲染是否使用mipmap。
getNinePatchChunk()获取图像的NinePatchChunk数据。
getFitDensitySize(int targetDensity)获取适应目标像素密度的图像缩放的尺寸。
getImageInfo()获取图像基本信息。
release()释放对象关联的本地资源。

开发流程如下

/**
 * @description 位图
 * @author PengHuAnZhi
 * @date 2021/1/17 13:52
 */
private void testPixelMap() {
    //创建位图对象PixelMap。
    // 指定初始化选项创建
    // 从像素颜色数组创建
    int[] defaultColors = new int[]{5, 5, 5, 5, 6, 6, 3, 3, 3, 0};
    /**
     *  可以指定的初始化选项有下面几个
     *  public AlphaType alphaType;//AlphaType是一个枚举类,其中定义了若干常量
     *  public boolean editable = false;//是否可编辑
     *  public PixelFormat pixelFormat;//描述图像像素格式,也是一个枚举类
     *  public boolean releaseSource = false;//字面意思是释放资源,我也不知道是什么
     *  public ScaleMode scaleMode;//又是一个枚举类,图像缩放效果
     *  public Size size;//大小吧
     *  public boolean useSourceIfMatch = false;//如果匹配使用资源?
     */
    PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
    initializationOptions.size = new Size(3, 2);
    initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
    PixelMap pixelMap1 = PixelMap.create(defaultColors, initializationOptions);
    // 以另外一个PixelMap作为数据源创建
    PixelMap pixelMap2 = PixelMap.create(pixelMap1, initializationOptions);
    //从位图对象中获取信息。
    long capacity = pixelMap1.getPixelBytesCapacity();
    long bytesNumber = pixelMap1.getPixelBytesNumber();
    int rowBytes = pixelMap1.getBytesNumberPerRow();
    byte[] ninePatchData = pixelMap1.getNinePatchChunk();
    //读写位图像素数据。
    // 读取指定位置像素
    int color = pixelMap1.readPixel(new Position(1, 1));
    // 读取指定区域像素
    int[] pixelArray = new int[50];
    Rect region = new Rect(0, 0, 10, 5);
    pixelMap1.readPixels(pixelArray, 0, 10, region);
    // 读取像素到Buffer
    IntBuffer pixelBuf = IntBuffer.allocate(50);
    pixelMap1.readPixels(pixelBuf);
    // 在指定位置写入像素
    pixelMap1.writePixel(new Position(1, 1), 0xFF112233);
    // 在指定区域写入像素
    pixelMap1.writePixels(pixelArray, 0, 10, region);
    // 写入Buffer中的像素
    pixelMap1.writePixels(defaultColors[0]);
}

五、图像属性解码

图像属性解码就是获取图像中包含的属性信息,比如EXIF属性

功能主要由ImageSourceExifUtils提供。

  • ImageSource
接口名描述
getThumbnailInfo()获取嵌入图像文件的缩略图的基本信息。
getImageThumbnailBytes()获取嵌入图像文件缩略图的原始数据。
getThumbnailFormat()获取嵌入图像文件缩略图的格式。
  • ExifUtils
接口名描述
getLatLong(ImageSource imageSource)获取嵌入图像文件的经纬度信息。
getAltitude(ImageSource imageSource, double defaultValue)获取嵌入图像文件的海拔信息。

开发流程如下

/**
 * @description 图像属性解码
 * @author PengHuAnZhi
 * @date 2021/1/17 14:02
 */
private void testImgValueDecode() {
    //1、创建图像数据源ImageSource对象,可以通过SourceOptions指定数据源的格式信息,此格式信息仅为给
    // 解码器的提示,正确提供能帮助提高解码效率,如果不设置或设置不正确,会自动检测正确的图像格式。
    ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
    srcOpts.formatHint = "image/jpeg";
    String pathName = "/path/to/image.jpg";
    ImageSource imageSource = ImageSource.create(pathName, srcOpts);
    //2、获取缩略图信息。
    int format = imageSource.getThumbnailFormat();
    byte[] thumbnailBytes = imageSource.getImageThumbnailBytes();
    //3、将缩略图解码为PixelMap对象
    ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
    PixelMap thumbnailPixelmap = imageSource.createThumbnailPixelmap(decodingOpts, false);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值