绘图文本(TimeStamp)覆盖从独立摄像头捕获的图像

时间:2012-07-11 15:34:12

标签: java android text bitmap timestamp

我的下面的代码点击打开相机,拍照,从相机获取照片,然后进入图像视图。但是我想拍摄图像并在图像上应用文本(某种时间戳,最好是图像中的时间戳,或者只是系统日期时间)并保存为jpeg。

如果有人能帮助我,那就太棒了。

public class PhotoIntentActivity extends Activity {

private static final int ACTION_TAKE_PHOTO_B = 1;

private static final String BITMAP_STORAGE_KEY = "viewbitmap";
private static final String IMAGEVIEW_VISIBILITY_STORAGE_KEY =  "imageviewvisibility";
private ImageView mImageView;
private Bitmap mImageBitmap;

private String mCurrentPhotoPath;

private static final String JPEG_FILE_PREFIX = "IMG_";
private static final String JPEG_FILE_SUFFIX = ".jpg";

private AlbumStorageDirFactory mAlbumStorageDirFactory = null;


/* Photo album for this application */
private String getAlbumName() {
    return getString(R.string.album_name);
}


private File getAlbumDir() {
    File storageDir = null;

    if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {

        storageDir = mAlbumStorageDirFactory.getAlbumStorageDir(getAlbumName());

        if (storageDir != null) {
            if (! storageDir.mkdirs()) {
                if (! storageDir.exists()){
                    Log.d("CameraSample", "failed to create directory");
                    return null;
                }
            }
        }

    } else {
        Log.v(getString(R.string.app_name), "External storage is not mounted READ/WRITE.");
    }

    return storageDir;
}

private File createImageFile() throws IOException {
    // Create an image file name

    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = JPEG_FILE_PREFIX + timeStamp + "_";
    File albumF = getAlbumDir();
    File imageF = File.createTempFile(imageFileName, JPEG_FILE_SUFFIX, albumF);

    return imageF;
}

private File setUpPhotoFile() throws IOException {

    File f = createImageFile();
    mCurrentPhotoPath = f.getAbsolutePath();

    return f;
}

private void setPic() {

    /* There isn't enough memory to open up more than a couple camera photos */
    /* So pre-scale the target bitmap into which the file is decoded */

    /* Get the size of the ImageView */
    int targetW = mImageView.getWidth();
    int targetH = mImageView.getHeight();

    /* Get the size of the image */
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;

    /* Figure out which way needs to be reduced less */
    int scaleFactor = 1;
    if ((targetW > 0) || (targetH > 0)) {
        scaleFactor = Math.min(photoW/targetW, photoH/targetH); 
    }

    /* Set bitmap options to scale the image decode target */
    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

 /* NEWELY ADDED CODE */
    /* Decode the JPEG file into a Bitmap */
    Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); 
    Bitmap replacedBitmap = timestampItAndSave(bitmap); 

    /* Associate the Bitmap to the ImageView */
    mImageView.setImageBitmap(replacedBitmap); 
    mImageView.setVisibility(View.VISIBLE);
 /* NEWELY ADDED CODE */
}

private void galleryAddPic() {
        Intent mediaScanIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
        File f = new File(mCurrentPhotoPath);
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
}

private void dispatchTakePictureIntent(int actionCode) {

    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    switch(actionCode) {
    case ACTION_TAKE_PHOTO_B:
        File f = null;

        try {
            f = setUpPhotoFile();
            mCurrentPhotoPath = f.getAbsolutePath();
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
        } catch (IOException e) {
            e.printStackTrace();
            f = null;
            mCurrentPhotoPath = null;
        }
        break;

    default:
        break;          
    } // switch

    startActivityForResult(takePictureIntent, actionCode);
}

private void handleBigCameraPhoto() {

    if (mCurrentPhotoPath != null) {
        setPic();
        galleryAddPic();
        mCurrentPhotoPath = null;
    }

}


Button.OnClickListener mTakePicOnClickListener = 
    new Button.OnClickListener() {
    public void onClick(View v) {
        dispatchTakePictureIntent(ACTION_TAKE_PHOTO_B);
    }
};


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mImageView = (ImageView) findViewById(R.id.imageView1);
    mImageBitmap = null;

    Button picBtn = (Button) findViewById(R.id.btnIntend);
    setBtnListenerOrDisable( 
            picBtn, 
            mTakePicOnClickListener,
            MediaStore.ACTION_IMAGE_CAPTURE
    );

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
        mAlbumStorageDirFactory = new FroyoAlbumDirFactory();
    } else {
        mAlbumStorageDirFactory = new BaseAlbumDirFactory();
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
    case ACTION_TAKE_PHOTO_B: {
        if (resultCode == RESULT_OK) {
            handleBigCameraPhoto();
        }
        break;
    } // ACTION_TAKE_PHOTO_B
  }
}

