笑い男カメラでインテントを試してみた。

シェアする

laughing man

ちょっとインテントの動きを理解したいなと調べたりコード書いたりしていた。
いろんなところではまっていたのでかなり時間を食ってしまったがやりたい事はだいたい出来たからまとめる。

以下のコードでは
自分のアプリからインテントでカメラを起動
もしくは他のアプリからインテントで画像を取得
カメラもしくは他のアプリから取得した画像を笑い男風に加工
その画像を保存
もしくはインテントで他のアプリに送信
を実装してます。

笑い男カメラの肝となる顔認識->BITMAP貼り付け部分は以下のサイトを参考にしました。

インテントに関しては以下のサイトを参考にしました。


Intentチュートリアル2

その他参考にしたサイトです。


に変換する方法 - hyoromoの日記"]

ありがとうございます。

まずは Manifest ファイル。
<intent-filter> ブロックでインテントの送信及び受信を行うという事を記述しています。
このアプリケーションでは、下記Javaのソースコード上にて記載していますが、アプリケーション起動時に即インテントが発生する様になってます。
intent to camera

二つ目の intent-filter を指定する事により、他のアプリケーションの share ボタンを押した時のアプリケーション一覧画面に自分のアプリケーションが表示されます。以下の画像は Quick Pic の share ボタンを押した例。
intent from viewer

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ryomatsu.helloandroid.HelloCamera2"
    android:versionCode="1"
    android:versionName="1.0">
    <uses-sdk android:minSdkVersion="7" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".hellocamera2"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="image/jpeg" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>

次に Java のコード

hellocamera2.java

