调整拼图内容区域起始位置

This commit is contained in:
2026-03-05 20:57:40 +08:00
parent 84d6a8fea9
commit 6b051846fc

View File

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