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

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 {
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)