Android calls system cameras, Custom cameras, and processes large images,

Source: Internet
Author: User

Android calls system cameras, Custom cameras, and processes large images,
Android calls system cameras and custom camera instances


This blog article mainly introduces two ways to use a camera to take a photo and display it on android, this example also involves processing large images (avoiding OOM) by Android, and briefly introduces the reason why SurfaceView has a black screen.


There are two ways for the Android app to take photos. The following shows the effect of the Demo in two forms.



Knowledge point:

1. Call the built-in camera applications of the system

Ii. customize our own photo page


Iii. Principles of Computer Image Parsing (how to correctly load images to Android applications)



Required permissions:


<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


1. Call the System camera program to take photos (method 1)


1. Define the required permissions
2. We need to define the Intent that calls the system Camera App. Of course, we need to set the Action in IntentFilter to open the activity we want.


MediaStore. ACTION_IMAGE_CAPTURE-this Action will enable the system camera for the photo. Returns an Image.


MediaStore. ACTION_VIDEO_CAPTURE-this Action will enable the video system camera. Returns a Video.


In MediaStore. ACTION_IMAGE_CAPTURE, we can see this section:


[The caller may pass an extra EXTRA_OUTPUT to control where this image will be


Written. If the EXTRA_OUTPUT is not present, then a small sized image is returned


As a Bitmap object in the extra field. This is useful for applications that only


Need a small image. If the EXTRA_OUTPUT is present, then the full-sized image will


Be written to the Uri value of EXTRA_OUTPUT .]



3. the API specifies the Uri where the image is stored. Otherwise, Bimmap will return to our current Activity in a compressed form.


Intent. putExtra (MediaStore. EXTRA_OUTPUT, fileUri); // set the image file name

The image will be stored in the File corresponding to the Uri we passed in.



4. after startActivityForResult (intent) is called to start such a system Camera app, the system then receives the message of success or failure returned in onActivityResult () of the current app Activity for corresponding processing.


5. "compression processing" (loading large images in Android applications) and displaying them in ImageView.


Ii. Custom cameras


1. Check whether the Camera exists and obtain the Camera.

2. Create a camera image preview class: extends SurfaceView and implements SurfaceHolder (My definition: MySurfaceView)
3. Add this preview class to a custom layout and add other buttons in layout.
4. Set the corresponding photo button and listen to the event
5. Capture and save images

6. Release the Camera. Otherwise, other applications will not be able to use it.


Iii. How Computers parse images and compress the Bitmap of large images in Android

This problem is a bit old-fashioned. We often encounter some image resources. When we load it into the memory, we find that the exception of insufficient memory is thrown, that is, OOM, of course, there are many out-of-memory (OOM) scenarios when images are loaded. For example, if a single image is not compressed, memory overflow occurs because the image occupies a large amount of memory and multiple images are loaded at a time, memory overflow.

Generally, a single large image is compressed when we load it. If multiple images are loaded, we may need some caching mechanisms, add some algorithms to ensure that the program does not have OOM.

The knowledge point we want to talk about here is related to the documentary picture comparison.

First, we know that an image is represented by many pixels, and the number of pixels is only related to the image resolution, but not the memory size occupied by the image. For example, if our desktop wallpaper has a resolution of 1280*768, then it has 1280*768 = 983040 pixels. What does this mean? We know that we want to represent the color of a pixel. We usually need three RGB colors, and R: 0 ~ 255 is equivalent to the location of two FF, which is 8 bits. In this case, RGB is combined, and the representation of one pixel requires 24 bits (this is the 24 bitmap we have heard in balance ), the 8-bit transparency is the 32 bitmap. How much space does an image occupy when it is loaded into the memory?

Calculation method: (pixel * number of bytes occupied by one pixel)/1024/1024 (MB)

