DEV Community

HarmonyOS
HarmonyOS

Posted on

How to resolve the issue of landscape display when loading network images using the Image component?

Read the original article:How to resolve the issue of landscape display when loading network images using the Image component?

Context

The image address displays in portrait orientation on other systems, and the browser also shows it correctly. However, when loaded on the HarmonyOS system, it appears in landscape orientation. The problematic code and screenshot are as follows:

Image("URL of the Image")
  .objectFit(ImageFit.Contain)
  .width('100%')
  .backgroundColor(0x181818)
Enter fullscreen mode Exit fullscreen mode

cke_8043.png

Description

  1. EXIF (Exchangeable Image File Format) is an image file format where the data storage is identical to that of the JPEG format. EXIF can be appended to files such as JPEG, TIFF, RIFF, and RAW, adding content related to digital camera shooting information and index images or version information of image processing software.
  2. ImageSource.getImageProperty: This interface can be used to obtain the value of a specified property key at a given index in an image. It only supports JPEG, PNG, and HEIF files (support varies across different hardware devices) and requires that the file contains EXIF information. The supportedFormats property can be used to check whether EXIF read and write operations for the HEIF format are supported.

Solution

The root cause of the issue is that the Exif information in the image contains a 90° rotation directive, and the HarmonyOS Image component rotates the image based on this information. If you do not want the image to be rotated, the application needs to handle the adaptation itself. Currently, you can try the following adaptation approach:

  1. Since the Image component cannot directly access the image data, you first need to obtain the image through a network request, setting the expected data type "expectDataType" to "arraybuffer". Then, use "createImageSource" to convert it into an "image.ImageSource" object.
  2. To retrieve the Exif information of the image, you can use the "getImageProperty" interface (with "PropertyKey" set to "Orientation") to get the rotation information. Then, determine whether the image needs to be rotated. If rotation is required, you can use the "rotate" property of the Image component to perform the rotation.
  3. Finally, convert the "imageSource" into a "PixelMap" object using the "imageSource.createPixelMap" interface, and then pass the "PixelMap" object to the Image component. Here is a code reference for the above steps:
// Necessary imports
import { image } from '@kit.ImageKit';
import { http } from '@kit.NetworkKit';

async getImageOrientation() {
        let angle = 0
        const testUrl = 'https://example.com/sample.jpeg'; // Example remote image
        // Make HTTP request, expect ArrayBuffer
        let mis = await http.createHttp().request(testUrl,
            {
                expectDataType: http.HttpDataType.ARRAY_BUFFER
            }
        )
        const imageSource: image.ImageSource = image.createImageSource(mis.result as ArrayBuffer);
        imageSource.getImageProperty(image.PropertyKey.ORIENTATION)
            .then((data: string) => {
                if (data === 'Right-top') { // Back-ups for other orientation types could be set
                    angle = 90 
                }
            })
        console.log('Image angle is:' + angle.toString()) // log image orientation
    }

Enter fullscreen mode Exit fullscreen mode

Note: To make an HTTP request, do not forget to add the necessary permission:

"requestPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "reason": "$string:reason"
      }
    ]
Enter fullscreen mode Exit fullscreen mode

If you need to display the image after downloading it, you can create a new "PixelMap" and attach it based on the download.

import { http } from '@kit.NetworkKit';
import { image } from '@kit.ImageKit';
import { common } from '@kit.AbilityKit';

@Entry
@Component
struct Index {
  @State pixelMap: image.PixelMap | undefined = undefined;
  @State angle: number = 0;

   // get context properly
  context = this.getUIContext().getHostContext() as common.UIAbilityContext;

  // Example remote image
  private testUrl: string = 'https://example.com/sample.jpeg';

  aboutToAppear(): void {
    this.downloadAndShow();
  }

  async downloadAndShow() {
    try {
      // Make HTTP request, expect ArrayBuffer
      let httpRequest = http.createHttp();
      let res = await httpRequest.request(this.testUrl, {
        method: http.RequestMethod.GET,
        expectDataType: http.HttpDataType.ARRAY_BUFFER,
        connectTimeout: 6000, // Set timeout for safer request
        readTimeout: 6000, // Set timeout for safer request
      });

      if (res.result) {
        // Create ImageSource from ArrayBuffer
        const imageSource: image.ImageSource = image.createImageSource(res.result as ArrayBuffer);

        // Read EXIF orientation
        let data = await imageSource.getImageProperty(image.PropertyKey.ORIENTATION);
        if (data === 'Right-top') {  // Back-ups for other orientation types could be set
          this.angle = 90;
        }
        // Create PixelMap for displaying in Image
        this.pixelMap = await imageSource.createPixelMap();
      }
    } catch (err) {
      console.error('Download or decode failed: ' + JSON.stringify(err));
    }
  }

  build() {
    RelativeContainer() {
      if (this.pixelMap) {
        Image(this.pixelMap)
          .objectFit(ImageFit.Contain)
          .rotate({ angle: this.angle })
          .width('100%')
          .height('100%')
      } else {
        Text('Loading...')
          .alignRules({
            center: { anchor: '__container__', align: VerticalAlign.Center },
            middle: { anchor: '__container__', align: HorizontalAlign.Center }
          })
      }
    }
    .height('100%')
    .width('100%')
  }
}
Enter fullscreen mode Exit fullscreen mode

cke_8043.png

Key Takeaways

  • When loading images, the Image component may be affected by the Exif information of the image, potentially leading to results that differ from expectations. In such cases, it is necessary to first read and analyze the Exif information of the image, and then configure the image loading with the correct properties.
  • If you want to download the image request.downloadFile from @ohos.request and then get the image source with fileIo.openSync (which works only on mobile) from @kit.CoreFileKit can be used.

Written by Emine Inan

Top comments (0)