Android Camera + SurfaceView for custom photos and androidsurfaceview
Force a horizontal screen on the Activity to ensure that the preview direction is correct. Use OrientationEventListener to listen to the device direction. when determining whether a portrait is taken, rotate the photo and save it. This ensures that the preview image is in the same direction as the saved image.
Running effect:
Code:
TestCameraActivity. java
Package com. example. testcamera; import java. io. byteArrayOutputStream; import java. io. fileOutputStream; import java. io. IOException; import java. util. list; import java. util. UUID; import android. annotation. suppressLint; import android. app. activity; import android. content. context; import android. content. intent; import android. graphics. bitmap; import android. graphics. bitmapFactory; import android. graphics. matrix; im Port android. hardware. camera; import android. hardware. camera. parameters; import android. hardware. camera. size; import android. OS. build; import android. OS. bundle; import android. util. log; import android. view. orientationEventListener; import android. view. surfaceHolder; import android. view. surfaceView; import android. view. view; import android. view. view. onClickListener; import android. widget. button; public class T EstCameraActivity extends Activity implements OnClickListener, SurfaceHolder. callback {private static final String TAG = "TestCameraActivity"; public static final String KEY_FILENAME = "filename"; private Button mTakePhoto; private SurfaceView mSurfaceView; private Camera mCamera; private String mFileName; private OrientationEventListener mOrEventListener; // The device direction listener private Boolean mCurrentOrientation ;/ /The current device has a horizontal screen of false and a vertical screen of true/* callback function when image data processing is not completed */private Camera. shutterCallback mShutter = new Camera. shutterCallback () {@ Overridepublic void onShutter () {// general display progress bar};/* callback function after image data processing */private Camera. pictureCallback mJpeg = new Camera. pictureCallback () {@ Overridepublic void onPictureTaken (byte [] data, Camera camera) {// Save the image mFileName = UUID. randomUUID (). toString () + ". jpg "; Log. I (TAG, mFileName); Fil EOutputStream out = null; try {out = openFileOutput (mFileName, Context. MODE_PRIVATE); byte [] newData = null; if (mCurrentOrientation) {// rotate the image and save Bitmap oldBitmap = BitmapFactory. decodeByteArray (data, 0, data. length); Matrix matrix = new Matrix (); matrix. setRotate (90); Bitmap newBitmap = Bitmap. createBitmap (oldBitmap, 0, 0, oldBitmap. getWidth (), oldBitmap. getHeight (), matrix, true); ByteArrayOutputStream Baos = new ByteArrayOutputStream (); newBitmap. compress (Bitmap. compressFormat. JPEG, 85, baos); newData = baos. toByteArray (); out. write (newData);} else {out. write (data) ;}} catch (IOException e) {e. printStackTrace ();} finally {try {if (out! = Null) out. close ();} catch (IOException e) {e. printStackTrace () ;}} Intent I = new Intent (TestCameraActivity. this, ShowPicture. class); I. putExtra (KEY_FILENAME, mFileName); startActivity (I); finish () ;};@ SuppressWarnings ("deprecation") @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_test_camera); mTakePhoto = (Button) findView ById (R. id. take_photo); mTakePhoto. setOnClickListener (this); // camera button listener startOrientationChangeListener (); // start the device direction listener mSurfaceView = (SurfaceView) findViewById (R. id. my_surfaceView); SurfaceHolder holder = mSurfaceView. getHolder (); holder. setType (SurfaceHolder. SURFACE_TYPE_PUSH_BUFFERS); holder. addCallback (this); // callback interface} private final void startOrientationChangeListener () {mOrEventListener = new Orientat IonEventListener (this) {@ Overridepublic void onOrientationChanged (int rotation) {if (rotation> = 0) & (rotation <= 45) | (rotation> = 315) | (rotation> = 135) & (rotation <= 225) {// portraitmCurrentOrientation = true; Log. I (TAG, "portrait screen");} else if (rotation> 45) & (rotation <135) | (rotation> 225) & (rotation <315) {// landscapemCurrentOrientation = false; Log. I (TAG, "Landscape") ;}}}; mOr EventListener. enable () ;}@ Overridepublic void onClick (View v) {// click the camera switch (v. getId () {case R. id. take_photo: mCamera. takePicture (mShutter, null, mJpeg); break; default: break; }}@ Overridepublic void surfaceChanged (SurfaceHolder holder, int format, int width, int height) {// when the SurfaceView size is changed (this method is also called when it is displayed on the screen for the first time), initialize the mCamera parameter and start the Camera preview Parameters parameters = mCamera. getParameters (); // get the Size of the mCamera parameter object LargestSize = getBestSupportedSize (parameters. getSupportedPreviewSizes (); parameters. setPreviewSize (largestSize. width, largestSize. height); // set the preview image size largestSize = getBestSupportedSize (parameters. getSupportedPictureSizes (); // you can specify the size of the captured image parameters. setPictureSize (largestSize. width, largestSize. height); mCamera. setParameters (parameters); try {mCamera. startPreview ();} catch (Exception e) {if (mCamera! = Null) {mCamera. release (); mCamera = null ;}}@ Overridepublic void surfaceCreated (SurfaceHolder holder) {// create a contact if (mCamera! = Null) {try {mCamera. setPreviewDisplay (holder);} catch (IOException e) {e. printStackTrace () ;}}@ Overridepublic void surfaceDestroyed (SurfaceHolder holder) {// cancel Camera preview if (mCamera! = Null) {mCamera. stopPreview () ;}@ SuppressLint ("NewApi") @ Overridepublic void onResume () {super. onResume (); // enable the camera if (Build. VERSION. SDK_INT> = Build. VERSION_CODES.GINGERBREAD) {mCamera = Camera. open (0); // I = 0 indicates the rear Camera} elsemCamera = Camera. open () ;}@ Overridepublic void onPause () {super. onPause (); // release the camera if (mCamera! = Null) {mCamera. release (); mCamera = null;} private Size getBestSupportedSize (List <Size> sizes) {// obtain the maximum SIZESize largestSize = sizes. get (0); int largestArea = sizes. get (0 ). height * sizes. get (0 ). width; for (Size s: sizes) {int area = s. width * s. height; if (area> largestArea) {largestArea = area; largestSize = s ;}} return largestSize ;}}
ShowPicture. java
Package com. example. testcamera; import android. app. activity; import android. graphics. bitmap; import android. graphics. bitmapFactory; import android. graphics. drawable. bitmapDrawable; import android. OS. bundle; import android. util. log; import android. view. display; import android. widget. imageView; public class ShowPicture extends Activity {private static final String TAG = "ShowPicture"; private ImageView mPictur E; public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_show_picture); mPicture = (ImageView) findViewById (R. id. picture); String fileName = getIntent (). getStringExtra (TestCameraActivity. KEY_FILENAME); // image path Log. I (TAG, fileName); String path = getFileStreamPath (fileName ). getAbsolutePath (); Display display = getWindowManager (). getdefadisdisp Lay (); // display size float destWidth = display. getWidth (); float destHeight = display. getHeight (); // read the local image size BitmapFactory. options options = new BitmapFactory. options (); options. inJustDecodeBounds = true; BitmapFactory. decodeFile (path, options); // if it is set to true, options still corresponds to this image, but the decoder does not allocate the memory float srcWidth = options for this image. outWidth; float srcHeight = options. outHeight; int inSampleSize = 1; if (srcHeight> destHeight | src Width> destWidth) {// if (srcWidth> srcHeight) {inSampleSize = Math when the image length and Width are greater than the screen Width. round (srcHeight/destHeight);} else {inSampleSize = Math. round (srcWidth/destWidth);} options = new BitmapFactory. options (); options. inSampleSize = inSampleSize; Bitmap bitmap = BitmapFactory. decodeFile (path, options); BitmapDrawable bDrawable = new BitmapDrawable (getResources (), bitmap); mPicture. setImageDrawable (bDr Awable) ;}@ Overridepublic void onDestroy () {if (! (MPicture. getDrawable () instanceof BitmapDrawable) return; // release the space occupied by bitmap BitmapDrawable B = (BitmapDrawable) mPicture. getDrawable (); B. getBitmap (). recycle (); mPicture. setImageDrawable (null );}}
Source code download