如何解决如何让新捕获的图像通过单击按钮立即获得水印
所以我有一个关于相机应用的小项目,当我点击Floating Action Button时,它不仅可以保存图像,而且我不能在新图像拍摄后直接添加水印.我想知道如何从 Textviews 制作水印,以应用到我制作的新照片并自动保存它。为此,我使用了 Canvas、Paint 和 Bitmap,但似乎没有一个尝试使其工作。它仅保存在设备内捕获的原始图像。
清单
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"tools:ignore="ScopedStorage"/>
Gradle 实现
implementation 'androidx.camera:camera-camera2:1.1.0-alpha01'
implementation 'androidx.camera:camera-lifecycle:1.1.0-alpha01'
implementation 'androidx.camera:camera-view:1.0.0-alpha21'
main_activity.xml
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<androidx.camera.view.PreviewView
android:id="@+id/previewView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="150dp"
android:layout_height="100dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.022"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.025">
<TextView
android:id="@+id/testText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/test_view"
android:textColor="#E91E63" />
</LinearLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/camera_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:importantForAccessibility="no"
app:backgroundTint="#B8AEAE"
app:borderWidth="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
package com.example.bitmapwatermark
import android.Manifest
import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Color.RED
import android.graphics.Paint
import android.graphics.Path
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.google.android.material.floatingactionbutton.FloatingActionButton
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
class MainActivity : AppCompatActivity() {
/**watermark private variables**/
private var paint = Paint()
private val config = Bitmap.Config.ARGB_8888
private val width = 1
private val height = 1
private var bitmap = Bitmap.createBitmap(width,height,config)
/**Camera variables**/
private var imageCapture: ImageCapture? = null
private lateinit var cameraExecutor: ExecutorService
private lateinit var outputDirectory: File
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
/**Checking for all permissions to be granted through method,* if so it will start the camera,if not checks for a request with permissions and request code**/
if (allPermissionsGranted()) {
startCamera()
} else {
ActivityCompat.requestPermissions(this,REQUIRED_PERMISSIONS,REQUEST_CODE_PERMISSIONS)
}
// Making a variable,connecting to the button and setting up a listener to initiate taking a photo through a method
val imageCaptureBtn = findViewById<FloatingActionButton>(R.id.camera_button)
imageCaptureBtn.setOnClickListener {
takePhoto().apply {
drawBitmap(bitmap,left = 5f,top = 5f,paint)
}
}
// Connecting the late init variable with a new method to get output directory
outputDirectory = getOutputDirectory()
cameraExecutor = Executors.newSingleThreadExecutor()
}
private fun getOutputDirectory(): File {
val mediaDir = externalMediaDirs.firstOrNull().let {
File(it,"BitmapWatermark").apply { mkdirs() } }
return if (mediaDir.exists())
mediaDir else filesDir
}
private fun takePhoto() {
val photoFile = File(outputDirectory,SimpleDateFormat(FILENAME_FORMAT,Locale.ENGLISH).format(System.currentTimeMillis()) + ".jpg")
val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
imageCapture?.takePicture(
outputOptions,ContextCompat.getMainExecutor(this),object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
val saveUri = Uri.fromFile(photoFile).apply { drawBitmap(bitmap,paint) }
val msg = "Photo capture succeeded: $saveUri"
Toast.makeText(baseContext,msg,Toast.LENGTH_SHORT).show()
Log.d(TAG,msg)
}
override fun onError(exception: ImageCaptureException) {
Toast.makeText(baseContext,"Photo capture failed: ${exception.message}",Toast.LENGTH_SHORT).show()
photoFile.delete()
}
}
)
}
private fun startCamera() {
val viewFinder = findViewById<PreviewView>(R.id.previewView)
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
// Used to bind the lifecycle of cameras to the lifecycle owner
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// Preview
val preview = Preview.Builder()
.build()
.also {
it.setSurfaceProvider(viewFinder.surfaceProvider)
}
imageCapture = ImageCapture.Builder()
.build()
// Select back camera as a default
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
// Unbind use cases before rebinding
cameraProvider.unbindAll()
// Bind use cases to camera
cameraProvider.bindToLifecycle(
this,cameraSelector,preview,imageCapture)
} catch (exc: Exception) {
Log.e(TAG,"Use case binding failed",exc)
}
},ContextCompat.getMainExecutor(this))
}
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(
baseContext,it) == PackageManager.PERMISSION_GRANTED
}
@SuppressLint("SetTextI18n")
fun drawBitmap(bitmap: Bitmap,left: Float,top: Float,paint: Paint?) {
val textText = findViewById<TextView>(R.id.testText)
val paintText = Paint()
paintText.textAlign
paintText.textSize = 14F
paintText.color = RED
paintText.getTextPath(textText.toString(),1,10,12f,path)
}
companion object {
private const val TAG = "CadIS for Android"
private const val FILENAME_FORMAT = "dd.MM.yyyy-HH:mm:ss"
private const val REQUEST_CODE_PERMISSIONS = 10
private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
private var path: Path = Path() // this gets us the new image
}
}
如果有人知道为什么它没有将 TextView 中的水印放置在与主 xml 文件相同的位置的问题,请告诉我放置的位置和操作。提前致谢。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。