Introduction:
The book is very fine, but also about some principles, principles need some knowledge of linear algebra, line generation are forgotten, mainly look at the back of the example is Ok, see instance stamp me.
The main content
- Color effect processing
- Graphic special effects processing
- Brush effect processing
- SurfaceView
The specific content
Android for image processing, the most commonly used data structure is Bitmap – Bitmap, which contains all the data of an image. The entire image is made up of dots and color values. The dot matrix is a matrix containing pixels, with the first element corresponding to a pixel of the image. The color value — ARGB, respectively, corresponds to the four channel components of transparency, red, green and blue, which together determine the color displayed by each pixel.
Color effect processing
Bitmap images are made up of dots and color values. A dot matrix is a matrix of pixels, each element of which corresponds to a pixel of the image. The color value — ARGB, respectively, corresponds to the four channel components of transparency, red, green and blue, which together determine the color displayed by each pixel.
Color matrix analysis
In color processing, we usually describe an image from three angles:
- Tone: The color that an object transmits.
- Saturation: The purity of a color, described from 0 (grey) to 100% (saturated).
- Brightness: The relative brightness or shade of a color.
In Android, the system will use a ColorMatrix — ColorMatrix to process the effects of these colors. The ColorMatrix in Android is a 4X5 numeric matrix, which is used to process the colors. For each pixel, there is a color component matrix to store the ARGB value.
According to the previous definition of matrix A and C, it can be obtained through the matrix multiplication operation rule:
The calculation process of matrix multiplication is as follows:
Let’s look at the color matrix A:
It can be found from this formula:
- The abcDE in the first line is used to determine the new color value R — red.
- The second line fghij is used to determine the new color value G – green.
- The third line kimno is used to determine the new color value B — blue.
- The fourth line PQRST is used to determine the new color value A – transparency.
- The fifth column of the matrix A, the ejot value, is used to determine the offset, or offset, in each component.
To explain it through a small example: First of all, let’s review the matrix transformation calculation formula, taking R component as an example, the calculation process is as follows:
R1 = a * R + b* G + c*B+d *A + e
Copy the code
If a = 1 and b, C, D, and e are all equal to 0, then R1 = R is calculated, so we can construct a matrix:
If you substitute this matrix formula into R1 is equal to AC, then according to the matrix multiplication algorithm, R1 is equal to R. Therefore, this matrix is usually used as the initial color matrix, which does not change the original color. So when we want to change color values, there are usually two ways to do it. One is to directly change the color offset, the value of the offset, to modify the color component. Another method is to adjust the value of the color component by directly changing the coefficient corresponding to the RGBA value. From the previous analysis, you know that to change the value of R1, you simply change the value of the fifth column. That is, change the color offset, and the other values save the values of the initial matrix, as shown in the figure:
In the above matrix, we modified the color offsets corresponding to R and G, so the final processing result is that the red and green of the image increase by 100 respectively. And we know that red mixed with green produces yellow, so the end result of the color manipulation is to make the whole image yellowish.
If you modify the value of a coefficient in the color component, the value of the initial matrix is still kept in the other values, as shown in the figure below:
In the above matrix, the coefficient G corresponding to the G component is changed, so that after the rectangle operation, the G component will become twice as large as before, and the final effect is that the tone of the image is more green.
Here is an example of how to change the hue, saturation, and brightness of an image through a matrix:
- Color: setRotate(int axis, float degree), the first parameter uses 0, 1, 2 respectively to represent Red, Green, Blue three colors, the second parameter needs to process the value.
ColorMatrix hueMatrix = new ColorMatrix();
hueMatrix.setRotate(0, hue);
hueMatrix.setRotate(1, hue);
hueMatrix.setRotate(2, hue);
Copy the code
- Saturation: setSaturation(float sat). The parameter represents the saturation value set.
ColorMatrix saturationMatrix = new ColorMatrix();
saturationMatrix.setSaturation(saturation);
Copy the code
- Brightness: setScale(float rscale,float gscale,float bscale,float ascale), parameters are red, green, blue, transparency brightness size value.
ColorMatrix lumMatrix = new ColorMatrix();
lumMatrix.setScale(lum, lum, lum, 1);
Copy the code
- In addition to using the above three methods for color effects alone, a postConcat() method is provided to blend the effects of a matrix, thus superimposing the effects.
ColorMatrix imageMatrix = new ColorMatrix();
imageMatrix.postConcat(hueMatrix);
imageMatrix.postConcat(saturationMatrix);
imageMatrix.postConcat(lumMatrix);
Copy the code
Commonly used image color matrix processing effect
- Gray effect:
- Image inversion:
- Nostalgic effect:
- Color removal effect:
- High saturation:
Pixel analysis
In Android, the bitmap.getPixels () method is provided to extract pixels in the entire Bitmap and store them in an array:
bitmap.getPixels(pixels, offset, stride, x, y, width, height);
Copy the code
The meanings of these parameters are as follows:
- Pixels: An array that receives bitmap color values.
- Offset: The first pixel index value written to pixels[].
- Stride: Pixels line spacing in []
- X: The x coordinate value of the first pixel read from the bitmap.
- Y: The y coordinate value of the first pixel read from the bitmap.
- Width: The pixel width to read from each row.
- Height: Number of rows read.
The following code is usually used:
bitmap.getPixels(oldPx, 0, bitmap.getWidth(), 0.0, width, height);
Copy the code
Next get the specific ARGB value for each pixel:
color = oldPx[i];
r = Color.red(color);
g = Color.green(color);
b = Color.blue(color);
a = Color.alpha(color);
Copy the code
The next step is to modify the pixel value to produce a new pixel value:
r1 = (int) (0.393 * r + 0.769 * g + 0.189 * b);
g1 = (int) (0.349 * r + 0.686 * g + 0.168 * b);
b1 = (int) (0.272 * r + 0.534 * g + 0.131 * b);
newPx[i] = Color.argb(a, r1, b1, g1);
Copy the code
Finally, using our new pixel value:
bmp.setPixels(newPx, 0, width, 0.0, width, height);
Copy the code
Graphic special effects processing
Android deformation Matrix — Matrix
For graph transformation, the system provides 3×3 proof to deal with:
As with the color matrix, the calculation method is matrix multiplication:
X1 = a x X +b x Y +c;
Y1 = d x X +e x Y +f;
1 = g x X +h x Y + i;
Copy the code
Like the color matrix, there is an initial matrix:
Image deformation processing includes the following four basic transformations:
- Translate: Translation.
- Rotate: Rotation transformation.
- Scale: Scale transformation.
- Skew: mistangent transformation.
Translation transformation: translation transformation is carried out for each pixel. The following translation formula can be found through calculation:
X = X0 + △X;
Y = Y0 + △Y;
Copy the code
Rotation transformation: The rotation transformation with any point as the rotation center can be completed through the following three steps:
- Shift the origin to O.
- The rotation transformation is performed using the rotation method centered at the origin of the coordinates described earlier.
- Restore the origin of coordinates.
Scaling transform: The calculation formula of scaling transform is as follows:
x = K1 X x0;
y = K2 X y0;
Copy the code
Staggered transformation: The calculation formula for the effect of staggered transformation is as follows:
x = x0 + k1 + y0
y = k2 x x0 + y0
Copy the code
To learn about the four graphical transformation matrices, you can convert a one-dimensional array to a graphical transformation matrix using the setValues() method:
private float [] mImageMatrix = new float[9];
Matrix matrix = new Matrix();
matrix.setValues(mImageMatrix);
canvas.drawBitmap(mBitmmap,matrix,null);
Copy the code
The Matrix class in Android also encapsulates several operations for us:
- Matrix.setrotate () : Rotation transformation.
- Matrix.settranslate () : Translation transform.
- Matrix.setscale () : Scale transformation.
- Matrix.setskew () : Mistangent transformation.
- Pre () and post() : Provide matrix forward and backward multiplication operations.
Here is an example of the different operations of forward and backward multiplication:
- Let’s shift it to 300, 100.
- Rotate it another 45 degrees.
- And then we move it to 200, 200.
matrix.setRotate(45);
matrix.postTranslate(200.200);
Copy the code
If you use the forward multiplication operation, the code is as follows:
matrix.setTranslate(200.200);
matrix.perRotate(45);
Copy the code
Pixel block analysis
DrawBitmapMesh () is similar to manipulating pixels to change color, except that the image is divided into smaller pieces and the entire image is modified by changing each piece:
canvas.drawBitmapMesh(Bitmap bitmap,int meshWidth,int meshHeight,float [] verts,
int vertOffset,int [] colors,int colorOffset,Paint paint);
Copy the code
Parameter analysis:
- Bitmap: Images to be distorted.
- MeshWidth: The number of horizontal meshes required.
- MeshHeight: Number of vertical grids required.
- Verts: an array of coordinates for grid intersections.
- VertOffset: Verts the number of (X,Y) coordinate pairs that the array starts to skip.
Brush effect processing
PorterDuffXfermode
PorterDuffXfermod sets the display of the intersection of the two layers, DST for the first drawing and SRC for the last drawing.
Take a rounded image as an example:
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test1);
mOut = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mOut);
mPaint = new Paint();
mPaint.setAntiAlias(true);
canvas.drawRoundRect(0.0, mBitmap.getWidth(), mBitmap.getHeight(), 80.80, mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(mBitmap,0.0,mPaint);
Copy the code
The effect of the image, because the picture is too large, only one corner can be seen:
Shader
A Shader is also called a Shader. Renderer, which can achieve rendering, gradient effects, etc. Android Shader includes the following types:
- BitmapShader: BitmapShader.
- LinearGradient: Linear Shader.
- RadialGradient: beam Shader.
- SweepGradient: Trapezoid Shader.
- ComposeShader: ComposeShader.
BitmapShader has three modes to choose from:
- CLAMP stretching: The last pixel of the image is drawn and repeated.
- 2. If you REPEAT yourself, you’ll have to do it again.
- MIRROR MIRROR: repeat horizontally and vertically.
Here’s an example of a circular image:
mBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.nice);
mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
mPaint = new Paint();
mPaint.setShader(mBitmapShader);
canvas.drawCircle(500.250.200,mPaint);
Copy the code
Effect:
Now change TileMode to REPEAT:
mBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);
mPaint = new Paint();
mPaint.setShader(mBitmapShader);
canvas.drawCircle(500.250.200,mPaint);
Copy the code
Use that LinearGradient:
mPaint = new Paint();
mPaint.setShader(new LinearGradient(0.0.400.400, Color.BLUE,Color.YELLOW, Shader.TileMode.REPEAT));
canvas.drawRect(0.0.400.400,mPaint);
Copy the code
Effect:
PathEffect
Let’s start with an intuitive picture:
Android provides several ways to draw PathEffect:
- No effect.
- CornerPathEffect: The corners become smoother.
- DiscretePathEffect: There are a lot of DiscretePathEffect.
- DashPathEffect: Draws dashed lines, using a single piece of data to set the interval between points.
- PathDashPathEffect: Draw dotted lines, you can use square dotted lines and circular dotted lines.
- ComposePathEffect: The feature that two paths can be arbitrarily combined.
Let’s look at an example of these effects:
public class PathEffectView extends View{
private Path mPath;
private PathEffect [] mEffect = new PathEffect[6];
private Paint mPaint;
/** * constructor *@param context
* @param attrs
*/
public PathEffectView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
/** * initializes */
private void init(a) {
mPaint = new Paint();
mPath = new Path();
mPath.moveTo(0.0);
for (int i = 0; i<= 30; i++){ mPath.lineTo(i*35, (float)(Math.random()*100)); }}@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mEffect[0] = null;
mEffect[1] = new CornerPathEffect(30);
mEffect[2] = new DiscretePathEffect(3.0 F.5.0 F);
mEffect[3] = new DashPathEffect(new float[] {20.10.5.10},0);
Path path = new Path();
path.addRect(0.0.8.8,Path.Direction.CCW);
mEffect[4] =new PathDashPathEffect(path,12.0,PathDashPathEffect.Style.ROTATE);
mEffect[5] = new ComposePathEffect(mEffect[3],mEffect[1]);
for (int i = 0; i<mEffect.length; i++){ mPaint.setPathEffect(mEffect[i]); canvas.drawPath(mPath,mPaint); canvas.translate(0.200); }}}Copy the code
Each time a Path is drawn, the canvas is shifted so that the various PathEffect is drawn in turn. Effect:
View’s twin – SurfaceView
The difference between SurfaceView and View
View drawing refresh interval is 16ms, if you do all the operations you need to perform in 16ms, then in the user’s visual, there will be no lag, otherwise, there will be a lag, so you can consider using SurfaceView instead of View drawing.
You’ll usually see something like this in Log:
Skipped 47 frames! The application may be doing too much work on its main thread
Copy the code
The main differences between SurfaceView and View:
- While The View works primarily with active updates, the surfaceVicw works primarily with passive updates, such as frequent refreshes.
- The View refreshes the screen in the main thread, whereas the surfaceView usually refreshes the page in a child thread.
- Views are drawn without double buffering, whereas surfaceVicw implements double buffering in the underlying implementation mechanism.
In summary, if your custom View needs to be refreshed frequently, or the refresh data processing is large, you can consider using SurfaceView instead of View.
The use of SurfaceView
SurfaceView
- Create a SurfaceView that inherits from the SurfaceView and implements two interfaces — surfaceHolder.callback and Runnable.
- Initializes the SurfacHolder object and registers the SurfaceHolder callback method.
- The Canvas object is obtained by the lockCanvas() method of the SurfacHolder object for drawing, and the Canvas content is committed by the unlockCanvasAndPost(mCanvas) method.
The entire template code using SurfaceView:
public class SurfaView extends SurfaceView implements SurfaceHolder.Callback.Runnable {
//SurfaceHolder
private SurfaceHolder mHolder;
// Canvas for drawing
private Canvas mCanvas;
// Child thread flag bit
private boolean mIsDrawing;
/** * constructor **@param context
* @param attrs
*/
public SurfaView(Context context, AttributeSet attrs) {
super(context, attrs);
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
setKeepScreenOn(true);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsDrawing = true;
new Thread(this).start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsDrawing = false;
}
@Override
public void run(a) {
while(mIsDrawing) { draw(); }}private void draw(a) {
try {
mCanvas = mHolder.lockCanvas();
} catch (Exception e) {
} finally {
if(mCanvas ! =null) {
/ / submitmHolder.unlockCanvasAndPost(mCanvas); }}}}Copy the code
Only pay attention to that, in the heart of the drawing mHolder. UnlockCanvasAndPost (mCanvas) method in the finally block of code, per the content submitted.