本文介绍了绘制文本(时间戳)在图像从单机相机拍摄的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有低于上点击我的code打开相机,拍照,获取从相机的照片,然后放入到一个ImageView的。不过,我想利用图像和图像应用文本(某种时间戳,无论是从图像preferably时间戳,或者仅仅是系统日期时间),并保存为JPEG格式。

如果有人能帮助我走出这将是真棒。

 公共类PhotoIntentActivity延伸活动{

私有静态最终诠释ACTION_TAKE_PHOTO_B = 1;

私有静态最后弦乐BITMAP_STORAG​​E_KEY =viewbitmap;
私有静态最后弦乐IMAGEVIEW_VISIBILITY_STORAG​​E_KEY =imageviewvisibility;
私人ImageView的mImageView;
私人位图mImageBitmap;

私人字符串mCurrentPhotoPath;

私有静态最后弦乐JPEG_FILE_ preFIX =IMG_;
私有静态最后弦乐JPEG_FILE_SUFFIX =.JPG;

私人AlbumStorageDirFactory mAlbumStorageDirFactory = NULL;


/ *相册此应用程序* /
私人字符串getAlbumName(){
    返回的getString(R.string.album_name);
}


私人文件getAlbumDir(){
    文件storageDir = NULL;

    如果(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){

        storageDir = mAlbumStorageDirFactory.getAlbumStorageDir(getAlbumName());

        如果(storageDir!= NULL){
            如果(!storageDir.mkdirs()){
                如果(!storageDir.exists()){
                    Log.d(CameraSample,无法创建目录);
                    返回null;
                }
            }
        }

    } 其他 {
        Log.v(的getString(R.string.app_name),外部存储没有装入读/写。);
    }

    返回storageDir;
}

私人文件createImageFile()抛出IOException异常{
    //创建一个图像文件名

    字符串的timeStamp =新的SimpleDateFormat(YYYYMMDD_HHMMSS)格式(新的Date())。
    字符串映像文件名称= JPEG_FILE_ preFIX +的timeStamp +_;
    文件albumF = getAlbumDir();
    文件imageF = File.createTempFile(映像文件名称,JPEG_FILE_SUFFIX,albumF);

    返回imageF;
}

私人文件setUpPhotoFile()抛出IOException异常{

    文件f = createImageFile();
    mCurrentPhotoPath = f.getAbsolutePath();

    返回F;
}

私人无效setPic(){

    / *没有足够的内存来开拓更多的超过两相机的照片* /
    / *所以pre-规模目标位到其中的文件是去codeD * /

    / *获取ImageView的大小* /
    INT targetW = mImageView.getWidth();
    INT targetH = mImageView.getHeight();

    / *获取图像的大小* /
    BitmapFactory.Options bmOptions =新BitmapFactory.Options();
    bmOptions.inJustDe codeBounds = TRUE;
    BitmapFactory.de codeFILE(mCurrentPhotoPath,bmOptions);
    INT photoW = bmOptions.outWidth;
    INT photoH = bmOptions.outHeight;

    / *找出需要降低少哪种方式* /
    INT比例因子= 1;
    如果((targetW大于0)||(targetH大于0)){
        比例因子= Math.min(photoW / targetW,photoH / targetH);
    }

    / *设置选项位图缩放图像德code目标* /
    bmOptions.inJustDe codeBounds = FALSE;
    bmOptions.inSampleSize =比例因子;
    bmOptions.inPurgeable =真;

 / * NEWELY ADDED code * /
    / *德code中的JPEG文件转换成位图* /
    点阵位图= BitmapFactory.de codeFILE(mCurrentPhotoPath,bmOptions);
    位图replacedBitmap = timestampItAndSave(位图);

    / *位图关联到ImageView的* /
    mImageView.setImageBitmap(replacedBitmap);
    mImageView.setVisibility(View.VISIBLE);
 / * NEWELY ADDED code * /
}

私人无效galleryAddPic(){
        意图mediaScanIntent =新的意向书(android.intent.action.MEDIA_SCANNER_SCAN_FILE);
        文件F =新的文件(mCurrentPhotoPath);
        乌里contentUri = Uri.fromFile(F);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
}

私人无效dispatchTakePictureIntent(INT行动code){

    意图takePictureIntent =新的意图(MediaStore.ACTION_IM​​AGE_CAPTURE);

    开关(动作code){
    案例ACTION_TAKE_PHOTO_B:
        文件F = NULL;

        尝试 {
            F = setUpPhotoFile();
            mCurrentPhotoPath = f.getAbsolutePath();
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(F));
        }赶上(IOException异常E){
            e.printStackTrace();
            F = NULL;
            mCurrentPhotoPath = NULL;
        }
        打破;

    默认:
        打破;
    } // 开关

    startActivityForResult(takePictureIntent,动作code);
}

