AnyWrite/ATakePhoto.java

Retired DISLab
< AnyWrite
Swpark (토론 | 기여) 사용자의 2013년 12월 18일 (수) 12:30 버전
(비교) ← 이전 판 | 현재 판 (비교) | 다음 판 → (비교)
이동: 둘러보기, 찾기

Preview로 내용을 보고 사진을 촬영하는 클래스이다. 그리고 DrawOnTop 클래스는 View 클래스로서 Preview 화면에 내용을 그려넣는 역할을 한다.

package hufs.dislab.anywrite;
 
import hufs.dislab.util.ImageUtil;
 
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
 
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Bitmap.CompressFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Toast;
 
/**
 * 사진을 촬영하는 액티비티이다.
 * 사진을 촬영한 다음 그 결과인 파일에 대한 노트를 설정하기 위하여
 * AddPhotoActivity를 호출한다.
 * @author swpark
 *
 */
public class ATakePhoto extends Activity {
    //private static final String TAG = "AnyWrite Camera";
    private Camera             mCamera = null;
    private MySurfaceView     mSurface = null;
    private DrawOnTop         mDraw = null;
    private String             mImageFile = null;
    private long             mCurrentFolder;
 
    public static final int REQ_ADD_PHOTO      = 1;
 
 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        //Log.i(TAG, "onCreate");
 
        super.onCreate(savedInstanceState);
 
