Making specific color in bitmap transparent - android

I have an Android application to display an image on another image, such that second image's white colour is transparent. To do this, I have used two ImageViews, with the original image to be overlaid as bitmap1 and the image to be made transparent as bitmap2. When I run this, I get some exceptions at the setPixel method.
Here's my code:
Bitmap bitmap2 = null;
int width = imViewOverLay.getWidth();
int height = imViewOverLay.getHeight();
for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
if(bitMap1.getPixel(x, y) == Color.WHITE)
{
bitmap2.setPixel(x, y, Color.TRANSPARENT);
}
else
{
bitmap2.setPixel(x, y, bitMap1.getPixel(x, y));
}
}
}
imViewOverLay is the ImageView of the overlay image. Any idea what might be going wrong in the above code?

The most obvious error is that you're not creating bitmap2 - unless you've not posted all the code of course.
You declare it and set it to null, but then don't do anything else until you try to call bitmap2.setPixel.

i think you need to make it mutable
Loading a resource to a mutable bitmap
i did this
BitmapFactory.Options bitopt=new BitmapFactory.Options();
bitopt.inMutable=true;
mSnareBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.snare, bitopt);
also, i found i needed to set alpha to something less than 255 for it to render the image with transparent background.
mPaint.setAlpha(250);
canvas.drawBitmap(mSnareBitmap, 0, 30, mPaint);
by the way, using white as your transparent color isn't a great idea because you will get aliasing problems at the edges of your opaque objects. i use green because my overlay images don't have any green in (like a green screen in the movies) then i can remove the green inside the loop and set the alpha value based on the inverse of the green value.
private void loadBitmapAndSetAlpha(int evtype, int id) {
BitmapFactory.Options bitopt=new BitmapFactory.Options();
bitopt.inMutable=true;
mOverlayBitmap[evtype] = BitmapFactory.decodeResource(getResources(), id, bitopt);
Bitmap bm = mOverlayBitmap[evtype];
int width = bm.getWidth();
int height = bm.getHeight();
for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
int argb = bm.getPixel(x, y);
int green = (argb&0x0000ff00)>>8;
if(green>0)
{
int a = green;
a = (~green)&0xff;
argb &= 0x000000ff; // save only blue
argb |= a; // put alpha back in
bm.setPixel(x, y, argb);
}
}
}
}

Related

Android color splash