私人无效handleBigCameraPhoto(){

    如果(mCurrentPhotoPath!= NULL){
        setPic();
        galleryAddPic();
        mCurrentPhotoPath = NULL;
    }

}


Button.OnClickListener mTakePicOnClickListener =
    新Button.OnClickListener(){
    公共无效的onClick(视图v){
        dispatchTakePictureIntent(ACTION_TAKE_PHOTO_B);
    }
};


/ **第一次创建活动时调用。 * /
@覆盖
公共无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.main);

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

    按钮picBtn =(按钮)findViewById(R.id.btnIntend);
    setBtnListenerOrDisable(
            picBtn,
            mTakePicOnClickListener,
            MediaStore.ACTION_IM​​AGE_CAPTURE
    );

    如果(Build.VERSION.SDK_INT> = Build.VERSION_ codeS.FROYO){
        mAlbumStorageDirFactory =新FroyoAlbumDirFactory();
    } 其他 {
        mAlbumStorageDirFactory =新BaseAlbumDirFactory();
    }
}

@覆盖
保护无效onActivityResult(INT申请code,INT结果code,意图数据){
    开关(要求code){
    案例ACTION_TAKE_PHOTO_B:{
        如果(结果code == RESULT_OK){
            handleBigCameraPhoto();
        }
        打破;
    } // ACTION_TAKE_PHOTO_B
  }
}

//一些生命周期的回调,使图像可以生存的方向变化
@覆盖
保护无效的onSaveInstanceState(包outState){
    outState.putParcelable(BITMAP_STORAG​​E_KEY,mImageBitmap);
    outState.putBoolean(IMAGEVIEW_VISIBILITY_STORAG​​E_KEY,(mImageBitmap = NULL)!);
    super.onSaveInstanceState(outState);
}

@覆盖
保护无效onRestoreInstanceState(包savedInstanceState){
    super.onRestoreInstanceState(savedInstanceState);
    mImageBitmap = savedInstanceState.getParcelable(BITMAP_STORAG​​E_KEY);
    mImageView.setImageBitmap(mImageBitmap);
    mImageView.setVisibility(
            savedInstanceState.getBoolean(IMAGEVIEW_VISIBILITY_STORAG​​E_KEY)?
                    ImageView.VISIBLE:ImageView.INVISIBLE
    );

}

/ **
 *表示指定的动作是否可以用作意图。本
 *方法查询包管理器进行安装的软件包,可以
 *要使用指定的操作意图做出回应。如果没有合适的包
 *发现,此方法返回false。
 * http://android-developers.blogspot.com/2009/01/can-i-use-this-intent.html
 *
 *参数范围内的应用程序的环境。
 *参数动作的意图行动,检查的可用性。
 *
 * @返回真,如果使用指定的操作的意图可以发送和
 *回应,否则为false。
 * /
公共静态布尔isIntentAvailable(上下文的背景下,串动){
    最终PackageManager packageManager = context.getPackageManager();
    最终意向意图=新的意图(动作);
    名单< ResolveInfo>名单=
        packageManager.queryIntentActivities(意向,
                PackageManager.MATCH_DEFAULT_ONLY);
    返回则为list.size()> 0;
}

