I am trying to add snow flow effect. but not succeed
I tried to do the effect of continuously flow the snow.
is it possible? if yes than please give suggestion.
my code is below.
public class MainActivity extends Activity {
private int COLOR_MAX = 0xff;
ImageView image;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = (ImageView)findViewById(R.id.imageView1);
Bitmap imagebitmap = BitmapFactory.decodeResource(getResources(),R.drawable.hydrangeas);
applySnowEffect(imagebitmap);
}
Bitmap applySnowEffect(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);
// random object
Random random = new Random();
int R, G, B, index = 0, thresHold = 50;
// 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 color
R = Color.red(pixels[index]);
G = Color.green(pixels[index]);
B = Color.blue(pixels[index]);
// generate threshold
thresHold = random.nextInt(COLOR_MAX );
if(R > thresHold && G > thresHold && B > thresHold) {
pixels[index] = Color.rgb(COLOR_MAX, COLOR_MAX, COLOR_MAX);
}
}
}
// output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
Toast.makeText(getApplicationContext(),"processed",10).show();
return bmOut;
}
I actually read about this the other day. You can use a particle system for Android. A library that can assist with that is found here - https://github.com/plattysoft/Leonids
Well I've just find the solution.
The source is here: code link
The main idea is SnowFallView extends View, and overriding onDraw(Canvas canvas) event, where we drawing our snow flakes drawables.
The code is just tested and works well.
Related
I am new to Android and need to process a bitmap to extract the pixel information into a multi-dimensional array by collecting only the black pixels i.e. R = 0, G = 0, and B = 0. I noticed that there is a GetPixel(x, y) method which is apparently slow and I need something like this instead. But I'm lost on how to implement a better GetPixel(x, y) method using information from GetPixels(). I am trying something like this currently:
private static int[][] GetPixels(Bitmap bmp)
{
int height = bmp.getHeight();
int width = bmp.getWidth();
int length = width * height;
int[] pixels = new int[length];
bmp.getPixels(pixels, 0, 0, 0, 0, width, height);
int[][]result = new int[width][height];
for(int pixel = 0, x = 0, y = 0; pixel < pixels.length; pixel += 4)
{
int argb = pixels[pixel];//how to access pixel information?
result[x][y] = argb;//store only black pixels??
x++;
if(y == width)
{
x = 0;
y++;
}
}
return result;
}
I am trying to set a region of pixels in a mutable bitmap a different color in my android app. Unfortunately I cannot get setPixels() to work properly. I am constantly getting ArrayOutOfBoundsExceptions. I think it may have something to do with the stride, but I'm really not sure. That is the only parameter that I still don't understand. The only other post I have seen on setPixels (not setPixel) is here: drawBitmap() and setPixels(): what's the stride? and it did not help me. I tried setting the stride as 0, as the width of the bitmap, as the width of the bitmap - the area i'm trying to draw and it still crashes. Here is my code:
public void updateBitmap(byte[] buf, int offset, int x, int y, int width, int height) {
// transform byte[] to int[]
IntBuffer intBuf = ByteBuffer.wrap(buf).asIntBuffer();
int[] intarray = new int[intBuf.remaining()];
intBuf.get(intarray);
int stride = ??????
screenBitmap.setPixels(intarray, offset, stride, x, y, width, height); // crash here
My bitmap is mutable, so I know that is not the problem. I am also certain that my byte array is being properly converted to an integer array. But I keep getting ArrayOutOfBoundsExceptions and I don't understand why. Please help me figure this out
EDIT -
here is how I construct the fake input:
int width = 1300;
int height = 700;
byte[] buf = new byte[width * height * 4 * 4]; // adding another * 4 here seems to work... why?
for (int i = 0; i < width * height * 4 * 4; i+=4) {
buf[i] = (byte)255;
buf[i + 1] = 3;
buf[i + 2] = (byte)255;
buf[i + 3] = 3;
}
//(byte[] buf, int offset, int x, int y, int width, int height) - for reference
siv.updateBitmap(buf, 0, 0, 0, width, height);
So the width and height are the correct amount of ints (at least it should be).
EDIT2 - here is the code for the original creation of screenBitmap:
public Bitmap createABitmap() {
int w = 1366;
int h = 766;
byte[] buf = new byte[h * w * 4];
for (int i = 0; i < h * w * 4;i+=4) {
buf[i] = (byte)255;
buf[i+1] = (byte)255;
buf[i+2] = 0;
buf[i+3] = 0;
}
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
IntBuffer intBuf = ByteBuffer.wrap(buf).asIntBuffer();
int[] intarray = new int[intBuf.remaining()];
intBuf.get(intarray);
Bitmap bmp = Bitmap.createBitmap(metrics, w, h, itmap.Config.valueOf("ARGB_8888"));
bmp.setPixels(intarray, 0, w, 0, 0, w, h);
return bmp;
}
It seems to work in this instance, not sure what the difference is
Short
I think, stride is the width of the image contained in pixels.
long
What I take from the documentation, the algorithm should work somehow like this:
public void setPixels (int[] pixels,
int offset,
int stride,
int x,
int y,
int width,
int height)
for (int rowIndex = 0; rowIndex < height; rowIndex++) {
int rowStart = offset + stride * rowIndex; // row position in pixels
int bitmapY = y + rowIndex; // y position in the bitmap
for (int columnIndex = 0; columnIndex < width; columnIndex++) {
int bitmapX = x + columnIndex; // x position in the bitmap
int pixelsIndex = rowStart + columnIndex; // position in pixels
setPixel(bitmapX, bitmapY, pixels[pixelsIndex]);
}
}
}
At least this is what I would do with these arguments because is allows you to have one pixels as source and cut out different images in different sizes.
Feel free to correct the algorithm if I am wrong.
So, say you have an image with pixelsWidth and pixelsHeight in pixels.
Then you want to copy a section at pixelsX and pixelsY with width and height to a bitmap at position bitmapX and bitmapY.
This should be the call:
bitmap.setPixels(
pixelsWidth * pixelsY + pixelsX, // offset
pixelsWidth, // stride
bitmapX, // x
bitmapY, // y
width,
height)
probably it should be:
screenBitmap.setPixels(intarray, 0, width / 4, x, y, width / 4, height);
because you have converted byte to int. your error is ArrayOutOfBoundsExceptions. check whether the size intBuf.remaining() = width * height / 4.
If you're trying to draw on a bitmap, your best approach would be to abandon this method and use a canvas instead:
Canvas canvas = new Canvas(screenBitmap);
You can then draw specific points (if you want to draw a pixel), or other shapes like rectangles, circles, etc:
canvas.drawPoint(x, y, paint);
etc
Hope this helps.
I have images which I display in my app. They are downloaded from the web. These images are pictures of objects on an almost-white background. I want this background to be white (#FFFFFF). I figure, if I look at pixel 0,0 (which should always be off-white), I can get the color value and replace every pixel in the image having that value with white.
This question has been asked before and the answer seems to be this:
int intOldColor = bmpOldBitmap.getPixel(0,0);
Bitmap bmpNewBitmap = Bitmap.createBitmap(bmpOldBitmap.getWidth(), bmpOldBitmap.getHeight(), Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpNewBitmap);
Paint paint = new Paint();
ColorFilter filter = new LightingColorFilter(intOldColor, Color.WHITE);
paint.setColorFilter(filter);
c.drawBitmap(bmpOriginal, 0, 0, paint);
However, this isn't working.
After running this code, the entire image seems to be the color I was wanting to remove. As in, the entire image is 1 solid color now.
I was also hoping to not have to loop through every pixel in the entire image.
Any ideas?
Here is a method I created for you to replace a specific color for the one you want. Note that all the pixels will get scanned on the Bitmap and only the ones that are equal will be replaced for the one you want.
private Bitmap changeColor(Bitmap src, int colorToReplace, int colorThatWillReplace) {
int width = src.getWidth();
int height = src.getHeight();
int[] pixels = new int[width * height];
// get pixel array from source
src.getPixels(pixels, 0, width, 0, 0, width, height);
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
int A, R, G, B;
int pixel;
// iteration through pixels
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
// get current index in 2D-matrix
int index = y * width + x;
pixel = pixels[index];
if(pixel == colorToReplace){
//change A-RGB individually
A = Color.alpha(colorThatWillReplace);
R = Color.red(colorThatWillReplace);
G = Color.green(colorThatWillReplace);
B = Color.blue(colorThatWillReplace);
pixels[index] = Color.argb(A,R,G,B);
/*or change the whole color
pixels[index] = colorThatWillReplace;*/
}
}
}
bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
return bmOut;
}
I hope that helped :)
I have the following problem. I started with a bitmap transformation routine that works
flawlessly for any kind of transformation I can throw at it.
Bitmap transform(Bitmap src) {
// ... any kind of transformation , for example GAMMA
double gama = 0.8;
int[] tR = new int[256];
int[] gG = new int[256];
int[] tB = new int[256];
for(int i = 0; i < 256; ++i) {
tR[i] = (int)Math.min(255, (int)((255.0 * Math.pow(i / 255.0, 1.0 / gama)) + 0.5));
tG[i] = (int)Math.min(255, (int)((255.0 * Math.pow(i / 255.0, 1.0 / gama)) + 0.5));
tB[i] = (int)Math.min(255, (int)((255.0 * Math.pow(i / 255.0, 1.0 / gama)) + 0.5));
}
// apply transformation to the old bitmap -> bmOut
int wid = src.getWidth(), hei = src.getHeight();
Bitmap bmOut = Bitmap.createBitmap(wid, hei, src.getConfig());
int A, R, G, B;
for(int x = 0; x < wid; x++) {
for(int y = 0; y < hei; y++) {
int pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
R = tR[Color.red(pixel)];
G = tG[Color.green(pixel)];
B = tB[Color.blue(pixel)];
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
return bmOut;
}
But it is PAINFULLY slow - caused by the getPixel() / setPixel() brothers, sisters.
No problem, says I, I'll just use a memory buffer (like in the old StretchBlt() days). So, I did a MAJOR rewrite, creating the following gem of software engineering :)
Bitmap transform(Bitmap src) {
// ... transformation array are built here
// apply transformation
int wid = src.getWidth(), hei = src.getHeight();
Bitmap bmOut = Bitmap.createBitmap(wid, hei, src.getConfig());
int[] pixs = new int[wid*hei]; // changed
src.getPixels(pixs, 0, wid, 0, 0, wid, hei); // changed
int A, R, G, B;
for(int x = 0; x < wid; x++) {
for(int y = 0; y < hei; y++) {
int off = ( x * y ) + y; // changed
int pixel = pixs[off]; // changed
A = Color.alpha(pixel);
R = tR[Color.red(pixel)];
G = tG[Color.green(pixel)];
B = tB[Color.blue(pixel)];
pixs[off] = Color.argb(A, R, G, B); // changed
}
}
bmOut.setPixels(pixs, 0, wid, 0, 0, wid, hei); // changed
return bmOut;
}
Runs fast, even gets a correct result IF THERE IS NO TRANSFORMATION. But it falls apart
if I try to massage the pixels (apply transformations). So I did comparison of ARGB pixels from getPixel() vs array of pixels values from getPixels(...) and they are different (well, the first 2 are the same, which leaves me with about zillion that are not).
array getPixel
a r g b a r g b
------------------
ff65340b ff65340b
ff64330a ff64330a
ff66320b ff63320a
ff65310a ff613008
ff66300c ff62300d
ff67310d ff62300d
ff68300d ff622d0d
ff69310e ff5f2a0a
....
Anybody knows what I'm doing wrong this time? I am not willing to give up the speed of
the mem-array solution yet.
Thanks, sean
It should be
int off = ( y * wid ) + x;
By the way, I think the two loops is unnecessary, you can simply do:
for (int off = pixs.length - 1; off >= 0; off--)
I have written the following function to change the gamma of a Bitmap, but it's kind of slow, even on small (300 by 300) bitmaps. How can I make this function run faster? For example, is there a better way (i.e., faster way) to access individual pixel values from a Bitmap?
public Bitmap apply(Bitmap bmp, float gamma) {
if (bmp == null)
return null;
int width = bmp.getWidth();
int height = bmp.getHeight();
int[] pixels = new int[width * height];
bmp.getPixels(pixels, 0, width, 0, 0, width, height);
int[] powers = new int[256];
for (int i = 0; i < powers.length; i++)
powers[i] = (int)(Math.pow(i / 255.0f, 1.0f / gamma) * 255);
for (int p = 0; p < pixels.length; p++) {
int r = Color.red(pixels[p]);
int g = Color.green(pixels[p]);
int b = Color.blue(pixels[p]);
int newR = powers[r];
int newG = powers[g];
int newB = powers[b];
pixels[p] = Color.rgb(newR, newG, newB);
}
Bitmap newBmp = Bitmap.createBitmap(pixels, 0, width, width, height, Config.ARGB_8888);
return newBmp;
}
As an optimization, I calculate the powers ahead of time on all possible pixel values (0 to 255), which helps, but it's not enough. Also, declaring all the int's outside of the second for loop didn't help much, so I left them in. Thanks in advance.
I would look into using OpenGL or RenderScript for that if you really want it to be fast. Both have nice integration on Android.