Resource management library for Compose Multiplatform applications providing type-safe access to images, strings, fonts, and drawable assets across all platforms.
—
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.
class DrawableResource(id: String, items: Set<ResourceItem>) : Resource(id, items)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.
@Composable
fun painterResource(resource: DrawableResource): PainterCreates a Painter from a drawable resource with automatic format detection. The function selects the appropriate painter type based on the file extension:
.xml files → Vector painter.svg files → SVG painterUsage:
@Composable
fun AppIcon() {
val icon = painterResource(Res.drawable.app_icon)
Image(
painter = icon,
contentDescription = "Application Icon",
modifier = Modifier.size(48.dp)
)
}@Composable
fun imageResource(resource: DrawableResource): ImageBitmapLoads a raster image as an ImageBitmap with automatic density scaling. The function selects the best density variant and scales appropriately for the current screen.
Usage:
@Composable
fun ProfilePhoto(user: User) {
val photo = imageResource(Res.drawable.default_profile)
Image(
bitmap = photo,
contentDescription = "Profile Photo",
contentScale = ContentScale.Crop,
modifier = Modifier
.size(80.dp)
.clip(CircleShape)
)
}Density Handling: The library automatically selects the best image density variant:
@Composable
fun vectorResource(resource: DrawableResource): ImageVectorLoads XML vector graphics as ImageVector objects. Supports Android Vector Drawable format with full path, group, and gradient support.
Usage:
@Composable
fun NavigationIcon(isSelected: Boolean) {
val icon = vectorResource(
if (isSelected) Res.drawable.ic_home_filled
else Res.drawable.ic_home_outline
)
Icon(
imageVector = icon,
contentDescription = "Home",
tint = if (isSelected) MaterialTheme.colors.primary
else MaterialTheme.colors.onSurface
)
}suspend fun getDrawableResourceBytes(
environment: ResourceEnvironment,
resource: DrawableResource
): ByteArrayRetrieves the raw byte content of a drawable resource. Useful for custom processing, external libraries, or passing to platform-specific APIs.
Parameters:
environment - Resource environment for variant selectionresource - The drawable resource to loadUsage:
suspend fun uploadImageToServer(imageResource: DrawableResource) {
val environment = getSystemResourceEnvironment()
val imageBytes = getDrawableResourceBytes(environment, imageResource)
// Upload bytes to server
uploadService.uploadImage(imageBytes)
}
suspend fun saveImageToFile(imageResource: DrawableResource, outputPath: String) {
val environment = getSystemResourceEnvironment()
val bytes = getDrawableResourceBytes(environment, imageResource)
File(outputPath).writeBytes(bytes)
}The library supports multiple density variants for optimal display quality:
drawable/ # Default (MDPI - 160dpi)
drawable-ldpi/ # Low density (120dpi)
drawable-hdpi/ # High density (240dpi)
drawable-xhdpi/ # Extra high density (320dpi)
drawable-xxhdpi/ # Extra extra high density (480dpi)
drawable-xxxhdpi/ # Extra extra extra high density (640dpi)Selection Algorithm:
Support for light and dark theme variants:
drawable/ # Default/light theme
drawable-night/ # Dark theme variantsUsage:
@Composable
fun ThemedIcon() {
// Automatically selects light/dark variant based on system theme
val icon = painterResource(Res.drawable.themed_icon)
Icon(imageVector = icon, contentDescription = "Themed Icon")
}The library automatically detects format based on file extension:
.png, .jpg, .jpeg, .webp → Bitmap handling.xml → Vector drawable parsing.svg → SVG parsing and renderingThe library includes automatic caching to improve performance:
// Images are cached by path and density
// Cache key format: "path-{density}dpi"
val cachedImage = imageResource(Res.drawable.large_image) // Cached on first loadBest Practices:
// For testing or memory management, cache can be cleared
// Note: This is internal API
internal fun dropImageCache()Common Exceptions:
MissingResourceException - Resource file not foundIllegalArgumentException - Invalid resource IDExample Error Handling:
@Composable
fun SafeImageLoad(resourceId: DrawableResource) {
try {
val image = painterResource(resourceId)
Image(painter = image, contentDescription = null)
} catch (e: MissingResourceException) {
// Show placeholder or error state
Icon(Icons.Default.ImageNotSupported, contentDescription = "Image not found")
}
}Provide multiple density variants for raster images:
drawable-mdpi/icon.png (48x48)
drawable-hdpi/icon.png (72x72)
drawable-xhdpi/icon.png (96x96)
drawable-xxhdpi/icon.png (144x144)Use vector drawables for simple graphics:
Use raster images for complex graphics:
Optimize image sizes for target platforms:
Provide theme variants when appropriate:
// Use same resource ID, library selects theme variant automatically
val icon = painterResource(Res.drawable.app_icon) // Auto light/darkThe library provides extension functions for decoding raw image bytes into Compose graphics objects.
fun ByteArray.decodeToImageBitmap(): ImageBitmapDecodes a byte array of a bitmap to an ImageBitmap. Supports JPEG, PNG, BMP, WEBP formats. Different platforms may support additional formats.
Usage:
suspend fun loadExternalImage(imageUrl: String): ImageBitmap {
val imageBytes = httpClient.get(imageUrl).readBytes()
return imageBytes.decodeToImageBitmap()
}
suspend fun processImageResource(): ImageBitmap {
val environment = getSystemResourceEnvironment()
val rawBytes = getDrawableResourceBytes(environment, Res.drawable.photo)
return rawBytes.decodeToImageBitmap()
}fun ByteArray.decodeToImageVector(density: Density): ImageVectorDecodes a byte array of a vector XML file to an ImageVector with the specified density for unit conversion.
Parameters:
density - Density to apply during converting the source units to ImageVector unitsUsage:
@Composable
fun CustomVectorProcessor() {
val density = LocalDensity.current
LaunchedEffect(Unit) {
val environment = getSystemResourceEnvironment()
val vectorBytes = getDrawableResourceBytes(environment, Res.drawable.vector_icon)
val processedVector = vectorBytes.decodeToImageVector(density)
// Further processing of the ImageVector
customVectorProcessor.process(processedVector)
}
}
suspend fun convertVectorResource(
resource: DrawableResource,
targetDensity: Density
): ImageVector {
val environment = getSystemResourceEnvironment()
val bytes = getDrawableResourceBytes(environment, resource)
return bytes.decodeToImageVector(targetDensity)
}Custom Image Processing:
suspend fun applyImageFilters(resource: DrawableResource): ImageBitmap {
val environment = getSystemResourceEnvironment()
val rawBytes = getDrawableResourceBytes(environment, resource)
val originalBitmap = rawBytes.decodeToImageBitmap()
return imageProcessor.applyFilters(originalBitmap)
}Dynamic Vector Manipulation:
@Composable
fun DynamicVectorIcon(resource: DrawableResource, color: Color) {
val density = LocalDensity.current
var processedVector by remember { mutableStateOf<ImageVector?>(null) }
LaunchedEffect(resource, color) {
val environment = getSystemResourceEnvironment()
val bytes = getDrawableResourceBytes(environment, resource)
val vector = bytes.decodeToImageVector(density)
// Apply dynamic color changes
processedVector = vectorColorProcessor.changeColor(vector, color)
}
processedVector?.let { vector ->
Icon(imageVector = vector, contentDescription = null)
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-compose-components--components-resources