public class hellocamera2 extends Activity {
    /** Called when the activity is first created. */
    private static final int CAMERA_ACTIVITY = 0;
    private static final String TAG = null;
    private static final int MENU_SHARE = Menu.FIRST + 1;
    private static final int MENU_RETAKE = MENU_SHARE + 1;
    private static final int MENU_SAVE = MENU_RETAKE + 1;
    private ImageView mImageView;
    private Bitmap mCameraBitmap;
    private Bitmap bitmap;
    private Bitmap newBitmap;
    private EditText editInput;
    private AlertDialog.Builder alertDialog;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.thelaughingman);
        mImageView =  (ImageView) findViewById(R.id.ImageView01);

        Intent intent = getIntent();
        if (Intent.ACTION_SEND.equals(intent.getAction())){
            // インテントで他のアプリケーションから画像を受け取った場合はここ
            // 画像が大きすぎる場合は処理できません。
            Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
            try {
                Bitmap bm = MediaStore.Images.Media.getBitmap(getContentResolver(),uri);
                setImageBitmap(bm);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            // アプリケーションを直接起動した場合はここ。
            // 起動後すぐインテントを投げてカメラを起動します。
            throwIntentCamera();
        }
    }

    // カメラ起動
    public void throwIntentCamera() {
        Intent mIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(mIntent, CAMERA_ACTIVITY);
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        Log.i(TAG, "Result code = " + resultCode);

        if (resultCode == RESULT_CANCELED) {
            return;
        }
        switch (requestCode) {
            case CAMERA_ACTIVITY: 
                Bundle b = intent.getExtras();
                Bitmap bm = (Bitmap) b.get("data");
                setImageBitmap(bm); 
                break;
        }
    }

    private void setImageBitmap(Bitmap bm) {
        this.mCameraBitmap = bm;
        setFaceImage();
    }

    //顔認識上書き 
    void setFaceImage(){
        FaceDetector.Face[] faces = new FaceDetector.Face[3]; // 結果受け取り用
        FaceDetector detector = new FaceDetector(
                mCameraBitmap.getWidth(), // ビットマップの幅
                mCameraBitmap.getHeight(), // ビットマップの高さ
                faces.length); // ここでは、最大3つの顔認識結果を受け取れるように指定
        int numFaces = detector.findFaces(mCameraBitmap, faces); // 顔認識実行
        if (numFaces > 0) {
            newBitmap = mCameraBitmap.copy(Bitmap.Config.RGB_565, true);
            Paint paint = new Paint();
            paint.setColor(Color.argb(255, 255, 0, 0)); // 赤
            paint.setStyle(Style.STROKE); // 塗りつぶしなしの線
            Canvas canvas = new Canvas(newBitmap);
            for (int i = 0; i < numFaces; i++) { // 認識した数だけ処理
                Face face = faces[i];
                PointF midPoint = new PointF(0, 0);
                face.getMidPoint(midPoint); // 顔認識結果を取得
                float eyesDistance = face.eyesDistance();
                // 描写元の設定
                Rect src = new Rect(); 
                src.left = 0 ;
                src.top = 0 ;
                src.right = bitmap.getWidth() ;
                src.bottom = bitmap.getHeight() ;
                // 描写先の設定
                RectF rect = new RectF(); 
                rect.left = midPoint.x - (eyesDistance*2) ;
                rect.top = midPoint.y - (eyesDistance*2) ;
                rect.right = midPoint.x + (eyesDistance*2) ;
                rect.bottom = midPoint.y + (eyesDistance*2) ;
                canvas.drawBitmap(bitmap, src, rect, paint); // 笑い男に
            }
            mImageView.setImageBitmap(newBitmap);
        }
    }

    @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            menu.add(Menu.NONE, MENU_SHARE, Menu.NONE, getResources().getString(R.string.menu_share));
            menu.add(Menu.NONE, MENU_RETAKE, Menu.NONE, getResources().getString(R.string.menu_retake));
            menu.add(Menu.NONE, MENU_SAVE, Menu.NONE, getResources().getString(R.string.menu_save));
            return super.onCreateOptionsMenu(menu);
        }

    public boolean onOptionsItemSelected(MenuItem item) {
        boolean rc = true;
        switch(item.getItemId()){
            case MENU_SHARE:
                share();
                break;
            case MENU_RETAKE:
                throwIntentCamera();
                break;
            case MENU_SAVE:
                save();
                break;
            default:
                rc = super.onOptionsItemSelected(item);
                break;
        }
        return rc;
    }

    // インテントで他のアプリケーションに送信。
    // なぜか twicca に送ると画像アップロード時にエラーが出る。。。
    public void share() {
        String filePath = saveImage("share.jpg");
        Uri uri = Uri.fromFile(new File(filePath));
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("image/jpeg");
        intent.putExtra(Intent.EXTRA_STREAM, uri);
        startActivity(intent);
    }

    // "画像を保存する"のダイアログを表示。
    // 保存場所はsdカードのルートディレクトリです。
    public void save() {
        editInput = new EditText(this);
        alertDialog = new AlertDialog.Builder(this);
        alertDialog.setIcon(R.drawable.icon);
        alertDialog.setTitle("plz input file name");
        alertDialog.setView(editInput);
        alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                String fileName = editInput.getText().toString();
                saveImage(fileName);
                Toast.makeText(hellocamera2.this, "saved", Toast.LENGTH_SHORT).show();    
            }
        });
        alertDialog.setNegativeButton("CANSEL", null);
        alertDialog.show();
    }

    // 画像を保存。
    public String saveImage(String fileName) {
        String esPath = Environment.getExternalStorageDirectory().getAbsolutePath();
        String filePath = esPath + "/" + fileName;
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        FileOutputStream fos = null;

        try {
            newBitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
            fos = new FileOutputStream(filePath);
            fos.write(os.toByteArray());
            return filePath;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
}

課題

  • 写真を撮ってもキャンバスに描画されない事がある。
  • twicca に画像を送ってもアップロード時にエラーが出る。
  • 画像が大きいと処理できない。

とりあえずはこんなとこかなー

Sponsored Link

シェアする

フォローする