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