ปรับแต่งรูปภาพ

คุณปรับแต่งรูปภาพได้โดยใช้พร็อพเพอร์ตี้ในImageคอมโพสิเบิล (contentScale, colorFilter) นอกจากนี้ คุณยังใช้ Modifiers ที่มีอยู่เพื่อใช้เอฟเฟกต์ต่างๆ กับ Image ได้ด้วย คุณสามารถใช้ตัวแก้ไขในคอมโพสิเบิลใดก็ได้ ไม่ใช่แค่คอมโพสิเบิล Image ส่วน contentScale และ colorFilter นั้นเป็นพารามิเตอร์ที่ชัดเจนในคอมโพสิเบิล Image

ขนาดเนื้อหา

ระบุตัวเลือก contentScale เพื่อครอบตัดหรือเปลี่ยนวิธีปรับขนาดรูปภาพภายในขอบเขต โดยค่าเริ่มต้น หากคุณไม่ได้ระบุตัวเลือก contentScale ระบบจะใช้ ContentScale.Fit

ในตัวอย่างด้านล่าง คอมโพสิชันรูปภาพถูกจำกัดให้มีขนาด 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 portrait ContentScale.Fit landscape
ContentScale.Crop: ครอบตัดรูปภาพให้อยู่ตรงกลางพื้นที่ว่าง ContentScale.Crop portrait ContentScale.Crop landscape
ContentScale.FillHeight: ปรับขนาดแหล่งที่มาโดยรักษาสัดส่วนการแสดงผลไว้เพื่อให้ขอบเขตตรงกับความสูงของปลายทาง ContentScale.FillHeight แนวตั้ง ContentScale.FillHeight แนวนอน
ContentScale.FillWidth: ปรับขนาดแหล่งที่มาโดยรักษาสัดส่วนการแสดงผลไว้เพื่อให้ขอบเขตตรงกับความกว้างของปลายทาง ContentScale.FillWidth แนวตั้ง ContentScale.FillWidth แนวนอน
ContentScale.FillBounds: ปรับขนาดเนื้อหาในแนวตั้งและแนวนอนอย่างไม่สม่ำเสมอเพื่อให้พอดีกับขอบเขตปลายทาง (หมายเหตุ: การดำเนินการนี้จะบิดเบือนรูปภาพหากคุณวางไว้ในคอนเทนเนอร์ที่ไม่ตรงกับสัดส่วนรูปภาพ) ContentScale.FillBounds แนวตั้ง ContentScale.FillBounds แนวนอน
ContentScale.Inside: ปรับขนาดแหล่งที่มาเพื่อรักษาสัดส่วนการแสดงผลภายในขอบเขตปลายทาง หากแหล่งที่มามีขนาดเล็กกว่าหรือเท่ากับปลายทางในทั้ง 2 มิติ การดำเนินการจะคล้ายกับ "ไม่มี" เนื้อหาจะอยู่ในขอบเขตเสมอ หากเนื้อหามีขนาดเล็กกว่าขอบเขต ระบบจะไม่ปรับขนาด รูปภาพต้นทางใหญ่กว่าขอบเขต ContentScale.Inside portrait, source image larger than bounds รูปภาพต้นทางเล็กกว่าขอบเขต ContentScale.Inside portrait, source image smaller than bounds รูปภาพต้นทางใหญ่กว่าขอบเขต ContentScale.Inside landscape, source image larger than bounds รูปภาพต้นทางเล็กกว่าขอบเขต ContentScale.Inside landscape, source image smaller than bounds
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)
)

การใช้ Modifier.aspectRatio(16f/9f) ในรูปภาพ
รูปที่ 6: การใช้ Modifier.aspectRatio(16f/9f) ในรูปภาพ

ตัวกรองสี - เปลี่ยนสีพิกเซลของรูปภาพ

องค์ประกอบรูปภาพมีพารามิเตอร์ 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)
)

ใช้ ColorFilter.tint กับ BlendMode.SrcIn
รูปที่ 7: ColorFilter.tint ใช้กับ BlendMode.SrcIn

BlendMode อื่นๆ จะทำให้เกิดผลลัพธ์ที่แตกต่างกัน ตัวอย่างเช่น การตั้งค่า BlendMode.Darken ด้วย Color.Green ในรูปภาพจะให้ผลลัพธ์ดังต่อไปนี้

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

Color.Green tint with BlendMode.Darken
รูปที่ 8: Color.Green tint with BlendMode.Darken

ดูข้อมูลเพิ่มเติมเกี่ยวกับโหมดการผสมต่างๆ ที่มีได้ในเอกสารอ้างอิงเกี่ยวกับ 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() โดยระบุ 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))
        )
)

ใช้ BlurEffect กับรูปภาพ
รูปที่ 12: BlurEffect ที่ใช้กับรูปภาพ

เมื่อเบลอ Images เราขอแนะนำให้ใช้ BlurredEdgeTreatment(Shape) แทน BlurredEdgeTreatment.Unbounded เนื่องจาก BlurredEdgeTreatment.Unbounded ใช้สำหรับเบลอการแสดงผลแบบกำหนดเองที่คาดว่าจะแสดงผลนอกขอบเขตของเนื้อหาต้นฉบับ สำหรับรูปภาพ รูปภาพจะไม่แสดงผลนอกขอบเขตของเนื้อหา แต่การเบลอสี่เหลี่ยมผืนผ้าที่โค้งมนอาจต้องใช้การแยกแยะนี้

ตัวอย่างเช่น หากเราตั้งค่า BlurredEdgeTreatment เป็น "ไม่จำกัด" ในรูปภาพด้านบน ขอบของรูปภาพจะปรากฏเบลอแทนที่จะคมชัด

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