AnimalRating/app/src/main/java/com/example/livingai/utils/SilhouetteManager.kt

78 lines
3.1 KiB
Kotlin

package com.example.livingai.utils
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import androidx.annotation.DrawableRes
import androidx.core.graphics.createBitmap
import java.util.concurrent.ConcurrentHashMap
object SilhouetteManager {
private val originals = ConcurrentHashMap<String, Bitmap>()
private val inverted = ConcurrentHashMap<String, Bitmap>()
private val bitmasks = ConcurrentHashMap<String, BooleanArray>()
fun initialize(context: Context, names: List<String>) {
names.forEach { name ->
val resId = context.resources.getIdentifier(name, "drawable", context.packageName)
if (resId != 0) {
val bmp = BitmapFactory.decodeResource(context.resources, resId)
originals[name] = bmp
val inv = invertBitmap(bmp)
inverted[name] = inv
bitmasks[name] = createBitmask(inv)
}
}
}
fun getOriginal(name: String): Bitmap? = originals[name]
fun getInverted(name: String): Bitmap? = inverted[name]
fun getBitmask(name: String): BooleanArray? = bitmasks[name]
private fun invertBitmap(src: Bitmap): Bitmap {
val bmOut = Bitmap.createBitmap(src.width, src.height, src.config ?: Bitmap.Config.ARGB_8888)
val canvas = Canvas(bmOut)
val paint = Paint()
val colorMatrix = android.graphics.ColorMatrix(
floatArrayOf(
-1f, 0f, 0f, 0f, 255f,
0f, -1f, 0f, 0f, 255f,
0f, 0f, -1f, 0f, 255f,
0f, 0f, 0f, 1f, 0f
)
)
paint.colorFilter = android.graphics.ColorMatrixColorFilter(colorMatrix)
canvas.drawBitmap(src, 0f, 0f, paint)
return bmOut
}
private fun createBitmask(bitmap: Bitmap): BooleanArray {
val w = bitmap.width
val h = bitmap.height
val mask = BooleanArray(w * h)
val pixels = IntArray(w * h)
bitmap.getPixels(pixels, 0, w, 0, 0, w, h)
for (i in pixels.indices) {
val c = pixels[i]
val alpha = Color.alpha(c)
// simple threshold: non-transparent and not near-white (assuming inverted is black on transparent/white)
// The inverted logic makes black -> white, white -> black.
// Wait, if original is black silhouette on transparent:
// Inverted: black becomes white, transparent becomes... white?
// Let's check invertBitmap logic.
// Matrix: R' = 255 - R, G' = 255 - G, B' = 255 - B, A' = A.
// If original is Black (0,0,0,255) -> White (255,255,255,255).
// If original is Transparent (0,0,0,0) -> Transparent (0,0,0,0).
// So "Inverted" means we have White silhouette on Transparent.
// We want bitmask where the silhouette is.
// So we look for non-transparent pixels.
mask[i] = alpha > 16
}
return mask
}
}