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 }) => 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 }) => 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: () => 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 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 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 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 501