Search in sources :

Example 1 with IconNormalizer

use of com.android.launcher3.icons.IconNormalizer in project Neo-Launcher by NeoApplications.

the class AdaptiveIconGenerator method loop.

private void loop() {
    if (Utilities.ATLEAST_OREO && shouldWrap) {
        if (roundIcon != null && roundIcon instanceof AdaptiveIconCompat) {
            icon = roundIcon;
        }
        Drawable extractee = icon;
        if (icon instanceof AdaptiveIconCompat) {
            if (!treatWhite) {
                onExitLoop();
                return;
            }
            AdaptiveIconCompat aid = (AdaptiveIconCompat) extractee;
            // we still check this seperately as this is the only information we need from the background
            if (!isSingleColor(aid.getBackground(), Color.WHITE)) {
                onExitLoop();
                return;
            }
            isBackgroundWhite = true;
            extractee = aid.getForeground();
        }
        if (extractee == null) {
            Log.e("AdaptiveIconGenerator", "extractee is null, skipping.");
            onExitLoop();
            return;
        }
        LauncherIcons li = LauncherIcons.obtain(context);
        IconNormalizer normalizer = li.getNormalizer();
        li.recycle();
        boolean[] outShape = new boolean[1];
        RectF bounds = new RectF();
        initTmpIfNeeded();
        // scale = normalizer.getScale(extractee, bounds, tmp.getIconMask(), outShape);
        scale = normalizer.getScale(extractee, bounds, tmp.getIconMask(), outShape, MIN_VISIBLE_ALPHA);
        matchesMaskShape = outShape[0];
        if (extractee instanceof ColorDrawable) {
            isFullBleed = true;
            fullBleedChecked = true;
        }
        width = extractee.getIntrinsicWidth();
        height = extractee.getIntrinsicHeight();
        aWidth = width * (1 - (bounds.left + bounds.right));
        aHeight = height * (1 - (bounds.top + bounds.bottom));
        // Check if the icon is squareish
        final float ratio = aHeight / aWidth;
        boolean isSquareish = 0.999 < ratio && ratio < 1.0001;
        boolean almostSquarish = isSquareish || (0.97 < ratio && ratio < 1.005);
        if (!isSquareish) {
            isFullBleed = false;
            fullBleedChecked = true;
        }
        final Bitmap bitmap = Utilities.drawableToBitmap(extractee);
        if (bitmap == null) {
            onExitLoop();
            return;
        }
        if (!bitmap.hasAlpha()) {
            isFullBleed = true;
            fullBleedChecked = true;
        }
        final int size = height * width;
        SparseIntArray rgbScoreHistogram = new SparseIntArray(NUMBER_OF_COLORS_GUESSTIMATION);
        final int[] pixels = new int[size];
        bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
        /*
             *   Calculate the number of padding pixels around the actual icon (i)
             *   +----------------+
             *   |      top       |
             *   +---+--------+---+
             *   |   |        |   |
             *   | l |    i   | r |
             *   |   |        |   |
             *   +---+--------+---+
             *   |     bottom     |
             *   +----------------+
             */
        float adjHeight = height - bounds.top - bounds.bottom;
        float l = bounds.left * width * adjHeight;
        float top = bounds.top * height * width;
        float r = bounds.right * width * adjHeight;
        float bottom = bounds.bottom * height * width;
        int addPixels = Math.round(l + top + r + bottom);
        // Any icon with less than 10% transparent pixels (padding excluded) is considered "full-bleed-ish"
        final int maxTransparent = (int) (round(size * .10) + addPixels);
        // Any icon with less than 27% transparent pixels (padding excluded) doesn't need a color mix-in
        final int noMixinScore = (int) (round(size * .27) + addPixels);
        int highScore = 0;
        int bestRGB = 0;
        int transparentScore = 0;
        for (int pixel : pixels) {
            int alpha = 0xFF & (pixel >> 24);
            if (alpha < MIN_VISIBLE_ALPHA) {
                // Drop mostly-transparent pixels.
                transparentScore++;
                if (transparentScore > maxTransparent) {
                    isFullBleed = false;
                    fullBleedChecked = true;
                    if (!extractColor && transparentScore > noMixinScore) {
                        break;
                    }
                }
                continue;
            }
            // Reduce color complexity.
            int rgb = ColorExtractor.posterize(pixel);
            if (rgb < 0) {
                // Defensively avoid array bounds violations.
                continue;
            }
            int currentScore = rgbScoreHistogram.get(rgb) + 1;
            rgbScoreHistogram.append(rgb, currentScore);
            if (currentScore > highScore) {
                highScore = currentScore;
                bestRGB = rgb;
            }
        }
        // add back the alpha channel
        bestRGB |= 0xff << 24;
        // not yet checked = not set to false = has to be full bleed, isBackgroundWhite = true = is adaptive
        isFullBleed |= !fullBleedChecked && !isBackgroundWhite;
        // return early if a mix-in isnt needed
        noMixinNeeded = !isFullBleed && !isBackgroundWhite && almostSquarish && transparentScore <= noMixinScore;
        if (isFullBleed || noMixinNeeded) {
            backgroundColor = bestRGB;
            onExitLoop();
            return;
        }
        if (!extractColor) {
            backgroundColor = Color.WHITE;
            onExitLoop();
            return;
        }
        // "single color"
        final int numColors = rgbScoreHistogram.size();
        boolean singleColor = numColors <= SINGLE_COLOR_LIMIT;
        // Convert to HSL to get the lightness and adjust the color
        final float[] hsl = new float[3];
        ColorUtils.colorToHSL(bestRGB, hsl);
        float lightness = hsl[2];
        boolean light = lightness > .5;
        // Apply dark background to mostly white icons
        boolean veryLight = lightness > .75 && singleColor;
        // Apply light background to mostly dark icons
        boolean veryDark = lightness < .35 && singleColor;
        // Adjust color to reach suitable contrast depending on the relationship between the colors
        final int opaqueSize = size - transparentScore;
        final float pxPerColor = opaqueSize / (float) numColors;
        float mixRatio = min(max(pxPerColor / highScore, .15f), .7f);
        // Vary color mix-in based on lightness and amount of colors
        int fill = (light && !veryLight) || veryDark ? 0xFFFFFFFF : 0xFF333333;
        backgroundColor = ColorUtils.blendARGB(bestRGB, fill, mixRatio);
    // backgroundColor = Utilities.findDominantColorByHue(bitmap, 20);
    }
    onExitLoop();
}
Also used : IconNormalizer(com.android.launcher3.icons.IconNormalizer) ColorDrawable(android.graphics.drawable.ColorDrawable) Drawable(android.graphics.drawable.Drawable) FixedScaleDrawable(com.android.launcher3.icons.FixedScaleDrawable) AdaptiveIconCompat(com.android.launcher3.AdaptiveIconCompat) RectF(android.graphics.RectF) Bitmap(android.graphics.Bitmap) ColorDrawable(android.graphics.drawable.ColorDrawable) SparseIntArray(android.util.SparseIntArray) LauncherIcons(com.android.launcher3.icons.LauncherIcons)