Can someone suggest me a fast method or a library for color splash effect? For example, I select a color and a photo gets desaturated for all colors except that one I have picked.
I have tried using pixel by pixel color check and then replace the color but it is too slow for big images.
int width = originalImage.getWidth();
int height = originalImage.getHeight();
int[] pixels = new int[width * height];
originalImage.getPixels(pixels, 0, width, 0, 0, width, height);
for (int x = 0; x < pixels.length; ++x) {
pixels[x] = Distance(pixels[x], fromColor) < 4 ? targetColor : pixels[x];
}
Bitmap newImage = Bitmap.createBitmap(width, height, originalImage.getConfig());
newImage.setPixels(pixels, 0, width, 0, 0, width, height);
public int Distance(int a, int b) {
return Math.abs(Color.red(a) - Color.red(b)) + Math.abs(Color.green(a) -
Color.green(b)) + Math.abs(Color.blue(a) - Color.blue(b));
}
EDIT:
Here are the original and the processed images, the color I am keeping is #ff9350:
You can try to go over possible color RGB values and prepareHashSet containing only those color values that should not be
desaturated. It seems that there should not be a lot of values.
After that you will be able to check whether the color should be desaturated or not. Thus, you will get rather long precalculation for a new given color, but your code that converts photo will become faster.
It can be implemented like so (haven't tested it under Android, just some kind of Java pseudo-code to show the idea):
// precalculation
Set<Color> keptColors = new HashSet<Color>();
final int MAX_DISTANCE = 4;
for (int r=red(fromColor)-MAX_DISTANCE; r<=red(fromColor)+MAX_DISTANCE; r++) {
for (int g=green(fromColor)-MAX_DISTANCE; g<=green(fromColor)+MAX_DISTANCE; g++) {
for (int b=blue(fromColor)-MAX_DISTANCE; b<=blue(fromColor)+MAX_DISTANCE; b++) {
if (Distance(rgb(r,g,b)), fromColor) < MAX_DISTANCE {
keptColors.add(rgb(r,g,b));
}
}
}
}
...
// in you photo processing code
keptColors.contains(pixels[x]) ? pixels[x] : targetColor;
use inRange function in OpenCV to isolate a Color
Scalar lower(0,100,100);
Scalar upper(10,255,255);
Core.inRange(hsv, lower, upper, segmentedImage);
check out this Answer

Remove Background of an Image, Split it in same sizes and Change color(overlay)

I've been searching the internet for changing colour or overlaying a specific part of a bitmap. I've a square bitmap and I want to change the colour in a matrix pattern that is in equal 9 blocks which can be understood from the following image. (Cyan colour line here is for demonstration only)
I've read about boundary fill algorithm in College but here for java, I came to know that it is too bulky to perform such an operation for 9 specific parts. And I don't know how to use Paint with Canvas for such a square scenario.
So is there a method or something which can help me figure out how to paint a specific square by providing the size or location without performing a huge task on UI.
Here's what I need to achieve:
I can change the color, location,size by myself if there's something which can help me out.
Also, as there is white background, is there a way to not paint the background or do I have to use PNG?
Update:
I'm successfully able to divide the image in 9 equal parts using following code but PorterDuffColorFilter is not working as expected.
Code:
public void splitBitmap(Bitmap bitmap) {
int width, height;
// Divide the original bitmap width by the desired vertical column count
width = bitmap.getWidth() / 3;
// Divide the original bitmap height by the desired horizontal row count
height = bitmap.getHeight() / 3;
// Loop the array and create bitmaps for each coordinate
for (int x = 0; x < 3; ++x) {
for (int y = 0; y < 3; ++y) {
// Create the sliced bitmap
smallimages.add(Bitmap.createBitmap(bitmap, x * width, y * height, width, height));
}
}
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
The above code provides 9 bitmaps which then set to a GridLayout. But No mode of PorterDuffColorFilter is useful. Either the images remain original or is painted completely. I've tried every one of the modes available and none worked.
I've done something similar to this so after changing my code a bit, I think this is what you want:
Assuming that you don't have PNG,
First, remove the white background from your image Source:
Setting the white color as Transparent, you can use any color you want.
private static final int[] FROM_COLOR = new int[]{255, 255, 255};
private static final int THRESHOLD = 3;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.test_colors);
ImageView iv = (ImageView) findViewById(R.id.img);
Drawable d = getResources().getDrawable(RES);
iv.setImageDrawable(adjust(d));
}
private Drawable adjust(Drawable d)
{
int to = Color.TRANSPARENT;
//Need to copy to ensure that the bitmap is mutable.
Bitmap src = ((BitmapDrawable) d).getBitmap();
Bitmap bitmap = src.copy(Bitmap.Config.ARGB_8888, true);
for(int x = 0;x < bitmap.getWidth();x++)
for(int y = 0;y < bitmap.getHeight();y++)
if(match(bitmap.getPixel(x, y)))
bitmap.setPixel(x, y, to);
return new BitmapDrawable(bitmap);
}
private boolean match(int pixel)
{
//There may be a better way to match, but I wanted to do a comparison ignoring
//transparency, so I couldn't just do a direct integer compare.
return Math.abs(Color.red(pixel) - FROM_COLOR[0]) < THRESHOLD &&
Math.abs(Color.green(pixel) - FROM_COLOR[1]) < THRESHOLD &&
Math.abs(Color.blue(pixel) - FROM_COLOR[2]) < THRESHOLD;
}
Above code will change the color to transparent and below code will split the bitmap into 9 same size bitmaps:
public void splitBitmap(Bitmap bitmap) {
ArrayList<Bitmap> smallimages = new ArrayList<>(9);
int width, height;
// Divide the original bitmap width by the desired vertical column count
width = bitmap.getWidth() / 3;
// Divide the original bitmap height by the desired horizontal row count
height = bitmap.getHeight() / 3;
// Loop the array and create bitmaps for each coordinate
for (int x = 0; x < 3; ++x) {
for (int y = 0; y < 3; ++y) {
// Create the sliced bitmap
smallimages.add(Bitmap.createBitmap(bitmap, x * width, y * height, width, height));
}
}
}
At last, you can use PorterDuffColorFilter on every bitmap:
imageView.setImageDrawable(arrayList.get(0));
imageView.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_ATOP);
There can be problems as it works for me and might not for you but this is the way you can achieve your needed result.
If any problem persists, I can help.

android get bitmap of imageview same as seen on screen

