【问题标题】:How to bind any image with the captured Camera image before saving it? [duplicate]如何在保存之前将任何图像与捕获的相机图像绑定? [复制]
【发布时间】:2025-11-23 22:35:02
【问题描述】:

可能重复:
Android: How to overlay-a-bitmap/draw-over a bitmap?

我已经在 amy 应用程序中实现了 android Camera 功能。

现在我想将任何透明图像与捕获的相机图像结合起来,然后将该图像保存到图库中,那么如何完成呢??

任何代码都会被真正欣赏。 谢谢。

编辑: 我正在使用此代码来捕获和保存图像所以,我应该如何实现这些东西。

takePhotoBtn.setOnClickListener(new OnClickListener() {
        public void onClick(View v) { // <5>

            ImageCaptureCallback iccb = null;

            try {
                String filename = timeStampFormat.format(new Date());
                ContentValues values = new ContentValues();
                values.put(Media.TITLE, filename);
                values.put(Media.DESCRIPTION, "Image capture by camera");
                Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);

                iccb = new ImageCaptureCallback( getContentResolver().openOutputStream(uri));

                // to put the Image on captured image.
                Canvas canvas = new Canvas();
                Bitmap kangoo = BitmapFactory.decodeResource(getResources(),
                        R.drawable.icon);
                canvas.drawColor(Color.argb(160, 21, 140, 21));
                canvas.drawBitmap(kangoo, 130, 10, null);


            } catch(Exception ex ){
                ex.printStackTrace();
                Log.e(getClass().getSimpleName(), ex.getMessage(), ex);
            }
          camera.takePicture(mShutterCallback, mPictureCallbackRaw, iccb);
        }
      });


Camera.PictureCallback mPictureCallbackRaw = new Camera.PictureCallback() {
    public void onPictureTaken(byte[] data, Camera c) {
        Log.e(getClass().getSimpleName(), "PICTURE CALLBACK RAW: " + data);
            System.out.println("\n\n\n\nThe Data in mPictureCallbackRaw is :"+data);
        //camera.startPreview(); // Added StastPreview();
    }
};

Camera.PictureCallback mPictureCallbackJpeg= new Camera.PictureCallback() {
    public void onPictureTaken(byte[] data, Camera c) {
        Log.e(getClass().getSimpleName(), "PICTURE CALLBACK JPEG: data.length = " + data);
        System.out.println("\n\n\n\nThe Data in mPictureCallbackJPEG is :"+data);
        camera.startPreview();
    }
};

Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback() {
    public void onShutter() {
        Log.e(getClass().getSimpleName(), "SHUTTER CALLBACK");
    }
};




public class ImageCaptureCallback implements PictureCallback  {

private OutputStream filoutputStream;
public ImageCaptureCallback(OutputStream filoutputStream) {
    this.filoutputStream = filoutputStream;
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
    try {
        Log.v(getClass().getSimpleName(), "onPictureTaken=" + data + " length = " + data.length);

        filoutputStream.write(data);
        filoutputStream.flush();
        filoutputStream.close();


    } catch(Exception ex) {
        ex.printStackTrace();
    }
}

}

【问题讨论】:

  • 我想我可以使用画布,但我不知道那是怎么回事。可能很容易,但我真的需要帮助来实现它。
  • 您可以使用画布组合两个位图图像。

标签: android android-layout android-emulator android-widget


【解决方案1】:

尝试将相机图像和透明图像这两个位图组合起来。这是图像的组合并存储在 SDCard 中。

public Bitmap combineImages(Bitmap c, Bitmap s) {

        Bitmap cs = null;
        int width, height = 0;

        if (c.getWidth() > s.getWidth()) {
            width = c.getWidth();
            height = c.getHeight();
        } else {
            width = s.getWidth() + s.getWidth();
            height = c.getHeight();
        }

        cs = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

        Canvas comboImage = new Canvas(cs);

        comboImage.drawBitmap(c, 0, 0, null);
        comboImage.drawBitmap(s, 100, 300, null);

        /******
         * 
         *   Write file to SDCard
         * 
         * ****/

        String tmpImg = String.valueOf(System.currentTimeMillis()) + ".png";
        OutputStream os = null;
        try {
            os = new FileOutputStream(Environment.getExternalStorageDirectory()
                    + "/"+tmpImg);
            cs.compress(CompressFormat.PNG, 100, os);
        } catch (IOException e) {
            Log.e("combineImages", "problem combining images", e);
        }
        return cs;
    }

【讨论】:

    【解决方案2】:

    Android 实现了多种图像合成算法。这是使用它们的简单方法。我在这台计算机上没有 Eclipse,因此以下代码未经测试(但应该可以工作或至少接近工作)。

    img1 和 img2 都是位图,其中一张是您从相机拍摄的。

    1) 创建一个新的空位图。我假设 img1 和 img2 的大小相同。如果没有,您可以调整它们的大小或使这个新位图的大小与最大的位图相同。

    Bitmap compositeImage = Bitmap.createBitmap(img1.getWidth(),
      img1.getWidth(), img1.getContig());
    

    2) 创建用于在位图上绘图的画布

    Canvas canvas = new Canvas(compositeImage);
    

    3) 将第一个图像绘制到新位图上

    Paint paint = new Paint();
    canvas.drawBitmap(img1, 0.0f, 0.0f, paint);
    

    4) Android 在 SDK 中有一套合成算法。这些方法以 Porter 和 Duff 命名,他们撰写了一篇描述合成图像算法的论文。 Android 将此设置称为“传输模式”。要查看可用的 Porter-Duff 传输模式,请访问 http://developer.android.com/reference/android/graphics/PorterDuff.Mode.html 或谷歌搜索。根据您的需要,我建议您查看 Multiply、Darken 和 Lighten。

    paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.MULTIPLY));
    

    5) 既然已经设置了传输模式,只需绘制第二张图像即可获得你想要的效果

    canvas.drawBitmap(img2, 0.0f, 0.0f, paint);
    

    现在,compositeImage 位图包含组合图像。

    编辑。好的,这是放在一起的代码,也许你可以把它放在你的 PictureCallback 中(jpeg 的,而不是原始的)。同样,它未经测试,但应该是好的或接近好的:

    public void onPictureTaken(byte[] data, Camera camera) {
      Bitmap img1 = BitmapFactory.decodeResource(getResources(), 
        R.drawable.icon); // assuming you really want to use the icon
      Bitmap img2 = BitmapFactory.decodeByteArray(data, 0, data.length);
      Bitmap composite = Bitmap.createBitmap(img2.getWidth(), img2.getHeight(), 
        img2.getConfig());
      Canvas canvas = new Canvas(composite);
      Paint paint = new Paint();
      canvas.drawBitmap(img2, 0.0f, 0.0f, paint);
      paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.MULTIPLY));
      canvas.drawBitmap(img1, 0.0f, 0.0f, paint);
    
      // It seems you want to insert the new image into the gallery
      ContentValues values = ...
      try {
        Uri imageFileUri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
        composite.compress(Bitmap.CompressFormat.JPEG, 90, 
          getContentResolver().openOutputStream(imageFileUri));
      } catch(Exception) {
        ...
      }
    }
    

    【讨论】:

    • 请查看我的更新问题,然后告诉我应该怎么做才能实现它。
    • 实际上我的保存图像不是位图格式。所以我不知道该怎么做。
    • 我也想做一些像你这样的代码。我想用略透明的绿色布局保存图像。
    • "takePicture" 中的第三个参数注册一个 PictureCallback,它总是在图像被捕获并压缩为 jpg 格式后被调用。您可以使用 BitmapFactory 将其转换为位图。您可以在此 PictureCallback 中合成两个图像。