如何使用Bitmap.createBitmap()重用现有的位图内存

时间:2017-08-21 22:37:29

标签: android bitmap

我正在尝试按照建议的使用BitmapFactory.Options.inBitmap的做法优化我的应用内存使用量。我想要做的是将位图切成高度为stripeHeight的条纹,如下所示:

val stripeHeight = 10
val largeBitmap = // the original bitmap
val placeholder = // the bitmap object I want to re purpose for each stripe
val options = BitmapFactory.Options()
options.inBitmap = placeholder
val rows = largeBitmap.height / stripeHeight

for (i in 0 until rows) {
    //how can I set the options object into createBitmap?
    val stripe = Bitmap.createBitmap(largeBitmap, 0, i * stripeHeight, largeBitmap.width, stripeHeight)
    it.onNext(stripe)
}

问题是Bitmap.createBitmap在其方法签名中不会使用BitmapFactory.Options。所以我不确定如何告诉android将新位图分配到前一个位图的内存空间。

1 个答案:

答案 0 :(得分:0)

一种方法如下:

fun doBitmapProcessing() {

    val STRIPE_HEIGHT = 10
    //assuming your largeBitmap is a 320x240 ARGB8888 image
    val largeBitmap: Bitmap = Bitmap.createBitmap(320, 240, Bitmap.Config.ARGB_8888)
    //then allocate a buffer of size 320 * 240 * 4 (4 channels in an ARGB image) bytes
    val byteBuffer: ByteBuffer = ByteBuffer.allocate(320 * 240 * 4)
    //create a bitmap of desired dimensions for the placeholder
    val placeholder: Bitmap = Bitmap.createBitmap(320, STRIPE_HEIGHT, Bitmap.Config.ARGB_8888)

    //copy the pixels from your large bitmap to a pre-allocated byte buffer
    largeBitmap.copyPixelsToBuffer(byteBuffer)
    //create an input stream from the pre-allocated buffer
    val inputStream: InputStream = ByteArrayInputStream(byteBuffer.array())
    //create the bitmap region decoder
    val bitmapRegionDecoder: BitmapRegionDecoder = BitmapRegionDecoder.newInstance(inputStream, true)

    //create options, as before
    val options = BitmapFactory.Options()
    options.inBitmap = placeholder

    val rows = largeBitmap.height / STRIPE_HEIGHT
    for (i in 0 until rows) {
        //call decode stream on the input stream containing your data from *largeImage*, and the options
        //in which you specify that you want the memory of *placeholder* to be overwritten.
        val region: Rect = Rect(0, i * STRIPE_HEIGHT, largeBitmap.width, i * STRIPE_HEIGHT + STRIPE_HEIGHT)
        val stripe: Bitmap = bitmapRegionDecoder.decodeRegion(region, options)
        it.onNext(stripe)
    }
}

请务必阅读BitmapFactory.Options#inBitmap的文档,并直接使用BitmapRegionDecoder.decodeRegion(...)而不是placeholder的结果,因为无法保证将使用相同的内存位置。

Bitmap.getPixels(...)& Bitmap.setPixels

fun doBitmapProcessing2() {
    val STRIPE_HEIGHT = 10
    //assuming your largeBitmap is in ARGB 8888 format
    val largeBitmap: Bitmap = Bitmap.createBitmap(320, 240, Bitmap.Config.ARGB_8888)
    //create a bitmap of desired dimensions for the placeholder
    val placeholder: Bitmap = Bitmap.createBitmap(320, STRIPE_HEIGHT, Bitmap.Config.ARGB_8888)
    //create int pixel array in which the colors will be saved
    val pixels = IntArray(320 * STRIPE_HEIGHT * 4)

    val rows = largeBitmap.height / STRIPE_HEIGHT
    for (i in 0 until rows) {
        //save colors from desired location into the pixels array
        largeBitmap.getPixels(pixels, 0, 320, 0, i * STRIPE_HEIGHT, 320, STRIPE_HEIGHT)
        //write the colors saved into the array to the placeholder bitmap
        placeholder.setPixels(pixels, 0, 320, 0, 0, 320, STRIPE_HEIGHT)
        it.onNext(placeholder)
    }
}

虽然我对第二个不太确定。 (以前没有使用getPixels / setPixels

希望这有帮助