Skip to content

Commit 48b786a

Browse files
feat(*): 添加水印工具类
1 parent 0c8fce1 commit 48b786a

File tree

2 files changed

+222
-0
lines changed

2 files changed

+222
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.pengxh.kt.lite.annotations
2+
3+
@Retention(AnnotationRetention.SOURCE)
4+
annotation class WaterMarkPosition {
5+
companion object {
6+
/**
7+
* 左上
8+
*/
9+
const val LEFT_TOP = 1
10+
11+
/**
12+
* 右上
13+
*/
14+
const val RIGHT_TOP = 2
15+
16+
/**
17+
* 左下
18+
*/
19+
const val LEFT_BOTTOM = 3
20+
21+
/**
22+
* 右下
23+
*/
24+
const val RIGHT_BOTTOM = 4
25+
26+
/**
27+
* 中间
28+
*/
29+
const val CENTER = 0
30+
}
31+
}
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
package com.pengxh.kt.lite.utils
2+
3+
import android.content.Context
4+
import android.graphics.Bitmap
5+
import android.graphics.Canvas
6+
import android.graphics.Color
7+
import android.graphics.Rect
8+
import android.graphics.Typeface
9+
import android.text.TextPaint
10+
import androidx.lifecycle.Lifecycle
11+
import androidx.lifecycle.LifecycleOwner
12+
import androidx.lifecycle.LifecycleRegistry
13+
import androidx.lifecycle.lifecycleScope
14+
import com.pengxh.kt.lite.annotations.WaterMarkPosition
15+
import kotlinx.coroutines.Dispatchers
16+
import kotlinx.coroutines.launch
17+
import kotlinx.coroutines.withContext
18+
import java.io.File
19+
import java.io.FileOutputStream
20+
21+
/**
22+
* 绘制水印
23+
*/
24+
class WaterMarkEngine : LifecycleOwner {
25+
26+
private val registry = LifecycleRegistry(this)
27+
private val textPaint by lazy { TextPaint() }
28+
private val textRect by lazy { Rect() }
29+
30+
private lateinit var context: Context
31+
private lateinit var originalBitmap: Bitmap
32+
private lateinit var marker: String
33+
private var textColor = Color.WHITE
34+
private var textSize = 16f
35+
private var textPadding = 10f
36+
private lateinit var addedListener: OnWaterMarkerAddedListener
37+
private var position = WaterMarkPosition.RIGHT_BOTTOM
38+
private lateinit var fileName: String
39+
40+
/**
41+
* 设置上下文
42+
* */
43+
fun setContext(context: Context): WaterMarkEngine {
44+
this.context = context
45+
return this
46+
}
47+
48+
/**
49+
* 设置原始Bitmap
50+
* */
51+
fun setOriginalBitmap(bitmap: Bitmap): WaterMarkEngine {
52+
this.originalBitmap = bitmap
53+
return this
54+
}
55+
56+
/**
57+
* 设置水印文字
58+
* */
59+
fun setTextMaker(marker: String): WaterMarkEngine {
60+
this.marker = marker
61+
return this
62+
}
63+
64+
/**
65+
* 设置水印文字颜色
66+
* */
67+
fun setTextColor(textColor: Int): WaterMarkEngine {
68+
this.textColor = textColor
69+
return this
70+
}
71+
72+
/**
73+
* 设置水印文字大小
74+
* */
75+
fun setTextSize(textSize: Float): WaterMarkEngine {
76+
this.textSize = textSize
77+
return this
78+
}
79+
80+
/**
81+
* 设置水印文字位置
82+
* */
83+
fun setMarkerPosition(@WaterMarkPosition position: Int): WaterMarkEngine {
84+
this.position = position
85+
return this
86+
}
87+
88+
/**
89+
* 设置水印文字距离Bitmap内边距
90+
* */
91+
fun setTextPadding(textPadding: Float): WaterMarkEngine {
92+
this.textPadding = textPadding
93+
return this
94+
}
95+
96+
/**
97+
* 设置水印图片保存路径
98+
* */
99+
fun setMarkedSavePath(fileName: String): WaterMarkEngine {
100+
this.fileName = fileName
101+
return this
102+
}
103+
104+
/**
105+
* 设置水印图片回调监听
106+
* */
107+
fun setOnWaterMarkerAddedListener(addedListener: OnWaterMarkerAddedListener): WaterMarkEngine {
108+
this.addedListener = addedListener
109+
return this
110+
}
111+
112+
/**
113+
* 开始添加水印
114+
* */
115+
fun start() {
116+
addedListener.onStart()
117+
//初始化画笔
118+
textPaint.color = textColor
119+
textPaint.typeface = Typeface.DEFAULT_BOLD
120+
textPaint.isDither = true // 获取清晰的图像采样
121+
textPaint.isFilterBitmap = true
122+
textPaint.textSize = textSize
123+
textPaint.getTextBounds(marker, 0, marker.length, textRect)
124+
125+
//添加水印
126+
val bitmapConfig = originalBitmap.config
127+
val copyBitmap = originalBitmap.copy(bitmapConfig, true)
128+
lifecycleScope.launch(Dispatchers.IO) {
129+
val canvas = Canvas(copyBitmap)
130+
val bitmapWidth = copyBitmap.width
131+
val bitmapHeight = copyBitmap.height
132+
133+
when (position) {
134+
WaterMarkPosition.LEFT_TOP -> {
135+
canvas.drawText(marker, textPadding, textPadding, textPaint)
136+
}
137+
138+
WaterMarkPosition.RIGHT_TOP -> {
139+
canvas.drawText(
140+
marker, bitmapWidth - textRect.width() - textPadding, textPadding, textPaint
141+
)
142+
}
143+
144+
WaterMarkPosition.LEFT_BOTTOM -> {
145+
canvas.drawText(marker, textPadding, bitmapHeight - textPadding, textPaint)
146+
}
147+
148+
WaterMarkPosition.RIGHT_BOTTOM -> {
149+
canvas.drawText(
150+
marker,
151+
bitmapWidth - textRect.width() - textPadding, bitmapHeight - textPadding,
152+
textPaint
153+
)
154+
}
155+
156+
WaterMarkPosition.CENTER -> {
157+
canvas.drawText(
158+
marker,
159+
(bitmapWidth - textRect.width()) / 2f, bitmapHeight / 2f,
160+
textPaint
161+
)
162+
}
163+
}
164+
165+
//编码照片是耗时操作,需要在子线程或者协程里面
166+
val file = File(fileName)
167+
val fileOutputStream = FileOutputStream(file)
168+
/**
169+
* 第一个参数如果是Bitmap.CompressFormat.PNG,那不管第二个值如何变化,图片大小都不会变化,不支持png图片的压缩
170+
* 第二个参数是压缩比重,图片存储在磁盘上的大小会根据这个值变化。值越小存储在磁盘的图片文件越小
171+
* */
172+
copyBitmap.compress(Bitmap.CompressFormat.JPEG, 75, fileOutputStream)
173+
fileOutputStream.flush()
174+
fileOutputStream.close()
175+
176+
withContext(Dispatchers.Main) {
177+
addedListener.onMarkAdded(file)
178+
}
179+
}
180+
}
181+
182+
override fun getLifecycle(): Lifecycle {
183+
return registry
184+
}
185+
186+
interface OnWaterMarkerAddedListener {
187+
fun onStart()
188+
189+
fun onMarkAdded(file: File)
190+
}
191+
}

0 commit comments

Comments
 (0)