如何编写一个在手机上自定义水印的拍照相机
时间: 2023-05-29 12:03:05 浏览: 91
步骤:
1. 创建一个新的 Android 项目,并命名为“CustomCamera”。
2. 在项目的 build.gradle 文件中添加以下依赖项:
```
dependencies {
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation 'com.android.support:cardview-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:support-annotations:28.0.0'
implementation 'com.squareup.picasso:picasso:2.5.2'
}
```
3. 在 AndroidManifest.xml 文件中添加以下权限:
```
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
```
4. 创建一个新的自定义相机类 CustomCameraView,继承 SurfaceView,并实现 SurfaceHolder.Callback 接口。
```java
public class CustomCameraView extends SurfaceView implements SurfaceHolder.Callback {
private Camera camera;
private SurfaceHolder holder;
public CustomCameraView(Context context) {
super(context);
holder = getHolder();
holder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = getBestPreviewSize(width, height, parameters);
parameters.setPreviewSize(size.width, size.height);
camera.setParameters(parameters);
camera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
}
private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {
Camera.Size result = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width <= width && size.height <= height) {
if (result == null) {
result = size;
} else {
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea) {
result = size;
}
}
}
}
return result;
}
}
```
5. 在 activity_main.xml 文件中添加以下代码:
```xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/bottom_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:padding="8dp">
<ImageView
android:id="@+id/image_view_watermark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:src="@drawable/ic_launcher_background" />
<Button
android:id="@+id/button_capture"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Capture" />
<Button
android:id="@+id/button_gallery"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Gallery" />
</LinearLayout>
</RelativeLayout>
```
6. 在 MainActivity.java 文件中添加以下代码:
```java
public class MainActivity extends AppCompatActivity {
private CustomCameraView customCameraView;
private ImageView imageViewWatermark;
private Button buttonCapture, buttonGallery;
private Bitmap bitmapWatermark;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
customCameraView = new CustomCameraView(this);
FrameLayout frameLayout = findViewById(R.id.frame_layout);
frameLayout.addView(customCameraView);
imageViewWatermark = findViewById(R.id.image_view_watermark);
bitmapWatermark = BitmapFactory.decodeResource(getResources(), R.drawable.watermark);
imageViewWatermark.setImageBitmap(bitmapWatermark);
buttonCapture = findViewById(R.id.button_capture);
buttonCapture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
customCameraView.takePicture(new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, imageViewWatermark.getWidth(), imageViewWatermark.getHeight(), false);
Bitmap resultBitmap = addWatermark(scaledBitmap, bitmapWatermark);
saveImage(resultBitmap);
}
});
}
});
buttonGallery = findViewById(R.id.button_gallery);
buttonGallery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 1);
}
});
}
private Bitmap addWatermark(Bitmap source, Bitmap watermark) {
Bitmap result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(source, 0, 0, null);
canvas.drawBitmap(watermark, 0, 0, null);
return result;
}
private void saveImage(Bitmap bitmap) {
String filename = "CustomCamera_" + System.currentTimeMillis() + ".jpg";
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), filename);
try {
FileOutputStream fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.close();
Toast.makeText(this, "Image saved to " + file.getAbsolutePath(), Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1 && resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
Picasso.get().load(uri).into(imageViewWatermark);
try {
InputStream inputStream = getContentResolver().openInputStream(uri);
bitmapWatermark = BitmapFactory.decodeStream(inputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
super.onActivityResult(requestCode, resultCode, data);
}
}
```
7. 编译并运行应用程序,在拍照时会显示一个水印图像,可以从相册中选择一个新的水印图像。当用户点击拍照按钮时,将拍摄的照片与水印合并,并将其保存到外部存储器的图片目录中。