Take the resolution of 1280*768, 32 bitmap as an example: memory size occupied: (1280*768*(32/8)/1024 = 1024 (MB)

After talking about this, let's talk about the rules of the Android system. The Android system strictly specifies the maximum memory that each application can allocate, we know that there is a VM value (when we create a simulator), which is what we call Heap Size ), sorry, OOM

In this case, we understand the principle of image size occupation, and try not to exceed the heap space, so OK, now the problem becomes simple. If we can know the size of an image before it is loaded, and then change its length and width, the resolution will decrease, the product becomes smaller. For example, our screen is only 320*240. At this time, you can only display a large-resolution image. Therefore, we often use image compression. Here is a concept called compression ratio:

Length: 1024/320 = 3.2 approximately 3

Width: 768/240 = 3.2

In this case, if we compress the image to this size, the final image will be loaded into the system.

(320*240*(32/8)/1024)/1024 = 0.29 (MB)


I hope everyone can understand this. Here I will first stick the code about processing this image in the camera instance first.

// ----------------------- Android big image processing method --------------------------- private void setPicToImageView (ImageView imageView, File imageFile) {int imageViewWidth = imageView. getWidth (); int imageViewHeight = imageView. getHeight (); BitmapFactory. options opts = new Options (); // set this parameter to get the Bitmap attribute information and put it in opts, instead of loading Bitmap to opts in memory. inJustDecodeBounds = true; BitmapFactory. decodeFile (imageFile. getPath (), opts); int bitmapWidth = opts. outWidth; int bitmapHeight = opts. outHeight; // take the largest proportion to ensure that the length or width of the entire image must be displayed on the screen with int scale = Math. max (imageViewWidth/bitmapWidth, imageViewHeight/bitmapHeight); // scale the opts. inSampleSize = scale; // opts can be recycled when the memory is insufficient. inPurgeable = true; // if it is set to false, bitmapopts must be loaded not only for Bitmap attributes. inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory. decodeFile (imageFile. getPath (), opts); imageView. setImageBitmap (bitmap );}


About heap space:

HEAP is the most memory-consuming part of the VM, which is usually dynamically allocated. The heap size is not static. Usually there is a allocation mechanism to control its size. For example, the initial HEAP size is 4 MB. When the space of 4 MB is occupied by more than 75%, the allocated HEAP size is 8 Mb. When the space of 8 Mb is occupied by more than 75%, the allocated HEAP size is 16 Mb. In turn, when the 16 m heap uses less than 30%, the size of the 16 m heap is reduced to 8 m. Resetting the heap size, especially compression, usually involves copying the memory. Therefore, changing the heap size has a negative impact on the efficiency.


Let's take a look at the code below ~~ For the convenience of everyone, the code structure may not be very standard!


Source code: http://download.csdn.net/detail/u011133213/7844683


Code Section:

I. Using a system camera


Click the button to enable the System camera Activity.

FindViewById (R. id. system_camera_btn ). setOnClickListener (new OnClickListener () {@ Overridepublic void onClick (View v) {Intent intent = new Intent (); intent. setAction (MediaStore. ACTION_IMAGE_CAPTURE); imageFileUri = getOutFileUri (TYPE_FILE_IMAGE); // get a File Uriintent. putExtra (MediaStore. EXTRA_OUTPUT, imageFileUri); startActivityForResult (intent, SYSTEM_CAMERA_REQUESTCODE );}});


Generate a File and obtain the Uri.

// ----------------------- Generate Uri --------------------------------------- // obtain the URIprivate Uri getOutFileUri (int fileType) of the output file {return Uri. fromFile (getOutFile (fileType);} // generate the output File private File getOutFile (int fileType) {String storageState = Environment. getExternalStorageState (); if (Environment. MEDIA_REMOVED.equals (storageState) {Toast. makeText (getApplicationContext (), "oh, no, SD card does not exist", Toast. LENGTH_SHORT ). Show (); return null;} File mediaStorageDir = new File (Environment. getExternalStoragePublicDirectory (Environment. DIRECTORY_PICTURES), "MyPictures"); if (! MediaStorageDir. exists () {if (! MediaStorageDir. mkdirs () {Log. I ("MyPictures", "An error occurred while creating the image storage path directory"); Log. I ("MyPictures", "mediaStorageDir:" + mediaStorageDir. getPath (); return null ;}} File file = new File (getFilePath (mediaStorageDir, fileType); return file ;} // generate the output File path private String getFilePath (File mediaStorageDir, int fileType) {String timeStamp = new SimpleDateFormat ("yyyyMMdd_HHmmss "). format (new Date (); String filePath = mediaStorageDir. getPath () + File. separator; if (fileType = TYPE_FILE_IMAGE) {filePath + = ("IMG _" + timeStamp + ". jpg ");} else if (fileType = TYPE_FILE_VEDIO) {filePath + = (" VIDEO _ "+ timeStamp + ". mp4 ") ;}else {return null;} return filePath ;}



2. Use a custom camera


Check whether the camera device exists:

/* Check whether the camera exists */private boolean checkCameraHardWare (Context context) {PackageManager packageManager = context. getPackageManager (); if (packageManager. hasSystemFeature (PackageManager. FEATURE_CAMERA) {return true;} return false ;}

Button:

FindViewById (R. id. myapp_camera_btn ). setOnClickListener (new OnClickListener () {@ Overridepublic void onClick (View v) {if (checkCameraHardWare (getApplicationContext () {Intent intent = new Intent (getApplicationContext (), MyCameraActivity. class); startActivity (intent);} else {Toast. makeText (getApplicationContext (), "No camera exists", Toast. LENGTH_SHORT ). show ();}}});

Custom SurfaceView class:

Package cn. panghu. camera; import android. content. context; import android. graphics. canvas; import android. graphics. rect; import android. hardware. camera; import android. util. attributeSet; import android. view. surface; import android. view. surfaceHolder; import android. view. surfaceView; public class MySurfaceView extends SurfaceView implements SurfaceHolder. callback {private Camera camera = null; private SurfaceHo Lder surfaceHolder = null; public MySurfaceView (Context context, Camera camera) {super (context); this. camera = camera; surfaceHolder = getHolder (); surfaceHolder. addCallback (this); surfaceHolder. setType (SurfaceHolder. SURFACE_TYPE_PUSH_BUFFERS);} public MySurfaceView (Context context) {super (context); // TODO Auto-generated constructor stub} @ Overridepublic void surfaceCreated (SurfaceHolder holder) {try {cam Era. setPreviewDisplay (surfaceHolder); camera. startPreview ();} catch (Exception e) {e. printStackTrace () ;}@ Overridepublic void surfaceChanged (SurfaceHolder holder, int format, int width, int height) {// No SurfaceViewif (surfaceHolder. getSurface () = null) {return;} // first stop the preview of Camera try {camera. stopPreview ();} catch (Exception e) {e. printStackTrace ();} // here we can make some changes. // Re-enable the preview function of Camera try {camera. setPreviewDisplay (surfaceHolder); camera. startPreview ();} catch (Exception e) {e. printStackTrace () ;}@ Overridepublic void surfaceDestroyed (SurfaceHolder holder ){}}

Custom camera Activity Class: (To prevent the SurfaceView from becoming black when the user presses the Home Key and then returns to our App, We need to write the code that SurfaceView loads to FrameLayout in onResume)

Package cn. panghu. camera; import java. io. file; import java. io. fileNotFoundException; import java. io. fileOutputStream; import java. io. IOException; import java. text. simpleDateFormat; import java. util. date; import android. app. activity; import android. hardware. camera; import android. hardware. camera. pictureCallback; import android.net. uri; import android. OS. bundle; import android. OS. environment; import android. util. Log; import android. view. view; import android. view. view. onClickListener; import android. widget. button; import android. widget. frameLayout; import android. widget. toast; import com. example. camerademoapp. r; public class MyCameraActivity extends Activity {private Button btn_camera_capture = null; private Button btn_camera_cancel = null; private Button btn_camera_ OK = null; private Camera camera Camera = null; private My SurfaceView mySurfaceView = null; private byte [] buffer = null; private final int TYPE_FILE_IMAGE = 1; private final int TYPE_FILE_VEDIO = 2; private PictureCallback pictureCallback = new PictureCallback () {@ Overridepublic void onPictureTaken (byte [] data, Camera camera) {if (data = null) {Log. I ("MyPicture", "picture taken data: null");} else {Log. I ("MyPicture", "picture taken data:" + data. length);} buf Fer = new byte [data. length]; buffer = data. clone () ;};@ Overrideprotected void onCreate (Bundle savedInstanceState) {// TODO Auto-generated method stubsuper. onCreate (savedInstanceState); setContentView (R. layout. mycamera_layout); btn_camera_capture = (Button) findViewById (R. id. camera_capture); btn_camera_ OK = (Button) findViewById (R. id. camera_ OK); btn_camera_cancel = (Button) findViewById (R. id. camera_canc El); btn_camera_capture.setOnClickListener (new OnClickListener () {@ Overridepublic void onClick (View v) {camera. takePicture (null, null, pictureCallback); btn_camera_capture.setVisibility (View. INVISIBLE); btn_camera_ OK .setVisibility (View. VISIBLE); btn_camera_cancel.setVisibility (View. VISIBLE) ;}}); btn_camera_ OK .setOnClickListener (new OnClickListener () {@ Overridepublic void onClick (View v) {// Save the saveImag Image EToFile (); camera. startPreview (); btn_camera_capture.setVisibility (View. VISIBLE); btn_camera_ OK .setVisibility (View. INVISIBLE); btn_camera_cancel.setVisibility (View. INVISIBLE) ;}}); btn_camera_cancel.setOnClickListener (new OnClickListener () {@ Overridepublic void onClick (View v) {camera. startPreview (); btn_camera_capture.setVisibility (View. VISIBLE); btn_camera_ OK .setVisibility (View. INVISIBLE); btn_camera_can Cel. setVisibility (View. INVISIBLE) ;}}) ;}@ Overrideprotected void onPause () {// TODO Auto-generated method stubsuper. onPause (); camera. release (); camera = null ;}@ Overrideprotected void onResume () {// TODO Auto-generated method stubsuper. onResume (); if (camera = null) {camera = getCameraInstance ();} // It must be placed in onResume. Otherwise, the Home key will appear and return to the APP, black screen mySurfaceView = new MySurfaceView (getApplicationContext (), camera); F RameLayout preview = (FrameLayout) findViewById (R. id. camera_preview); preview. addView (mySurfaceView);}/* Get a Camera object */private Camera getCameraInstance () {camera = null; try {Camera = Camera. open ();} catch (Exception e) {e. printStackTrace ();} return camera;} // ----------------------- Save the image watermark private void saveImageToFile () {File file = getOutFile (TYPE_FILE_IMAGE); if (file = = Null) {Toast. makeText (getApplicationContext (), "file creation failed, please check SD card read and write permissions", Toast. LENGTH_SHORT ). show (); return;} Log. I ("MyPicture", "Custom camera image path:" + file. getPath (); Toast. makeText (getApplicationContext (), "Save image path:" + file. getPath (), Toast. LENGTH_SHORT ). show (); if (buffer = null) {Log. I ("MyPicture", "Custom camera Buffer: null");} else {try {FileOutputStream fos = new FileOutputStream (file); fos. write (buffer); fos. close ();} Catch (IOException e) {e. printStackTrace () ;}}// ------------------------- generate Uri --------------------------------------- // obtain the URIprivate Uri of the output file getOutFileUri (int fileType) {return Uri. fromFile (getOutFile (fileType);} // generate the output File private File getOutFile (int fileType) {String storageState = Environment. getExternalStorageState (); if (Environment. MEDIA_REMOVED.equals (storageState) {Toast. makeText (getApplicationCo Ntext (), "oh, no, SD card does not exist", Toast. LENGTH_SHORT ). show (); return null;} File mediaStorageDir = new File (Environment. getExternalStoragePublicDirectory (Environment. DIRECTORY_PICTURES), "MyPictures"); if (! MediaStorageDir. exists () {if (! MediaStorageDir. mkdirs () {Log. I ("MyPictures", "An error occurred while creating the image storage path directory"); Log. I ("MyPictures", "mediaStorageDir:" + mediaStorageDir. getPath (); return null ;}} File file = new File (getFilePath (mediaStorageDir, fileType); return file ;} // generate the output File path private String getFilePath (File mediaStorageDir, int fileType) {String timeStamp = new SimpleDateFormat ("yyyyMMdd_HHmmss "). format (new Date (); String filePath = mediaStorageDir. getPath () + File. separator; if (fileType = TYPE_FILE_IMAGE) {filePath + = ("IMG _" + timeStamp + ". jpg ");} else if (fileType = TYPE_FILE_VEDIO) {filePath + = (" VIDEO _ "+ timeStamp + ". mp4 ") ;}else {return null;} return filePath ;}}






Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.