Android 以编程方式模糊 ImageView Drawable



我想在Android中以编程方式模糊和取消模糊图像。

我听说 API 14 之后不再支持 android 标志"blur",但无论如何我都想使用 Java 方法。我的主要问题是从 Imageview 可绘制对象操作位图。

如何从图像视图中获取位图并对其进行操作(可能会使用高斯模糊)并将其设置回图像视图?我认为该过程涉及提取可绘制对象,将可绘制对象转换为位图,在该位图上执行模糊方法,然后执行相反的操作,直到再次将其设置为图像视图

但我希望这个过程详细说明,谢谢

以下是实现高斯模糊的代码。愿这可以帮助您

import android.graphics.Bitmap;
import android.graphics.Matrix;
/**
 * @author robert.hinds
 *
 * Wrapper class for the Android Bitmap - used by all filters
 *
 */
public class AndroidImage {
    //original bitmap image
    private Bitmap image;
    //format of image (jpg/png)
    private String formatName;
    //dimensions of image
    private int width, height;
    // RGB Array Color
    protected int[] colourArray;
    public AndroidImage(Bitmap img){        
        this.image =  img;
        formatName = "jpg";
        width = img.getWidth();
        height = img.getHeight();
        updateColourArray();
    }

    /**
     * Method to reset the image to a solid colour
     * 
     * @param color - colour to rest the entire image to
     */
    public void clearImage(int color){
        for(int y=0; y<height; y++){
            for(int x=0; x<width; x++){
                image.setPixel(x, y, color);
            }
        }
    }

    /**
     * Set colour array for image - called on initialisation
     * by constructor
     * 
     * @param bitmap
     */
    private void updateColourArray(){
        colourArray = new int[width * height];
        image.getPixels(colourArray, 0, width, 0, 0, width, height);
        int r, g, b;
        for (int y = 0; y < height; y++){
            for (int x = 0; x < width; x++){
                int index = y * width + x;
                r = (colourArray[index] >> 16) & 0xff;
                g = (colourArray[index] >> 8) & 0xff;
                b = colourArray[index] & 0xff;
                colourArray[index] = 0xff000000 | (r << 16) | (g << 8) | b;
            }
        }
    }

    /**
     * Method to set the colour of a specific pixel
     * 
     * @param x
     * @param y
     * @param colour
     */
    public void setPixelColour(int x, int y, int colour){
        colourArray[((y*image.getWidth()+x))] = colour;
        image.setPixel(x, y, colour);
    }
    /**
     * Get the colour for a specified pixel
     * 
     * @param x
     * @param y
     * @return colour
     */
    public int getPixelColour(int x, int y){
        return colourArray[y*width+x];
    }
    /**
     * Set the colour of a specified pixel from an RGB combo
     * 
     * @param x
     * @param y
     * @param c0
     * @param c1
     * @param c2
     */
    public void setPixelColour(int x, int y, int c0, int c1, int c2){
        colourArray[((y*image.getWidth()+x))] = (255 << 24) + (c0 << 16) + (c1 << 8) + c2;
        image.setPixel(x, y, colourArray[((y*image.getWidth()+x))]);
    }
    /**
     * Method to get the RED colour for the specified 
     * pixel 
     * @param x
     * @param y
     * @return colour of R
     */
    public int getRComponent(int x, int y){
        return (getColourArray()[((y*width+x))]& 0x00FF0000) >>> 16;
    }

    /**
     * Method to get the GREEN colour for the specified 
     * pixel 
     * @param x
     * @param y
     * @return colour of G
     */
    public int getGComponent(int x, int y){
        return (getColourArray()[((y*width+x))]& 0x0000FF00) >>> 8;
    }

    /**
     * Method to get the BLUE colour for the specified 
     * pixel 
     * @param x
     * @param y
     * @return colour of B
     */
    public int getBComponent(int x, int y){
        return (getColourArray()[((y*width+x))] & 0x000000FF);
    }

    /**
     * Method to rotate an image by the specified number of degrees
     * 
     * @param rotateDegrees
     */
    public void rotate (int rotateDegrees){
        Matrix mtx = new Matrix();
        mtx.postRotate(rotateDegrees);
        image = Bitmap.createBitmap(image, 0, 0, width, height, mtx, true);
        width = image.getWidth();
        height = image.getHeight();
        updateColourArray();
    }

    /**
     * @return the image
     */
    public Bitmap getImage() {
        return image;
    }

    /**
     * @param image the image to set
     */
    public void setImage(Bitmap image) {
        this.image = image;
    }

    /**
     * @return the formatName
     */
    public String getFormatName() {
        return formatName;
    }

    /**
     * @param formatName the formatName to set
     */
    public void setFormatName(String formatName) {
        this.formatName = formatName;
    }

    /**
     * @return the width
     */
    public int getWidth() {
        return width;
    }

    /**
     * @param width the width to set
     */
    public void setWidth(int width) {
        this.width = width;
    }

    /**
     * @return the height
     */
    public int getHeight() {
        return height;
    }

    /**
     * @param height the height to set
     */
    public void setHeight(int height) {
        this.height = height;
    }

    /**
     * @return the colourArray
     */
    public int[] getColourArray() {
        return colourArray;
    }

    /**
     * @param colourArray the colourArray to set
     */
    public void setColourArray(int[] colourArray) {
        this.colourArray = colourArray;
    }
}

import com.bvise.fotoflipper.core.AndroidImage;


public interface IAndroidFilter {
    public AndroidImage process(AndroidImage imageIn);
}

