package org.appsroid.fxpro.bitmap;
import java.io.IOException;
import java.util.Random;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.LightingColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.media.ExifInterface;
public class BitmapProcessing {
// [-360, +360] -> Default = 0
public static Bitmap rotate(Bitmap bitmap, float degrees) {
Matrix matrix = new Matrix();
matrix.postRotate(degrees);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
public static Bitmap flip(Bitmap bitmap, boolean horizontal, boolean vertical) {
Matrix matrix = new Matrix();
matrix.preScale(horizontal ? -1 : 1, vertical ? -1 : 1);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
public static Bitmap emboss(Bitmap src) {
double[][] EmbossConfig = new double[][] {
{ -1 , 0, -1 },
{ 0 , 4, 0 },
{ -1 , 0, -1 }
};
ConvolutionMatrix convMatrix = new ConvolutionMatrix(3);
convMatrix.applyConfig(EmbossConfig);
convMatrix.Factor = 1;
convMatrix.Offset = 127;
return ConvolutionMatrix.computeConvolution3x3(src, convMatrix);
}
// [0, 150], default => 100
public static Bitmap cfilter(Bitmap src, double red, double green, double blue) {
red = (double) red / 100;
green = (double) green / 100;
blue = (double) blue / 100;
// image size
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// color information
int A, R, G, B;
int pixel;
// scan through all pixels
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
// apply filtering on each channel R, G, B
A = Color.alpha(pixel);
R = (int)(Color.red(pixel) * red);
G = (int)(Color.green(pixel) * green);
B = (int)(Color.blue(pixel) * blue);
// set new color pixel to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
src.recycle();
src = null;
// return final image
return bmOut;
}
public static Bitmap gaussian(Bitmap src) {
double[][] GaussianBlurConfig = new double[][] {
{ 1, 2, 1 },
{ 2, 4, 2 },
{ 1, 2, 1 }
};
ConvolutionMatrix convMatrix = new ConvolutionMatrix(3);
convMatrix.applyConfig(GaussianBlurConfig);
convMatrix.Factor = 16;
convMatrix.Offset = 0;
return ConvolutionMatrix.computeConvolution3x3(src, convMatrix);
}
// bitOffset = (16, 32, 64, 128)
public static Bitmap cdepth(Bitmap src, int bitOffset) {
// get image size
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// color information
int A, R, G, B;
int pixel;
// scan through all pixels
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
// round-off color offset
R = ((R + (bitOffset / 2)) - ((R + (bitOffset / 2)) % bitOffset) - 1);
if(R < 0) { R = 0; }
G = ((G + (bitOffset / 2)) - ((G + (bitOffset / 2)) % bitOffset) - 1);
if(G < 0) { G = 0; }
B = ((B + (bitOffset / 2)) - ((B + (bitOffset / 2)) % bitOffset) - 1);
if(B < 0) { B = 0; }
// set pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
src.recycle();
src = null;
return bmOut;
}
public static Bitmap sharpen(Bitmap src) {
double[][] SharpConfig = new double[][] {
{ 0 , -2 , 0 },
{ -2, 11, -2 },
{ 0 , -2 , 0 }
};
ConvolutionMatrix convMatrix = new ConvolutionMatrix(3);
convMatrix.applyConfig(SharpConfig);
convMatrix.Factor = 3;
return ConvolutionMatrix.computeConvolution3x3(src, convMatrix);
}
public static Bitmap noise(Bitmap source) {
final int COLOR_MAX = 0xFF;
// get image size
int width = source.getWidth();
int height = source.getHeight();
int[] pixels = new int[width * height];
// get pixel array from source
source.getPixels(pixels, 0, width, 0, 0, width, height);
// a random object
Random random = new Random();
int index = 0;
// iteration through pixels
for(int y = 0; y < height; ++y) {
for(int x = 0; x < width; ++x) {
// get current index in 2D-matrix
index = y * width + x;
// get random color
int randColor = Color.rgb(random.nextInt(COLOR_MAX),
random.nextInt(COLOR_MAX), random.nextInt(COLOR_MAX));
// OR
pixels[index] |= randColor;
}
}
// output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, source.getConfig());
bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
source.recycle();
source = null;
return bmOut;
}
// [-255, +255] -> Default = 0
public static Bitmap brightness(Bitmap src, int value) {
// image size
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// color information
int A, R, G, B;
int pixel;
// scan through all pixels
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
// increase/decrease each channel
R += value;
if(R > 255) { R = 255; }
else if(R < 0) { R = 0; }
G += value;
if(G > 255) { G = 255; }
else if(G < 0) { G = 0; }
B += value;
if(B > 255) { B = 255; }
else if(B < 0) { B = 0; }
// apply new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
src.recycle();
src = null;
return bmOut;
}
public static Bitmap sepia(Bitmap src) {
// image size
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// constant grayscale
final double GS_RED = 0.3;
final double GS_GREEN = 0.59;
final double GS_BLUE = 0.11;
// color information
int A, R, G, B;
int pixel;
// scan through all pixels
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
// get color on each channel
A = Color.alpha(pixel);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
// apply grayscale sample
B = G = R = (int)(GS_RED * R + GS_GREEN * G + GS_BLUE * B);
// apply intensity level for sepid-toning on each channel
R += 110;
if(R > 255) { R = 255; }
G += 65;
if(G > 255) { G = 255; }
B += 20;
if(B > 255) { B = 255; }
// set new pixel color to output image
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
src.recycle();
src = null;
return bmOut;
}
// red, green, blue [0, 48]
public static Bitmap gamma(Bitmap src, double red, double green, double blue) {
red = (double) (red + 2) / 10.0;
green = (double) (green + 2) / 10.0;
blue = (double) (blue + 2) / 10.0;
// create output image
Bitmap bmOut = Bitmap.createBitmap(src.getWidth(), src.getHeight(), src.getConfig());
// get image size
int width = src.getWidth();
int height = src.getHeight();
// color information
int A, R, G, B;
int pixel;
// constant value curve
final int MAX_SIZE = 256;
final double MAX_VALUE_DBL = 255.0;
final int MAX_VALUE_INT = 255;
final double REVERSE = 1.0;
// gamma arrays
int[] gammaR = new int[MAX_SIZE];
int[] gammaG = new int[MAX_SIZE];
int[] gammaB = new int[MAX_SIZE];
// setting values for every gamma channels
for(int i = 0; i < MAX_SIZE; ++i) {
gammaR[i] = (int)Math.min(MAX_VALUE_INT,
(int)((MAX_VALUE_DBL * Math.pow(i / MAX_VALUE_DBL, REVERSE / red)) + 0.5));
gammaG[i] = (int)Math.min(MAX_VALUE_INT,
(int)((MAX_VALUE_DBL * Math.pow(i / MAX_VALUE_DBL, REVERSE / green)) + 0.5));
gammaB[i] = (int)Math.min(MAX_VALUE_INT,
(int)((MAX_VALUE_DBL * Math.pow(i / MAX_VALUE_DBL, REVERSE / blue)) + 0.5));
}
// apply gamma table
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
// look up gamma
R = gammaR[Color.red(pixel)];
G = gammaG[Color.green(pixel)];
B = gammaB[Color.blue(pixel)];
// set new color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
src.recycle();
src = null;
// return final image
return bmOut;
}
// [-100, +100] -> Default = 0
public static Bitmap contrast(Bitmap src, double value) {
// image size
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
// create a mutable empty bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// create a canvas so that we can draw the bmOut Bitmap from source bitmap
Canvas c = new Canvas();
c.setBitmap(bmOut);
// draw bitmap to bmOut from src bitmap so we can modify it
c.drawBitmap(src, 0, 0, new Paint(Color.BLACK));
// color information
int A, R, G, B;
int pixel;
// get contrast value
double contrast = Math.pow((100 + value) / 100, 2);
// scan through all pixels
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
// apply filter contrast for every channel R, G, B
R = Color.red(pixel);
R = (int)(((((R / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if(R < 0) { R = 0; }
else if(R > 255) { R = 255; }
G = Color.green(pixel);
G = (int)(((((G / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if(G < 0) { G = 0; }
else if(G > 255) { G = 255; }
B = Color.blue(pixel);
B = (int)(((((B / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if(B < 0) { B = 0; }
else if(B > 255) { B = 255; }
// set new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
src.recycle();
src = null;
return bmOut;
}
// [0, 200] -> Default = 100
public static Bitmap saturation(Bitmap src, int value) {
float f_value = (float) (value / 100.0);
int w = src.getWidth();
int h = src.getHeight();
Bitmap bitmapResult =
Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvasResult = new Canvas(bitmapResult);
Paint paint = new Paint();
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(f_value);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
paint.setColorFilter(filter);
canvasResult.drawBitmap(src, 0, 0, paint);
src.recycle();
src = null;
return bitmapResult;
}
public static Bitmap grayscale(Bitmap src) {
//Array to generate Gray-Scale image
float[] GrayArray = {
0.213f, 0.715f, 0.072f, 0.0f, 0.0f,
0.213f, 0.715f, 0.072f, 0.0f, 0.0f,
0.213f, 0.715f, 0.072f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
};
ColorMatrix colorMatrixGray = new ColorMatrix(GrayArray);
int w = src.getWidth();
int h = src.getHeight();
Bitmap bitmapResult = Bitmap
.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvasResult = new Canvas(bitmapResult);
Paint paint = new Paint();
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrixGray);
paint.setColorFilter(filter);
canvasResult.drawBitmap(src, 0, 0, paint);
src.recycle();
src = null;
return bitmapResult;
}
public static Bitmap vignette(Bitmap image) {
final int width = image.getWidth();
final int height = image.getHeight();
float radius = (float) (width/1.2);
int[] colors = new int[] { 0, 0x55000000, 0xff000000 };
float[] positions = new float[] { 0.0f, 0.5f, 1.0f };
RadialGradient gradient = new RadialGradient(width / 2, height / 2, radius, colors, positions, Shader.TileMode.CLAMP);
//RadialGradient gradient = new RadialGradient(width / 2, height / 2, radius, Color.TRANSPARENT, Color.BLACK, Shader.TileMode.CLAMP);
Canvas canvas = new Canvas(image);
canvas.drawARGB(1, 0, 0, 0);
final Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setShader(gradient);
final Rect rect = new Rect(0, 0, image.getWidth(), image.getHeight());
final RectF rectf = new RectF(rect);
canvas.drawRect(rectf, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(image, rect, rect, paint);
return image;
}
// hue = [0, 360] -> Default = 0
public static Bitmap hue(Bitmap bitmap, float hue) {
Bitmap newBitmap = bitmap.copy(bitmap.getConfig(), true);
final int width = newBitmap.getWidth();
final int height = newBitmap.getHeight();
float [] hsv = new float[3];
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
int pixel = newBitmap.getPixel(x,y);
Color.colorToHSV(pixel,hsv);
hsv[0] = hue;
newBitmap.setPixel(x,y,Color.HSVToColor(Color.alpha(pixel),hsv));
}
}
bitmap.recycle();
bitmap = null;
return newBitmap;
}
public static Bitmap tint(Bitmap src, int color) {
// image size
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
// create a mutable empty bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
Paint p = new Paint(Color.RED);
ColorFilter filter = new LightingColorFilter(color, 1);
p.setColorFilter(filter);
Canvas c = new Canvas();
c.setBitmap(bmOut);
c.drawBitmap(src, 0, 0, p);
src.recycle();
src = null;
return bmOut;
}
public static Bitmap invert(Bitmap src) {
Bitmap output = Bitmap.createBitmap(src.getWidth(), src.getHeight(), src.getConfig());
int A, R, G, B;
int pixelColor;
int height = src.getHeight();
int width = src.getWidth();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
pixelColor = src.getPixel(x, y);
A = Color.alpha(pixelColor);
R = 255 - Color.red(pixelColor);
G = 255 - Color.green(pixelColor);
B = 255 - Color.blue(pixelColor);
output.setPixel(x, y, Color.argb(A, R, G, B));
}
}
src.recycle();
src = null;
return output;
}
// percent = [0, 150], type = (1, 2, 3) => (R, G, B)
public static Bitmap boost(Bitmap src, int type, float percent) {
percent = (float) percent / 100;
int width = src.getWidth();
int height = src.getHeight();
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
int A, R, G, B;
int pixel;
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
if(type == 1) {
R = (int)(R * (1 + percent));
if(R > 255) R = 255;
}
else if(type == 2) {
G = (int)(G * (1 + percent));
if(G > 255) G = 255;
}
else if(type == 3) {
B = (int)(B * (1 + percent));
if(B > 255) B = 255;
}
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
src.recycle();
src = null;
return bmOut;
}
public static final Bitmap sketch(Bitmap src) {
int type = 6;
int threshold = 130;
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[3][3];
for(int y = 0; y < height - 2; ++y) {
for(int x = 0; x < width - 2; ++x) {
// get pixel matrix
for(int i = 0; i < 3; ++i) {
for(int j = 0; j < 3; ++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;
sumR = (type*Color.red(pixels[1][1])) - Color.red(pixels[0][0]) - Color.red(pixels[0][2]) - Color.red(pixels[2][0]) - Color.red(pixels[2][2]);
sumG = (type*Color.green(pixels[1][1])) - Color.green(pixels[0][0]) - Color.green(pixels[0][2]) - Color.green(pixels[2][0]) - Color.green(pixels[2][2]);
sumB = (type*Color.blue(pixels[1][1])) - Color.blue(pixels[0][0]) - Color.blue(pixels[0][2]) - Color.blue(pixels[2][0]) - Color.blue(pixels[2][2]);
// get final Red
R = (int)(sumR + threshold);
if(R < 0) { R = 0; }
else if(R > 255) { R = 255; }
// get final Green
G = (int)(sumG + threshold);
if(G < 0) { G = 0; }
else if(G > 255) { G = 255; }
// get final Blue
B = (int)(sumB + threshold);
if(B < 0) { B = 0; }
else if(B > 255) { B = 255; }
result.setPixel(x + 1, y + 1, Color.argb(A, R, G, B));
}
}
src.recycle();
src = null;
return result;
}
public static Bitmap modifyOrientation(Bitmap bitmap, String image_url) throws IOException {
ExifInterface ei = new ExifInterface(image_url);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
return rotate(bitmap, 90);
case ExifInterface.ORIENTATION_ROTATE_180:
return rotate(bitmap, 180);
case ExifInterface.ORIENTATION_ROTATE_270:
return rotate(bitmap, 270);
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
return flip(bitmap, true, false);
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
return flip(bitmap, false, true);
default:
return bitmap;
}
}
}