I am working on photo collage project on Android. I want to know how to implement the following collage effect?
So there are two photos will fit into each triangle.
or more complex shape like this: (this will hod 5 photos)
It's not that easy.
One solution would be to remove the unwanted pixel of your image like the following snippet from this thread (cuts off the top right corner):
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView iv = (ImageView) findViewById(R.id.your_image);
int drawableId = R.drawable.your_drawable;
cutOffTopRightCorner(iv, drawableId, skewWidth);
}
#SuppressLint("NewApi")
private void cutOffTopRightCorner(ImageView iv, int resId, int skewWidth) {
Bitmap bm = BitmapFactory.decodeResource(getResources(), resId).copy(Config.ARGB_8888, true);
bm.setHasAlpha(true);
final int bmWidth = bm.getWidth();
for (int i = bmWidth; i > bmWidth - skewWidth; --i) {
for (int k = 0; k < i - (bmWidth - skewWidth); ++k) {
bm.setPixel(i - 1, k, Color.TRANSPARENT);
}
}
iv.setImageBitmap(bm);
}
Another solution would be to work with FrameLayouts (differenz z-indices) and to overlay your images with other images or drawables.
You can also have a look into this thread.
Related
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.
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();
So, what I am trying to do is if I click the button, it will tint a image that is on the same screen with orange color (70%).
Button OrangeButton= (Button) findViewById(R.id.OButton);
OrangeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
imageCapture = (ImageView) findViewById(R.id.imageCapture);
BitmapDrawable drawable = (BitmapDrawable) imageCapture
.getDrawable();
final Bitmap imgbitmap = drawable.getBitmap();
// convert bitmap to hokie tint
Bitmap imgnew;
imgnew = toOrange(imgbitmap);
// convert bitmap to imageview
imageCapture.setImageBitmap(imgnew);
}
});
}
Here is my orange method.
public Bitmap toOrange(Bitmap bmpOriginal) {
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
int orangeFilter = new Color().rgb(255, 165, 0);
int maroonFilter = new Color().rgb(115, 24, 44);
for (int j = 0; j < height - 1; j++) {
for (int i = 0; i < width - 1; i++) {
I am pretty sure that I have a problem, here.
int newColor = (int) (bmpOriginal.getPixel(i, j) * 0.7 + orangeFilter
* 0.3);
bmpOriginal.setPixel(i, j, newColor);
}
}
return bmpOriginal;
}
I tried bmpOriginal.setPixel(5, 5, Color.Red) outside of this loob, and it made an error too. So I know that the setPixel is not working. How can I fix this problem?
Since you're not posting what exactly the error is, I'm assuming that the Bitmap is immutable, which means you can't change it. You could try making a mutable copy of it, see http://developer.android.com/reference/android/graphics/Bitmap.html
An easier way could be to apply a color filter to your ImageView like so:
imageCapture.setColorFilter(Color.rgb(255, 165, 0));
Im extending the View class in order to have a "drawable" view witch contains the desired background.
The problem is when this class works fine in other activity (same app).
Here is the class that extends View:
public class BackgroundMap extends View {
private String strmap;
private int totalWidth;
public BackgroundMap(Context context, String map, int w, int h) {
super(context);
super.setLayoutParams(new LayoutParams(w, h));
totalWidth = w;
strmap = map;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Resources res = getResources();
int eachBoxSize = totalWidth/10;
float left = 0;
float top = 0;
Paint paint = new Paint();
for(char c : strmap.toCharArray()){
Bitmap bm = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(res, Terrain.getResource(c)), eachBoxSize, eachBoxSize, false);
canvas.drawBitmap(bm, left, top, paint);
if(left == totalWidth - eachBoxSize){
left = 0;
top += eachBoxSize;
}else{
left += eachBoxSize;
}
}
}
}
This view works like this: somelayout.addView(new BackgroundMap(arg..));
the String map argument means an array of terrains (char) ids that point to several little png images.
and this is how i use it in my Activity:
ly_rbtn_image = (FrameLayout) findViewById(R.id.ly_rbtn_image);
ly_rbtn_image.post(new Runnable() {
#Override
public void run() {
imagewidth = ly_rbtn_image.getWidth();
ly_rbtn_image.addView(new BackgroundMap(getApplicationContext(), str, imagewidth, imagewidth));
}
});
i check with logcat the width of parent layout and it has 225px. As you can see the image below only build the first row of bitmaps... but this IS NOT a loop problem
I check inside the custom view loop at onDraw method if there was a problem here but it iterate the whole string (100 chars, 10x10 bitmaps)
hope u can help me :S
http://deviantsart.com/1afcam8.png
solved. please delete me.
the bitmaps were pushed at right till the end of the loop. So in fact, i didnt know why this happened.
UNTIL I CHECKED THE BOUNDS OF THE RESULT VIEW IN LOGCAT x))) the view had 2000 pixels width and 20 height... there we go:
When i get the total width of the device, casually was a number divisible by 10 (10x10 grid) so in fact was lucky not having this problem before (building the same map in other view).
Then, the problem was the need to print the same map (or grid) in an other view, not big as the device width, so the total width (parent width) was not divisible by the number of columns of the grid (im ashamed x)).
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);
}
}
}
}