이미지 맞춤설정

이미지는 Image 컴포저블의 속성(contentScale, colorFilter)을 사용하여 맞춤설정할 수 있습니다. 기존 Modifiers를 적용하여 Image에 다양한 효과를 적용할 수도 있습니다. 수정자는 Image 컴포저블뿐만 아니라 모든 컴포저블에서 사용할 수 있지만 contentScalecolorFilterImage 컴포저블의 명시적 매개변수입니다.

콘텐츠 크기 조정

이미지를 자르거나 경계 내에서 이미지의 크기가 조정되는 방식을 변경하도록 contentScale 옵션을 지정합니다. 기본적으로 contentScale 옵션을 지정하지 않으면 ContentScale.Fit이 사용됩니다.

아래 예에서 Image 컴포저블은 테두리가 있는 150dp 크기로 제한되고 배경은 Image 컴포저블에서 노란색으로 설정되어 아래 표의 여러 ContentScale 옵션을 보여줍니다.

val imageModifier = Modifier
    .size(150.dp)
    .border(BorderStroke(1.dp, Color.Black))
    .background(Color.Yellow)
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Fit,
    modifier = imageModifier
)

ContentScale 옵션을 다르게 설정하면 출력도 달라집니다. 아래는 필요한 ContentScale 모드를 올바르게 선택하는 데 도움이 되는 표입니다.

소스 이미지 세로 모드 소스 이미지 가로 모드 소스 이미지
ContentScale 결과 - 세로 모드 이미지: 결과 - 가로 모드 이미지:
ContentScale.Fit: 가로세로 비율(기본값)을 유지하면서 이미지의 크기를 균일하게 조정합니다. 콘텐츠가 크기보다 작으면 이미지는 경계에 맞게 확대 조정됩니다. ContentScale.Fit 세로 모드 ContentScale.Fit 가로 모드
ContentScale.Crop: 사용 가능한 공간에 맞게 이미지를 가운데를 중심으로 자릅니다. ContentScale.Crop 세로 모드 ContentScale.Crop 가로 모드
ContentScale.FillHeight: 경계가 대상 높이와 일치하도록 가로세로 비율을 유지하면서 소스의 크기를 조정합니다. ContentScale.FillHeight 세로 모드 ContentScale.FillHeight 가로 모드
ContentScale.FillWidth: 경계가 대상 너비와 일치하도록 가로세로 비율을 유지하면서 소스의 크기를 조정합니다. ContentScale.FillWidth 세로 모드 ContentScale.FillWidth 가로 모드
ContentScale.FillBounds: 대상 경계를 채우도록 콘텐츠의 크기를 균일하지 않게 세로 및 가로로 조정합니다. (참고: 이미지의 정확한 비율과 일치하지 않는 컨테이너에 배치하면 이미지가 왜곡됩니다.) ContentScale.FillBounds 세로 모드 ContentScale.FillBounds 가로 모드
ContentScale.Inside: 대상 경계 내에서 가로세로 비율을 유지하도록 소스의 크기를 조정합니다. 소스가 두 측정기준에서 모두 대상보다 작거나 같으면 `None`과 유사하게 동작합니다. 콘텐츠는 항상 경계 내에 포함됩니다. 콘텐츠가 경계보다 작으면 크기 조정이 적용되지 않습니다. 소스 이미지가 경계보다 큼 ContentScale.Inside 세로 모드. 소스 이미지가 경계보다 큼 소스 이미지가 경계보다 작음 ContentScale.Inside 세로 모드. 소스 이미지가 경계보다 작음 소스 이미지가 경계보다 큼 ContentScale.Inside 가로 모드. 소스 이미지가 경계보다 큼 소스 이미지가 경계보다 작음 ContentScale.Inside 가로 모드. 소스 이미지가 경계보다 작음
ContentScale.None: 소스에 크기 조정을 적용하지 않습니다. 콘텐츠가 대상 경계보다 작으면 영역에 맞게 크기가 확대 조정되지 않습니다. 소스 이미지가 경계보다 큼 ContentScale.None 세로 모드. 소스 이미지가 경계보다 큼 소스 이미지가 경계보다 작음 ContentScale.None 세로 모드. 소스 이미지가 경계보다 작음 소스 이미지가 경계보다 큼 ContentScale.None 가로 모드. 소스 이미지가 경계보다 큼 소스 이미지가 경계보다 작음 ContentScale.None 가로 모드. 소스 이미지가 경계보다 작음

