blob: 4b2d13121f6bcff514edb52531d1aeac1abeba29 [file] [log] [blame]
Lucas Dupinba57b4a2019-01-21 14:55:57 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.statusbar
18
Lucas Dupinba57b4a2019-01-21 14:55:57 -080019import android.content.Context
20import android.graphics.Bitmap
21import android.graphics.Canvas
22import android.graphics.Point
23import android.graphics.Rect
24import android.renderscript.Allocation
25import android.renderscript.Element
26import android.renderscript.RenderScript
27import android.renderscript.ScriptIntrinsicBlur
28import android.util.MathUtils
29import com.android.internal.graphics.ColorUtils
Robert Snoebergerfb1e9262019-05-01 11:39:09 -040030import com.android.systemui.statusbar.notification.MediaNotificationProcessor
Lucas Dupinba57b4a2019-01-21 14:55:57 -080031
32import javax.inject.Inject
33import javax.inject.Singleton
34
35private const val COLOR_ALPHA = (255 * 0.7f).toInt()
36private const val BLUR_RADIUS = 25f
37private const val DOWNSAMPLE = 6
38
39@Singleton
40class MediaArtworkProcessor @Inject constructor() {
41
42 private val mTmpSize = Point()
43 private var mArtworkCache: Bitmap? = null
44
Robert Snoebergerfb1e9262019-05-01 11:39:09 -040045 fun processArtwork(context: Context, artwork: Bitmap): Bitmap {
Lucas Dupinba57b4a2019-01-21 14:55:57 -080046 if (mArtworkCache != null) {
47 return mArtworkCache!!
48 }
49
50 context.display.getSize(mTmpSize)
51 val renderScript = RenderScript.create(context)
Lucas Dupin9afac5a2019-02-14 15:26:51 -080052 val rect = Rect(0, 0, artwork.width, artwork.height)
Lucas Dupinba57b4a2019-01-21 14:55:57 -080053 MathUtils.fitRect(rect, Math.max(mTmpSize.x / DOWNSAMPLE, mTmpSize.y / DOWNSAMPLE))
Lucas Dupin3e361da2019-03-05 08:01:06 -080054 var inBitmap = Bitmap.createScaledBitmap(artwork, rect.width(), rect.height(),
Lucas Dupinba57b4a2019-01-21 14:55:57 -080055 true /* filter */)
Lucas Dupin3e361da2019-03-05 08:01:06 -080056 // Render script blurs only support ARGB_8888, we need a conversion if we got a
57 // different bitmap config.
58 if (inBitmap.config != Bitmap.Config.ARGB_8888) {
59 val oldIn = inBitmap
60 inBitmap = oldIn.copy(Bitmap.Config.ARGB_8888, false /* isMutable */)
61 oldIn.recycle()
62 }
Lucas Dupinba57b4a2019-01-21 14:55:57 -080063 val input = Allocation.createFromBitmap(renderScript, inBitmap,
64 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE)
65 val outBitmap = Bitmap.createBitmap(inBitmap.width, inBitmap.height,
66 Bitmap.Config.ARGB_8888)
67 val output = Allocation.createFromBitmap(renderScript, outBitmap)
68 val blur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript))
69 blur.setRadius(BLUR_RADIUS)
70 blur.setInput(input)
71 blur.forEach(output)
72 output.copyTo(outBitmap)
73
Robert Snoebergerfb1e9262019-05-01 11:39:09 -040074 val swatch = MediaNotificationProcessor.findBackgroundSwatch(artwork)
75
Lucas Dupinba57b4a2019-01-21 14:55:57 -080076 input.destroy()
77 output.destroy()
78 inBitmap.recycle()
Lucas Dupin9afac5a2019-02-14 15:26:51 -080079 blur.destroy()
Lucas Dupinba57b4a2019-01-21 14:55:57 -080080
81 val canvas = Canvas(outBitmap)
Robert Snoebergerfb1e9262019-05-01 11:39:09 -040082 canvas.drawColor(ColorUtils.setAlphaComponent(swatch.rgb, COLOR_ALPHA))
Lucas Dupinba57b4a2019-01-21 14:55:57 -080083 return outBitmap
84 }
85
86 fun clearCache() {
87 mArtworkCache?.recycle()
88 mArtworkCache = null
89 }
90}