Example 2 with IconNormalizer

use of com.android.launcher3.icons.IconNormalizer in project android_packages_apps_404Launcher by P-404.

the class AdaptiveIconWrapper method wrap.

@TargetApi(26)
public Drawable wrap(Drawable icon, int backgroundColor) {
    if (Utilities.ATLEAST_OREO && !(icon instanceof AdaptiveIconDrawable)) {
        boolean[] outShape = new boolean[1];
        mWrapper.setBounds(0, 0, 1, 1);
        LauncherIcons icons = LauncherIcons.obtain(mContext);
        IconNormalizer normalizer = icons.getNormalizer();
        float scale = normalizer.getScale(icon, null, mWrapper.getIconMask(), outShape);
        icons.recycle();
        if (!outShape[0]) {
            FixedScaleDrawable fsd = ((FixedScaleDrawable) mWrapper.getForeground());
            fsd.setDrawable(icon);
            fsd.setScale(scale);
            ((ColorDrawable) mWrapper.getBackground()).setColor(backgroundColor);
            return mWrapper;
        }
    }
    return icon;
}
Also used : ColorDrawable(android.graphics.drawable.ColorDrawable) LauncherIcons(com.android.launcher3.icons.LauncherIcons) IconNormalizer(com.android.launcher3.icons.IconNormalizer) AdaptiveIconDrawable(android.graphics.drawable.AdaptiveIconDrawable) FixedScaleDrawable(com.android.launcher3.icons.FixedScaleDrawable) TargetApi(android.annotation.TargetApi)

Aggregations

ColorDrawable (android.graphics.drawable.ColorDrawable)2 FixedScaleDrawable (com.android.launcher3.icons.FixedScaleDrawable)2 IconNormalizer (com.android.launcher3.icons.IconNormalizer)2 LauncherIcons (com.android.launcher3.icons.LauncherIcons)2 TargetApi (android.annotation.TargetApi)1 Bitmap (android.graphics.Bitmap)1 RectF (android.graphics.RectF)1 AdaptiveIconDrawable (android.graphics.drawable.AdaptiveIconDrawable)1 Drawable (android.graphics.drawable.Drawable)1 SparseIntArray (android.util.SparseIntArray)1 AdaptiveIconCompat (com.android.launcher3.AdaptiveIconCompat)1