Image 컴포저블을 도형으로 자르기

이미지를 도형에 맞도록 하려면 내장된 clip 수정자를 사용합니다. 이미지를 원형으로 자르려면 Modifier.clip(CircleShape)을 사용하세요.

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(200.dp)
        .clip(CircleShape)
)

CircleShape로 이미지 자르기
그림 1: CircleShape로 이미지 자르기

모서리가 둥근 도형: 둥근 모서리의 크기와 함께 Modifier.clip(RoundedCornerShape(16.dp))을 사용합니다.

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(200.dp)
        .clip(RoundedCornerShape(16.dp))
)

RoundedCornerShape로 이미지 자르기
그림 2: RoundedCornerShape로 이미지 자르기

Shape를 확장하고 도형을 자를 수 있도록 Path를 제공하여 도형 자르기를 자체적으로 만들 수도 있습니다.

class SquashedOval : Shape {
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        val path = Path().apply {
            // We create an Oval that starts at ¼ of the width, and ends at ¾ of the width of the container.
            addOval(
                Rect(
                    left = size.width / 4f,
                    top = 0f,
                    right = size.width * 3 / 4f,
                    bottom = size.height
                )
            )
        }
        return Outline.Generic(path = path)
    }
}

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(200.dp)
        .clip(SquashedOval())
)

맞춤 경로 도형으로 이미지 자르기
그림 3: 맞춤 경로 도형으로 이미지 자르기

Image 컴포저블에 테두리 추가

일반적인 작업은 Modifier.border()Modifier.clip()과 결합하여 이미지 주위에 테두리를 만드는 것입니다.

val borderWidth = 4.dp
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(150.dp)
        .border(
            BorderStroke(borderWidth, Color.Yellow),
            CircleShape
        )
        .padding(borderWidth)
        .clip(CircleShape)
)

이미지를 자르고 그 주변에 테두리 제공
그림 4: 이미지를 자르고 그 주변에 테두리 제공

그라데이션 테두리를 만들려면 Brush API를 사용하여 이미지 주위에 무지개 그라데이션 테두리를 그리면 됩니다.

val rainbowColorsBrush = remember {
    Brush.sweepGradient(
        listOf(
            Color(0xFF9575CD),
            Color(0xFFBA68C8),
            Color(0xFFE57373),
            Color(0xFFFFB74D),
            Color(0xFFFFF176),
            Color(0xFFAED581),
            Color(0xFF4DD0E1),
            Color(0xFF9575CD)
        )
    )
}
val borderWidth = 4.dp
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(150.dp)
        .border(
            BorderStroke(borderWidth, rainbowColorsBrush),
            CircleShape
        )
        .padding(borderWidth)
        .clip(CircleShape)
)

무지개 그라데이션 원 테두리
그림 5: 무지개 그라데이션 원 테두리

맞춤 가로세로 비율 설정

이미지를 맞춤 가로세로 비율로 변환하려면 Modifier.aspectRatio(16f/9f)를 사용하여 이미지(또는 관련 컴포저블)에 맞춤 비율을 제공합니다.

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    modifier = Modifier.aspectRatio(16f / 9f)
)

Image에서 Modifier.aspectRatio(16f/9f) 사용
그림 6: Image에서 Modifier.aspectRatio(16f/9f) 사용

색상 필터: 이미지의 픽셀 색상 변환

Image 컴포저블에는 이미지의 개별 픽셀 출력을 변경할 수 있는 colorFilter 매개변수가 있습니다.

이미지 색조 조정

ColorFilter.tint(color, blendMode)를 사용하면 주어진 색상의 혼합 모드가 Image 컴포저블에 적용됩니다. ColorFilter.tint(color, blendMode)BlendMode.SrcIn을 사용하여 콘텐츠의 색조를 조정합니다. 즉, 이미지가 화면에 표시되는 곳에 제공된 색상이 표시됩니다. 이는 테마를 다르게 설정해야 하는 아이콘과 벡터에 유용합니다.

