Bitmap Pixel-Level Operation for Android Particle Papers

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 QQ WeChat 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.

Keywords: Mobile Java Android github Javascript

Added by fireMind on Fri, 17 May 2019 07:40:53 +0300