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

我的下面的代码点击打开相机,拍照,从相机获取照片,然后进入imageview。 但是我想拍摄图像并在图像上应用文本(某种时间戳,最好是图像中的时间戳,或者只是系统日期时间)并保存为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 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模拟器上获取错误。 记录猫。

  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. (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):at android .app.Activity.dispatchActivityResult(Activity.java:4649)07-12 20:54:01.000:E / AndroidRuntime(545):at 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; } 

您不希望将它放在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; 那有必要吗?