import android.graphics.Bitmap;
import android.graphics.Color;
public class ConvolutionMatrix
{
    public static final int SIZE = 3;
    public double[][] Matrix;
    public double Factor = 1;
    public double Offset = 1;
    public ConvolutionMatrix(int size) {
        Matrix = new double[size][size];
    }
    public void setAll(double value) {
        for (int x = 0; x < SIZE; ++x) {
            for (int y = 0; y < SIZE; ++y) {
                Matrix[x][y] = value;
            }
        }
    }
    public void applyConfig(double[][] config) {
        for(int x = 0; x < SIZE; ++x) {
            for(int y = 0; y < SIZE; ++y) {
                Matrix[x][y] = config[x][y];
            }
        }
    }
    public static Bitmap computeConvolution3x3(Bitmap src, ConvolutionMatrix matrix) {
        int width = src.getWidth();
        int height = src.getHeight();
        Bitmap result = Bitmap.createBitmap(width, height, src.getConfig());
        int A, R, G, B;
        int sumR, sumG, sumB;
        int[][] pixels = new int[SIZE][SIZE];
        for(int y = 0; y < height - 2; ++y) {
            for(int x = 0; x < width - 2; ++x) {
                // get pixel matrix
                for(int i = 0; i < SIZE; ++i) {
                    for(int j = 0; j < SIZE; ++j) {
                        pixels[i][j] = src.getPixel(x + i, y + j);
                    }
                }
                // get alpha of center pixel
                A = Color.alpha(pixels[1][1]);
                // init color sum
                sumR = sumG = sumB = 0;
                // get sum of RGB on matrix
                for(int i = 0; i < SIZE; ++i) {
                    for(int j = 0; j < SIZE; ++j) {
                        sumR += (Color.red(pixels[i][j]) * matrix.Matrix[i][j]);
                        sumG += (Color.green(pixels[i][j]) * matrix.Matrix[i][j]);
                        sumB += (Color.blue(pixels[i][j]) * matrix.Matrix[i][j]);
                    }
                }
                // get final Red
                R = (int)(sumR / matrix.Factor + matrix.Offset);
                if(R < 0) { R = 0; }
                else if(R > 255) { R = 255; }
                // get final Green
                G = (int)(sumG / matrix.Factor + matrix.Offset);
                if(G < 0) { G = 0; }
                else if(G > 255) { G = 255; }
                // get final Blue
                B = (int)(sumB / matrix.Factor + matrix.Offset);
                if(B < 0) { B = 0; }
                else if(B > 255) { B = 255; }
                // apply new pixel
                result.setPixel(x + 1, y + 1, Color.argb(A, R, G, B));
            }
        }
        // final image
        return result;
    }
}

import android.graphics.Bitmap;
import com.bvise.fotoflipper.core.AndroidImage;
import com.bvise.fotoflipper.core.ConvolutionMatrix;
import com.bvise.fotoflipper.filters.IAndroidFilter;
public class GaussianBlur implements IAndroidFilter{
    @Override
    public AndroidImage process(AndroidImage imageIn) {
        // TODO Auto-generated method stub
        Bitmap src=imageIn.getImage();
        double[][] GaussianBlurConfig = new double[][] {
                { 1, 2, 1 },
                { 2, 4, 2 },
                { 1, 2, 1 }
            };
            ConvolutionMatrix convMatrix = new ConvolutionMatrix(3);
            convMatrix.applyConfig(GaussianBlurConfig);
            convMatrix.Factor = 200;
            convMatrix.Offset = 0;
            return new AndroidImage(ConvolutionMatrix.computeConvolution3x3(src, convMatrix));
    }

}

为了模糊图像视图或位图,renderScript 与毕加索库结合使用。

public class Blur implements Transformation {
    protected static final int UP_LIMIT = 25;
    protected static final int LOW_LIMIT = 1;
    protected final Context context;
    protected final int blurRadius;

    public Blur(Context context, int radius) {
        this.context = context;
        if(radius<LOW_LIMIT){
            this.blurRadius = LOW_LIMIT;
        }else if(radius>UP_LIMIT){
            this.blurRadius = UP_LIMIT;
        }else
            this.blurRadius = radius;
    }
    @Override
    public Bitmap transform(Bitmap source) {
        Bitmap sourceBitmap = source;
        Bitmap blurredBitmap;
        blurredBitmap = Bitmap.createBitmap(sourceBitmap);
        RenderScript renderScript = RenderScript.create(context);
        Allocation input = Allocation.createFromBitmap(renderScript, 
                sourceBitmap, 
                Allocation.MipmapControl.MIPMAP_FULL, 
                Allocation.USAGE_SCRIPT);

        Allocation output = Allocation.createTyped(renderScript, input.getType());
        ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(renderScript, 
                                    Element.U8_4(renderScript));
        script.setInput(input);
        script.setRadius(blurRadius);
        script.forEach(output);
        output.copyTo(blurredBitmap);
        source.recycle();
        return blurredBitmap;
    }
    @Override
    public String key() {
        return "blurred";
    }
}

添加此类后,使用 Picasso 模糊图像视图或任何位图

Picasso.with(context).load("load-from-whatever-source").transform(new Blur(context, 20)).into("wherever");

我在这个博客中找到了这个答案。

从 Android 12(API 级别 31)开始,有一个新的 View API 来应用模糊效果android.view.View#setRenderEffect

image.setRenderEffect(
    RenderEffect.createBlurEffect(
        20.0f, 20.0f, Shader.TileMode.CLAMP
    )
)

您可以使用完全用 Kotlin 编写的线圈库,

imageView.load("your_source") {
    transformations(BlurTransformation(applicationContext,20f))
}

相关内容

  • 没有找到相关文章

最新更新