fun resize(x: Bitmap, max: Int): Bitmap {
var width = x.width
var height = x.height
val scale: Double = width.toDouble() / height.toDouble()
if (scale > 1) {
width = max
var newHeight = width / scale
height = newHeight.toInt()
} else {
height = max
var newWidth = height * scale
width = newWidth.toInt()
}
return Bitmap.createScaledBitmap(x, width / 2, height / 2, true)
}
This is the code to execute it
val smallBitmap = small(bitmap!!, 300)
val outputStream = ByteArrayOutputStream()
smallBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
val byteArray = outputStream.toByteArray()
I have 2 fragments. And I am picking photo from the gallery and pass it to other fragment. And when I send it the photos come out too pixelated and blurry. It's because of resize and scaling. But I do not know what to do.
Related
I have getting one problem, when i am convert view to bitmap then resize bitmap it's getting low quality of image using scale.
My code is here,
`fun scaleBitmap(bitmap: Bitmap, wantedWidth: Int, wantedHeight: Int): Bitmap? {
val originalWidth = bitmap.width.toFloat()
val originalHeight = bitmap.height.toFloat()
val output =Bitmap.createBitmap(wantedWidth,wantedHeight,Bitmap.Config.ARGB_8888)
val canvas = Canvas(output)
val m = Matrix()
val scalex = wantedWidth / originalWidth
val scaley = wantedHeight / originalHeight
val xTranslation = 0.2f
val yTranslation = (wantedHeight - originalHeight * scaley) / 1.0f
m.postScale(scalex, scaley)
m.postTranslate(xTranslation, yTranslation)
canvas.drawBitmap(bitmap, m, Paint(Paint.FILTER_BITMAP_FLAG))
return output
}`
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.
I am trying to make an extension function to use it in a different class. I am trying to create it but it does not work. Can anyone solve this problem.
Here is my extension:
fun resize.toBitmap(image: Bitmap, maxWidth: Int, maxHeight: Int): Bitmap {
var image = image
return if (maxHeight > 0 && maxWidth > 0) {
val width = image.width
val height = image.height
val ratioBitmap = width.toFloat() / height.toFloat()
val ratioMax = maxWidth.toFloat() / maxHeight.toFloat()
var finalWidth = maxWidth
var finalHeight = maxHeight
if (ratioMax > ratioBitmap) {
finalWidth = (maxHeight.toFloat() * ratioBitmap).toInt()
} else {
finalHeight = (maxWidth.toFloat() / ratioBitmap).toInt()
}
image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true)
image
} else {
image
}
And this is how I try to reach it:
var bitmap = Bitmap.createBitmap(drawingCacheBitmap)
bitmap = resize(bitmap, 200, 100)
Try this
fun Bitmap.resizeImage(image: Bitmap, maxWidth: Int, maxHeight: Int): Bitmap {
val width = image.width
val height = image.height
val scaleWidth = maxWidth.toFloat() / width
val scaleHeight = maxHeight.toFloat() / height
val matrix = Matrix()
matrix.postScale(scaleWidth, scaleHeight)
// Create a New bitmap
val resizedBitmap = Bitmap.createBitmap(
image, 0, 0, width, height, matrix, false)
resizedBitmap.recycle()
return resizedBitmap
}
And call this extension function like this,
bitmap = resizeImage(bitmap, 200, 100)
I made an inline function downsizing bitmap and create another.
private fun Bitmap.limitSizeTo(maxSize: Int): Bitmap {
var width = this.width
var height = this.height
val bitmapRatio = width.toFloat() / height.toFloat()
if (bitmapRatio > 1) {
width = maxSize
height = (width / bitmapRatio).toInt()
} else {
height = maxSize
width = (height * bitmapRatio).toInt()
}
return Bitmap.createScaledBitmap(this, width, height, true)
}
As is:
var resizedBitmap = bitmap.limitSizeTo(100)
doSomething(resizedBitmap)
To be:
bitmap.limitSizeTo(100)
doSomething(bitmap)
What I tried, but not compiling is:
private fun Bitmap.limitSizeTo(maxSize: Int): Bitmap {
var width = this.width
var height = this.height
val bitmapRatio = width.toFloat() / height.toFloat()
if (bitmapRatio > 1) {
width = maxSize
height = (width / bitmapRatio).toInt()
} else {
height = maxSize
width = (height * bitmapRatio).toInt()
}
this = Bitmap.createScaledBitmap(this, width, height, true)
}
I think 'to be' code is more cool, is it?
Anyone know how to do it?
No this not possible and not desirable anyway IMO. You cannot change the receiver of an extension function like this, the best possible way is to simply return a new, edited, immutable instance. Just as you did in the first place:
val resizedBitmap = bitmap.limitSizeTo(100)
doSomething(resizedBitmap)
I am using the zing library for generating the QR code and I have generated the simple QR Code using URL,Text etc. but my question is that how can i generate the QR Code with company logo in middle of Qr Code.
I have found so many answer in stack overflow but non of them can solve my problem.
I already generated for my project (Kotlin answer)
fun CreateQRCode(qrCodeData: String) {
try {
val hintMap = HashMap<EncodeHintType, ErrorCorrectionLevel>()
val width = 250
val height = 250
val smallestDimension = if (width < height) width else height
hintMap[EncodeHintType.ERROR_CORRECTION] = ErrorCorrectionLevel.H
val qrCodeWriter = QRCodeWriter()
val bitMatrix = qrCodeWriter.encode(
qrCodeData,
BarcodeFormat.QR_CODE,
smallestDimension, smallestDimension) // width x height
val pixels = IntArray(smallestDimension * smallestDimension)
// All are 0, or black, by default
for (y in 0 until height) {
val offset = y * smallestDimension
for (x in 0 until smallestDimension) {
//pixels[offset + x] = matrix.get(x, y) ? BLACK : WHITE;
pixels[offset + x] = if (bitMatrix.get(x, y))
ResourcesCompat.getColor(resources, R.color.colorPrimary, null)
else
Color.WHITE
}
}
// var image = DataMatrixWriter.toBufferedImage(bitMatrix)
// Load logo image
// var overly = getOverly(LOGO);
val bitmap = Bitmap.createBitmap(smallestDimension, smallestDimension, Bitmap.Config.ARGB_8888)
bitmap.setPixels(pixels, 0, smallestDimension, 0, 0, smallestDimension, smallestDimension)
//setting bitmap to image view
val options = BitmapFactory.Options()
options.outWidth = 250
options.inJustDecodeBounds = false
options.outHeight = 250
var overlay = BitmapFactory.decodeResource(getResources(), R.mipmap.sugary_qr_icon, options);
overlay = Bitmap.createScaledBitmap(overlay, 50, 50, true)
val merged = mergeBitmaps(overlay, bitmap)
var _params = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)
_params.addRule(Gravity.CENTER_VERTICAL)
// ivQrCode!!.setPadding(180, 180, 180, 180)
ivQrCode!!.layoutParams = _params;
ivQrCode!!.setImageBitmap(merged)
// return bitmap;
} catch (er: Exception) {
if (debug)
er.printStackTrace()
}
}
mergeBitmaps function
private fun mergeBitmaps(overlay: Bitmap, bitmap: Bitmap): Bitmap {
val height = bitmap.height
val width = bitmap.width
val combined = Bitmap.createBitmap(width, height, bitmap.config)
val canvas = Canvas(combined)
val canvasWidth = canvas.width
val canvasHeight = canvas.height
canvas.drawBitmap(bitmap, Matrix(), null)
Log.e("WIDTH", canvasWidth.toString() + " " + overlay.width)
val centreX = (canvasWidth - overlay.width) / 2
val centreY = (canvasHeight - overlay.height) / 2
canvas.drawBitmap(overlay, centreX.toFloat(), centreY.toFloat(), null)
val bmOverlay = Bitmap.createBitmap(overlay.width, overlay.height, overlay.config);
var canvas = Canvas(bmOverlay);
canvas.drawBitmap(overlay, Matrix(), null);
canvas.drawBitmap(bitmap, 0f, 0f, null);
return bmOverlay
}