Image(
    painter = painterResource(id = R.drawable.baseline_directions_bus_24),
    contentDescription = stringResource(id = R.string.bus_content_description),
    colorFilter = ColorFilter.tint(Color.Yellow)
)

BlendMode.SrcIn으로 적용된 ColorFilter.tint
그림 7: BlendMode.SrcIn으로 적용된 ColorFilter.tint

다른 BlendMode는 효과도 다릅니다. 예를 들어 이미지에서 Color.Green을 사용하여 BlendMode.Darken을 설정하면 결과는 다음과 같습니다.

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.tint(Color.Green, blendMode = BlendMode.Darken)
)

BlendMode.Darken의 Color.Green 색조
그림 8: BlendMode.Darken의 Color.Green 색조

사용 가능한 다양한 혼합 모드에 관한 자세한 내용은 BlendMode 참조 문서를 확인하세요.

색상 매트릭스로 Image 필터 적용

색상 매트릭스 ColorFilter 옵션을 사용하여 이미지를 변환하세요. 예를 들어 이미지에 흑백 필터를 적용하려면 ColorMatrix를 사용하고 채도를 0f로 설정하면 됩니다.

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.colorMatrix(ColorMatrix().apply { setToSaturation(0f) })
)

채도가 0(흑백 이미지)인 색상 매트릭스
그림 9: 채도가 0(흑백 이미지)인 색상 매트릭스

Image 컴포저블의 대비 또는 밝기 조정

이미지의 대비와 밝기를 변경하려면 ColorMatrix를 사용하여 값을 변경하면 됩니다.

val contrast = 2f // 0f..10f (1 should be default)
val brightness = -180f // -255f..255f (0 should be default)
val colorMatrix = floatArrayOf(
    contrast, 0f, 0f, 0f, brightness,
    0f, contrast, 0f, 0f, brightness,
    0f, 0f, contrast, 0f, brightness,
    0f, 0f, 0f, 1f, 0f
)
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.colorMatrix(ColorMatrix(colorMatrix))
)

ColorMatrix를 사용하여 이미지 밝기와 대비 조정
그림 10: ColorMatrix를 사용하여 이미지 밝기와 대비 조정

Image 컴포저블의 색상 반전

이미지의 색상을 반전하려면 다음과 같이 ColorMatrix를 설정하여 색상을 반전합니다.

val colorMatrix = floatArrayOf(
    -1f, 0f, 0f, 0f, 255f,
    0f, -1f, 0f, 0f, 255f,
    0f, 0f, -1f, 0f, 255f,
    0f, 0f, 0f, 1f, 0f
)
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.colorMatrix(ColorMatrix(colorMatrix))
)

이미지의 반전 색상
그림 11: 이미지의 반전 색상

Image 컴포저블 블러 처리

이미지를 블러 처리하려면 Modifier.blur()를 사용하여 radiusXradiusY를 제공합니다. 이는 각각 가로 및 세로 방향의 블러 반경을 지정합니다.

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(150.dp)
        .blur(
            radiusX = 10.dp,
            radiusY = 10.dp,
            edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp))
        )
)

이미지에 적용된 BlurEffect
그림 12: 이미지에 적용된 BlurEffect

Images를 블러 처리할 때는 BlurredEdgeTreatment.Unbounded 대신 BlurredEdgeTreatment(Shape)를 사용하는 것이 좋습니다. BlurredEdgeTreatment.Unbounded는 원본 콘텐츠의 경계 밖에서 렌더링될 것으로 예상되는 임의의 렌더링을 블러 처리하는 데 사용되기 때문입니다. 이미지의 경우 콘텐츠 경계 밖에서 렌더링되지 않을 가능성이 높습니다. 반면 모서리가 둥근 직사각형을 블러 처리하려면 이러한 구별이 필요할 수 있습니다.

예를 들어 위 이미지에서 BlurredEdgeTreatment를 Unbounded로 설정하면 이미지의 가장자리가 선명하지 않고 흐리게 표시됩니다.

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(150.dp)
        .blur(
            radiusX = 10.dp,
            radiusY = 10.dp,
            edgeTreatment = BlurredEdgeTreatment.Unbounded
        )
        .clip(RoundedCornerShape(8.dp))
)

BlurEdgeTreatment.Unbounded
그림 13: BlurEdgeTreatment.Unbounded