getPixels and setPixels on canvas drawn objects - android

I have created a diagonal white line on a custom view from one corner of screen to another corner using this-
canvas.drawLine(0, 0, MainActivity.width+10, MainActivity.height, paint);
I know how to getPixels and setPixels on a Bitmap, like this-
public Bitmap generateAlphaMask(Bitmap bmpTop,Bitmap bmpBottom) {
int width = bmpTop.getWidth();
int height = bmpTop.getHeight();
boolean[][] res = new boolean[width][height];
int[] colors = new int[width * height];
bmpTop.getPixels(colors, 0, width, 0, 0, width, height);
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
int cell = y * width + x;
int redVal = Color.red(colors[cell]);
int greenVal = Color.green(colors[cell]);
int blueVal = Color.blue(colors[cell]);
int alpha = Color.alpha(colors[cell]);
res[x][y] = alpha == ALPHA_THRESHOLD;
if (res[x][y]) {
bmpBottom.setPixel(x, y, Color.TRANSPARENT);
}
}
}
return bmpBottom;
}
But I want to store Pixel Positions from canvas where the pixel is "not white".
Help me regarding this.

Related

Save segmentation result of Selfie segmentation with ML Kit on Android as A Bitmap with transparent background

Save segmentation result of Selfie segmentation with ML Kit on Android as A Bitmap with transparent background
I am following this tutorial and code for Selfie segmentation
Here
I have referred this code from the tutorial
ByteBuffer mask = segmentationMask.getBuffer();
int maskWidth = segmentationMask.getWidth();
int maskHeight = segmentationMask.getHeight();
for (int y = 0; y < maskHeight; y++) {
for (int x = 0; x < maskWidth; x++) {
// Gets the confidence of the (x,y) pixel in the mask being in the foreground.
float foregroundConfidence = mask.getFloat();
}
}
Which generates a Mask
Then I have Referred the Sample app Which generates a purple background Mask
Here
using this code
#ColorInt
private int[] maskColorsFromByteBuffer(ByteBuffer byteBuffer) {
#ColorInt int[] colors = new int[maskWidth * maskHeight];
for (int i = 0; i < maskWidth * maskHeight; i++) {
float backgroundLikelihood = 1 - byteBuffer.getFloat();
if (backgroundLikelihood > 0.9) {
colors[i] = Color.argb(128, 255, 0, 255);
} else if (backgroundLikelihood > 0.2) {
// Linear interpolation to make sure when backgroundLikelihood is 0.2, the alpha is 0 and
// when backgroundLikelihood is 0.9, the alpha is 128.
// +0.5 to round the float value to the nearest int.
int alpha = (int) (182.9 * backgroundLikelihood - 36.6 + 0.5);
colors[i] = Color.argb(alpha, 255, 0, 255);
}
}
return colors;
}
Now I want to generate an Image with the original images detected mask and Overlay it on a Transparent Image and save that bitmap for this I am using this code
public Bitmap generateMaskBgImage(Bitmap image, Bitmap bg) {
//Bg is Transparent Png Image.
Bitmap bgBitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), image.getConfig());
for (int y = 0; y < maskHeight; y++) {
for (int x = 0; x < maskWidth; x++) {
int bgConfidence = (int) ((1.0 - maskBuffer.getFloat()) * 255);
int bgPixel = bg.getPixel(x, y);
bgPixel = ColorUtils.setAlphaComponent(bgPixel, bgConfidence);
bgBitmap.setPixel(x, y, bgPixel);
}
}
maskBuffer.rewind();
return bitmapUtils.mergeBitmaps(image, bgBitmap);
}
However it generates an Image with the desired mask but with a Black back ground, How can we save that image with Transparent background.
You can try this (color1 is the color you set in the mask):
private Bitmap performBW(Bitmap originBitmap,Bitmap maskBitmap) {
Bitmap bmOut = Bitmap.createBitmap(originBitmap.getWidth(), originBitmap.getHeight(),
originBitmap.getConfig());
int w = originBitmap.getWidth();
int h = originBitmap.getHeight();
int[] colors = new int[w * h];
int[] colorsMask=new int[maskBitmap.getWidth() * maskBitmap.getHeight()];
originBitmap.getPixels(colors, 0, w, 0, 0, w, h);
maskBitmap.getPixels(colorsMask, 0, w, 0, 0, w, h);
int pos;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
pos = i * w + j;
if (colorsMask[pos] == color1) colors[pos]=Color.TRANSPARENT;
}
}
bmOut.setPixels(colors, 0, w, 0, 0, w, h);
return bmOut;
}

