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