私人无效setBtnListenerOrDisable(
        按钮BTN,
        Button.OnClickListener onClickListener,
        字符串intentName
){
    如果(isIntentAvailable(这一点,intentName)){
        btn.setOnClickListener(onClickListener);
    } 其他 {
        btn.setText(
            的getText(R.string.cannot)的ToString()++ btn.getText());
        btn.setClickable(假);
    }
}

  }
 

获取错误4.0的模拟器。登录猫。

  07-12 20:53:50.510:D / gralloc_goldfish(545):仿真器没有检测GPU的仿真。
 07-12 20:53:54.861:W / IInputConnectionWrapper(545):showStatusIcon上的非活动InputConnection
 07-12 20:54:00.700:D / dalvikvm(545):GC_FOR_ALLOC释放114K,3%的自由10052K / 10311K,暂停217ms
 07-12 20:54:00.710:I / dalvikvm堆(545):增长堆(破片的情况下),以11.072MB为1228816字节分配
 07-12 20:54:00.860:D / dalvikvm(545):GC_CONCURRENT释放3K,免费3%11249K / 11527K,暂停4毫秒+ 3ms的
 07-12 20:54:00.960:D / AndroidRuntime(545):关闭虚拟机
 07-12 20:54:00.960:W / dalvikvm(545):主题ID = 1:螺纹退出与未捕获的异常(组= 0x409961f8)
 07-12 20:54:01.000:E / AndroidRuntime(545):致命异常:主要
 07-12 20:54:01.000:E / AndroidRuntime(545):java.lang.RuntimeException的:不提供结果ResultInfo {谁= NULL,请求= 1,结果= -1,数据= NULL}到活动{com.example .android.photobyintent / com.example.android.photobyintent.PhotoIntentActivity}:java.lang.IllegalStateException:传递给帆布构造不可变的位图
 07-12 20:54:01.000:E / AndroidRuntime(545):在android.app.ActivityThread.deliverResults(ActivityThread.java:2976)
 07-12 20:54:01.000:E / AndroidRuntime(545):在android.app.ActivityThread.handleSendResult(ActivityThread.java:3019)
 07-12 20:54:01.000:E / AndroidRuntime(545):在android.app.ActivityThread.access $ 1100(ActivityThread.java:122)
 07-12 20:54:01.000:E / AndroidRuntime(545):在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1176)
 07-12 20:54:01.000:E / AndroidRuntime(545):在android.os.Handler.dispatchMessage(Handler.java:99)
 07-12 20:54:01.000:E / AndroidRuntime(545):在android.os.Looper.loop(Looper.java:137)
 07-12 20:54:01.000:E / AndroidRuntime(545):在android.app.ActivityThread.main(ActivityThread.java:4340)
 07-12 20:54:01.000:E / AndroidRuntime(545):在java.lang.reflect.Method.invokeNative(本机方法)
 07-12 20:54:01.000:E / AndroidRuntime(545):在java.lang.reflect.Method.invoke(Method.java:511)
 07-12 20:54:01.000:E / AndroidRuntime(545):在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:784)
 07-12 20:54:01.000:E / AndroidRuntime(545):在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
 07-12 20:54:01.000:E / AndroidRuntime(545):在dalvik.system.NativeStart.main(本机方法)
 07-12 20:54:01.000:E / AndroidRuntime(545):致:java.lang.IllegalStateException:不可改变位图传递到画布构造
 07-12 20:54:01.000:E / AndroidRuntime(545):在android.graphics.Canvas< INIT> (Canvas.java:133)
 07-12 20:54:01.000:E / AndroidRuntime(545):在com.example.android.photobyintent.PhotoIntentActivity.timestampItAndSave(PhotoIntentActivity.java:103)
 07-12 20:54:01.000:E / AndroidRuntime(545):在com.example.android.photobyinten
 

