Rounded Corner Bitmaps
public static Bitmap createRoundedBitmap(Bitmap sourceBitmap, float cornerRadius) {
Bitmap resultBitmap = Bitmap.createBitmap(sourceBitmap.getWidth(), sourceBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(resultBitmap);
final int maskColor = 0xff424242;
final Paint paint = new Paint();
final Rect imageBounds = new Rect(0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight());
final RectF boundsF = new RectF(imageBounds);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(maskColor);
canvas.drawRoundRect(boundsF, cornerRadius, cornerRadius, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(sourceBitmap, imageBounds, imageBounds, paint);
return resultBitmap;
}
Filter Effects
Grayscale (Black and White) Conversion
public static Bitmap convertToGrayscale(Bitmap sourceBitmap) {
int width = sourceBitmap.getWidth();
int height = sourceBitmap.getHeight();
int[] pixelArray = new int[width * height];
sourceBitmap.getPixels(pixelArray, 0, width, 0, 0, width, height);
final int fullAlpha = 0xFF << 24;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int currentPixel = pixelArray[y * width + x];
int red = (currentPixel & 0x00FF0000) >> 16;
int green = (currentPixel & 0x0000FF00) >> 8;
int blue = currentPixel & 0x000000FF;
int grayscaleValue = (int) (red * 0.3 + green * 0.59 + blue * 0.11);
int grayscalePixel = fullAlpha | (grayscaleValue << 16) | (grayscaleValue << 8) | grayscaleValue;
pixelArray[y * width + x] = grayscalePixel;
}
}
Bitmap resultBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
resultBitmap.setPixels(pixelArray, 0, width, 0, 0, width, height);
return resultBitmap;
}
Gaussian Blur
public static Bitmap applyGaussianBlur(Bitmap sourceBitmap) {
int[] blurKernel = new int[] {1, 2, 1, 2, 4, 2, 1, 2, 1};
int width = sourceBitmap.getWidth();
int height = sourceBitmap.getHeight();
Bitmap resultBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
int[] pixelArray = new int[width * height];
sourceBitmap.getPixels(pixelArray, 0, width, 0, 0, width, height);
final int normalizationFactor = 16;
for (int y = 1; y < height -1; y++) {
for (int x =1; x < width -1; x++) {
int kernelIndex =0;
int totalRed =0, totalGreen=0, totalBlue=0;
for (int dy = -1; dy <=1; dy++) {
for (int dx=-1; dx <=1; dx++) {
int currentPixel = pixelArray[(y+dy)*width + (x+dx)];
totalRed += Color.red(currentPixel) * blurKernel[kernelIndex];
totalGreen += Color.green(currentPixel) * blurKernel[kernelIndex];
totalBlue += Color.blue(currentPixel) * blurKernel[kernelIndex];
kernelIndex++;
}
}
totalRed /= normalizationFactor;
totalGreen /= normalizationFactor;
totalBlue /= normalizationFactor;
totalRed = Math.min(255, Math.max(0, totalRed));
totalGreen = Math.min(255, Math.max(0, totalGreen));
totalBlue = Math.min(255, Math.max(0, totalBlue));
pixelArray[y*width +x] = Color.argb(255, totalRed, totalGreen, totalBlue);
}
}
resultBitmap.setPixels(pixelArray, 0, width, 0,0, width, height);
return resultBitmap;
}
Sketch Effect
public static Bitmap applySketchEffect(Bitmap sourceBitmap) {
int width = sourceBitmap.getWidth();
int height = sourceBitmap.getHeight();
int[] sourcePixels = new int[width*height];
int[] invertedPixels = new int[width*height];
sourceBitmap.getPixels(sourcePixels,0, width,0,0,width,height);
// Convert to grayscale and invert
for (int y=0; y<height; y++) {
for(int x=0; x<width; x++) {
int idx = y*width +x;
int r = Color.red(sourcePixels[idx]);
int g = Color.green(sourcePixels[idx]);
int b = Color.blue(sourcePixels[idx]);
int gray = (r+g+b)/3;
sourcePixels[idx] = gray;
invertedPixels[idx] = 255 - gray;
}
}
// Apply Gaussian blur to inverted grayscale
applyGaussianBlurToGrayscale(invertedPixels,5.0,5.0,width,height);
// Blend original and blurred inverted
for(int y=0; y<height; y++) {
for(int x=0; x<width; x++) {
int idx = y*width +x;
int gray = sourcePixels[idx];
int blurredInv = invertedPixels[idx];
int sketchValue = (gray <<8) / (256 - blurredInv);
sketchValue = Math.min(255, Math.max(0, sketchValue));
sourcePixels[idx] = Color.rgb(sketchValue, sketchValue, sketchValue);
}
}
sourceBitmap.setPixels(sourcePixels,0,width,0,0,width,height);
return sourceBitmap;
}
private static int applyGaussianBlurToGrayscale(int[] pixels, double horizontalSigma, double verticalSigma, int width, int height) {
int[] tempSrc = new int[Math.max(width, height)];
int[] tempDst = new int[Math.max(width, height)];
double[] posVals = new double[Math.max(width, height)];
double[] negVals = new double[Math.max(width, height)];
double[] posN = new double[5], negN = new double[5];
double[] posD = new double[5], negD = new double[5];
double[] posBd = new double[5], negBd = new double[5];
// Process vertical direction
if (verticalSigma >0) {
verticalSigma = Math.abs(verticalSigma)+1.0;
double stdDev = Math.sqrt(-(verticalSigma*verticalSigma)/(2*Math.log(1.0/255.0)));
calculateBlurConstants(posN, negN, posD, negD, posBd, negBd, stdDev);
for(int col=0; col<width; col++) {
Arrays.fill(posVals, 0);
Arrays.fill(negVals, 0);
for(int y=0; y<height; y++) {
tempSrc[y] = pixels[y*width +col];
}
int posSrcIdx=0, negSrcIdx=height-1;
int posValIdx=0, negValIdx=height-1;
int[] posInit = new int[4], negInit = new int[4];
posInit[0] = tempSrc[0];
negInit[0] = tempSrc[height-1];
for(int y=0; y<height; y++) {
int terms = y<4 ? y :4;
for(int i=0; i<=terms; i++) {
posVals[posValIdx] += posN[i] * tempSrc[posSrcIdx -i] - posD[i] * posVals[posValIdx -i];
negVals[negValIdx] += negN[i] * tempSrc[negSrcIdx +i] - negD[i] * negVals[negValIdx +i];
}
for(int i=terms+1; i<=4; i++) {
posVals[posValIdx] += (posN[i] - posBd[i]) * posInit[0];
negVals[negValIdx] += (negN[i] - negBd[i]) * negInit[0];
}
posSrcIdx++; negSrcIdx--;
posValIdx++; negValIdx--;
}
mergeBlurResults(posVals, negVals, tempDst, 1, height);
for(int y=0; y<height; y++) {
pixels[y*width +col] = tempDst[y];
}
}
}
// Process horizontal direction
if (horizontalSigma>0) {
horizontalSigma = Math.abs(horizontalSigma)+1.0;
double stdDev;
if (horizontalSigma != verticalSigma) {
stdDev = Math.sqrt(-(horizontalSigma*horizontalSigma)/(2*Math.log(1.0/255.0)));
calculateBlurConstants(posN, negN, posD, negD, posBd, negBd, stdDev);
}
for(int y=0; y<height; y++) {
Arrays.fill(posVals,0);
Arrays.fill(negVals,0);
for(int x=0; x<width; x++) {
tempSrc[x] = pixels[y*width +x];
}
int posSrcIdx=0, negSrcIdx=width-1;
int posValIdx=0, negValIdx=width-1;
int[] posInit = new int[4], negInit = new int[4];
posInit[0] = tempSrc[0];
negInit[0] = tempSrc[width-1];
for(int x=0; x<width; x++) {
int terms = x<4 ?x:4;
for(int i=0; i<=terms; i++) {
posVals[posValIdx] += posN[i] * tempSrc[posSrcIdx -i] - posD[i] * posVals[posValIdx -i];
negVals[negValIdx] += negN[i] * tempSrc[negSrcIdx +i] - negD[i] * negVals[negValIdx +i];
}
for(int i=terms+1; i<=4; i++) {
posVals[posValIdx] += (posN[i]-posBd[i])*posInit[0];
negVals[negValIdx] += (negN[i]-negBd[i])*negInit[0];
}
posSrcIdx++; negSrcIdx--;
posValIdx++; negValIdx--;
}
mergeBlurResults(posVals, negVals, tempDst,1, width);
for(int x=0; x<width; x++) {
pixels[y*width +x] = tempDst[x];
}
}
}
return 0;
}
private static void mergeBlurResults(double[] src1, double[] src2, int[] dest, int bytes, int length) {
int idx=0;
for(int i=0; i<length*bytes; i++) {
double sum = src1[idx] + src2[idx];
sum = Math.min(255, Math.max(0, sum));
dest[idx] = (int)sum;
idx++;
}
}
private static void calculateBlurConstants(double[] posN, double[] negN, double[] posD, double[] negD, double[] posBd, double[] negBd, double stdDev) {
double div = Math.sqrt(2*Math.PI)*stdDev;
double x0 = -1.783/stdDev;
double x1 = -1.723/stdDev;
double x2 = 0.6318/stdDev;
double x3 =1.997/stdDev;
double x4=1.6803/div;
double x5=3.735/div;
double x6=-0.6803/div;
double x7=-0.2598/div;
posN[0] = x4+x6;
posN[1] = Math.exp(x1)*(x7*Math.sin(x3)-(x6+2*x4)*Math.cos(x3)) + Math.exp(x0)*(x5*Math.sin(x2)-(2*x6+x4)*Math.cos(x2));
posN[2] = 2*Math.exp(x0+x1)*((x4+x6)*Math.cos(x3)*Math.cos(x2) -x5*Math.cos(x3)*Math.sin(x2)-x7*Math.cos(x2)*Math.sin(x3)) +x6*Math.exp(2*x0)+x4*Math.exp(2*x1);
posN[3] = Math.exp(x1+2*x0)*(x7*Math.sin(x3)-x6*Math.cos(x3)) + Math.exp(x0+2*x1)*(x5*Math.sin(x2)-x4*Math.cos(x2));
posN[4] =0.0;
posD[0] =0.0;
posD[1] = -2*Math.exp(x1)*Math.cos(x3) -2*Math.exp(x0)*Math.cos(x2);
posD[2] =4*Math.cos(x3)*Math.cos(x2)*Math.exp(x0+x1)+Math.exp(2*x1)+Math.exp(2*x0);
posD[3] =-2*Math.cos(x2)*Math.exp(x0+2*x1)-2*Math.cos(x3)*Math.exp(x1+2*x0);
posD[4] =Math.exp(2*x0+2*x1);
System.arraycopy(posD,0,negD,0,5);
negN[0] =0.0;
for(int i=1; i<5; i++) {
negN[i] = posN[i] - posD[i]*posN[0];
}
double sumPosN=0, sumNegN=0, sumD=0;
for(int i=0; i<5; i++) {
sumPosN += posN[i];
sumNegN += negN[i];
sumD += posD[i];
}
double a = sumPosN/(1+sumD);
double b = sumNegN/(1+sumD);
for(int i=0; i<5; i++) {
posBd[i] = posD[i]*a;
negBd[i] = negD[i]*b;
}
}
Laplacien Sharpening
public static Bitmap applyLaplacianSharpening(Bitmap sourceBitmap) {
int[] sharpenKernel = new int[] {-1,-1,-1, -1,9,-1, -1,-1,-1};
int width = sourceBitmap.getWidth();
int height = sourceBitmap.getHeight();
Bitmap resultBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
int[] pixelArray = new int[width*height];
sourceBitmap.getPixels(pixelArray,0,width,0,0,width,height);
final float sharpenStrength =0.3f;
for(int y=1; y<height-1; y++) {
for(int x=1; x<width-1; x++) {
int kernelIdx=0;
int totalRed=0, totalGreen=0, totalBlue=0;
for(int dy=-1; dy<=1; dy++) {
for(int dx=-1; dx<=1; dx++) {
int currentPixel = pixelArray[(y+dy)*width + (x+dx)];
totalRed += (int)(Color.red(currentPixel)*sharpenKernel[kernelIdx]*sharpenStrength);
totalGreen += (int)(Color.green(currentPixel)*sharpenKernel[kernelIdx]*sharpenStrength);
totalBlue += (int)(Color.blue(currentPixel)*sharpenKernel[kernelIdx]*sharpenStrength);
kernelIdx++;
}
}
totalRed = Math.min(255, Math.max(0, totalRed));
totalGreen = Math.min(255, Math.max(0, totalGreen));
totalBlue = Math.min(255, Math.max(0, totalBlue));
pixelArray[y*width +x] = Color.argb(255, totalRed, totalGreen, totalBlue);
}
}
resultBitmap.setPixels(pixelArray,0,width,0,0,width,height);
return resultBitmap;
}
Embosss Effect
public static Bitmap applyEmbossEffect(Bitmap sourceBitmap) {
int width = sourceBitmap.getWidth();
int height = sourceBitmap.getHeight();
Bitmap resultBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
int[] pixelArray = new int[width*height];
sourceBitmap.getPixels(pixelArray,0,width,0,0,width,height);
for(int y=1; y<height-1; y++) {
for(int x=1; x<width-1; x++) {
int currentIdx = y*width +x;
int currentPixel = pixelArray[currentIdx];
int rightPixel = pixelArray[currentIdx +1];
int red = Color.red(rightPixel) - Color.red(currentPixel) +127;
int green = Color.green(rightPixel) - Color.green(currentPixel) +127;
int blue = Color.blue(rightPixel) - Color.blue(currentPixel) +127;
red = Math.min(255, Math.max(0, red));
green = Math.min(255, Math.max(0, green));
blue = Math.min(255, Math.max(0, blue));
pixelArray[currentIdx] = Color.argb(255, red, green, blue);
}
}
resultBitmap.setPixels(pixelArray,0,width,0,0,width,height);
return resultBitmap;
}