morristech
1/10/2018 - 8:48 AM

Batch convert <vector> to png for mdpi..xxxhdpi using Canvas api

Batch convert to png for mdpi..xxxhdpi using Canvas api

/**
 * Run convertVectorsToPngs() test, get the pngs from the device by "adb pull <the path>" and paste the res folders
 * into your android project.
 *
 * @author Pär Amsen 01/2018
 */
@RunWith(AndroidJUnit4::class)
class Vector2Png {
    lateinit var context: Context
    lateinit var baseDir: File
    
    @Before
    fun before() {
        context = InstrumentationRegistry.getTargetContext()
        baseDir = File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "converted_res").apply { mkdir() }
    }

    @Test
    fun convertVectorsToPngs() {
        val drawableResources = R.drawable()
        val c = R.drawable::class.java
        val fields = c.declaredFields

        val max = fields.size
        val excluded = listOf("EXCLUSIONS HERE")
        val configs = listOf(1f to "mdpi", 1.5f to "hdpi", 2f to "xhdpi", 3f to "xxhdpi", 4f to "xxxhdpi")
        
        for (i in 0 until max) {
            val resourceId: Int
            try {
                resourceId = fields[i].getInt(drawableResources)
            } catch (e: Exception) {
                continue
            }

            val name = context.resources.getResourceEntryName(resourceId)
            if(excluded.contains(name)) continue

            configs.forEach { convertToPng(name, resourceId, it.first, it.second) }
        }

        Assert.assertTrue(true)
    }

    fun convertToPng(name: String, resId: Int, multiplier: Float, dirSuffix: String) {
        val xpp: XmlResourceParser

        try {
            xpp = context.resources.getXml(resId)
        } catch (e: Exception) {
            return
        }

        xpp.next()
        if (xpp.name != "vector") xpp.next()
        if (xpp.name != "vector") return

        val count = xpp.attributeCount
        val map = (0 until count).map { xpp.getAttributeName(it) to it }.toMap()
        val w = xpp.getAttributeValue(map["width"]!!).removeSuffix("dip").toFloat() * multiplier
        val h = xpp.getAttributeValue(map["height"]!!).removeSuffix("dip").toFloat() * multiplier

        val b = Bitmap.createBitmap(w.toInt(), h.toInt(), Bitmap.Config.ARGB_8888)
        val c = Canvas(b)
        val d = ContextCompat.getDrawable(context, resId)!!
        d.bounds = Rect(0, 0, w.toInt(), h.toInt())
        d.draw(c)

        val dir = File(baseDir, "drawable-$dirSuffix").apply {
            mkdir()
            listFiles().forEach { delete() }
        }
        b.compress(Bitmap.CompressFormat.PNG, 100, FileOutputStream(File(dir, "$name.png")))

        println("=== ${dir.absolutePath}")

        Assert.assertTrue(true)
    }
}