or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

font-resources.mdimage-drawable-resources.mdindex.mdplural-string-resources.mdresource-environment.mdstring-array-resources.mdstring-resources.md

image-drawable-resources.mddocs/

0

# Image and Drawable Resources

1

2

Image and drawable resources provide type-safe access to visual assets including raster images, vector graphics, and SVG files. The library automatically handles format detection, density-aware scaling, and platform-specific optimizations.

3

4

## Core Types

5

6

```kotlin { .api }

7

class DrawableResource(id: String, items: Set<ResourceItem>) : Resource(id, items)

8

```

9

10

A drawable resource represents any visual asset that can be rendered as an image, vector, or painter. This includes PNG, JPEG, WebP, XML vectors, and SVG files.

11

12

## Composable Functions

13

14

### Automatic Painter Creation

15

16

```kotlin { .api }

17

@Composable

18

fun painterResource(resource: DrawableResource): Painter

19

```

20

21

Creates a Painter from a drawable resource with automatic format detection. The function selects the appropriate painter type based on the file extension:

22

- `.xml` files → Vector painter

23

- `.svg` files → SVG painter

24

- Other formats → Bitmap painter

25

26

**Usage:**

27

```kotlin

28

@Composable

29

fun AppIcon() {

30

val icon = painterResource(Res.drawable.app_icon)

31

Image(

32

painter = icon,

33

contentDescription = "Application Icon",

34

modifier = Modifier.size(48.dp)

35

)

36

}

37

```

38

39

### Bitmap Image Loading

40

41

```kotlin { .api }

42

@Composable

43

fun imageResource(resource: DrawableResource): ImageBitmap

44

```

45

46

Loads a raster image as an ImageBitmap with automatic density scaling. The function selects the best density variant and scales appropriately for the current screen.

47

48

**Usage:**

49

```kotlin

50

@Composable

51

fun ProfilePhoto(user: User) {

52

val photo = imageResource(Res.drawable.default_profile)

53

Image(

54

bitmap = photo,

55

contentDescription = "Profile Photo",

56

contentScale = ContentScale.Crop,

57

modifier = Modifier

58

.size(80.dp)

59

.clip(CircleShape)

60

)

61

}

62

```

63

64

**Density Handling:**

65

The library automatically selects the best image density variant:

66

1. Exact or higher density match (preferred)

67

2. Lower density with upscaling

68

3. Default (MDPI) with scaling

69

4. LDPI as last resort

70

71

### Vector Graphics Loading

72

73

```kotlin { .api }

74

@Composable

75

fun vectorResource(resource: DrawableResource): ImageVector

76

```

77

78

Loads XML vector graphics as ImageVector objects. Supports Android Vector Drawable format with full path, group, and gradient support.

79

80

**Usage:**

81

```kotlin

82

@Composable

83

fun NavigationIcon(isSelected: Boolean) {

84

val icon = vectorResource(

85

if (isSelected) Res.drawable.ic_home_filled

86

else Res.drawable.ic_home_outline

87

)

88

Icon(

89

imageVector = icon,

90

contentDescription = "Home",

91

tint = if (isSelected) MaterialTheme.colors.primary

92

else MaterialTheme.colors.onSurface

93

)

94

}

95

```

96

97

## Suspend Functions

98

99

### Raw Resource Bytes

100

101

```kotlin { .api }

102

suspend fun getDrawableResourceBytes(

103

environment: ResourceEnvironment,

104

resource: DrawableResource

105

): ByteArray

106

```

107

108

Retrieves the raw byte content of a drawable resource. Useful for custom processing, external libraries, or passing to platform-specific APIs.

109

110

**Parameters:**

111

- `environment` - Resource environment for variant selection

112

- `resource` - The drawable resource to load

113

114

**Usage:**

115

```kotlin

116

suspend fun uploadImageToServer(imageResource: DrawableResource) {

117

val environment = getSystemResourceEnvironment()

118

val imageBytes = getDrawableResourceBytes(environment, imageResource)

119

120

// Upload bytes to server

121

uploadService.uploadImage(imageBytes)

122

}

123

124

suspend fun saveImageToFile(imageResource: DrawableResource, outputPath: String) {

125

val environment = getSystemResourceEnvironment()

126

val bytes = getDrawableResourceBytes(environment, imageResource)

127

File(outputPath).writeBytes(bytes)

128

}

129

```