// Some lifecycle callbacks so that the image can survive orientation change
@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putParcelable(BITMAP_STORAGE_KEY, mImageBitmap);
    outState.putBoolean(IMAGEVIEW_VISIBILITY_STORAGE_KEY, (mImageBitmap != null) );
    super.onSaveInstanceState(outState);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    mImageBitmap = savedInstanceState.getParcelable(BITMAP_STORAGE_KEY);
    mImageView.setImageBitmap(mImageBitmap);
    mImageView.setVisibility(
            savedInstanceState.getBoolean(IMAGEVIEW_VISIBILITY_STORAGE_KEY) ? 
                    ImageView.VISIBLE : ImageView.INVISIBLE
    );

}

/**
 * Indicates whether the specified action can be used as an intent. This
 * method queries the package manager for installed packages that can
 * respond to an intent with the specified action. If no suitable package is
 * found, this method returns false.
 * http://android-developers.blogspot.com/2009/01/can-i-use-this-intent.html
 *
 * @param context The application's environment.
 * @param action The Intent action to check for availability.
 *
 * @return True if an Intent with the specified action can be sent and
 *         responded to, false otherwise.
 */
public static boolean isIntentAvailable(Context context, String action) {
    final PackageManager packageManager = context.getPackageManager();
    final Intent intent = new Intent(action);
    List<ResolveInfo> list =
        packageManager.queryIntentActivities(intent,
                PackageManager.MATCH_DEFAULT_ONLY);
    return list.size() > 0;
}

private void setBtnListenerOrDisable( 
        Button btn, 
        Button.OnClickListener onClickListener,
        String intentName
) {
    if (isIntentAvailable(this, intentName)) {
        btn.setOnClickListener(onClickListener);            
    } else {
        btn.setText( 
            getText(R.string.cannot).toString() + " " + btn.getText());
        btn.setClickable(false);
    }
}

  }

在4.0模拟器上获取错误。 Log Cat。

 07-12 20:53:50.510: D/gralloc_goldfish(545): Emulator without GPU emulation detected.
 07-12 20:53:54.861: W/IInputConnectionWrapper(545): showStatusIcon on inactive      InputConnection
 07-12 20:54:00.700: D/dalvikvm(545): GC_FOR_ALLOC freed 114K, 3% free 10052K/10311K,      paused 217ms
 07-12 20:54:00.710: I/dalvikvm-heap(545): Grow heap (frag case) to 11.072MB for           1228816-byte allocation
 07-12 20:54:00.860: D/dalvikvm(545): GC_CONCURRENT freed 3K, 3% free 11249K/11527K,      paused 4ms+3ms
 07-12 20:54:00.960: D/AndroidRuntime(545): Shutting down VM
 07-12 20:54:00.960: W/dalvikvm(545): threadid=1: thread exiting with uncaught      exception (group=0x409961f8)
 07-12 20:54:01.000: E/AndroidRuntime(545): FATAL EXCEPTION: main
 07-12 20:54:01.000: E/AndroidRuntime(545): java.lang.RuntimeException: Failure      delivering result ResultInfo{who=null, request=1, result=-1, data=null} to activity      {com.example.android.photobyintent/com.example.android.photobyintent.PhotoIntentActivity}:      java.lang.IllegalStateException: Immutable bitmap passed to Canvas constructor
 07-12 20:54:01.000: E/AndroidRuntime(545):     at      android.app.ActivityThread.deliverResults(ActivityThread.java:2976)
 07-12 20:54:01.000: E/AndroidRuntime(545):     at      android.app.ActivityThread.handleSendResult(ActivityThread.java:3019)
 07-12 20:54:01.000: E/AndroidRuntime(545):     at      android.app.ActivityThread.access$1100(ActivityThread.java:122)
 07-12 20:54:01.000: E/AndroidRuntime(545):     at      android.app.ActivityThread$H.handleMessage(ActivityThread.java:1176)
 07-12 20:54:01.000: E/AndroidRuntime(545):     at android.os.Handler.dispatchMessage(Handler.java:99)
 07-12 20:54:01.000: E/AndroidRuntime(545):     at android.os.Looper.loop(Looper.java:137)
 07-12 20:54:01.000: E/AndroidRuntime(545):     at android.app.ActivityThread.main(ActivityThread.java:4340)
 07-12 20:54:01.000: E/AndroidRuntime(545):     at java.lang.reflect.Method.invokeNative(Native Method)
 07-12 20:54:01.000: E/AndroidRuntime(545):     at java.lang.reflect.Method.invoke(Method.java:511)
 07-12 20:54:01.000: E/AndroidRuntime(545):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
 07-12 20:54:01.000: E/AndroidRuntime(545):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
 07-12 20:54:01.000: E/AndroidRuntime(545):     at dalvik.system.NativeStart.main(Native Method)
 07-12 20:54:01.000: E/AndroidRuntime(545): Caused by: java.lang.IllegalStateException: Immutable bitmap passed to Canvas constructor
 07-12 20:54:01.000: E/AndroidRuntime(545):     at android.graphics.Canvas.<init>  (Canvas.java:133)
 07-12 20:54:01.000: E/AndroidRuntime(545):     at com.example.android.photobyintent.PhotoIntentActivity.timestampItAndSave(PhotoIntentActivity.java:103)
 07-12 20:54:01.000: E/AndroidRuntime(545):     at com.example.android.photobyinten

