1/*
2 * Copyright (C) 2017 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.notification;
18
19import android.graphics.Bitmap;
20import android.graphics.BitmapShader;
21import android.graphics.Canvas;
22import android.graphics.Color;
23import android.graphics.ColorMatrix;
24import android.graphics.ColorMatrixColorFilter;
25import android.graphics.LinearGradient;
26import android.graphics.Paint;
27import android.graphics.PorterDuff;
28import android.graphics.PorterDuffXfermode;
29import android.graphics.Shader;
30import android.graphics.Xfermode;
31import android.graphics.drawable.Drawable;
32
33/**
34 * A utility class to colorize bitmaps with a color gradient and a special blending mode
35 */
36public class ImageGradientColorizer {
37    public Bitmap colorize(Drawable drawable, int backgroundColor, boolean isRtl) {
38        int width = drawable.getIntrinsicWidth();
39        int height = drawable.getIntrinsicHeight();
40        int size = Math.min(width, height);
41        int widthInset = (width - size) / 2;
42        int heightInset = (height - size) / 2;
43        drawable = drawable.mutate();
44        drawable.setBounds(- widthInset, - heightInset, width - widthInset, height - heightInset);
45        Bitmap newBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
46        Canvas canvas = new Canvas(newBitmap);
47
48        // Values to calculate the luminance of a color
49        float lr = 0.2126f;
50        float lg = 0.7152f;
51        float lb = 0.0722f;
52
53        // Extract the red, green, blue components of the color extraction color in
54        // float and int form
55        int tri = Color.red(backgroundColor);
56        int tgi = Color.green(backgroundColor);
57        int tbi = Color.blue(backgroundColor);
58
59        float tr = tri / 255f;
60        float tg = tgi / 255f;
61        float tb = tbi / 255f;
62
63        // Calculate the luminance of the color extraction color
64        float cLum = (tr * lr + tg * lg + tb * lb) * 255;
65
66        ColorMatrix m = new ColorMatrix(new float[] {
67                lr, lg, lb, 0, tri - cLum,
68                lr, lg, lb, 0, tgi - cLum,
69                lr, lg, lb, 0, tbi - cLum,
70                0, 0, 0, 1, 0,
71        });
72
73        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
74        LinearGradient linearGradient =  new LinearGradient(0, 0, size, 0,
75                new int[] {0, Color.argb(0.5f, 1, 1, 1), Color.BLACK},
76                new float[] {0.0f, 0.4f, 1.0f}, Shader.TileMode.CLAMP);
77        paint.setShader(linearGradient);
78        Bitmap fadeIn = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
79        Canvas fadeInCanvas = new Canvas(fadeIn);
80        drawable.clearColorFilter();
81        drawable.draw(fadeInCanvas);
82
83        if (isRtl) {
84            // Let's flip the gradient
85            fadeInCanvas.translate(size, 0);
86            fadeInCanvas.scale(-1, 1);
87        }
88        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
89        fadeInCanvas.drawPaint(paint);
90
91        Paint coloredPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
92        coloredPaint.setColorFilter(new ColorMatrixColorFilter(m));
93        coloredPaint.setAlpha((int) (0.5f * 255));
94        canvas.drawBitmap(fadeIn, 0, 0, coloredPaint);
95
96        linearGradient =  new LinearGradient(0, 0, size, 0,
97                new int[] {0, Color.argb(0.5f, 1, 1, 1), Color.BLACK},
98                new float[] {0.0f, 0.6f, 1.0f}, Shader.TileMode.CLAMP);
99        paint.setShader(linearGradient);
100        fadeInCanvas.drawPaint(paint);
101        canvas.drawBitmap(fadeIn, 0, 0, null);
102
103        return newBitmap;
104    }
105}
106