Android basic notes (15th)-graphic, big picture OOM, usage and exercises of painting tools, androidoom
- Principle of computer graphics Representation
- OOM is displayed when a large image is loaded.
- Scale and load large image resources
- Create a copy of the source Image
- Common graph processing APIs
- Mito xiuxiu for Dummies
- Painting version
Principle of computer graphics Representation
The first thing to note is that the size required for storing an image in memory is very different from the size required for completely displaying the image on the screen device.
For example, we can clearly see that the storage space occupied by this image on the hard disk is 303KB, that is, 310272 bytes. However, if you want to completely display such images on the screen device, the memory space needed is far more than that.
There is such a formula:Memory required for Image Display = Image Width pixel x Image Height pixel x size of each pixel
How can we know the pixel size? When we click "Save As image", the following message is displayed:
In turn, we will introduce the meaning.
-
Monochrome bitmap:
-
It is either black or white, and can be expressed in one bit. It requires 1/8 bytes to represent a pixel value. In this case, the image above is displayed in the memory to be loaded: 1920*1200*1/8/1024/1024 = 0.2 M.
-
16 bitmap:
-
1/2 bytes is required to represent a pixel value. In this case, it is required to prepare the loading memory: 1920*1200*1/2/1024/1024 = 1.09 M.
-
256 bitmap:
-
Indicates that a pixel value needs to be expressed in 1 byte. In this case, the chip is loaded into the memory to prepare for display: 1920*1200*1/1024/1024 = 2.19 M.
-
24-Bit Bitmap:
-
It indicates that a pixel value must be 3 bytes. In this case, it is required to load the chip into the memory for display: 1920*1200*3/1024/1024 = 6.59 M.
-
In the Android operating system, ARGB is used to represent a pixel value.
-
A Indicates transparency. In this case, you need to: 1920*1200*4/1024/1024 = 8.79 M to prepare for loading memory.
In Andorid, the default VM Heap provided by the system for the application is 16 Mb. If the image is not compressed, an OOM exception will occur.
OOM is displayed when a large image is loaded.
Let's load a large image. The image resource is as follows, and the size is 1.7 MB.
Create a project and addImageView
Control, andMainActivity
In the left-side navigation pane.
ImageView iv = (ImageView) findViewById(R.id.iv);Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/dog.jpg");iv.setImageBitmap(bitmap );
The code is very simple. An error occurs at runtime. Let's see what the error is:
As you can see, the application Applied to the System30720012Bytes, And then it appearsOutOfMemoryErrorError.
The next section describes how to load a large image without the OOM function.
Scale and load large image resources
We can see that the picture of the dog is 2400*3200, and our mobile phone is only 320*480. If it is put directly, an exception will occur; otherwise, resources will be wasted.
Google engineers have already prepared a solution to useBitmapFactory
To parse the resource, first obtain the width and height of the loaded image, calculate the zoom ratio based on the screen width and height of the mobile phone device, and then use the zoom ratio to load the image resource to the memory.
The Code is also relatively simple, please refer:
ImageView iv = (ImageView) findViewById (R. id. iv );//★1. use the window manager to obtain the width and height of the mobile phone screen. WindowManager wm = (WindowManager) getSystemService (WINDOW_SERVICE); int screenHeight = wm. getdefadisplay display (). getHeight (); int screenWidth = wm. getdefadisplay display (). getWidth ();//★2. obtain image attributes and configure BitmapFactory without loading images into memory. options options = new Options (); // this parameter is set to true. If you use BitmapFactory to parse a resource, Bitmap is not returned, but the resource configuration is set: the width and height of the sample slice options. inJustDecodeBounds = true; BitmapFactory. decodeFile ("/mnt/sdcard/dog.jpg", options); // get the image width and height int outHeight = options. outHeight; int outWidth = options. outWidth ;//★3. the zoom ratio is calculated based on the screen width and Image Width. int scale = 0; int scaleH = outHeight/screenHeight; int scaleW = outWidth/screenWidth; scale = scaleH> scaleW? ScaleH: scaleW ;//★4. parse image resources based on the scaling ratio and return Bitmapoptions. inJustDecodeBounds = false; options. inSampleSize = scale; Bitmap bitmap = BitmapFactory. decodeFile ("/mnt/sdcard/dog.jpg", options); iv. setImageBitmap (bitmap );
Create a copy of the source Image
Bitmap loaded to memory on Android cannot be modified. It can only be modified and painted on its copy. So how to create a copy of the source image?
-
Perform the following steps:
-
① Prepare a white paper with the same width and height as the source image and its configuration.
-
② Put white paper on the canvas
-
③ Prepare a pen
-
④ Prepare a matrix
The Code is also relatively simple, which involvesCanvas
,Paint
,Matrix
Class, the following is a simple copy of the source code:
ImageView srcImageView = (ImageView) findViewById (R. id. iv_src); ImageView copyImageView = (ImageView) findViewById (R. id. iv_copy); // The original Bitmap srcBitmap = BitmapFactory. decodeFile ("/mnt/sdcard/meinv.jpg"); srcImageView. setImageBitmap (srcBitmap); // copy // 1. prepare a white paper with the same width and height as the source image. Bitmap copyBitmap = Bitmap. createBitmap (srcBitmap. getWidth (), srcBitmap. getHeight (), srcBitmap. getConfig (); // 2. place White Paper on the Canvas canvas Canvas = new Canvas (copyBitmap); // 3. prepare a pen for painting = new Paint (); // 4. prepare a Matrix matrix Matrix = new Matrix (); // use the specified matrix to draw the canvas. drawBitmap (srcBitmap, matrix, paint); copyImageView. setImageBitmap (copyBitmap );
The test results are as follows:
Common graph processing APIs
For example, when learning animation, the image processing operations are also divided into the following types. The key step of the operation is to use the matrix for changes. Google engineers have helped us to complete these operations.
-
Translation:
-
The Code is as follows:
// Original Bitmap srcBitmap = BitmapFactory. decodeFile ("/mnt/sdcard/meinv.jpg"); srcImageView. setImageBitmap (srcBitmap); // copy Bitmap copyBitmap = Bitmap. createBitmap (srcBitmap. getWidth (), srcBitmap. getHeight (), srcBitmap. getConfig (); Canvas canvas = new Canvas (copyBitmap); Paint paint = new Paint (); Matrix matrix = new Matrix ();//★Use the matrix translation graph matrix. setTranslate (150, 50); canvas. drawBitmap (srcBitmap, matrix, paint); copyImageView. setImageBitmap (copyBitmap );
The test diagram is as follows:
-
Scaling:
-
The scaling code is as follows:
//★Use a matrix to scale the image // use the image center point as the origin point to reduce the size of matrix. setScale (0.5f, 0.5f, srcBitmap. getWidth ()/2, srcBitmap. getHeight ()/2) by 0.5 times );
Test diagram:
-
Rotation:
-
The rotation code is as follows:
//★Use a matrix image // rotate 30 degrees matrix. setRotate (30, srcBitmap. getWidth ()/2, srcBitmap. getHeight ()/2) based on the image center point );
Test diagram:
-
Image:
-
The Image Code is as follows:
//★Use a matrix to image matrix. setScale (-1.0f, 1.0f); matrix. postTranslate (srcBitmap. getWidth (), 0 );
Test diagram:
Reflection:
-
The reflected code is as follows:
//★Use a matrix to map the image to matrix. setScale (1.0f,-1.0f); matrix. postTranslate (0, srcBitmap. getHeight ());
Test diagram:
Mito xiuxiu for Dummies
Purpose: use the color matrix to modify the color of the image (simple + simple = trainer ):
The interface layout is as follows:
Below the layout is three<SeekBar>
La S, used to modify the color value of an image.
The Code is as follows:
Public class MainActivity extends Activity implements attributes {private Bitmap srcBitmap; private SeekBar sb_red; private SeekBar sb_green; private SeekBar sb_blue; private ImageView iv; @ Override protected void onCreate (Bundle attributes) {super. onCreate (savedInstanceState); requestWindowFeature (Window. FEATURE_NO_TITLE); setContentView (R. layout. activity_main); sb_red = (SeekBar) findViewById (R. id. sb_red); sb_green = (SeekBar) findViewById (R. id. sb_green); sb_blue = (SeekBar) findViewById (R. id. sb_blue); iv = (ImageView) findViewById (R. id. iv); srcBitmap = BitmapFactory. decodeFile ("/mnt/sdcard/meinv.jpg"); iv. setImageBitmap (srcBitmap); hour (this); sb_green.setOnSeekBarChangeListener (this);} // @ Override public void onStopTrackingTouch (SeekBar seekBar) {int currentPosition = seekBar. getProgress (); Bitmap copyBitmap = Bitmap. createBitmap (srcBitmap. getWidth (), srcBitmap. getHeight (), srcBitmap. getConfig (); Canvas canvas = new Canvas (copyBitmap); Paint paint = new Paint ();//★Use the color matrix to draw the image ColorMatrix colorMatrix = new ColorMatrix (); float rf = 0; float gf = 0; float bf = 0; // modify the color switch (seekBar. getId () {case R. id. sb_red: rf = currentPosition/10f; break; case R. id. sb_blue: bf = currentPosition/10f; break; case R. id. sb_green: gf = currentPosition/10f; break;} colorMatrix. set (new float [] {// rf, 0, 0, 0, 0, // 0, gf, 0, 0, 0, // 0, 0, bf, 0, 0, // 0, 0, 0, 1, 0}); ColorFilter filter = new ColorMatrixColorFilter (colorMatrix );//★Set the color matrix filter paint for the paint brush. setColorFilter (filter); canvas. drawBitmap (srcBitmap, new Matrix (), paint); iv. setImageBitmap (copyBitmap);} // @ Override public void onProgressChanged (SeekBar seekBar, int progress, boolean fromUser) during sliding) {}// @ Override public void onStartTrackingTouch (SeekBar seekBar ){}}
Test results:
There is nothing very important. Just know the color matrix.
Painting version
Let's take a look at what it looks like after molding:
It's still funny after I make it myself.
-
Perform the following steps to create a canvas:
-
① Prepare a background image
-
② Copy a background image for painting on it
-
③ Register
ImageView
A touch event; when you press and move, record the touch point, draw a picture and set it
Imageview
.
-
④ Added the "bold paint brush" and "color change function"
Next, let's take a step.
Step 1Prepare a background image and add it to the SD card.
Code for setting the background image:
iv = (ImageView) findViewById(R.id.iv);srcBitmap = BitmapFactory.decodeFile("/mnt/sdcard/bk.png");iv.setImageBitmap(srcBitmap);
Step 2,Make a copy of the background image for painting on it
// Obtain a copy copyBitmap = Bitmap. createBitmap (srcBitmap. getWidth (), srcBitmap. getHeight (), srcBitmap. getConfig (); // obtain the canvas Canvas = new canvas (copyBitmap); // obtain the paint brush Paint = new paint (); // obtain a matrix Matrix = new matrix (); canvas. drawBitmap (srcBitmap, matrix, paint); // draw a straight line // canvas. drawLine (0, 0,100,100, paint); iv. setImageBitmap (copyBitmap); // registers the touch Event Callback iv. setOnTouchListener (this );
Step 3,Register oneImageView
A touch event; when you press and move, record the touch point, draw a picture and set itImageview
.
// Start coordinate point private int startX; private int startY; @ Overridepublic boolean onTouch (View v, MotionEvent event) {switch (event. getAction () {case MotionEvent. ACTION_DOWN: startX = (int) event. getX (); startY = (int) event. getY (); System. out. println ("coordinate point (" + startX + "," + startY + ")"); break; case MotionEvent. ACTION_MOVE: int nowX = (int) event. getX (); int nowY = (int) event. getY (); System. out. println ("Starting Point of movement (" + startX + "," + startY + ")"); System. out. println ("Mobile ending coordinate point (" + nowX + "," + nowY + ")"); canvas. drawLine (startX, startY, nowX, nowY, paint); iv. setImageBitmap (copyBitmap); startX = nowX; startY = nowY; break; case MotionEvent. ACTION_UP: break; default: break;} // If the returned value is true, the event is consumed and is not passed down. // If the returned value is false, the event is not consumed, and continue to pass down; return true ;}
Step 4, Added the "bold paint brush" and "color change function"
// Color content int [] colors = {Color. RED, Color. GREEN, Color. BLUE}; private int colorIndex; // modify the color public void changecolor (View v) {paint. setColor (colors [colorIndex ++ % 3]);} // paint width private int paintWidth; // bold paint brush public void overstriking (View v) {paint. setStrokeWidth (++ paintWidth );}