How to change color of a Bitmap that has anti-aliasing?

I have a drawable that represents a white circle with anti-aliasing that needs to be coloured in runtime.
Here's a scaled image of it:
As you can see, there are few semi-transparent pixels.
If I try to color them the fast way (which takes roughly 6-9 ms for 192x192 px drawable), I will have troubles with semi-transparent.
public static void changeBitmapColor(#NonNull Bitmap src, #ColorInt int newColor) {
Paint paint = new Paint();
ColorFilter filter = new PorterDuffColorFilter(newColor, PorterDuff.Mode.SRC_IN);
paint.setColorFilter(filter);
Canvas canvas = new Canvas(src);
canvas.drawBitmap(src, 0, 0, paint);
}
Here's the drawable after being coloured by setting ColorFilter:
If I do it using brute-force algorithm, it takes roughly 100ms to go over all pixels and apply alpha parameter to a new color:
public static void changeBitmapColor2(#NonNull Bitmap src, #ColorInt int newColor) {
int w = src.getWidth();
int h = src.getHeight();
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int color = src.getPixel(x, y);
int alpha = color >>> 24;
if (alpha == 0) {
continue;
}
color = (newColor & 0x00ffffff) | (alpha << 24);
src.setPixel(x, y, color);
}
}
}
The resulting image of 2nd algorithm:
Is there anything I could do with 1st algorithm that it will result in a better quality colouring without sacrificing the performance?
Turns out, the 2nd algorithm had the right idea, but poor implementation. The key was to batch pixel retrieval and set, i.e. using pixel array:
public static void changeBitmapColor2(#NonNull Bitmap src, #ColorInt int newColor) {
int width = src.getWidth();
int height = src.getHeight();
int[] pixels = new int[height * width];
src.getPixels(pixels, 0, width, 0, 0, width, height);
int newColorNoAlpha = newColor & 0x00ffffff;
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
int currentPixel = i * width + j;
int color = pixels[currentPixel];
int alpha = color >>> 24;
if (alpha == 0) {
continue;
}
pixels[currentPixel] = newColorNoAlpha | (alpha << 24);
}
}
src.setPixels(pixels, 0, width, 0, 0, width, height);
}
This batching has reduced time to change color of 200x200 image from 100-120ms to 1-4 ms :)

Android add subtle noise to Bitmap

Anyone know how to add subtle noise to grayscale image?
I have a grayscale image that I want to add some subtle black and white noise to. Anyone know how to do this?
I'm currently using this method, but this is just generating random colors and swapping existing pixels with those colors. How can I add some subtle black and white noise to only SOME pixels on a bitmap?
public static Bitmap applyFleaEffect(Bitmap source) {
// get source 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);
// create 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(255),
random.nextInt(255), random.nextInt(255));
// OR
pixels[index] |= randColor;
}
}
// output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, source.getConfig());
bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
return bmOut;
}
}
UPDATE: Adding complete code to show grayscale step, and attempted noise step
//First, apply greyscale to make Image black and white
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, mBitmap.getConfig());
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
//Apply noise after grayscale
int[] pixels = new int[width * height];
bmpGrayscale.getPixels(pixels, 0, width, 0, 0, width, height);
// a random object
Random random = new Random();
int index = 0;
// Note: Declare the c and randColor variables outside of the for loops
int co = 0;
int randColor = 0;
// iteration through pixels
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
if (random.nextInt(101) < percentNoise) {
// Skip this iteration a certain percentage of the time
continue;
}
// get current index in 2D-matrix
index = y * width + x;
co = random.nextInt(255);
randColor = Color.rgb(co, co, co);
pixels[index] |= randColor;
}
}
// output bitmap
mBitmap = Bitmap.createBitmap(width, height, bmpGrayscale.getConfig());
mBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
c.drawBitmap(mBitmap, 0, 0, paint);
return bmpGrayscale;
}
First, randColor is not likely to be a gray-scale color with your code. To generate a random, gray-scale color:
int c = random.nextInt(255);
int randColor = Color.rgb(c, c, c);
With that in mind, here is how I would re-write your code (note: adjust the percentNoise parameter to your liking):
public static Bitmap applyFleaEffect(Bitmap source, int percentNoise) {
// get source 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);
// create a random object
Random random = new Random();
int index = 0;
// Note: Declare the c and randColor variables outside of the for loops
int c = 0;
int randColor = 0;
// iterate through pixels
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
if (random.nextInt(101) < percentNoise) {
// Skip this iteration a certain percentage of the time
continue;
}
// get current index in 2D-matrix
index = y * width + x;
// get random color
c = random.nextInt(255);
randColor = Color.rgb(c, c, c);
pixels[index] |= randColor;
}
}
Bitmap bmOut = Bitmap.createBitmap(width, height, source.getConfig());
bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
return bmOut;
}

