Android/Compose

[Compose][Image] 이미지 커스터마이징

네모메모 2024. 6. 2. 17:25
반응형

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

이미지 커스터마이징 (Customize an image )

 

  • `Image 컴포저블`의 속성인 `contentScale` , `colorFilter`들을 사용하여 맞춤설정할 수 있습니다.
  • 위 속성은 Image 컴포저블의 Modifiers를 사용하여 적용가능함
    (`contentScale` 및 `colorFilter`는 Image 컴포저블의 명시적 매개변수)

 

 

 


1. `contentScale` 옵션 :  콘텐츠 크기 조정 

  • 이미지를 자르거나 경계 내에서 이미지의 크기가 조정되는 방식을 변경하는 옵션 (디폴트는 ContentScale.Fit)
  • ex) Image 컴포저블은 테두리가 있는 150dp 크기로 제한되고 배경은 Image 컴포저블에서 노란색으로 설정
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.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 가로 모드. 소스 이미지가 경계보다 작음

 

 

 


 

2. `Modifier.clip()` : Image 컴포저블을 도형으로 자르기

  • 이미지를 도형에 맞도록 잘라서 표현 시, `clip()` modifier를 사용합니다.
  • contentScale = ContentScale.Crop : (위에 설명했듯이) Image 컴포저블에서 사용되는 하나의 옵션입니다. 이 옵션을 사용하면 이미지가 컨테이너에 맞게 크기가 조절되는 동시에 이미지가 잘릴 수 있습니다.이 옵션은 주로 이미지가 화면에 차게 표시되길 원할 사용됩니다
  • 예를 들어, 원래 이미지의 가로 세로 비율이 컨테이너와 다를 경우, ContentScale.Crop을 사용하면 이미지가 잘릴 수 있습니다. 이때, 이미지의 중앙 부분이 유지되고, 나머지 부분은 잘립니다. 이를 통해 이미지를 중앙에 맞추고 컨테이너를 가득 채울 수 있습니다.
  • Ex1) 이미지를 원형으로 자르려면, 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)
)
 

Figure 1 : Clipping an image with CircleShape

 

 

  • Ex2) radius를 적용한 라운드된 도형으로 자르려면, 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))
)
 

 

Figure 2 : Clipping an image with RoundedCornerShape

 

  • Ex3) 커스텀한 형태로 도형을 자르려면 , 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())
)

Figure 3 : Clipping an image with custom path shape

 

 

 


3. Image 컴포저블에 테두리 추가 : `Modifier.border()`와 `Modifier.clip()`를 결합

  • 1) 일반적으론 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 : 이미지를 자르고 그 주변에 테두리 제공

 

 

  • 2) 그라데이션 테두리를 만들려면 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 : 무지개 그라데이션 원 테두리

 

 

 

 


 

4. `Modifier.aspectRatio(가로비율f/세로비율f)` : 맞춤 가로세로 비율 설정

 

  • 이미지를 맞춤 가로세로 비율로 변환하려면, Modifier.aspectRatio(16f/9f)를 사용하여 이미지(또는 관련 컴포저블)에 맞춤 비율을 제공해야 함
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    modifier = Modifier.aspectRatio(16f / 9f)
)
 

 

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

 

 

 

 

 


5.  이미지의 픽셀 색상 변환 : Image 컴포저블의 colorFilter 매개변수

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

 


5-1.  ColorFilter.tint(color, blendMode) : 이미지 색조 조정

  • 주어진 색상의 혼합 모드가 Image 컴포저블에 적용됨
  • BlendMode.SrcIn을 사용하여 콘텐츠의 색조를 조정합니다. 이미지가 화면에 표시되는 곳에 제공된 색상이 표시됩니다.
  • 테마를 다르게 설정해야 하는 아이콘과 벡터에 유용
  • color 파라미터
    • ex1)
Image(
    painter = painterResource(id = R.drawable.baseline_directions_bus_24),
    contentDescription = stringResource(id = R.string.bus_content_description),
    colorFilter = ColorFilter.tint(Color.Yellow)
)
 

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

 

 

  • BlendMode 파라미터
    • BlendMode 참조 문서를 확인
    • ex2) 다른 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)
)
 

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

 


