I am trying to draw text on bitmap but text size differs in different pictures. Text size keeps is too small on some bitmaps and large on some. I have noticed that it is small on big resolution bitmaps. This is how I'm trying to draw. Please tell what I'm doing wrong
val originalBitmap = MediaStore.Images.Media.getBitmap(
context.contentResolver,
uri
)
val bitmap = convertToMutable(
originalBitmap
)
val ratio = originalBitmap.width/bitmap.width
val scale = context.resources.displayMetrics.density
val canvas = Canvas(bitmap)
val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
textPaint.color = Color.WHITE
textPaint.textSize = 7f * scale
textPaint.style = Paint.Style.FILL
val locBound = Rect()
textPaint.getTextBounds(location,0,location.length,locBound)
val txtWidth = (canvas.width - 15)
val txtHeight = textPaint.measureText("yY")
val txtTopX = ((bitmap.width - txtWidth) - 15).toFloat()
val txtTopY = ((bitmap.height - txtHeight) - 20).toFloat()
canvas.drawMultilineText(
location,
textPaint,
txtWidth,
txtTopX,
txtTopY,
0,
location.length,
Layout.Alignment.ALIGN_OPPOSITE
)`
fun Canvas.drawMultilineText(
text: CharSequence,
textPaint: TextPaint,
width: Int,
x: Float,
y: Float,
start: Int = 0,
end: Int = text.length,
alignment: Layout.Alignment = Layout.Alignment.ALIGN_NORMAL,
spacingMult: Float = 1f,
spacingAdd: Float = 0f,
includePad: Boolean = true,
ellipsizedWidth: Int = width,
ellipsize: TextUtils.TruncateAt? = null
) {
val cacheKey = "$text-$start-$end-$textPaint-$width-$alignment-" +
"$spacingMult-$spacingAdd-$includePad-$ellipsizedWidth-$ellipsize"
// The public constructor was deprecated in API level 28,
// but the builder is only available from API level 23 onwards
val staticLayout =
StaticLayoutCache[cacheKey] ?: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
StaticLayout.Builder.obtain(text, start, end, textPaint, width)
.setAlignment(alignment)
.setLineSpacing(spacingAdd, spacingMult)
.setIncludePad(includePad)
.setEllipsizedWidth(ellipsizedWidth)
.setEllipsize(ellipsize)
.build()
} else {
StaticLayout(
text, start, end, textPaint, width, alignment,
spacingMult, spacingAdd, includePad, ellipsize, ellipsizedWidth
)
.apply { StaticLayoutCache[cacheKey] = this }
}
staticLayout.draw(this, x, y)
}
Here is the result I'm getting First Image Second Image Third Image
You can set font size based on your image size. for example your font size can be 0.03 of image size. So in this way your font size on image can be change base on your image size. so you need to do this as bellow:
var imageSize = max(originalBitmap.width, originalBitmap.height)
var fontScale = 0.03
var textSize = imageSize * fontScale
textPaint.textSize = textSize
You must note that image can be landscape or portrait. so we get width or height that is greater as imageSize
. You can change fontScale
according to your needs.
Also, I think there is no need to use scale variable in textSize
computing. because it is a display metric and can be different in various devices, so must not be affected in bitmap text size, and text size must only define based on bitmap image size.