t.PhotoIntentActivity.setPic(PhotoIntentActivity.java:154)      07-12 20:54:01.000:E / AndroidRuntime(545):at com.example.android.photobyintent.PhotoIntentActivity.handleBigCameraPhoto(PhotoIntentActivity.java:199)      07-12 20:54:01.000:E / AndroidRuntime(545):at com.example.android.photobyintent.PhotoIntentActivity.onActivityResult(PhotoIntentActivity.java:244)      07-12 20:54:01.000:E / AndroidRuntime(545):在android.app.Activity.dispatchActivityResult(Activity.java:4649)      07-12 20:54:01.000:E / AndroidRuntime(545):在android.app.ActivityThread.deliverResults(ActivityThread.java:2972)      07-12 20:54:01.000:E / AndroidRuntime(545):... 11更多

使用绘制位图更新了代码。

  private Bitmap timestampItAndSave(Bitmap toEdit){
    Bitmap dest = Bitmap.createBitmap(toEdit.getWidth(), toEdit.getHeight(), Bitmap.Config.ARGB_8888);

       SimpleDateFormat sdf = new     SimpleDateFormat("YYYY-MM-DD HH:MM:SS");
      String dateTime = sdf.format(Calendar.getInstance().getTime()); // reading local time in the system

    Canvas cs = new Canvas(dest);
    Paint tPaint = new Paint();
    tPaint.setTextSize(35);
    tPaint.setColor(Color.BLUE);
    tPaint.setStyle(Style.FILL);
    float height = tPaint.measureText("yY");
    cs.drawText(dateTime, 20f, height+15f, tPaint);
    cs.drawBitmap(dest,0 ,0,tPaint);
   try {
        dest.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(new File(Environment.getExternalStorageDirectory() + "/timestamped")));

    } catch (FileNotFoundException e) {
    e.printStackTrace();
    return null;
  }
    return dest;
}

1 个答案:

答案 0 :(得分:5)

您不希望将其放在onDraw方法中,因为只要View无效(您不想要),就会调用它。

只需创建一个方法并将该代码放入其中。在你得到图像之后调用它,就像这样:

private Bitmap timestampItAndSave(Bitmap toEdit){
    Bitmap dest = Bitmap.createBitmap(toEdit.getWidth(), toEdit.getHeight(), Bitmap.Config.ARGB_8888);

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String dateTime = sdf.format(Calendar.getInstance().getTime()); // reading local time in the system

    Canvas cs = new Canvas(dest);
    Paint tPaint = new Paint();
    tPaint.setTextSize(35);
    tPaint.setColor(Color.BLUE);
    tPaint.setStyle(Style.FILL);
    float height = tPaint.measureText("yY");
    cs.drawText(dateTime, 20f, height+15f, tPaint);
    try {
        dest.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(new File(Environment.getExternalStorageDirectory() + "/timestamped")));
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    return null;
  }
    return dest;
}

我还建议不要将它保存到“/ sdcard /”,而是使用Environment.getExternalStorageDirectory()(已经为你实现)

编辑:还注意到你正在从myImageBitmap创建第二个Bitmap;那是必要的吗?