在从独立相机捕获的图像上绘制文本(时间戳)

2024-01-16

我的代码如下,单击即可打开相机,拍照,从相机获取照片,然后放入图像视图中。不过,我想拍摄图像并在图像上应用文本(某种时间戳,最好是图像的时间戳,或者只是系统日期时间)并保存为 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 模拟器上出现错误。日志猫。

 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): 在 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 更多

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

  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 创建第二个位图;有必要吗?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在从独立相机捕获的图像上绘制文本(时间戳) 的相关文章

随机推荐

  • 不使用 Spark 从 Parquet 读取特定列

    我正在尝试在不使用 Apache Spark 的情况下读取 Parquet 文件 并且我能够做到这一点 但我发现很难读取特定列 我无法找到任何好的谷歌资源 因为几乎所有帖子都是关于使用 parquet 文件读取的 下面是我的代码 impor
  • 运行 Google App Engine 移动后端客户端时出错

    我正在按照教程进行操作移动后端入门 https developers google com cloud samples mbs getting started 但是 当我尝试运行下载的客户端时 出现以下异常 05 23 14 48 49 9
  • 2个二叉树是否相等[重复]

    这个问题在这里已经有答案了 可能的重复 判断两个二叉树是否相等 https stackoverflow com questions 1482822 determine if two binary trees are equal 昨天去面试了
  • SCSS 扩展嵌套选择器并覆盖嵌套规则集

    好的 我有一个带有嵌套选择器的占位符 block title font size 12px 我想扩展它并添加到 title class superblock extend block title font weight bold 我想要的答
  • 为什么我无法在 Jupyter Notebook 上导入 geopy.distance.vincenty()?我安装了geopy 2.0.0

    from geopy distance import vincenty 我刚刚安装了geopy包2 0 0 我想使用geopy distance vincenty 作为这个doc https kite com python docs geo
  • 旋转相机时的OpenGL光照问题

    我在游戏世界中绘制建筑物 并使用以下代码对它们进行着色 GLfloat light ambient 0 0f 0 0f 0 0f 1 0f GLfloat light position 135 66f 129 83f 4 7f 1 0f g
  • 使用 boto,我如何命名新生成的 EC2 实例?

    我正在使用 boto 生成一个基于 AMI 的新 EC2 实例 ami run 方法有许多参数 但没有 name 参数 也许它被称为不同的东西 import boto c boto connect ec2 ec2 key ec2 secre
  • Javascript 超越属性访问器

    我在这里阅读了很多关于 JS 访问器的内容 并发现这对我有好处 这是我用于本地字段的内容 TYPE DEFAULT VALUE number 0 string array object typeOf function object if t
  • 如何测试 URL 是否为有效图像(在 JavaScript 中)?

    提交表单时 我想确保某个字段是有效的图像 URL 我可以在我的服务器上创建一个 AJAX 端点 它会卷曲 URL 并使用图像库解析输出 但这感觉有点矫枉过正 我可以逃脱做一个 img 元素然后以某种方式同步检查响应 你可以做一个 img 元
  • 带有 .htaccess 的多个查询参数 RESTful URL

    我想对我正在开发的网站使用以下 RESTful URL http mysite com Products category bags colours black 谁能告诉我如何使用 htaccess 实现此目的 Oscar 这是一个 hta
  • 如何从命令行获取文件句柄?

    我有一个以文件句柄作为参数的子例程 如何从命令行指定的文件路径创建文件句柄 我不想自己对这个文件进行任何处理 我只想将其传递给另一个子例程 该子例程返回一个包含文件中所有解析数据的哈希数组 我正在使用的命令行输入如下所示 getfile p
  • 如何在 Eclipse 中集成 SBT scala

    如何在eclipse中集成SBT scala 我也在关注这篇文章 我想在 scala 中添加现有项目 如何编译它以及如何在eclipse中使用build sbt SBT 集成测试设置 https stackoverflow com ques
  • Template.instance() 和 this 之间的区别

    Template instance 和这个有什么区别 使用其中之一有优势吗 Template name onRendered function var template Template instance var instance this
  • Redis sub/pub 和 php/nodejs

    开始开发一个新项目 使用 redis 作为 sub pub 系统来显示 mysql 数据库的结果 因此 如果有更新 我想将这些更新从 mysql 发布到我的网页 我的问题是 哪种选择更好 选项1 我应该通过nodejs 和socket io
  • 使用 DateTime.TryParse 检查字符串是否为有效日期

    我在用DateTime TryParse 函数检查特定字符串是否是有效的日期时间 不依赖于任何区域性 令我惊讶的是 该函数返回true对于 1 1 1 1 等偶数字符串 我怎么解决这个问题 Update 这是否意味着 如果我想检查特定字符串
  • 从 javascript 显示 Android 键盘

    我希望能够在导航到页面后在移动浏览器 例如 Android 上显示键盘 我已经看到了一些解决方法 用javascript在手机上显示虚拟键盘 https stackoverflow com questions 6837543 show vi
  • 以下示例中给出的结构有何不幸之处?

    15 6 2 初始化基数和成员 N4713 节在第 11 项之后有以下示例 struct A A default OK A int v v v OK const int v 42 OK A a1 error ill formed bindi
  • `more.com` 返回“内存不足”。

    环境详情 x64 Win7 SP1 企业版 Windows PowerShell v5 0 没有加载任何配置文件 我的本地电源外壳 questions tagged powershell会话正在返回 内存不足 当我尝试执行时help or
  • 如何对随时间缓慢变化的数据进行建模?

    假设我得到了大量 200 万行 数据 这些数据应该是静态且不变的 应该是 这些数据每月重新发布一次 有哪些方法可以用于 1 了解哪些数据点逐月发生变化以及 2 使用给定时间点的数据 解决方案1 天真地保存每个数据快照 并按日期注释 差异意识
  • 在从独立相机捕获的图像上绘制文本(时间戳)

    我的代码如下 单击即可打开相机 拍照 从相机获取照片 然后放入图像视图中 不过 我想拍摄图像并在图像上应用文本 某种时间戳 最好是图像的时间戳 或者只是系统日期时间 并保存为 jpeg 如果有人能帮助我那就太好了 public class