i want to get exacly bitmap show on screen after(scale,filtercolor,...) and work with its pixel for example in order to remove transparent pixel :
for (int y = 0; y < sourceBitmap1.getHeight(); y++)
for (int x = 0; x < sourceBitmap1.getWidth(); x++)
if (sourceBitmap1.getPixel(x, y) == Color.TRANSPARENT) {
//todo do something
}
but it is important to get bitmap related to target Imageview. as i see other post can do this with this method:
public static Bitmap loadBitmapFromView(ImageView i) {
i.setDrawingCacheEnabled(true);
i.measure(FrameLayout.MeasureSpec.makeMeasureSpec(0, FrameLayout.MeasureSpec.UNSPECIFIED),
FrameLayout.MeasureSpec.makeMeasureSpec(0, FrameLayout.MeasureSpec.UNSPECIFIED));
i.layout(0, 0, i.getMeasuredWidth(), i.getMeasuredHeight());
i.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(i.getDrawingCache(true));
i.setDrawingCacheEnabled(false);
return b;
}
but method return null , any idea?
thanks in advanced
try this to get bitmap from imageview
Bitmap bitmap = ((BitmapDrawable) imgview.getDrawable()).getBitmap();

Android create bitmap from RGB 2D arrays

I am working on an android watermarking project, and I need to make a method to generate 2D arrays for R,G and B and recreate the image after getting it back from the WM method that is done by someone else.(I don't have this method, so I can't change it).
Here is how I created the R,G, B from the bitmap:
Bitmap image = BitmapFactory.decodeFile("/sdcard/Watermarking/WM_20151208_183746_1282108897-1.jpg");
int height = image.getHeight();
int width = image.getWidth();
short [][] red = new short[height][width];
short [][] green = new short[height][width];
short [][] blue = new short[height][width];
int column = 0;
int row = 0;
while(row < height)
{
while(column < width)
{
int pixel = image.getPixel(column, row);
red[row][column] = (short) Color.red(pixel);
green[row][column] = (short) Color.green(pixel);
blue[row][column] = (short) Color.blue(pixel);
column++;
}
row++;
}
displayImage(red, green, blue);
And here is the method that I am doing to test that what I did was correct:
public void displayImage(short [][] red, short [][] green, short [][] blue)
{
short height = (short) red.length;
short width = (short) red[0].length;
Bitmap image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
int column = 0;
int row = 0;
while(row < height)
{
while(column < width)
{
image.setPixel(column, row, Color.rgb(red[row][column], green[row][column], blue[row][column]));
column++;
}
row++;
}
ImageView imageView = (ImageView) findViewById(R.id.imageView);
imageView.setImageBitmap (image);
}
The image that appears is a black image, even though it should be correct. Any help is appreciated.
by simply debugging your code, you are only filling the first row of the array repeatedly by not resetting the column variable
add:
column = 0;
after both loops (in filling and reading the array);

Android move ImageView to a specific pixel color

I made a treasure map in photoshop and I made a transparent image with coloured hotspots to put over the treasure map so I can make it clickable.
When I click on the colored dots (that are invisible), Android detects the color clicked and does the appropriate methods, just as asked.
Now I have an imageview, that would be my player, and each day I want it to move to another colored hotspot on the map (each hotspot represents a day of the week).
I have this code, but the position is way off:
private void moveToColor(ImageView iv, int toColor) {
Bitmap bm = BitmapFactory.decodeResource(getResources(),R.drawable.hotspots);
int width = bm.getWidth();
int height = bm.getHeight();
int[] pixels = new int[width * height];
bm.getPixels(pixels, 0, width, 0, 0, width, height);
for (int ix = 0; ix < width; ++ix) {
for (int iy = 0; iy < height; ++iy) {
if (toColor == bm.getPixel(ix, iy)) {
iv.animate().translationX((float)ix);
iv.animate().translationY((float)iy);
return;
}
}
}
}
sometimes it will move the imageview close to the toColor, and other times it is completely off or not even on the map.
Any pointers on how I could do this. I tried it with a buffer copypixelstobuffer, but I didn't understand very well how that works. Because above is quite slow..
Thanks!
Sure it is off, read the description of the translationX property carefully: http://developer.android.com/reference/android/view/View.html#attr_android:translationX
"This value is added post-layout to the left property of the view"
It's relative to the left of the view, i.e. it's displacement, not absolute position.
Instead, use
iv.animate().x((float)ix);
and it's twin brother .y()
I actually found that if I change
Bitmap bm = BitmapFactory.decodeResource(getResources(),R.drawable.hotspots);
int width = bm.getWidth();
int height = bm.getHeight();
to this:
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.hotspots);
bm = Bitmap.createScaledBitmap(bm,size.x, size.y, true);
int width = bm.getWidth();
int height = bm.getHeight();
where size.x and size.y come from
display = getWindowManager().getDefaultDisplay();
size = new Point();
display.getSize(size);
Then the position is not that far off. It is still not completely where I want it, the player is positioned on the bottom of the dot, but at least it is a step closer.

Categories

Resources