5-2. ColorMatrix : Image에 필터 적용

  • Image에 필터를 적용하려면 ColorMatrix를 사용하여 값을 변경하면 됩니다.
    • Image 컴포저블의 colorFilter속성에 ColorMatrix 적용    
      colorFilter = ColorFilter.colorMatrix(ColorMatrix().apply { setToSaturation(0f) })

    • Ex) 이미지에 흑백 필터를 적용하려면, ColorMatrix를 사용하고 채도를 0f로 설정
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.colorMatrix(ColorMatrix().apply { setToSaturation(0f) })
)
 

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

 


5-3. ColorMatrix :  이미지 대비 또는 밝기 조정

  • 이미지의 대비와 밝기를 변경하려면 ColorMatrix를 사용하여 값을 변경하면 됩니다.
    • Image 컴포저블의 colorFilter속성에 ColorMatrix 적용 
    • Ex)  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))
)

 

 

 


5-4. ColorMatrix :  이미지 색상 반전

  • 이미지의 색상을 반전하려면 ColorMatrix를 사용하여 값을 변경하면 됩니다.
    • Image 컴포저블의 colorFilter속성에 ColorMatrix 적용 
    • Ex)  이미지의 반전 색상
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))
)
 

 

 

 


6. `Modifier.blur()` : Image 컴포저블 블러 처리

  • 이미지 블러 처리하려면 `Modifier.blur( radiusX, radiusY, edgeTreatment )`를 사용
  • 주의) 블러 효과는 Android 12 이상에서만 지원됩니다. 이전 Android 버전에서 이 Modifier를 사용하려고 하면 무시됩니다.
    • radiusX, radiusY 파라미터 : 각각 가로 및 세로 방향의 블러 반경을 지정함
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))
        )
)
 

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

 

  • 'edgeTreatment: BlurredEdgeTreatment'  파라미터
    • BlurredEdgeTreatment : 그래픽 요소의 테두리를 흐릿하게 만들어주며 아래 2가지 타입을 가집니다.
      1. BlurredEdgeTreatment.Unbounded:
        - UI 요소의 모든 가장자리를 둥글게 만듭니다. 테두리의 흐림 효과는 UI 요소의 모든 가장자리에 동일하게 적용됩니다.
        - 주의) 원본 콘텐츠의 경계 밖에서 렌더링될 것으로 예상되는 임의의 렌더링을 블러 처리하는 데 사용되기 때문에 
         이미지의 경우 콘텐츠 경계 밖에서 렌더링되지 않을 가능성이 높습니다.
           ㄴ> 예를 들어 위 이미지에서 BlurredEdgeTreatment를 Unbounded로 설정하면 이미지의 가장자리가 선명하지 않고 흐리게 표시됩니다.

      2. BlurredEdgeTreatment(Shape): 이 형태는 주어진 Shape을 기반으로하여 외곽선의 형태를 정의합니다. 주어진 Shape에 따라 테두리의 흐림 효과가 적용됩니다. 예를 들어, 사각형 모양의 버튼이나 카드의 외곽선을 흐리게 만들고자 할 때 사용됩니다. 이 경우에는 Shape을 정의하여 해당 모양을 기준으로 외곽선을 흐리게 할 수 있습니다.
    • BlurredEdgeTreatment.Unbounded 대신 BlurredEdgeTreatment(Shape)를 사용하는 것이 좋습니다.
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))
)
 

그림 13 : BlurEdgeTreatment.Unbounded

 

 

 

 

 

 

 


출처

https://developer.android.com/develop/ui/compose/graphics/images/customize?_gl=1*1hmb1s3*_up*MQ..*_ga*MTIwNTIxOTMwNC4xNzE3MTQ3ODQy*_ga_6HH9YJMN9M*MTcxNzMwNTQ0OC4yLjAuMTcxNzMwNTQ0OC4wLjAuMA..

반응형