Zero, preface
1. There are three core points of particle effect: collecting particles, changing particles and displaying particles.
2.Bitmap can acquire pixels and get the color value of each pixel.
3. You can combine a picture with particles and perform many unexpected effects on particle manipulation.
4. The source code of this project is shown in the first article of the Jiwen Specification at the end of the article. The file is BitmapSplitView.java.
First, initial knowledge
1. What is Bitmap pixel-level operation?
I believe you all know that a jpg or png enlarged will be a small grid, called a pixel (px), and a small grid is a color.
A jpg or png image is a collection of many colors, which are encapsulated in the Bitmap class.
You can use Bitmap to get any pixel and modify it. For a pixel, color information is the main part.
Pixel.png
2. Get the first pixel
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.iv_200x200); int color_0_0 = bitmap.getPixel(0, 0);//Get the first row, the first pixel color
Use this color to draw a circle to test:
First point. png
3. Get the color values of all pixels
Here I represents the number of columns, J represents the number of rows, mColArr[i][j] represents the pixel color values of column I and row J of a picture
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.iv_200x200); mColArr = new int[bitmap.getWidth()][bitmap.getHeight()]; for (int i = 0; i < bitmap.getWidth(); i++) { for (int j = 0; j < bitmap.getHeight(); j++) { mColArr[i][j] = bitmap.getPixel(i, j); } }
II. Analysis:
1. Let's first look at how to create a Bitmap object
Create a new 2*2 ARGB_8888 image: the color is black (0,0), red (1,0), white (0,1), blue (1,1)
Bitmap bitmap = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888); bitmap.setPixel(0, 0, Color.BLACK); bitmap.setPixel(1, 0, Color.RED); bitmap.setPixel(0, 1, Color.WHITE); bitmap.setPixel(1, 1, Color.BLUE);
2. Save bitmap to local
To save a bitmap is to compress it into an output stream and write it into a file.
Output result. png
/** * Save bitmap to local * * @param path Route * @param mBitmap picture * @return Route */ public static String saveBitmap(String path, Bitmap mBitmap) { File filePic = FileHelper.get().createFile(path + ".png"); try { FileOutputStream fos = new FileOutputStream(filePic); mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.flush(); fos.close(); } catch (IOException e) { e.printStackTrace(); return null; } return filePic.getAbsolutePath(); }
3. What exactly did bitmap. getPixel say?
int pixel_0_0 = bitmap.getPixel(0, 0); int pixel_1_0 = bitmap.getPixel(1, 0); int pixel_0_1 = bitmap.getPixel(0, 1); int pixel_1_1 = bitmap.getPixel(1, 1); //Black: pixel_0_0:-16777216 //Red: pixel_1_0:-65536 //White: pixel_0_1:-1 //Blue: pixel_1_1:-16776961
It's all negative numbers. It's not easy to understand: in fact, that's the color value.
There are several ways in the Color class to easily get the corresponding argb values. Here's a test to see.
In fact, int is bitwise calculated and the values of four channels of argb are separated.
printColor("pixel_0_0", pixel_0_0);//Black: a:255, r:0, g:0, b:0 printColor("pixel_1_0", pixel_1_0);//Red: a:255, r:255, g:0, b:0 printColor("pixel_0_1", pixel_0_1);//White: a:255, r:255, g:255, b:255 printColor("pixel_1_1", pixel_1_1);//Blue: a:255, r:0, g:0, b:255 /** * Split the color from int into argb and print it out * @param msg * @param color */ private void printColor(String msg, int color) { int a = Color.alpha(color); int r = Color.red(color); int g = Color.green(color); int b = Color.blue(color); L.d(msg + "----a:" + a + ", r:" + r + ", g:" + g + ", b:" + b + L.l()); }
2. The pattern reproduction of bitmap:
Now that the pixel color information is available, does not it mean that I have it all over the world?
1. Particle Carriers for Bitmap Copying
public class Ball implements Cloneable { public float aX;//acceleration public float aY;//Acceleration Y public float vX;//Speed X public float vY;//Speed Y public float x;//Point X public float y;//Point Y public int color;//colour public float r;//radius public long born;//Birth time public Ball clone() { Ball clone = null; try { clone = (Ball) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } }
2. Initialized particles:
Coordinate analysis. png
private int d = 50;//Pixel Edge Length for Copying private List<Ball> mBalls = new ArrayList<>();//Particle set
/** * Root Pixel Initialization Particles * @param bitmap * @return */ private List<Ball> initBall(Bitmap bitmap) { for (int i = 0; i < bitmap.getHeight(); i++) { for (int j = 0; j < bitmap.getWidth(); j++) { Ball ball = new Ball(); ball.x = i * d + d / 2; ball.y = j * d + d / 2; ball.color = bitmap.getPixel(i, j); mBalls.add(ball); } } return mBalls; }
3. Drawing of square particles (original copy):
Graphic reproduction.png
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); canvas.translate(mCoo.x, mCoo.y); for (Ball ball : mBalls) { mPaint.setColor(ball.color); canvas.drawRect( ball.x - d / 2, ball.y - d / 2, ball.x + d / 2, ball.y + d / 2, mPaint); } canvas.restore(); HelpDraw.draw(canvas, mGridPicture, mCooPicture); }
4. Copy other picture resource files
As long as it's bitmap, we can decode the picture into Bitmap.
Note: This is just a demonstration. It's better to draw a bitmap in its native form. Particularization at the pixel level is based on its advantages, such as motion.
//Load the image array mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.iv_200x200); initBall(mBitmap);
Photo resources for original copy.png
5. Circle Reengraving
The picture in 4 here is no longer a bitmap, but something stacked up by a small square that has its own color.
However, we can use it to achieve some interesting things, such as drawing a circle instead of a square.
Now you know what pixel-level operations are. Maybe you will sigh, how can you play, first take back your chin, there is more amazing behind it.
Round duplicate image resource. png
for (Ball ball : mBalls) { mPaint.setColor(ball.color); canvas.drawCircle(ball.x, ball.y, d/2, mPaint); }
6. Reengraving of Other Shapes
You can replace particle units with arbitrary graphics, or mix particles of various shapes, depending on your operation.
Pixel units are in your hands, and there's nothing you can't do.
Pentagram Photo Resources. png ____________
for (int i = 0; i < mBalls.size(); i++) { canvas.save(); int line = i % mBitmap.getHeight(); int row = i / mBitmap.getWidth(); canvas.translate(row * 2 * d, line * 2 * d); mPaint.setColor(mBalls.get(i).color); canvas.drawPath(CommonPath.nStarPath(5, d, d / 2), mPaint); canvas.restore(); }
3. About color operation:
stay Color chapter The use of ColorFilter and Color Matrix to change the color of the image is described in detail.
Now that we have the color of the ball here, how about changing the color of the ball uniformly?
Note: The following is the side door of changing color, mainly for demonstration. Ordinary use ColorFilter and Color Matrix
Color Processing.png
1. The following is the algorithm of black-and-white image.
Used in JavaScript before, in Python, and now finally in java, I can't help feeling that the language has no boundaries and the truth is eternal.
So you'd better collect the relevant truth, no matter when it's not out of date, it's not wrong, just like 1 + 1 = 2.
/** * Root Pixel Initialization Particles * * @param bitmap * @return */ private List<Ball> initBall(Bitmap bitmap) { for (int i = 0; i < bitmap.getHeight(); i++) { for (int j = 0; j < bitmap.getWidth(); j++) { Ball ball = new Ball(); ball.x = i * d + d / 2; ball.y = j * d + d / 2; //Getting a, r, g, b of pixels int color_i_j = bitmap.getPixel(i, j); int a = Color.alpha(color_i_j); int r = Color.red(color_i_j); int g = Color.green(color_i_j); int b = Color.blue(color_i_j); ball.color = blackAndWhite(a, r, g, b); mBalls.add(ball); } } return mBalls; } /** * Match black and white */ private int blackAndWhite(int a, int r, int g, int b) { //Piece together new colors int grey = (int) (r * 0.3 + g * 0.59 + b * 0.11); if (grey > 255 / 2) { grey = 255; } else { grey = 0; } return Color.argb(a, grey, grey, grey); }
2. Grey Processing Function
/** * Match grey color */ private int grey(int a, int r, int g, int b) { //Piece together new colors int grey = (int) (r * 0.3 + g * 0.59 + b * 0.11); return Color.argb(a, grey, grey, grey); }
3. Color reversal
//Color reversal private int reverse(int a, int r, int g, int b) { //Piece together new colors return Color.argb(a, 255-r, 255-g, 255-b); }
IV. Particle Motion
Here's where the most important thing is, the core analysis of getting the ball moving Android Native Drawing lets you understand the motion of View:
Gravity diffusion. gif
1. Method of Particularizing a Picture
Here the velocity x direction is a positive and negative probability random value, so the particle will show a left-right movement trend.
There is a certain y-direction velocity, but the acceleration aY downward, leading to particles downward movement, the combined effect is scattered on both sides and fall.
To change the way a particle moves, just change these parameters of the particle.
/** * Root Pixel Initialization Particles * * @param bitmap * @return */ private void initBall(Bitmap bitmap) { for (int i = 0; i < bitmap.getHeight(); i++) { for (int j = 0; j < bitmap.getWidth(); j++) { Ball ball = new Ball();//Generating Particles - Each Particle has some random attribute information ball.x = i * d + d / 2; ball.y = j * d + d / 2; ball.vX = (float) (Math.pow(-1, Math.ceil(Math.random() * 1000)) * 20 * Math.random()); ball.vY = rangeInt(-15, 35); ball.aY = 0.98f; ball.color = bitmap.getPixel(i, j); ball.born = System.currentTimeMillis(); mBalls.add(ball); } } }
2. Update Ball
/** * Update ball */ private void updateBall() { for (int i = 0; i < mBalls.size(); i++) { Ball ball = mBalls.get(i); if (System.currentTimeMillis() - mRunTime > 2000) { mBalls.remove(i); } ball.x += ball.vX; ball.y += ball.vY; ball.vY += ball.aY; ball.vX += ball.aX; } }
3. Initialization time flow: Value Animator
//Initialization time stream Value Animator mAnimator = ValueAnimator.ofFloat(0, 1); mAnimator.setRepeatCount(-1); mAnimator.setDuration(2000); mAnimator.setInterpolator(new LinearInterpolator()); mAnimator.addUpdateListener(animation -> { updateBall();//Update Ball Position invalidate(); });
4. Click to open Value Animator
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mRunTime = System.currentTimeMillis();//Record click time mAnimator.start(); break; } return true; }
Well, that's all for this article. Are you more aware of what Bitmap is?
Hope this article can give you some inspiration, you can make something more cool.
Postscript: Jasper Specification
1. The Growth Record and Corrigendum List of this Paper
Project source code | date | Remarks |
---|---|---|
V0.1--github | 2018-11-17 | Bitmap Pixel-Level Operation for Android Particle Papers |
2. More about me
Pen name | hobby | ||
---|---|---|---|
Zhang Fengjie | 1981462002 | zdl1994328 | language |
My github | My short book | My Nuggets | Personal website |
Author: Zhang Fengjie
Link: https://www.jianshu.com/p/12184d861646
Source: Brief Book
The copyright of the brief book belongs to the author. For any form of reprinting, please contact the author for authorization and indicate the source.