130

131

## Resource Variants and Selection

132

133

### Density Qualifiers

134

135

The library supports multiple density variants for optimal display quality:

136

137

```

138

drawable/ # Default (MDPI - 160dpi)

139

drawable-ldpi/ # Low density (120dpi)

140

drawable-hdpi/ # High density (240dpi)

141

drawable-xhdpi/ # Extra high density (320dpi)

142

drawable-xxhdpi/ # Extra extra high density (480dpi)

143

drawable-xxxhdpi/ # Extra extra extra high density (640dpi)

144

```

145

146

**Selection Algorithm:**

147

1. Find exact or next higher density

148

2. Scale down if necessary (preferred)

149

3. Fall back to lower density with upscaling

150

4. Use default (MDPI) if no specific density available

151

152

### Theme Variants

153

154

Support for light and dark theme variants:

155

156

```

157

drawable/ # Default/light theme

158

drawable-night/ # Dark theme variants

159

```

160

161

**Usage:**

162

```kotlin

163

@Composable

164

fun ThemedIcon() {

165

// Automatically selects light/dark variant based on system theme

166

val icon = painterResource(Res.drawable.themed_icon)

167

Icon(imageVector = icon, contentDescription = "Themed Icon")

168

}

169

```

170

171

## Supported Formats

172

173

### Raster Images

174

- **PNG** - Full transparency support, recommended for icons

175

- **JPEG** - Efficient for photos, no transparency

176

- **WebP** - Modern format with excellent compression

177

178

### Vector Graphics

179

- **XML Vector Drawable** - Android's vector format with paths, groups, gradients

180

- **SVG** - Scalable Vector Graphics with broad compatibility

181

182

### Format Detection

183

The library automatically detects format based on file extension:

184

- `.png`, `.jpg`, `.jpeg`, `.webp` → Bitmap handling

185

- `.xml` → Vector drawable parsing

186

- `.svg` → SVG parsing and rendering

187

188

## Performance Considerations

189

190

### Image Caching

191

192

The library includes automatic caching to improve performance:

193

194

```kotlin

195

// Images are cached by path and density

196

// Cache key format: "path-{density}dpi"

197

val cachedImage = imageResource(Res.drawable.large_image) // Cached on first load

198

```

199

200

### Memory Management

201

202

**Best Practices:**

203

1. Use appropriate image densities to avoid unnecessary memory usage

204

2. Consider WebP format for better compression

205

3. Use vector graphics for simple icons and illustrations

206

4. Lazy load images in lists and grids

207

208

### Cache Control

209

210

```kotlin

211

// For testing or memory management, cache can be cleared

212

// Note: This is internal API

213

internal fun dropImageCache()

214

```

215

216

## Platform-Specific Behavior

217

218

### Android

219

- Native bitmap decoding with hardware acceleration

220

- Automatic density selection based on screen density

221

- Vector drawable native support

222

223

### Desktop (JVM)

224

- Skia-based rendering for consistent appearance

225

- Density simulation for high-DPI displays

226

- SVG support through integrated parser

227

228

### iOS

229

- Core Graphics integration for optimal performance

230

- Retina display support with automatic scaling

231

- Memory-efficient image loading

232

233

### Web (JS/Wasm)

234

- Canvas-based rendering for vectors

235

- Efficient image loading with browser caching

236

- Progressive loading for better user experience

237

238

## Error Handling

239

240

**Common Exceptions:**

241

- `MissingResourceException` - Resource file not found

242

- `IllegalArgumentException` - Invalid resource ID

243

- Rendering errors for corrupted or unsupported image formats

244

245

**Example Error Handling:**

246

```kotlin

247

@Composable

248

fun SafeImageLoad(resourceId: DrawableResource) {

249

try {

250

val image = painterResource(resourceId)

251

Image(painter = image, contentDescription = null)

252

} catch (e: MissingResourceException) {

253

// Show placeholder or error state

254

Icon(Icons.Default.ImageNotSupported, contentDescription = "Image not found")

255

}

256

}

257

```

258

259

## Best Practices

260

261

1. **Provide multiple density variants** for raster images:

262

