调整拼图内容区域起始位置
This commit is contained in:
@@ -30,7 +30,7 @@ import java.util.Locale
|
||||
*/
|
||||
object ImageProcessor {
|
||||
|
||||
private val dateFormat = SimpleDateFormat("yyyy年-MM月-dd日 HH:mm:ss", Locale.getDefault())
|
||||
private val dateFormat = SimpleDateFormat("yyyy年M月d日 HH:mm:ss", Locale.getDefault())
|
||||
private val fileNameFormat = SimpleDateFormat("yyyyMMddHHmm", Locale.getDefault())
|
||||
|
||||
/**
|
||||
@@ -92,6 +92,7 @@ object ImageProcessor {
|
||||
|
||||
/**
|
||||
* 添加水印到图片
|
||||
* 右下角半透明白色文字,带黑色描边/阴影,高质感摄影风格
|
||||
*/
|
||||
fun addWatermark(
|
||||
sourceBitmap: Bitmap,
|
||||
@@ -99,51 +100,54 @@ object ImageProcessor {
|
||||
locationText: String,
|
||||
style: WatermarkStyle
|
||||
): Bitmap {
|
||||
android.util.Log.d("ImageProcessor", "addWatermark called, timeText=$timeText, locationText=$locationText")
|
||||
|
||||
val result = sourceBitmap.copy(Bitmap.Config.ARGB_8888, true)
|
||||
val canvas = Canvas(result)
|
||||
|
||||
// 使用固定的字体大小,基于图片宽度比例
|
||||
val baseFontSize = result.width / 40f // 字体大小为图片宽度的1/40
|
||||
val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||
textSize = baseFontSize
|
||||
color = style.textColor.toArgb()
|
||||
typeface = Typeface.DEFAULT_BOLD
|
||||
textAlign = Paint.Align.CENTER
|
||||
}
|
||||
|
||||
val watermarkText = "$timeText $locationText"
|
||||
val textWidth = paint.measureText(watermarkText)
|
||||
val textHeight = paint.fontMetrics.let { it.descent - it.ascent }
|
||||
// 字体大小:图片宽度的1/40,现代简洁字体
|
||||
val baseFontSize = result.width / 40f
|
||||
val lineHeight = baseFontSize * 1.3f
|
||||
|
||||
android.util.Log.d("ImageProcessor", "Watermark: width=$textWidth, height=$textHeight, text=$watermarkText")
|
||||
|
||||
// 计算位置(底部中央)
|
||||
val padding = result.width / 30f // 边距为图片宽度的1/30
|
||||
val x = result.width / 2f
|
||||
// 位置:右下角
|
||||
val padding = result.width / 30f
|
||||
val x = result.width - padding
|
||||
val y = result.height - padding
|
||||
|
||||
// 绘制背景
|
||||
val bgColorInt = style.backgroundColor.toArgb()
|
||||
android.util.Log.d("ImageProcessor", "Background color int: $bgColorInt")
|
||||
if (bgColorInt != 0) {
|
||||
val bgPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||
color = bgColorInt
|
||||
// 绘制水印文字 - 先绘制阴影/描边,再绘制主文字
|
||||
fun drawTextWithShadow(text: String, textY: Float) {
|
||||
// 绘制阴影(向右下偏移)
|
||||
val shadowPaint = android.graphics.Paint().apply {
|
||||
isAntiAlias = true
|
||||
textSize = baseFontSize
|
||||
color = android.graphics.Color.argb(120, 0, 0, 0)
|
||||
typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL)
|
||||
textAlign = android.graphics.Paint.Align.RIGHT
|
||||
}
|
||||
val bgRect = RectF(
|
||||
x - textWidth / 2 - padding / 2,
|
||||
y - textHeight - padding / 2,
|
||||
x + textWidth / 2 + padding / 2,
|
||||
y + padding / 2
|
||||
)
|
||||
canvas.drawRoundRect(bgRect, 8f, 8f, bgPaint)
|
||||
android.util.Log.d("ImageProcessor", "Background drawn at x=$x, y=$y")
|
||||
canvas.drawText(text, x + 1.5f, textY + 1.5f, shadowPaint)
|
||||
|
||||
// 绘制主文字 - 半透明白色
|
||||
val textPaint = android.graphics.Paint().apply {
|
||||
isAntiAlias = true
|
||||
textSize = baseFontSize
|
||||
color = android.graphics.Color.argb(230, 255, 255, 255)
|
||||
typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL)
|
||||
textAlign = android.graphics.Paint.Align.RIGHT
|
||||
}
|
||||
canvas.drawText(text, x, textY, textPaint)
|
||||
}
|
||||
|
||||
// 绘制文字
|
||||
canvas.drawText(watermarkText, x, y, paint)
|
||||
android.util.Log.d("ImageProcessor", "Text drawn at x=$x, y=$y")
|
||||
// 绘制水印
|
||||
if (timeText.isNotBlank()) {
|
||||
// 时间行
|
||||
drawTextWithShadow(timeText, y)
|
||||
|
||||
// 位置行(在时间上方)
|
||||
if (locationText.isNotBlank()) {
|
||||
drawTextWithShadow(locationText, y - lineHeight - 8)
|
||||
}
|
||||
} else if (locationText.isNotBlank()) {
|
||||
// 只有位置信息
|
||||
drawTextWithShadow(locationText, y)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -169,8 +173,9 @@ object ImageProcessor {
|
||||
val rows = layoutType.rows
|
||||
|
||||
val outputWidth = 1920
|
||||
val cellWidth = outputWidth / cols
|
||||
val cellHeight = outputWidth / cols // 保持正方形格子
|
||||
val cellSpacing = 16 // 单元格间距 16px (约 4dp * 4)
|
||||
val cellWidth = (outputWidth - cellSpacing * (cols + 1)) / cols
|
||||
val cellHeight = cellWidth // 保持正方形格子
|
||||
|
||||
// 底部文字区域高度
|
||||
val textAreaHeight = if (title.isNotBlank() || content.isNotBlank()) {
|
||||
@@ -180,7 +185,7 @@ object ImageProcessor {
|
||||
}
|
||||
|
||||
// 图片区域高度
|
||||
val imageAreaHeight = cellHeight * rows
|
||||
val imageAreaHeight = cellHeight * rows + cellSpacing * (rows + 1)
|
||||
|
||||
val outputHeight = imageAreaHeight + textAreaHeight
|
||||
|
||||
@@ -197,8 +202,8 @@ object ImageProcessor {
|
||||
val col = index % cols
|
||||
val row = index / cols
|
||||
|
||||
val left = col * cellWidth
|
||||
val top = row * cellHeight
|
||||
val left = cellSpacing + col * (cellWidth + cellSpacing)
|
||||
val top = cellSpacing + row * (cellHeight + cellSpacing)
|
||||
|
||||
try {
|
||||
val sourceBitmap = tryLoadBitmap(context, imageItem)
|
||||
@@ -228,85 +233,53 @@ object ImageProcessor {
|
||||
if (textAreaHeight > 0) {
|
||||
val textTop = imageAreaHeight
|
||||
|
||||
// 绘制白色背景
|
||||
// 绘制统一的深灰色背景
|
||||
val bgColor = android.graphics.Color.argb(255, 60, 60, 60) // 深灰色
|
||||
canvas.drawRect(
|
||||
0f, textTop.toFloat(),
|
||||
outputWidth.toFloat(), outputHeight.toFloat(),
|
||||
Paint().apply { color = Color.WHITE }
|
||||
Paint().apply { color = bgColor }
|
||||
)
|
||||
|
||||
// 绘制分割线
|
||||
canvas.drawLine(
|
||||
0f, textTop.toFloat(),
|
||||
outputWidth.toFloat(), textTop.toFloat(),
|
||||
Paint().apply {
|
||||
color = Color.LTGRAY
|
||||
strokeWidth = 2f
|
||||
}
|
||||
)
|
||||
val padding = 30f
|
||||
val titleHeight: Float
|
||||
|
||||
// 绘制标题
|
||||
// 绘制标题 - 粗体白色居中
|
||||
if (title.isNotBlank()) {
|
||||
val titlePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||
textSize = titleStyle.fontSize * 2f // 放大标题
|
||||
color = titleStyle.textColor.toArgb()
|
||||
typeface = Typeface.DEFAULT_BOLD
|
||||
textAlign = Paint.Align.CENTER
|
||||
textSize = outputWidth / 25f
|
||||
color = android.graphics.Color.WHITE
|
||||
typeface = Typeface.create("sans-serif", Typeface.BOLD) // 粗体无衬线
|
||||
textAlign = android.graphics.Paint.Align.CENTER
|
||||
}
|
||||
|
||||
// 标题背景
|
||||
val titleBgPaint = Paint().apply {
|
||||
color = titleStyle.backgroundColor.toArgb()
|
||||
}
|
||||
val titleWidth = titlePaint.measureText(title)
|
||||
val titleHeight = titlePaint.fontMetrics.let { it.descent - it.ascent }
|
||||
val titleBgRect = RectF(
|
||||
(outputWidth - titleWidth) / 2 - 20,
|
||||
textTop + 20f,
|
||||
(outputWidth + titleWidth) / 2 + 20,
|
||||
textTop + 20f + titleHeight + 20
|
||||
)
|
||||
canvas.drawRoundRect(titleBgRect, 8f, 8f, titleBgPaint)
|
||||
|
||||
// 标题文字
|
||||
canvas.drawText(title, outputWidth / 2f, textTop + 20f + titleHeight, titlePaint)
|
||||
titleHeight = titlePaint.fontMetrics.let { it.descent - it.ascent }
|
||||
canvas.drawText(title, outputWidth / 2f, textTop + padding + titleHeight, titlePaint)
|
||||
} else {
|
||||
titleHeight = 0f
|
||||
}
|
||||
|
||||
// 绘制内容
|
||||
// 绘制内容 - 细体白色靠左
|
||||
if (content.isNotBlank()) {
|
||||
val contentPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||
textSize = contentStyle.fontSize * 1.5f // 放大内容
|
||||
color = contentStyle.textColor.toArgb()
|
||||
typeface = Typeface.DEFAULT
|
||||
textSize = outputWidth / 35f
|
||||
color = android.graphics.Color.WHITE
|
||||
typeface = Typeface.create("sans-serif", Typeface.NORMAL) // 细体
|
||||
textAlign = android.graphics.Paint.Align.LEFT
|
||||
}
|
||||
|
||||
val padding = 40f
|
||||
val contentMaxWidth = outputWidth - padding * 2
|
||||
val contentLines = wrapText(content, contentPaint, contentMaxWidth)
|
||||
val lineHeight = contentPaint.fontMetrics.let { it.descent - it.ascent }
|
||||
|
||||
// 内容背景
|
||||
val contentBgPaint = Paint().apply {
|
||||
color = contentStyle.backgroundColor.toArgb()
|
||||
}
|
||||
|
||||
// 从标题下方开始绘制内容
|
||||
// 内容起始Y坐标 - 标题下方再往下移一行
|
||||
val contentStartY = if (title.isNotBlank()) {
|
||||
textTop + 80f + lineHeight
|
||||
textTop + padding + titleHeight + lineHeight + 20
|
||||
} else {
|
||||
textTop + 20f + lineHeight
|
||||
textTop + padding + lineHeight * 2
|
||||
}
|
||||
|
||||
val totalContentHeight = contentLines.size * lineHeight + 20
|
||||
val contentBgRect = RectF(
|
||||
padding - 10,
|
||||
contentStartY - lineHeight - 10,
|
||||
outputWidth - padding + 10,
|
||||
contentStartY + totalContentHeight
|
||||
)
|
||||
canvas.drawRoundRect(contentBgRect, 8f, 8f, contentBgPaint)
|
||||
|
||||
// 内容文字
|
||||
// 内容文字(靠左)
|
||||
var y = contentStartY
|
||||
contentLines.forEach { line ->
|
||||
canvas.drawText(line, padding, y, contentPaint)
|
||||
|
||||
Reference in New Issue
Block a user