t.PhotoIntentActivity.setPic(PhotoIntentActivity.java:154)     07-12 20:54:01.000:E / AndroidRuntime(545):在com.example.android.photobyintent.PhotoIntentActivity.handleBigCameraPhoto(PhotoIntentActivity.java:199)     07-12 20:54:01.000:E / AndroidRuntime(545):在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 ...更多

更新code与平局位图。

 私人位图timestampItAndSave(位图toEdit){
    位图DEST = Bitmap.createBitmap(toEdit.getWidth(),toEdit.getHeight(),Bitmap.Config.ARGB_8888);

       SimpleDateFormat的SDF =新的SimpleDateFormat(YYYY-MM-DD HH:MM:SS);
      串日期时间= sdf.format(Calendar.getInstance()的getTime()); //读取本地时间在系统中

    帆布CS =新的Canvas(DEST);
    油漆tPaint =新的油漆();
    tPaint.setTextSize(35);
    tPaint.setColor(Color.BLUE);
    tPaint.setStyle(Style.FILL);
    浮球高度= tPaint.measureText(YY);
    cs.drawText(日期时间,20F,身高+ 15F,tPaint);
    cs.drawBitmap(目标,0,0,tPaint);
   尝试 {
        dest.com preSS(Bitmap.Com pressFormat.JPEG,100,新的FileOutputStream(新文件(Environment.getExternalStorageDirectory()+/时间戳)));

    }赶上(FileNotFoundException异常E){
    e.printStackTrace();
    返回null;
  }
    返回DEST;
}
 

解决方案

您不想放,在OnDraw中的方法,因为这是被称为每当查看无效(你不想要的)。

只需创建一个方法,并把那个code里面。说它是你得到后的图像,像这样:

 私人位图timestampItAndSave(位图toEdit){
    位图DEST = Bitmap.createBitmap(toEdit.getWidth(),toEdit.getHeight(),Bitmap.Config.ARGB_8888);

    SimpleDateFormat的SDF =新的SimpleDateFormat(YYYY-MM-DD HH:MM:SS);
    串日期时间= sdf.format(Calendar.getInstance()的getTime()); //读取本地时间在系统中

    帆布CS =新的Canvas(DEST);
    油漆tPaint =新的油漆();
    tPaint.setTextSize(35);
    tPaint.setColor(Color.BLUE);
    tPaint.setStyle(Style.FILL);
    浮球高度= tPaint.measureText(YY);
    cs.drawText(日期时间,20F,身高+ 15F,tPaint);
    尝试 {
        dest.com preSS(Bitmap.Com pressFormat.JPEG,100,新的FileOutputStream(新文件(Environment.getExternalStorageDirectory()+/时间戳)));
    }赶上(FileNotFoundException异常E){
    e.printStackTrace();
    返回null;
  }
    返回DEST;
}
 

我也建议不要将其保存为/ SD卡/而是使用Environment.getExternalStorageDirectory()(已经实行了你)

编辑:也注意到您要创建第二个Bitmap出myImageBitmap的;是必要的吗?

I have my code below that on click opens the camera, takes a photo, gets the photo from the camera, then puts in into a imageview. However i want to take the image and apply Text (Some sort of time stamp, either the time stamp from the image preferably, or just the system datetime) on the image and save as a jpeg.

If anyone can help me out that would be awesome.

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);
    }
}

  }

Getting error on 4.0 emulators. 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): 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 more

Updated code with draw bit map.

  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;
}
解决方案

You don't want to put that in the onDraw method, as that's called whenever the View is invalidated (which you don't want).

Just create a method and put that code inside it. Call it after you've gotten the image, like so:

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;
}

I also recommend not saving it to "/sdcard/" but instead use Environment.getExternalStorageDirectory() (already implemented for you)

Edit: Also noticed you're creating a second Bitmap out of myImageBitmap; is that necessary?

这篇关于绘制文本(时间戳)在图像从单机相机拍摄的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-26 10:19