```

263

drawable-mdpi/icon.png (48x48)

264

drawable-hdpi/icon.png (72x72)

265

drawable-xhdpi/icon.png (96x96)

266

drawable-xxhdpi/icon.png (144x144)

267

```

268

269

2. **Use vector drawables for simple graphics**:

270

- Icons, simple illustrations

271

- Graphics that need to scale without quality loss

272

- UI elements with solid colors

273

274

3. **Use raster images for complex graphics**:

275

- Photographs

276

- Complex illustrations with gradients

277

- Images with many colors and details

278

279

4. **Optimize image sizes** for target platforms:

280

- Consider platform-specific limitations

281

- Use appropriate compression settings

282

- Test on actual devices for performance

283

284

5. **Provide theme variants** when appropriate:

285

```kotlin

286

// Use same resource ID, library selects theme variant automatically

287

val icon = painterResource(Res.drawable.app_icon) // Auto light/dark

288

```

289

290

## Image Decoder Extensions

291

292

The library provides extension functions for decoding raw image bytes into Compose graphics objects.

293

294

### Bitmap Decoder

295

296

```kotlin { .api }

297

fun ByteArray.decodeToImageBitmap(): ImageBitmap

298

```

299

300

Decodes a byte array of a bitmap to an ImageBitmap. Supports JPEG, PNG, BMP, WEBP formats. Different platforms may support additional formats.

301

302

**Usage:**

303

```kotlin

304

suspend fun loadExternalImage(imageUrl: String): ImageBitmap {

305

val imageBytes = httpClient.get(imageUrl).readBytes()

306

return imageBytes.decodeToImageBitmap()

307

}

308

309

suspend fun processImageResource(): ImageBitmap {

310

val environment = getSystemResourceEnvironment()

311

val rawBytes = getDrawableResourceBytes(environment, Res.drawable.photo)

312

return rawBytes.decodeToImageBitmap()

313

}

314

```

315

316

### Vector Decoder

317

318

```kotlin { .api }

319

fun ByteArray.decodeToImageVector(density: Density): ImageVector

320

```

321

322

Decodes a byte array of a vector XML file to an ImageVector with the specified density for unit conversion.

323

324

**Parameters:**

325

- `density` - Density to apply during converting the source units to ImageVector units

326

327

**Usage:**

328

```kotlin

329

@Composable

330

fun CustomVectorProcessor() {

331

val density = LocalDensity.current

332

333

LaunchedEffect(Unit) {

334

val environment = getSystemResourceEnvironment()

335

val vectorBytes = getDrawableResourceBytes(environment, Res.drawable.vector_icon)

336

val processedVector = vectorBytes.decodeToImageVector(density)

337

338

// Further processing of the ImageVector

339

customVectorProcessor.process(processedVector)

340

}

341

}

342

343

suspend fun convertVectorResource(

344

resource: DrawableResource,

345

targetDensity: Density

346

): ImageVector {

347

val environment = getSystemResourceEnvironment()

348

val bytes = getDrawableResourceBytes(environment, resource)

349

return bytes.decodeToImageVector(targetDensity)

350

}

351

```

352

353

### Decoder Use Cases

354

355

**Custom Image Processing:**

356

```kotlin

357

suspend fun applyImageFilters(resource: DrawableResource): ImageBitmap {

358

val environment = getSystemResourceEnvironment()

359

val rawBytes = getDrawableResourceBytes(environment, resource)

360

val originalBitmap = rawBytes.decodeToImageBitmap()

361

362

return imageProcessor.applyFilters(originalBitmap)

363

}

364

```

365

366

**Dynamic Vector Manipulation:**

367

```kotlin

368

@Composable

369

fun DynamicVectorIcon(resource: DrawableResource, color: Color) {

370

val density = LocalDensity.current

371

var processedVector by remember { mutableStateOf<ImageVector?>(null) }

372

373

LaunchedEffect(resource, color) {

374

val environment = getSystemResourceEnvironment()

375

val bytes = getDrawableResourceBytes(environment, resource)

376

val vector = bytes.decodeToImageVector(density)

377

378

// Apply dynamic color changes

379

processedVector = vectorColorProcessor.changeColor(vector, color)

380

}

381

382

processedVector?.let { vector ->

383

Icon(imageVector = vector, contentDescription = null)

384

}

385

}

386

```