I was doing the simple feature that I am taking the photo with Camerax and uploading the photo to Imagga to do the face detection by using this API, and here is the API result [Face(confidence=100.0, coordinates=Coordinates(height=1243, width=1243, xmax=2660, xmin=1417, ymax=3359, ymin=2116), face_id=)]
And base on the API document, the Coordinates are parameters that I needed to input to drawRect(xmin, ymin, xmax, ymax, paint), but the rectangle is always in the wrong position on the screen.
I've tried total 64 combinations of those four points but non is correct.
What have I done wrong? here's my code
take and upload photo to Imagga:
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
Log.e(TAG, "onImageSaved: " + output.savedUri)
savedUri = output.savedUri
val file = File(getPath(savedUri, applicationContext) ?: "")
val mFile = RequestBody.create(MediaType.parse("image/*"), file)
val fileToUpload = MultipartBody.Part.createFormData("image", file.name, mFile)
photoJob?.cancel()
photoJob = lifecycleScope.launch {
binding.isLoading = true
mainViewMode.startFaceDetection(fileToUpload)
}
}
fun getPath(contentUri: Uri?, context: Context): String? {
var res: String? = null
val proj = arrayOf(MediaStore.Images.Media.DATA)
val cursor: Cursor = context.contentResolver.query(contentUri!!, proj, null, null, null)!!
if (cursor.moveToFirst()) {
val index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
res = cursor.getString(index)
}
cursor.close()
return res
}
receive face detection results from Imagga:
mainViewMode.apply {
faceResult.observe(this#MainActivity) {
showDetectionResult(it, savedUri)
}
}
private fun showDetectionResult(it: FaceDetectionResp, savedUri: Uri?) {
Log.e(TAG, "startFaceDetection: ${it.result.faces}")
val originBitmap = MediaStore.Images.Media.getBitmap(contentResolver, savedUri)
val bmp = originBitmap!!.copy(originBitmap.config, true)
val canvas = Canvas(bmp)
val paint = Paint().apply {
color = Color.GREEN
style = Paint.Style.STROKE
strokeWidth = 5f
}
val left = it.result.faces[0].coordinates.xmin.toFloat()
val top = it.result.faces[0].coordinates.ymin.toFloat()
val right = it.result.faces[0].coordinates.xmax.toFloat()
val bottom = it.result.faces[0].coordinates.ymax.toFloat()
// it did draw the rectangle but never in the right position that I expected
canvas.drawRect(left, top, right, bottom, paint)
//because I got landscape photo, so I rotate the bitmap to portrait
binding.ivFace.setImageBitmap(rotateImage(bmp, -90f))
}
fun rotateImage(source: Bitmap, angle: Float): Bitmap? {
val matrix = Matrix()
matrix.postRotate(angle)
return Bitmap.createBitmap(
source, 0, 0, source.width, source.height,
matrix, true
)
}
I've been stuck in this for a week, can anyone help me?
Related
Heyho,
I'm quiet new to Kotlin, but I came across this problem:
I have a library function, that generates an image(QR-Code). Now I'd like to display that image... But I've no idea how. The documentation only explains how to save the image locally. But I'm not really interested in saving it. So I can either get the image as a FileStream or as a ByteArray. Any possibility to display any of these as an Image in the UI?
An Example:
#Composable
fun QrCode(stand: String) {
Text(text = "QR-Code:", fontSize = 16.sp)
//? Image(QRCode(stand).render().getBytes()) // this obviously won't work
}
Any ideas?
In order to display an Image, you can refer this.
#Composable
fun BitmapImage(bitmap: Bitmap) {
Image(
bitmap = bitmap.asImageBitmap(),
contentDescription = "some useful description",
)
}
So the remaining is to find a way to convert your target input into a Bitmap.
If you have ByteArray of the image file, you can refer to this.
fun convertImageByteArrayToBitmap(imageData: ByteArray): Bitmap {
return BitmapFactory.decodeByteArray(imageData, 0, imageData.size)
}
If you just possess the QR String, you can refer this to convert QR String to a Bitmap.
fun encodeAsBitmap(source: String, width: Int, height: Int): Bitmap? {
val result: BitMatrix = try {
MultiFormatWriter().encode(source, BarcodeFormat.QR_CODE, width, height, null)
} catch (e: Exception) {
return null
}
val w = result.width
val h = result.height
val pixels = IntArray(w * h)
for (y in 0 until h) {
val offset = y * w
for (x in 0 until w) {
pixels[offset + x] = if (result[x, y]) Color.BLACK else Color.WHITE
}
}
val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
bitmap.setPixels(pixels, 0, width, 0, 0, w, h)
return bitmap
}
And you need to add this dependency implementation 'com.google.zxing:core:3.3.1' when you decide to use the above code.
I have managed to export my recyclerview in a PDF file but I am realizing that the image that is as a header is not showing in the pdf, I only know the questions and the answers that are the check boxes
I have tried the following code to show the recyclerview in pdf.
This is my activity
`
fun getScreenshotFromRecyclerView(view: RecyclerView): Bitmap? {
val adapter = view.adapter
var bigBitmap: Bitmap? = null
if (adapter != null) {
val size = listado2.size
var height = 0
val paint = Paint()
var iHeight = 0
val maxMemory = (Runtime.getRuntime().maxMemory() / 1024).toInt()
// Use 1/8th of the available memory for this memory cache.
val cacheSize = maxMemory / 8
val bitmaCache =
LruCache<String, Bitmap>(cacheSize)
for (i in 0 until size) {
val holder =
adapter.createViewHolder(view, adapter.getItemViewType(i))
adapter.onBindViewHolder(holder, i)
holder.itemView.measure(
View.MeasureSpec.makeMeasureSpec(
view.width,
View.MeasureSpec.EXACTLY
),
View.MeasureSpec.makeMeasureSpec(
0,
View.MeasureSpec.UNSPECIFIED
)
)
holder.itemView.layout(
0,
0,
holder.itemView.measuredWidth,
holder.itemView.measuredHeight
)
holder.itemView.isDrawingCacheEnabled = true
holder.itemView.buildDrawingCache()
val drawingCache = holder.itemView.drawingCache
if (drawingCache != null) {
bitmaCache.put(i.toString(), drawingCache)
}
// holder.itemView.setDrawingCacheEnabled(false);
// holder.itemView.destroyDrawingCache();
height += holder.itemView.measuredHeight
}
bigBitmap =
Bitmap.createBitmap(view.measuredWidth, height, Bitmap.Config.ARGB_8888)
val bigCanvas = Canvas(bigBitmap)
bigCanvas.drawColor(Color.WHITE)
for (i in 0 until size) {
val bitmap = bitmaCache[i.toString()]
bigCanvas.drawBitmap(bitmap!!, 0f, iHeight.toFloat(), paint)
iHeight += bitmap.height
bitmap.recycle()
}
}
return bigBitmap
}
`
This is my CreateFile.kt class
`
open fun salvarPDF(bitmap: Bitmap, nombreDeArchivo : String): String?{
archivo = File(pasta, "$nombreDeArchivo.pdf")
val archivoPDF = PdfDocument()
val pageInfo: PdfDocument.PageInfo = PageInfo.Builder(bitmap.width, bitmap.height, 1).create()
val pagina : PdfDocument.Page = archivoPDF.startPage(pageInfo)
val canvas : Canvas = pagina.canvas
canvas.drawBitmap(bitmap,null, Rect(0,0,bitmap.width, bitmap.height),null)
archivoPDF.finishPage(pagina)
try {
archivo!!.createNewFile()
val streamDeSalidad: OutputStream = FileOutputStream(archivo)
archivoPDF.writeTo(streamDeSalidad)
streamDeSalidad.close()
archivoPDF.close()
}catch (e: IOException){
return "error en crear$e"
}
return "creado"
}
`
This is the result in PDF
But it should come out as follows.
Any idea where in the code I am failing.
I am working On Google map in android and Image not displayed when i set in My customView Below in function createCustomMarker().Please recommend me if doing some wrong. But I set the drawable from drawable folder then displayed But not from String url.
override fun onMapReady(googleMap: GoogleMap?) {
mMap = googleMap
mMap?.animateCamera(CameraUpdateFactory.zoomTo(16.0f))
mMap?.mapType = GoogleMap.MAP_TYPE_NORMAL
mMap?.setMinZoomPreference(6.0f)
mMap?.setMaxZoomPreference(21.0f)
mMap?.isIndoorEnabled = false
mMap?.isMyLocationEnabled = true
val coordinate =
LatLng(prefs?.current_lati?.toDouble()!!, prefs?.current_longi?.toDouble()!!) //Store these lat lng values somewhere. These should be constant.
val location = CameraUpdateFactory.newLatLngZoom(
coordinate, 15f
)
for(i in 0..arraylist?.size){
var lat=arraylist?.get(i)?.latitude
var longi=arraylist?.get(i)?.longitude
mMap!!.addMarker(MarkerOptions().position(LatLng(lat!!,longi!!)).icon(BitmapDescriptorFactory.fromBitmap(createCustomMarker( requireContext(),arraylist?.get(i)!!.image))))}
mMap!!.moveCamera(CameraUpdateFactory.newLatLng(locationArrayList!![i]))
mMap!!.animateCamera(location)
}
private fun createCustomMarker(context: Context, userImage: String): Bitmap {
val marker: View =
(context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater).inflate(
R.layout.lay_cutom_marker,
null
)
val markerImage: ImageView = marker.findViewById(R.id.img_res)
var bmp: Bitmap? = null
// val url = URL(userImage)
Glide.with(context).load(userImage)
.placeholder(R.drawable.ic_user).error(R.drawable.ic_user).into(markerImage)
val displayMetrics = DisplayMetrics()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
context.display?.getRealMetrics(displayMetrics)
} else {
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
}
marker.layoutParams = ViewGroup.LayoutParams(52, ViewGroup.LayoutParams.WRAP_CONTENT)
marker.measure(displayMetrics.widthPixels, displayMetrics.heightPixels)
marker.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels)
marker.buildDrawingCache()
bmp = Bitmap.createBitmap(
marker.measuredWidth, marker.measuredHeight,
Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bmp)
marker.draw(canvas)
return bmp
}
Maybe it is because of you make icon after that image is loading in drawable as you load an image. you need to increase wait time until image has been loaded after that do all stuff regarding iconGenerator.
I have an android app in Kotlin which depends on CameraX to analyze images and pass them to tensorflow lite image detection model ( not classification ). The problem is we get YUV or RGBA Output images and we need an argb bitmap to pass to tflite model to detect objects we have been struggling for weeks and we have a deadline soon help please.
ImageAnalysis.Analyzer {
private val supportedImages = listOf(ImageFormat.FLEX_RGBA_8888, ImageFormat.FLEX_RGB_888)
private var data = ""
#SuppressLint("UnsafeOptInUsageError")
override fun analyze(image: ImageProxy) {
if (image.format in supportedImages) {
val options = ObjectDetector.ObjectDetectorOptions.builder()
.setScoreThreshold(0.2F)
.setBaseOptions(BaseOptions.builder().build())
.build()
val objectDetector =
ObjectDetector.createFromFileAndOptions(
context, Model.createModel(context, "model.tflite").path, options
)
val bitmap = toBitmap(image)
val tfImage = TensorImage.fromBitmap(bitmap)
val results: List<Detection> = objectDetector.detect(tfImage)
for (result in results) {
val categories = result.categories
for (category in categories) {
val label = category.label
val boundingBox = result.boundingBox
data += "label : $label | bounding : $boundingBox"
}
}
listener(data)
image.close()
}
}
private fun toBitmap(image: ImageProxy): Bitmap {
val r = image.planes[0].buffer.int
val g = image.planes[1].buffer.int
val b = image.planes[2].buffer.int
val a = image.planes[3].buffer.int
var color = Color.argb(a, r, g, b)
val rect = Rect(0, 0, 1, 1)
color = ColorUtils.compositeColors(color, Color.WHITE)
val bitmap = Bitmap.createBitmap(rect.width(), rect.height(), Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
val paint = Paint()
paint.color = color
canvas.drawRect(rect, paint)
savePic(bitmap = bitmap!!, display_name = Random(100000L).toString())
return bitmap
}
private fun savePic(bitmap: Bitmap, display_name: String): Boolean {
val mediaCollection = latest {
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
} ?: MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val contentValues = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, "${display_name}.jpg")
put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
put(MediaStore.Images.Media.WIDTH, bitmap.width)
put(MediaStore.Images.Media.HEIGHT, bitmap.height)
}
return try {
context.contentResolver.insert(mediaCollection, contentValues)?.also { uri ->
context.contentResolver.openOutputStream(uri).use { outputStream ->
if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)) {
throw IOException("could not save bitmap!")
}
}
} ?: throw IOException("could not create media store entry")
return true
} catch (e: IOException) {
e.printStackTrace()
false
}
}
}```
Here is the function that converts YUV_420_888 imageproxy into argb format bitmap.
I know a late answer but providing for others.
fun imageToBitmap(image: Image): Bitmap {
val planes: Array<Image.Plane> = image.planes
val yBuffer: ByteBuffer = planes[0].buffer
val uBuffer: ByteBuffer = planes[1].buffer
val vBuffer: ByteBuffer = planes[2].buffer
val ySize = yBuffer.remaining()
val uSize = uBuffer.remaining()
val vSize = vBuffer.remaining()
val nv21 = ByteArray(ySize + uSize + vSize)
//U and V are swapped
yBuffer[nv21, 0, ySize]
vBuffer[nv21, ySize, vSize]
uBuffer[nv21, ySize + vSize, uSize]
val yuvImage = YuvImage(nv21, ImageFormat.NV21, image.width, image.height, null)
val out = ByteArrayOutputStream()
yuvImage.compressToJpeg(Rect(0, 0, yuvImage.width, yuvImage.height), 75, out)
val imageBytes: ByteArray = out.toByteArray()
return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
}
Provide imageproxy from cameraX analyser to this function and it will provide the bitmap.
I'm making a small project, but yet different. So I found out that the bitmap works when the image is implemented from Android Studio and include it as resources(example: BitmapFactory.decodeResources(resources, R.drawable.image.jpg)) in order for the watermark to work, however I am struggling with something similar, but selecting a certain image from the android device, using by code of course, but later one probably gonna be questions once the gallery is selected to automatically place the watermark, but like I said that's a different question for another time. My question is there any possible way, when I press the watermark button, to automatically locate and place the image from the Android device on to the imageview, after that to place the text watermark ?
Also on the console log, I'm receiving this message: E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /data/user/0/com.example.cameraxapp/files (Is a directory)
If any of you know the issue that I am having, please let me know and examples, will also be helpful. Thank you in advance!
Manifest
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
ActivityGallery.xml(It can be even in MainActivity.xml)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#8A8A8A"
android:backgroundTint="#8A8A8A"
tools:context=".ActivityGallery">
<Button
android:id="#+id/watermarkSetBtn"
android:layout_width="75dp"
android:layout_height="wrap_content"
android:backgroundTint="#4CAF50"
android:text="#string/watermark"
android:textSize="11sp"
app:layout_constraintTop_toBottomOf="#id/imageViewPhoto"
app:layout_constraintEnd_toStartOf="#id/saveButton"
app:layout_constraintStart_toEndOf="#id/pickPhotoButton"
app:layout_constraintBottom_toBottomOf="parent"
/>
<ImageView
android:id="#+id/imageViewPhoto"
android:layout_width="match_parent"
android:layout_height="670dp"
android:importantForAccessibility="no"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#android:drawable/ic_menu_gallery" />
</androidx.constraintlayout.widget.ConstraintLayout>
GalleryActivity.kt
The main function for the watermark as Bitmap
private fun addWatermark(bitmap: Bitmap, watermarkText: String, options: WatermarkOptions = WatermarkOptions()): Bitmap {
val result = bitmap.copy(bitmap.config, true)
val canvas = Canvas(result)
val paint = Paint(ANTI_ALIAS_FLAG or DITHER_FLAG)
paint.textAlign = when (options.corner) {
Corner.TOP_LEFT,
Corner.BOTTOM_LEFT -> Paint.Align.LEFT
Corner.TOP_RIGHT,
Corner.BOTTOM_RIGHT -> Paint.Align.RIGHT
}
val textSize = result.width * options.textSizeToWidthRatio
paint.textSize = textSize
paint.color = options.textColor
if (options.shadowColor != null) {
paint.setShadowLayer(textSize / 2, 0f, 0f, options.shadowColor)
}
if (options.typeface != null) {
paint.typeface = options.typeface
}
val padding = result.width * options.paddingToWidthRatio
val coordinates = calculateCoordinates(watermarkText, paint, options, canvas.width, canvas.height, padding)
canvas.drawText(watermarkText, coordinates.x, coordinates.y, paint)
return result
}
private fun calculateCoordinates(watermarkText: String, paint: Paint, options: WatermarkOptions, width: Int, height: Int, padding: Float): PointF {
val x = when (options.corner) {
Corner.TOP_LEFT,
Corner.BOTTOM_LEFT -> {
padding
}
Corner.TOP_RIGHT,
Corner.BOTTOM_RIGHT -> {
width - padding
}
}
val y = when (options.corner) {
Corner.BOTTOM_LEFT,
Corner.BOTTOM_RIGHT -> {
height - padding
}
Corner.TOP_LEFT,
Corner.TOP_RIGHT -> {
val bounds = Rect()
paint.getTextBounds(watermarkText, 0, watermarkText.length, bounds)
val textHeight = bounds.height()
textHeight + padding
}
}
return PointF(x, y)
}
enum class Corner {
TOP_LEFT,
TOP_RIGHT,
BOTTOM_LEFT,
BOTTOM_RIGHT
}
data class WatermarkOptions(
val corner: Corner = Corner.BOTTOM_RIGHT,
val textSizeToWidthRatio: Float = 0.04f,
val paddingToWidthRatio: Float = 0.03f,
#ColorInt val textColor: Int = Color.WHITE,
#ColorInt val shadowColor: Int? = Color.BLACK,
val typeface: Typeface? = null
)
companion object {
//private const val FILENAME_FORMAT = "yyyy.MM.dd-HH"
private const val TAG = "CameraXBasic"
}
Placing it on onCreate method
private lateinit var mImageView: ImageView
private lateinit var mWatermarkSet: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_gallery)
//Views
mImageView = findViewById(R.id.imageViewPhoto)
mWatermarkSet = findViewById(R.id.watermarkSetBtn)
mWatermarkSet.setOnClickListener {
if (filesDir.isDirectory) {
val internalStorage = filesDir.absolutePath
val pathName = "$internalStorage"
//resources, R.drawable.gefvqkbbslamdpkxf1zv_bigstock_aerial_view_of_blue_lakes_and__227291596
val originalBitmap = BitmapFactory.decodeFile(pathName)?.let { it ->
addWatermark(
it,
"#Test",
WatermarkOptions(
Corner.TOP_RIGHT,
textSizeToWidthRatio = 0.03f,
paddingToWidthRatio = 0.03f,
Color.GREEN,
Color.BLACK,
typeface = null
)
)
}
mImageView.setImageBitmap(originalBitmap)
}
}
}