一 开发环境

系统:OpenHarmony 5.1.0 Release

产品:rk3568

 

二 问题现象

使用Image组件加载部分网络图片时,图片会变成横屏展示,该如何解决?

Image('图片地址')
  .objectFit(ImageFit.Contain)
  .width('100%')
  .backgroundColor(0x181818)

 

三 背景知识

1. Exif(Exchangeable image file format 可交换图像文件格式),是一种图像文件格式,其数据存储与JPEG格式是完全相同的,EXIF可以附加于JPEG、TIFF、RIFF、RAW等文件之中,为其增加有关数码相机拍摄信息的内容和索引图或图像处理软件的版本信息。
2. ImageSource.getImageProperty:可以通过该接口获取图片中给定索引处图像的指定属性键的值,仅支持JPEG、PNG和HEIF(不同硬件设备支持情况不同)文件,且需要包含Exif信息。其中可以通过supportedFormats属性查询是否支持HEIF格式的Exif读写

 

四 解决方案

该问题的根本原因是图片里的Exif信息存在旋转90°的信息,Image组件会读取图片中的信息并旋转。如果不想旋转需要应用自行进行适配,目前可尝试如下以下方案适配:

1. 由于Image组件无法拿到图片数据,需要先通过网络请求获取图片,设置传输数据类型expectDataType为arraybuffer,然后使用createImageSource转换成image.ImageSource对象。
2. 获取图片Exif信息,可以通过getImageProperty接口 (PropertyKey传入"Orientation")获取旋转信息。通过判断图片是否要旋转,并将不同返回值的旋转角度返回给Image组件的rotate属性进行旋转。
3. 若需要将网络图片保存至本地使用,可以下载网络图片获取图片数据后,通过imageSource.createPixelMap接口,转成PixelMap对象,最后将PixelMap对象的图片给到Image组件。

import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { image } from '@kit.ImageKit';

@Entry
@Component
struct ImageExample2 {
  @State pixelMapImg: PixelMap | undefined = undefined;
  @State imageUrl: string = 'https://www.example.com/xxx.png'
  @State angel: number = 0;

  aboutToAppear() {
    this.requestImageUrl(this.imageUrl); // 请填写一个具体的网络图片地址
  }

  requestImageUrl(url: string) {
    http.createHttp().request(url,
      {
        expectDataType: http.HttpDataType.ARRAY_BUFFER
      },
      (error: BusinessError, data: http.HttpResponse) => {
        if (error) {
          console.error(`request image failed: url: ${url}, code: ${error.code}, message: ${error.message}`);
        } else {
          let imgData: ArrayBuffer = data.result as ArrayBuffer;
          console.info(`request image success, size: ${imgData.byteLength}`);
          let imgSource: image.ImageSource = image.createImageSource(imgData);
          imgSource.createPixelMap().then((pixelMap: PixelMap) => {
            imgSource.getImageProperty(image.PropertyKey.ORIENTATION).then((data:string)=>{
              console.info('image orientation data is',data)
              if (data === 'Right-top'){
                this.angel = 90;
              }
            })
            console.info('image createPixelMap success');
            this.pixelMapImg = pixelMap;
            imgSource.release();
          }).catch(() => {
            imgSource.release();
          })
        }
      })
  }

  build() {
    Column() {
      Image(this.imageUrl)
        .objectFit(ImageFit.None)
        .width('100%')
        .height('100%')
        .rotate({ angle: this.angel })
    }
  }
}

若需要下载图片后进行展示,可以通过downloadFile方法将图片下载到本地后,创建新PixelMap进行展示。

downloadImage(){
  let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  let tempPath = context.filesDir + '/' + new Date().getTime() + '.jpeg';
  try {
    request.downloadFile(this.getUIContext().getHostContext(), {
      url: this.imageUrl,
      filePath: tempPath
    }).then((downloadTask: request.DownloadTask) => {
      downloadTask.on('complete', async () => {
        let file = fileIo.openSync(tempPath, fileIo.OpenMode.READ_ONLY);
        let imgSource: image.ImageSource = image.createImageSource(file.fd);
        imgSource.createPixelMap().then((pixelMap: PixelMap) => {
          imgSource.getImageProperty(image.PropertyKey.ORIENTATION).then((data: string) => {
            console.info('===', data)
            if (data === 'Right-top') {
              this.angel = 90;
            }
          })
          console.info('image createPixelMap success');
          this.pixelMapImg = pixelMap;
          imgSource.release();
        }).catch(() => {
          imgSource.release();
        })
      })
    })
  } catch (error) {
    console.error('download error',error)
  }
}

自API 14起,对于包含EXIF信息的图片可以通过设置图片的通用属性orientation为ImageRotateOrientation.AUTO,读取图片携带的EXIF元数据作为显示方向,支持旋转和镜像。

五 总结

Image在加载图片时受图片的Exif信息的影响,可能会和预期不符,此时需要先读取并分析图片的Exif信息,然后再用正确的属性配置加载图片。

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