• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Image
2
3The **\<Image>** component is used to render and display local and online images.
4
5> **NOTE**
6>
7> This component is supported since API version 7. Updates will be marked with a superscript to indicate their earliest API version.
8
9
10## Required Permissions
11
12To use online images, the application must have the **ohos.permission.INTERNET** permission. For details about how to apply for a permission, see [Declaring Permissions](../../security/accesstoken-guidelines.md).
13
14
15## Child Components
16
17Not supported
18
19
20## APIs
21
22Image(src: string | PixelMap | Resource)
23
24Obtains an image from the specified source for subsequent rendering and display.
25
26Since API version 9, this API is supported in ArkTS widgets.
27
28**Parameters**
29
30| Name | Type                                    | Mandatory  | Description                                    |
31| ---- | ---------------------------------------- | ---- | ---------------------------------------- |
32| src  |  string \| [PixelMap](../apis/js-apis-image.md#pixelmap7) \| [Resource](ts-types.md#resource) | Yes   | Image source. Both local and online images are supported.<br>When using an image referenced using a relative path, for example, **Image("common/test.jpg")**, the **\<Image>** component cannot be called across bundles or modules. Therefore, you are advised to use **\$r** to reference image resources that need to be used globally.<br>- The following image formats are supported: PNG, JPG, BMP, SVG, GIF.<br>\- Base64 strings are supported. The value format is data:image/[png\|jpeg\|bmp\|webp];base64,[base64 data], where [base64 data] is a Base64 string.<br/>\- Strings with the **datashare://** prefix are supported, which are used to access the image path provided by a Data ability.<br/>\- Strings with the **file:///data/storage** prefix are supported, which are used to read image resources in the **files** folder in the installation directory of the current application. Ensure that the application has the read permission to the files in the specified path.<br/>**NOTE**<br/>- ArkTS widgets support GIF animations, but the animations only play once on display.<br/>- ArkTS widgets do not support the strings with the **http://**, **datashare://**, or **file:///data/storage** prefix.<br>- ArkTS widgets do not support the [PixelMap](../apis/js-apis-image.md#pixelmap7) type. |
33
34## Attributes
35
36In addition to the [universal attributes](ts-universal-attributes-size.md), the following attributes are supported.
37
38| Name                      | Type                                    | Description                                      |
39| ------------------------ | ---------------------------------------- | ---------------------------------------- |
40| alt                      | string \| [Resource](ts-types.md#resource)| Placeholder image displayed during loading. Local images are supported.<br>Since API version 9, this API is supported in ArkTS widgets.|
41| objectFit                | [ImageFit](ts-appendix-enums.md#imagefit) | Image scale mode.<br>Default value: **ImageFit.Cover**<br>Since API version 9, this API is supported in ArkTS widgets.|
42| objectRepeat             | [ImageRepeat](ts-appendix-enums.md#imagerepeat) | Whether the image is repeated.<br>Default value: **ImageRepeat.NoRepeat**<br>Since API version 9, this API is supported in ArkTS widgets.<br>**NOTE**<br>This attribute is not applicable to SVG images.|
43| interpolation            | [ImageInterpolation](#imageinterpolation) | Interpolation effect of the image. This attribute is intended to alleviate aliasing that occurs when a low-definition image is zoomed in.<br>Default value: **ImageInterpolation.None**<br>Since API version 9, this API is supported in ArkTS widgets.<br>**NOTE**<br>This attribute is not applicable to SVG images.<br>This attribute is not applicable to **PixelMap** objects.|
44| renderMode               | [ImageRenderMode](#imagerendermode)      | Rendering mode of the image.<br>Default value: **ImageRenderMode.Original**<br>Since API version 9, this API is supported in ArkTS widgets.<br>**NOTE**<br>This attribute is not applicable to SVG images.|
45| sourceSize               | {<br>width: number,<br>height: number<br>} | Size of the decoded image. The original image is decoded into a **pixelMap** of the specified size, in px.<br>Since API version 9, this API is supported in ArkTS widgets.<br>**NOTE**<br>This attribute is not applicable to **PixelMap** objects or SVG images.|
46| matchTextDirection       | boolean                                  | Whether to display the image in the system language direction. When this parameter is set to true, the image is horizontally flipped in the right-to-left (RTL) language context.<br>Default value: **false**<br>Since API version 9, this API is supported in ArkTS widgets.|
47| fitOriginalSize          | boolean                                  | Whether to fit the component to the original size of the image source when the component size is not set.<br>Default value: **false**<br>Since API version 9, this API is supported in ArkTS widgets.|
48| fillColor                | [ResourceColor](ts-types.md#resourcecolor) | Fill color. This attribute only applies to an SVG image. Once set, the fill color will replace that of the SVG image.<br>Since API version 9, this API is supported in ArkTS widgets.|
49| autoResize               | boolean                                  | Whether to resize the image source used for drawing based on the size of the display area during image decoding. This resizing can help reduce the memory usage.<br>Default value: **true**<br>Since API version 9, this API is supported in ArkTS widgets.|
50| syncLoad<sup>8+</sup>    | boolean                                  | Whether to load the image synchronously. By default, the image is loaded asynchronously. During synchronous loading, the UI thread is blocked and the placeholder diagram is not displayed.<br>Default value: **false**<br>Since API version 9, this API is supported in ArkTS widgets.|
51| copyOption<sup>9+</sup>  | [CopyOptions](ts-appendix-enums.md#copyoptions9) | Whether the image can be copied. (SVG images cannot be copied.)<br>When **copyOption** is set to a value other than **CopyOptions.None**, the image can be copied in various manners, such as long pressing, right-clicking, or pressing Ctrl+C.<br>Default value: **CopyOptions.None**<br>This API is supported in ArkTS widgets.|
52| colorFilter<sup>9+</sup> | [ColorFilter](ts-types.md#colorfilter9)  | Color filter of the image.<br>This API is supported in ArkTS widgets.      |
53
54>  **NOTE**
55>
56>  To use shortcut keys to copy the image, the image must be in focus. To enable the image to gain focus, set both the **focusable** and **focusOnTouch** attributes to **true**.
57>
58>  For SVG images, only the following tags are included in the supported list: **svg**, **rect**, **circle**, **ellipse**, **path**, **line**, **polyline**, and **polygon**.
59
60### ImageInterpolation
61
62Since API version 9, this API is supported in ArkTS widgets.
63
64| Name    | Description                       |
65| ------ | ------------------------- |
66| None   | Interpolation image data is not used.               |
67| High   | The interpolation image data is used at the high level, which may affect the image rendering speed.|
68| Medium | The interpolation image data is used at the medium level.             |
69| Low    | The interpolation image data is used at the low level.             |
70
71### ImageRenderMode
72
73Since API version 9, this API is supported in ArkTS widgets.
74
75| Name      | Description                   |
76| -------- | --------------------- |
77| Original | The image is rendered based on the original image, including the color.       |
78| Template | The image is rendered as a template image, and its color is ignored.|
79
80## Events
81
82In addition to the [universal events](ts-universal-events-click.md), the following events are supported.
83
84| Name                                      | Description                                    |
85| ---------------------------------------- | ---------------------------------------- |
86| onComplete(callback: (event?: { width: number, height: number, componentWidth: number,<br> componentHeight: number, loadingStatus: number }) =&gt; void) | Triggered when an image is successfully loaded. The size of the loaded image is returned.<br>- **width**: width of the image, in pixels.<br>- **height**: height of the image, in pixels.<br>- **componentWidth**: width of the container component, in pixels.<br>- **componentHeight**: height of the container component, in pixels.<br>- **loadingStatus**: image loading status.<br>Since API version 9, this API is supported in ArkTS widgets.<br>**NOTE**<br>The value **1** means that the image is successfully loaded, and **0** means the opposite.|
87| onError(callback: (event?: { componentWidth: number, componentHeight: number , message<sup>9+</sup>: string }) =&gt; void) | Triggered when an exception occurs during image loading.<br>- **componentWidth**: width of the container component, in pixels.<br>- **componentHeight**: height of the container component, in pixels.<br>Since API version 9, this API is supported in ArkTS widgets.|
88| onFinish(event: () =&gt; void) | Triggered when the animation playback in the loaded SVG image is complete. If the animation is an infinite loop, this callback is not triggered.<br>Since API version 9, this API is supported in ArkTS widgets.|
89
90## Example
91
92### Loading Images
93
94Load and display different types of images and set the scale mode of the images.
95
96```ts
97@Entry
98@Component
99struct ImageExample1 {
100  private on: string = 'www.example.com'
101  @State src: string = this.on
102
103  build() {
104    Column() {
105      Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start }) {
106        Text('default').fontSize(16).fontColor(0xcccccc).height(30)
107        Row({ space: 5 }) {
108          Image($r('app.media.ic_png'))
109            .width(110).height(110).border({ width: 1 })
110            .overlay('png', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
111          Image($r('app.media.ic_gif'))
112            .width(110).height(110).border({ width: 1 })
113            .overlay('gif', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
114          Image($r('app.media.ic_svg'))
115            .width(110).height(110).border({ width: 1 })
116            .overlay('svg', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
117        }
118        Row({ space: 5 }) {
119          Image($r('app.media.img_example'))
120            .width(110).height(110).border({ width: 1 })
121            .overlay('jpg', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
122          Image(this.src)
123            .width(110).height(110).border({ width: 1 })
124            .overlay('network', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
125        }.margin({ top: 25, bottom: 10 })
126      }
127
128      Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start }) {
129        Text('objectFit').fontSize(16).fontColor(0xcccccc).height(30)
130        Row({ space: 5 }) {
131          Image($r('app.media.img_example'))
132            .border({ width: 1 })
133            .objectFit(ImageFit.None).width(110).height(110)
134            .overlay('None', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
135          Image($r('app.media.img_example'))
136            .border({ width: 1 })
137            .objectFit(ImageFit.Fill).width(110).height(110)
138            .overlay('Fill', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
139          Image($r('app.media.img_example'))
140            .border({ width: 1 })
141            .objectFit(ImageFit.Cover).width(110).height(110)
142            .overlay('Cover', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
143        }
144        Row({ space: 5 }) {
145          Image($r('app.media.img_example_w250'))
146            .border({ width: 1 })
147            .objectFit(ImageFit.Contain).width(110).height(110)
148            .overlay('Contain', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
149          Image($r('app.media.img_example_w250'))
150            .border({ width: 1 })
151            .objectFit(ImageFit.ScaleDown).width(110).height(110)
152            .overlay('ScaleDown', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
153        }.margin({ top: 25 })
154      }
155    }.height(320).width(360).padding({ right: 10, top: 10 })
156  }
157}
158```
159
160![en-us_image_0000001211898484](figures/en-us_image_0000001211898484.gif)
161
162
163
164### Loading Online Images
165
166The default network timeout period is 5 minutes for loading online images. When using an online image, you are advised to use **alt** to configure the placeholder image displayed during loading. If more flexible network configuration is required, you can use the [HTTP](../../connectivity/http-request.md) tool provided in the SDK to send a network request, and then decode the returned data into **PixelMap** objects in the **\<Image>** component. For details about image development, see [Image Processing](../../media/image-overview.md). The code snippet is as follows:
167
168```tsx
169// @ts-nocheck
170import http from '@ohos.net.http'
171import ResponseCode from '@ohos.net.http'
172import image from '@ohos.multimedia.image'
173
174
175@Entry
176@Component
177struct Index {
178
179  // Create a PixelMap state variable to receive online images.
180  @State image: PixelMap = undefined
181
182  build() {
183    Column({space: 10}) {
184      Button ("Get Online Image")
185        .onClick(() => {
186          this.httpRequest()
187        })
188      Image(this.image).height(100).width(100)
189    }
190    .width('100%')
191    .height('100%')
192    .padding(10)
193  }
194
195  // Request an online image.
196  private httpRequest() {
197    let httpRequest = http.createHttp()
198
199    httpRequest.request(
200      "https://www.example.com/xxx.png",   // Enter a specific URL of the online image.
201      (error, data) => {
202        if(error) {
203          console.log("error code: " + error.code + ", msg: " + error.message)
204        } else {
205          let code = data.responseCode
206          if(ResponseCode.ResponseCode.OK == code) {
207            let imageSource = image.createImageSource(data.result)
208            let options = {alphaType: 0,                     // Opacity
209                           editable: false,                  // Whether the image is editable
210                           pixelFormat: 3,                   // Pixel format
211                           scaleMode: 1,                     // Scale mode
212                           size: {height: 100, width: 100}} // Image size
213            imageSource.createPixelMap(options).then((pixelMap) => {
214              this.image = pixelMap
215            })
216          } else {
217            console.log("response code: " + code)
218          }
219        }
220      }
221    )
222  }
223}
224```
225
226> **NOTE**
227>
228> For details about the request mode, timeout, and additional request parameters for loading online images, see [request()](../../reference/apis/js-apis-http.md) in the HTTP module.
229
230### Setting Attributes
231
232```ts
233@Entry
234@Component
235struct ImageExample2 {
236
237  build() {
238    Column({ space: 10 }) {
239      Text('renderMode').fontSize(12).fontColor(0xcccccc).width('96%').height(30)
240      Row({ space: 50 }) {
241        Image($r('app.media.img_example'))
242          .renderMode(ImageRenderMode.Original).width(100).height(100)
243          .border({ width: 1 })
244          .overlay('Original', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
245        Image($r('app.media.img_example'))
246          .renderMode(ImageRenderMode.Template).width(100).height(100)
247          .border({ width: 1 })
248          .overlay('Template', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
249      }
250
251      Text('alt').fontSize(12).fontColor(0xcccccc).width('96%').height(30)
252      Image('')
253        .alt($r('app.media.Image_none'))
254        .width(100).height(100).border({ width: 1 })
255
256      Text('sourceSize').fontSize(12).fontColor(0xcccccc).width('96%')
257      Row({ space: 50 }) {
258        Image($r('app.media.img_example'))
259          .sourceSize({
260            width: 150,
261            height: 150
262          })
263          .objectFit(ImageFit.ScaleDown).width('25%').aspectRatio(1)
264          .border({ width: 1 })
265          .overlay('w:150 h:150', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
266        Image($r('app.media.img_example'))
267          .sourceSize({
268            width: 200,
269            height: 200
270          })
271          .objectFit(ImageFit.ScaleDown).width('25%').aspectRatio(1)
272          .border({ width: 1 })
273          .overlay('w:200 h:200', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
274      }
275
276      Text('objectRepeat').fontSize(12).fontColor(0xcccccc).width('96%').height(30)
277      Row({ space: 5 }) {
278        Image($r('app.media.ic_health_heart'))
279          .width(120).height(125).border({ width: 1 })
280          .objectRepeat(ImageRepeat.XY).objectFit(ImageFit.ScaleDown)
281          .overlay('ImageRepeat.XY', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
282        Image($r('app.media.ic_health_heart'))
283          .width(110).height(125).border({ width: 1 })
284          .objectRepeat(ImageRepeat.Y).objectFit(ImageFit.ScaleDown)
285          .overlay('ImageRepeat.Y', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
286        Image($r('app.media.ic_health_heart'))
287          .width(110).height(125).border({ width: 1 })
288          .objectRepeat(ImageRepeat.X).objectFit(ImageFit.ScaleDown)
289          .overlay('ImageRepeat.X', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
290      }
291    }.height(150).width('100%').padding({ right: 10 })
292  }
293}
294```
295
296![en-us_image_0000001212058474](figures/en-us_image_0000001212058474.png)
297
298### Invoking Events
299
300```ts
301@Entry
302@Component
303struct ImageExample3 {
304  @State widthValue: number = 0
305  @State heightValue: number = 0
306  private on: Resource = $r('app.media.image_on')
307  private off: Resource = $r('app.media.image_off')
308  private on2off: Resource = $r('app.media.image_on2off')
309  private off2on: Resource = $r('app.media.image_off2on')
310  @State src: Resource = this.on
311
312  build() {
313    Column() {
314      Row({ space: 20 }) {
315        Column() {
316          Image($r('app.media.img_example1'))
317            .alt($r('app.media.ic_public_picture'))
318            .sourceSize({
319              width: 900,
320              height: 900
321            })
322            .objectFit(ImageFit.Cover)
323            .height(180).width(180)
324            // Obtain the size of an image after the image loading is complete.
325            .onComplete((msg: { width: number,height: number }) => {
326              this.widthValue = msg.width
327              this.heightValue = msg.height
328            })
329            .onError(() => {
330              console.log('load image fail')
331            })
332            .overlay('\nwidth: ' + String(this.widthValue) + ' height: ' + String(this.heightValue), {
333              align: Alignment.Bottom,
334              offset: { x: 0, y: 20 }
335            })
336        }
337        // Add a click event so that a specific image is loaded upon clicking.
338        Image(this.src)
339          .width(120).height(120)
340          .onClick(() => {
341            if (this.src == this.on || this.src == this.off2on) {
342              this.src = this.on2off
343            } else {
344              this.src = this.off2on
345            }
346          })
347          .onFinish(() => {
348            if (this.src == this.off2on) {
349              this.src = this.on
350            } else {
351              this.src = this.off
352            }
353          })
354      }
355    }.width('100%')
356  }
357}
358```
359
360![en-us_image_0000001256858397](figures/en-us_image_0000001256858397.gif)
361
362###  Rendering Sandbox Images
363
364```ts
365import fileio from '@ohos.fileio';
366import fs from '@ohos.file.fs';
367import context from '@ohos.app.ability.common';
368
369@Entry
370@Component
371struct LoadImageExample {
372  @State resourcesPath: string = ''
373  @State sandboxPath: string = ''
374  context: context.UIAbilityContext = getContext(this) as context.UIAbilityContext
375
376  build() {
377    Column() {
378      Button ('Read Sandbox Image')
379        .margin({ bottom: 10, top: 10 })
380        .onClick(() => {
381          this.sandboxPath = this.context.getApplicationContext().filesDir + '/icon.png'
382          console.log(`Read the sandbox image=========>${this.sandboxPath}`)
383          let fd = fs.openSync(this.sandboxPath, 0o100)
384          console.log(`create file========>${fd}`)
385          let srcPath = this.context.bundleCodeDir + '/entry/resources/base/media/icon.png'
386          console.log('mySrcpath' + srcPath)
387          fileio.copyFileSync(srcPath, this.sandboxPath) // Copy the image to the sandbox path.
388          this.sandboxPath = 'file://' + this.context.getApplicationContext().filesDir + '/icon.png'
389        })
390      Button ('Read Image')
391        .margin({ bottom: 10 })
392        .onClick(() => {
393          this.resourcesPath = 'file://' + this.context.bundleCodeDir + '/entry/resources/base/media/icon.png'
394        })
395      Text(`Image path: ${this.resourcesPath}`)
396        .fontSize(20)
397        .margin({ bottom: 10 })
398      Image(this.resourcesPath)
399        .width(100)
400        .height(100)
401        .colorFilter([
402          0.30, 0.59, 0.11, 0, 0,
403          0.30, 0.59, 0.11, 0, 0,
404          0.30, 0.59, 0.11, 0, 0,
405          0, 0, 0, 1.0, 0
406        ])
407      Text(`Sandbox image path: ${this.sandboxPath}`)
408        .fontSize(20)
409        .margin({ bottom: 10 })
410      Image(this.sandboxPath)
411        .width(100)
412        .height(100)
413    }
414    .width('100%').height('100%')
415  }
416}
417```
418
419### Applying a Filter to an Image
420
421```ts
422// xxx.ets
423@Entry
424@Component
425struct colorFilterExample {
426  @State colorFilterR: number = 0
427  @State colorFilterG: number = 0
428  @State colorFilterB: number = 0
429  @State colorFilterA: number = 0
430
431  build() {
432    Row() {
433      Column() {
434        Image($r('app.media.sky'))
435          .width(200)
436          .height(200)
437        Image($r('app.media.sky'))
438          .width(200)
439          .height(200)
440          .colorFilter([
441          this.colorFilterR, 0, this.colorFilterR, 0, 0,
442            0, this.colorFilterG, this.colorFilterG, 0, 0,
443          this.colorFilterB, 0, this.colorFilterB, 0, 0,
444            0, 0, this.colorFilterA, 0, 0
445          ])
446
447        Row() {
448          Text('R')
449          Slider({
450            min: 0,
451            max: 1,
452            step: 0.01
453          })
454            .onChange((valueR) => {
455              this.colorFilterR = valueR
456            })
457        }
458
459        Row() {
460          Text('G')
461          Slider({
462            min: 0,
463            max: 1,
464            step: 0.01
465          })
466            .onChange((valueG) => {
467              this.colorFilterG = valueG
468            })
469        }
470
471        Row() {
472          Text('B')
473          Slider({
474            min: 0,
475            max: 1,
476            step: 0.01
477          })
478            .onChange((valueB) => {
479              this.colorFilterB = valueB
480            })
481        }
482
483        Row() {
484          Text('A')
485          Slider({
486            min: 0,
487            max: 1,
488            step: 0.01
489          })
490            .onChange((valueA) => {
491              this.colorFilterA = valueA
492            })
493        }
494      }.width('90%').alignItems(HorizontalAlign.Center)
495    }.height('100%').width('100%').justifyContent(FlexAlign.Center)
496  }
497}
498```
499
500![colorFilter](figures/colorFilter.gif)
501