Android: Convert Grayscale to Binary Image

i hava done with get grayscale value, but i don't know how to use function to convert the grayscale to be binary image. Please help me, here my function code:
public Bitmap toBinary(Bitmap bmpOriginal) {
int width, height, threshold;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
threshold = 127;
final Bitmap bmpBinary = null;
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get one pixel color
int pixel = bmpOriginal.getPixel(x, y);
//get grayscale value
int gray = (int)(pixel & 0xFF);
//get binary value
if(gray < threshold){
bmpBinary.setPixel(x, y, 0);
} else{
bmpBinary.setPixel(x, y, 255);
}
}
}
return bmpBinary;
}
here my full code:
public class MainActivity extends Activity {
ImageView img;
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//convert imageview to bitmap
img =(ImageView) findViewById(R.id.imageView1);
BitmapDrawable drawable = (BitmapDrawable) img.getDrawable();
final Bitmap imgbitmap = drawable.getBitmap();
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//convert bitmap to grayscale
Bitmap imgnew;
imgnew = toGrayscale(imgbitmap);
//convert to binary
imgnew = toBinary(imgnew);
//convert bitmap to imageview
ImageView imgbit;
imgbit = (ImageView) findViewById(R.id.imageView2);
imgbit.setImageBitmap(imgnew);
}
});
}
public Bitmap toGrayscale(Bitmap bmpOriginal){
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
public Bitmap toBinary(Bitmap bmpOriginal) {
int width, height, threshold;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
threshold = 127;
final Bitmap bmpBinary = null;
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get one pixel color
int pixel = bmpOriginal.getPixel(x, y);
//get grayscale value
int gray = (int)(pixel & 0xFF);
//get binary value
if(gray < threshold){
bmpBinary.setPixel(x, y, 0);
} else{
bmpBinary.setPixel(x, y, 255);
}
}
}
return bmpBinary;
}
}
First, you get a NullReferenceException because bmpBinary is NULL.
Second, to get one Color chanel you can use int red = Color.red(pixel);
Third, to set a pixel white use bmpBinary.setPixel(x, y, 0xFFFFFFFF);
I modified your code a bit:
public Bitmap toBinary(Bitmap bmpOriginal) {
int width, height, threshold;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
threshold = 127;
Bitmap bmpBinary = Bitmap.createBitmap(bmpOriginal);
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get one pixel color
int pixel = bmpOriginal.getPixel(x, y);
int red = Color.red(pixel);
//get binary value
if(red < threshold){
bmpBinary.setPixel(x, y, 0xFF000000);
} else{
bmpBinary.setPixel(x, y, 0xFFFFFFFF);
}
}
}
return bmpBinary;
}
An even better way is not to use just the value of one color chanel but a weighted average of red green and blue for example:
int gray = (int)(red * 0.3 + green * 0.59 + blue * 0.11);

android noise effect on bitmap

I am writing some function to add noise effect on bitmap. I found similar question: Add noise effect to a drawing
Bitmap outputBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
BitmapShader shader = new BitmapShader (bitmap, TileMode.REPEAT, TileMode.REPEAT);
Paint paint = new Paint();
paint.setShader(shader);
Canvas c = new Canvas(outputBitmap);
c.drawBitmap(bitmap, 0, 0, paint);
How should i add color filter to get such a result? Could you provide somple code?
i suggested that use this code.
public static final int COLOR_MIN = 0x00;
public static final int COLOR_MAX = 0xFF;
public static Bitmap applyFleaEffect(Bitmap source) {
// 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);
return bmOut;
}
welcome.

Categories

Resources