10847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek/*
20847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek * Copyright (C) 2017 The Android Open Source Project
30847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek *
40847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek * Licensed under the Apache License, Version 2.0 (the "License");
50847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek * you may not use this file except in compliance with the License.
60847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek * You may obtain a copy of the License at
70847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek *
80847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek *      http://www.apache.org/licenses/LICENSE-2.0
90847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek *
100847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek * Unless required by applicable law or agreed to in writing, software
110847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek * distributed under the License is distributed on an "AS IS" BASIS,
120847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek * See the License for the specific language governing permissions and
140847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek * limitations under the License
150847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek */
160847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek
170847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekpackage com.android.systemui.statusbar.notification;
180847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek
190847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekimport android.graphics.Bitmap;
200847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekimport android.graphics.BitmapShader;
210847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekimport android.graphics.Canvas;
220847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekimport android.graphics.Color;
230847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekimport android.graphics.ColorMatrix;
240847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekimport android.graphics.ColorMatrixColorFilter;
250847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekimport android.graphics.LinearGradient;
260847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekimport android.graphics.Paint;
270847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekimport android.graphics.PorterDuff;
280847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekimport android.graphics.PorterDuffXfermode;
290847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekimport android.graphics.Shader;
300847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekimport android.graphics.Xfermode;
310847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekimport android.graphics.drawable.Drawable;
320847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek
330847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek/**
340847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek * A utility class to colorize bitmaps with a color gradient and a special blending mode
350847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek */
360847acd4d48deb716de99d259364bc99b592a8bcSelim Cinekpublic class ImageGradientColorizer {
37b49a070d816c85110f59f10acd52688a4cadae73Selim Cinek    public Bitmap colorize(Drawable drawable, int backgroundColor, boolean isRtl) {
380847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        int width = drawable.getIntrinsicWidth();
390847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        int height = drawable.getIntrinsicHeight();
400847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        int size = Math.min(width, height);
410847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        int widthInset = (width - size) / 2;
420847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        int heightInset = (height - size) / 2;
430847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        drawable = drawable.mutate();
440847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        drawable.setBounds(- widthInset, - heightInset, width - widthInset, height - heightInset);
450847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        Bitmap newBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
460847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        Canvas canvas = new Canvas(newBitmap);
470847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek
480847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        // Values to calculate the luminance of a color
490847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        float lr = 0.2126f;
500847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        float lg = 0.7152f;
510847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        float lb = 0.0722f;
520847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek
530847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        // Extract the red, green, blue components of the color extraction color in
540847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        // float and int form
550847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        int tri = Color.red(backgroundColor);
560847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        int tgi = Color.green(backgroundColor);
570847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        int tbi = Color.blue(backgroundColor);
580847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek
590847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        float tr = tri / 255f;
600847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        float tg = tgi / 255f;
610847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        float tb = tbi / 255f;
620847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek
630847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        // Calculate the luminance of the color extraction color
640847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        float cLum = (tr * lr + tg * lg + tb * lb) * 255;
650847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek
660847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        ColorMatrix m = new ColorMatrix(new float[] {
670847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek                lr, lg, lb, 0, tri - cLum,
680847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek                lr, lg, lb, 0, tgi - cLum,
690847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek                lr, lg, lb, 0, tbi - cLum,
700847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek                0, 0, 0, 1, 0,
710847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        });
720847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek
730847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
740847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        LinearGradient linearGradient =  new LinearGradient(0, 0, size, 0,
750847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek                new int[] {0, Color.argb(0.5f, 1, 1, 1), Color.BLACK},
760847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek                new float[] {0.0f, 0.4f, 1.0f}, Shader.TileMode.CLAMP);
770847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        paint.setShader(linearGradient);
780847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        Bitmap fadeIn = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
790847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        Canvas fadeInCanvas = new Canvas(fadeIn);
800847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        drawable.clearColorFilter();
810847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        drawable.draw(fadeInCanvas);
82b49a070d816c85110f59f10acd52688a4cadae73Selim Cinek
83b49a070d816c85110f59f10acd52688a4cadae73Selim Cinek        if (isRtl) {
84b49a070d816c85110f59f10acd52688a4cadae73Selim Cinek            // Let's flip the gradient
85b49a070d816c85110f59f10acd52688a4cadae73Selim Cinek            fadeInCanvas.translate(size, 0);
86b49a070d816c85110f59f10acd52688a4cadae73Selim Cinek            fadeInCanvas.scale(-1, 1);
87b49a070d816c85110f59f10acd52688a4cadae73Selim Cinek        }
880847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
890847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        fadeInCanvas.drawPaint(paint);
900847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek
91ca585d29ba32637dc1b335ff527a7e777048d250Selim Cinek        Paint coloredPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
92ca585d29ba32637dc1b335ff527a7e777048d250Selim Cinek        coloredPaint.setColorFilter(new ColorMatrixColorFilter(m));
93ca585d29ba32637dc1b335ff527a7e777048d250Selim Cinek        coloredPaint.setAlpha((int) (0.5f * 255));
94ca585d29ba32637dc1b335ff527a7e777048d250Selim Cinek        canvas.drawBitmap(fadeIn, 0, 0, coloredPaint);
95ca585d29ba32637dc1b335ff527a7e777048d250Selim Cinek
96ca585d29ba32637dc1b335ff527a7e777048d250Selim Cinek        linearGradient =  new LinearGradient(0, 0, size, 0,
97ca585d29ba32637dc1b335ff527a7e777048d250Selim Cinek                new int[] {0, Color.argb(0.5f, 1, 1, 1), Color.BLACK},
980847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek                new float[] {0.0f, 0.6f, 1.0f}, Shader.TileMode.CLAMP);
990847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        paint.setShader(linearGradient);
100ca585d29ba32637dc1b335ff527a7e777048d250Selim Cinek        fadeInCanvas.drawPaint(paint);
101ca585d29ba32637dc1b335ff527a7e777048d250Selim Cinek        canvas.drawBitmap(fadeIn, 0, 0, null);
102ca585d29ba32637dc1b335ff527a7e777048d250Selim Cinek
1030847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek        return newBitmap;
1040847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek    }
1050847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek}
106