        Intent intent = getIntent();
        mCurrentFolder = intent.getLongExtra(AMainList.PARENT, AMainList.NO_SELECTED);
 
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                             WindowManager.LayoutParams.FLAG_FULLSCREEN);
 
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
 
        if (mSurface == null) {
            mSurface = new MySurfaceView(this);
            setContentView(mSurface);
        }
 
        if (mDraw == null) {
            mDraw = new DrawOnTop(this);      
            addContentView(mDraw, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        }
 
        if (mSurface != null)
            mSurface.setOnClickListener(listener);
    }
 
    @Override
    public void onBackPressed() {
        //Log.d(TAG, "onBackPressed");
        if (mCamera != null) {
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
        Toast.makeText(ATakePhoto.this, R.string.canceled, Toast.LENGTH_SHORT)
              .show();
 
        setResult(Activity.RESULT_CANCELED);
        finish();
    }
 
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        setResult(resultCode);
        finish();
    }
 
    OnClickListener listener = new OnClickListener() {        
        public void onClick(View v) {
            //Log.d(TAG, "TakePhotoActivity.OnClickListener.onClick");
            try {
                mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
            } catch (NullPointerException e) {
                String error = getResources().getString(R.string.camera_error) + ": Null Pointer";
                Toast.makeText(ATakePhoto.this, error, Toast.LENGTH_SHORT).show();
                setResult(Activity.RESULT_CANCELED);
                finish();
            }
        }
    };
 
    ShutterCallback shutterCallback = new ShutterCallback() {
        public void onShutter() {
            //Log.d(TAG, "TakePhotoActivity.ShutterCallback.onShutter");
        }
    };
 
    /** Handles data for raw picture */    
    PictureCallback rawCallback = new PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) {
            //Log.d(TAG, "rawCallback.PictureCallback.onPictureTaken");
        }
    };
 
    /** Handles data for jpeg picture */
    PictureCallback jpegCallback = new PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) {
            //Log.d(TAG, "jpegCallback.PictureCallback.onPictureTaken");
            FileOutputStream outStream = null;
            try {
                SharedPreferences pref = getSharedPreferences(Preferences.PREF_NAME, Activity.MODE_PRIVATE);
                String imageFolder = pref.getString(Preferences.IMAGE_FOLDER,
                                                    Preferences.DEFAULT_IMAGE_FOLDER);
 
                String tempFile = Note.strGetCurrentTime();
                tempFile = tempFile.replace(':', '.');
                mImageFile = imageFolder + "/" + tempFile + ".jpg";
 
                outStream = new FileOutputStream(mImageFile);
                outStream.write(data);
                outStream.close();
 
                // Thumbnail을 만든다.
                Bitmap bitmap = ImageUtil.getThumbnail(ATakePhoto.this, mImageFile,
                                                      AMainList.THUMBNAIL_SIZE);
                String thumnail = imageFolder + "/" + tempFile + ".thumb.jpg";
                outStream = new FileOutputStream(thumnail);
                bitmap.compress(CompressFormat.JPEG, 50, outStream);
                outStream.flush();
                outStream.close();
 
                // 삽입하기 위하여 AddPhotoActivity를 띄운다.
                Intent intent = new Intent(ATakePhoto.this, AAddPhoto.class);
                intent.putExtra(AMainList.PARENT, mCurrentFolder);
                intent.putExtra(PNotes.KEY_IMAGE_PATH, mImageFile);
                startActivityForResult(intent, REQ_ADD_PHOTO);
            } catch (NullPointerException e) {
                String error = getResources().getString(R.string.camera_error) + ": Null Pointer";
                Toast.makeText(ATakePhoto.this, error, Toast.LENGTH_SHORT).show();
                setResult(Activity.RESULT_CANCELED);
                finish();
            } catch (FileNotFoundException e) {
                String error = getResources().getString(R.string.camera_error) + ": File not found";
                Toast.makeText(ATakePhoto.this, error, Toast.LENGTH_SHORT).show();
                setResult(Activity.RESULT_CANCELED);
                finish();
            } catch (IOException e) {
                String error = getResources().getString(R.string.camera_error) + ": IO";
                Toast.makeText(ATakePhoto.this, error, Toast.LENGTH_SHORT).show();
                setResult(Activity.RESULT_CANCELED);
                finish();
            }
        }
    };
 
    /**
     * 사진을 찍기 위하여 등장하는 Preview를 핸들링하는 뷰이다.
     * @author swpark
     *
     */
    class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
 
        private SurfaceHolder holder;
 
        public MySurfaceView(Context context) {
            super(context);        
            //Log.i(TAG, "MySurfaceView");
 
            try {
                holder = getHolder();
                holder.addCallback(this);
                holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            } catch (NullPointerException e) {
                Toast.makeText(ATakePhoto.this, R.string.camera_error, Toast.LENGTH_SHORT).show();
                setResult(Activity.RESULT_CANCELED);
                finish();                
            }
        }
 
 
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            // The Surface has been created, acquire the camera and tell it where
            // to draw.
 
            //Log.i(TAG, "surfaceCreated");
            try {
                mCamera = Camera.open();    
                mCamera.setPreviewDisplay(holder);
            } catch (NullPointerException e) {
                Toast.makeText(ATakePhoto.this, R.string.camera_error, Toast.LENGTH_SHORT).show();
                setResult(Activity.RESULT_CANCELED);
                finish();
            } catch (IOException e) {
                mCamera.release();
                mCamera = null;
                Toast.makeText(ATakePhoto.this, R.string.camera_error, Toast.LENGTH_SHORT).show();
                setResult(Activity.RESULT_CANCELED);
                finish();
            }
        }
 
        public void surfaceDestroyed(SurfaceHolder holder) {
            //Log.i(TAG, "surfaceDestroyed");
 
            if (mCamera != null) {
                mCamera.setPreviewCallback(null);
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            }
        }
 
        private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
            final double ASPECT_TOLERANCE = 0.05;
            double targetRatio = (double) w / h;
            if (sizes == null) return null;
 
            Size optimalSize = null;
            double minDiff = Double.MAX_VALUE;
 
            int targetHeight = h;
 
            // Try to find an size match aspect ratio and size
            for (Size size : sizes) {
                double ratio = (double) size.width / size.height;
                if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
 
            // Cannot find the one match the aspect ratio, ignore the requirement
            if (optimalSize == null) {
                minDiff = Double.MAX_VALUE;
                for (Size size : sizes) {
                    if (Math.abs(size.height - targetHeight) < minDiff) {
                        optimalSize = size;
                        minDiff = Math.abs(size.height - targetHeight);
                    }
                }
            }
            return optimalSize;
        }
 
 
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            //Log.i(TAG, "surfaceChanged");
 
            if (mCamera != null) {
                Camera.Parameters parameters = mCamera.getParameters();
 
                try {
                    List<Size> sizes = parameters.getSupportedPreviewSizes();
                    Size optimalSize = getOptimalPreviewSize(sizes, width, height);
                    parameters.setPreviewSize(optimalSize.width, optimalSize.height);
 
                    mCamera.setParameters(parameters);
                    mCamera.startPreview();
                } catch (NullPointerException e) {
                    Toast.makeText(ATakePhoto.this, R.string.camera_error, Toast.LENGTH_SHORT).show();
                    ATakePhoto.this.finish();
                    return;
                }
            }
        }
 
    }
 
    /**
     * Preview 화면에 오버레이를 하기 위하여 만든 뷰로서 단순히 화면
     * 중앙에 클릭하라는 메시지를 출력한다.
     * @author swpark
     *
     */
    class DrawOnTop extends View {
 
        public DrawOnTop(Context context) {
            super(context);
            //Log.i(TAG, "DrawOnTop");
        }
 
        @Override
        protected void onDraw(Canvas canvas) {
            //Log.d(TAG, "draw");
 
            Paint paint = new Paint();
            paint.setColor(Color.RED);
            paint.setShadowLayer(1, 1, 1, Color.YELLOW);
            paint.setAlpha(100);
            paint.setTextSize(25);
            String msg = getResources().getString(R.string.click_to_take_picture);
            Rect bounds = new Rect();
            paint.getTextBounds(msg, 0, msg.length(), bounds);
            canvas.drawText(
                    msg,
                    canvas.getWidth() / 2 - bounds.right / 2,
                    canvas.getHeight() / 2 - bounds.bottom / 2,
                    paint);
        }
 
    }
}
개인 도구
이름공간
변수
행위
둘러보기
구성원
연구
연구실
기타
도구모음
인쇄/내보내기