循环裁剪一张图片,保存到安卓的文件中
原文:https://www . geeksforgeeks . org/circular-crop-a-image-and-save-to-file-in-Android/
市场上有多种应用程序可以帮助处理图像处理,但大多数应用程序都无法产生非常基本的操作。裁剪是一个简单的应用程序,可以通过裁剪来调整图像的大小。当涉及到自由手动或形状裁剪时,这一任务变得复杂,这意味着将图像裁剪成所需的形状。
在本文中,我们将向您展示如何创建一个应用程序,以循环方式裁剪图像并将其存储在本地设备中。没有外部库或服务用于生成此应用程序。
逐步实施
第一步:在安卓工作室新建项目
要在安卓工作室创建新项目,请参考如何在安卓工作室创建/启动新项目。我们在 Kotlin 中演示了该应用程序,因此在创建新项目时,请确保选择 Kotlin 作为主要语言。
第二步:在 activity_main.xml 或布局文件中添加一个 ImageView 和两个 Buttons
可扩展标记语言
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- Image will be loaded here -->
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="500dp"
android:layout_centerInParent="true" />
<!-- Button to perform Cropping -->
<Button
android:id="@+id/btnCrop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="Crop" />
<!-- Button to save the image in ImageView -->
<Button
android:id="@+id/btnSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="Save" />
</RelativeLayout>
步骤 3:在 res >可绘制文件夹中添加所需图像
添加时,为其指定所需的名称。作为参考,这张图片是“image.png”,它是从互联网上下载的,并直接复制到可绘制的文件夹中。
第四步:为 MainActivity.kt 编写以下代码
这段代码中有两个函数:
- 获取圆形位图(位图) :裁剪图像
- 保存 MediaToStorage(位图) :保存图像。参考如何在安卓系统中抓取视图截图并保存到图库?
请参考评论,以便更好地理解。
我的锅
import android.content.ContentValues
import android.graphics.*
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.provider.MediaStore
import android.widget.Button
import android.widget.ImageView
import android.widget.Toast
import androidx.annotation.RequiresApi
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStream
import java.lang.Integer.min
class MainActivity : AppCompatActivity() {
// Declaring the UI elements from the layout file
private lateinit var buttonCrop: Button
private lateinit var buttonSave: Button
private lateinit var imageView: ImageView
// Declaring the Bitmap
private lateinit var bitmap: Bitmap
@RequiresApi(Build.VERSION_CODES.N)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Initializing the UI elements
imageView = findViewById(R.id.iv)
buttonCrop = findViewById(R.id.btnCrop)
buttonSave = findViewById(R.id.btnSave)
// Declaring resource address ( type integer)
val bitmapResourceID: Int = R.drawable.image
// Setting the ImageView with the Image
imageView.setImageBitmap(BitmapFactory.decodeResource(resources, bitmapResourceID))
bitmap = BitmapFactory.decodeResource(resources, bitmapResourceID)
// When Crop button is clicked
buttonCrop.setOnClickListener {
// runs a custom function on the original image
bitmap = getCircularBitmap(bitmap)
// Sets the ImageView with the editted/cropped Image
imageView.setImageBitmap(bitmap)
}
// When Save button is clicked
buttonSave.setOnClickListener {
// Save whatever the bitmap is (edited/uneditted) into the device.
saveMediaToStorage(bitmap)
}
}
// Function to crop the image in a circle
@RequiresApi(Build.VERSION_CODES.N)
private fun getCircularBitmap(srcBitmap: Bitmap?): Bitmap {
// Select whichever of width or height is minimum
val squareBitmapWidth = min(srcBitmap!!.width, srcBitmap.height)
// Generate a bitmap with the above value as dimensions
val dstBitmap = Bitmap.createBitmap(
squareBitmapWidth,
squareBitmapWidth,
Bitmap.Config.ARGB_8888
)
// Initializing a Canvas with the above generated bitmap
val canvas = Canvas(dstBitmap)
// initializing Paint
val paint = Paint()
paint.isAntiAlias = true
// Generate a square (rectangle with all sides same)
val rect = Rect(0, 0, squareBitmapWidth, squareBitmapWidth)
val rectF = RectF(rect)
// Operations to draw a circle
canvas.drawOval(rectF, paint)
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
val left = ((squareBitmapWidth - srcBitmap.width) / 2).toFloat()
val top = ((squareBitmapWidth - srcBitmap.height) / 2).toFloat()
canvas.drawBitmap(srcBitmap, left, top, paint)
srcBitmap.recycle()
// Return the bitmap
return dstBitmap
}
// Function to save an Image
private fun saveMediaToStorage(bitmap: Bitmap) {
val filename = "${System.currentTimeMillis()}.jpg"
var fos: OutputStream? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
this.contentResolver?.also { resolver ->
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
}
val imageUri: Uri? = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
fos = imageUri?.let { resolver.openOutputStream(it) }
}
} else {
val imagesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
val image = File(imagesDir, filename)
fos = FileOutputStream(image)
}
fos?.use {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, it)
Toast.makeText(this , "Captured View and saved to Gallery" , Toast.LENGTH_SHORT).show()
}
}
}
第四步:在 AndroidManifest.xml 文件中添加存储权限
在设备中存储图像需要此权限。
可扩展标记语言
<manifest....">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application....>
</application>
</manifest>
输出: