问题
I want to programmatically blur and unblur images in Android.
I hear that android flag "blur" is no longer supported after API 14 , but I wanted to use Java methods anyway. My main problem is manipulating the bitmap from an Imageview drawable.
How would I get the bitmap from an imageview and manipulate it (will probably use gaussian blur) and set it back to the imageview? I think the process involves extracting the drawable, converting the drawable to a bitmap, doing my blur method on that bitmap and then doing the reverse till it is set to the imageview again
but I would like that process spelled out, thank you
回答1:
Following are the codes for implementing gaussian blur. May this can help you
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));
}
}
回答2:
For blurring an imageView or bitmap, renderScript is used in conjunction with Picasso library.
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";
}
}
Once you have added this class use the Picasso to blur the imageview or any bitmap
Picasso.with(context).load("load-from-whatever-source").transform(new Blur(context, 20)).into("wherever");
I found this answer in this blog.
来源:https://stackoverflow.com/questions/14555937/android-programmatically-blur-imageview-drawable