I'm trying to overlay two bitmaps.
This code works fine on below android 9. On android 9 and above the application crash.
private fun overlay(base: Bitmap, blend: Bitmap): Bitmap {
return try {
val result: Bitmap =
base.copy(Bitmap.Config.ARGB_8888, true)
val p = Paint()
p.xfermode = PorterDuffXfermode(PorterDuff.Mode.ADD)
p.shader = BitmapShader(blend, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
val c = Canvas()
c.setBitmap(result)
c.drawBitmap(base, 0f, 0f, null)
c.drawRect(0f, 0f, base.width.toFloat(), base.height.toFloat(), p)
result
} catch (e: Exception) {
println(e.message.toString())
base
}
}
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ex.image, PID: 26562
java.lang.IllegalArgumentException: Software rendering doesn't support hardware bitmaps
at android.graphics.BaseCanvas.onHwBitmapInSwMode(BaseCanvas.java:632)
at android.graphics.BaseCanvas.throwIfHwBitmapInSwMode(BaseCanvas.java:639)
at android.graphics.BaseCanvas.throwIfCannotDraw(BaseCanvas.java:73)
at android.graphics.MiuiCanvas.throwIfCannotDraw(MiuiCanvas.java:329)
at android.graphics.BaseCanvas.drawBitmap(BaseCanvas.java:113)
at android.graphics.MiuiCanvas.drawBitmap(MiuiCanvas.java:98)
at android.graphics.Canvas.drawBitmap(Canvas.java:1613)
at com.ex.image.fragments.FiltersFragment.overlay(FiltersFragment.kt:103)
at com.ex.image.fragments.FiltersFragment.applyFilter(FiltersFragment.kt:86)
at com.ex.image.adapters.FilterRecyclerAdapter.onBindViewHolder$lambda-0(FilterRecyclerAdapter.kt:39)
at com.ex.image.adapters.FilterRecyclerAdapter.$r8$lambda$KexXVg24JaLUI6vIkMTUBOYKnlY(Unknown
Source:0)
at com.ex.image.adapters.FilterRecyclerAdapter$$ExternalSyntheticLambda0.onClick(Unknown
Source:4)
at android.view.View.performClick(View.java:7509)
at android.view.View.performClickInternal(View.java:7486)
at android.view.View.access$3600(View.java:841)
at android.view.View$PerformClick.run(View.java:28710)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:8056)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:656)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
Note:
I have already turn off the HARDWARE_ACCELERATED for android 9 above.
Related
I made an android app (Android Studio + Kotlin) that uses CameraX. So this is my code to start the camera:
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener(Runnable {
// Used to bind the lifecycle of cameras to the lifecycle owner
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// Preview
val preview = Preview.Builder()
.build()
.also {
it.setSurfaceProvider(viewFinder.surfaceProvider)
}
// Select back camera as a default
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
// Unbind use cases before rebinding
cameraProvider.unbindAll()
// Bind use cases to camera
cameraProvider.bindToLifecycle(
this, cameraSelector, preview
)
} catch (exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(this))
}
Now I wanted to get a bitmap of the viewFinder so that I can determine the color of the pixel in the center:
val bitmap = viewFinder.bitmap
val pixel = bitmap?.getPixel(width / 2, height / 2 - 30)
val pixel2 = if (pixel != null) pixel else -1
bitmap is Bitmap? and pixel is Int?
When I run the app everything works completely fine but then sometimes it crashes and shoots out this message:
at com.example.colorblind.MainActivity$onCreate$r$1.run(MainActivity.kt:116)
Line 116 is the line with val pixel = bitmap?.getPixel(width / 2, height / 2 - 30). If I then add a line before the code so that it hops to line 117 everything works perfectly fine again until the same error occurs. Then I need to change the line again. How can I fix this problem because I can't publish the app like this if it sometimes randomly crashes while opening.
I hope I was able to explain the problem properly.
EDIT
This is the only message I get when it crashes:
2022-02-16 20:43:53.123 7337-7337/com.example.colorblind E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.colorblind, PID: 7337
java.lang.IllegalArgumentException: y must be < bitmap.height()
at android.graphics.Bitmap.checkPixelAccess(Bitmap.java:1958)
at android.graphics.Bitmap.getPixel(Bitmap.java:1863)
at com.example.colorblind.MainActivity$onCreate$r$1.run(MainActivity.kt:116)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
I know there are other questions that was answered to many times and I tried to find the answer, but I couldn't understand of it most. I want to make the camera to take a photo, but instead of making a physical image file, I want it directly to make it into a bitmap and display it in an ImageView from a different activity, however I constantly getting the Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference, that's because of the viewFinder.bitmap is a null and decided to make a seperate function getBitmap(): Bitmap?. I don't know what it wants me to do honestly or any lead from this, all I want to do is to make the photo straight to ImageView as a bitmap. Thank you in advance.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.camerax5, PID: 5472
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.camerax5/com.example.camerax5.VirtualPreview}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3141)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3284)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1972)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7179)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:164)
at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:157)
at android.content.Context.obtainStyledAttributes(Context.java:677)
at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:842)
at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:809)
at androidx.appcompat.app.AppCompatDelegateImpl.findViewById(AppCompatDelegateImpl.java:633)
at androidx.appcompat.app.AppCompatActivity.findViewById(AppCompatActivity.java:259)
at com.example.camerax5.MainActivity.getBitmap(MainActivity.kt:118)
at com.example.camerax5.VirtualPreview.onCreate(VirtualPreview.kt:19)
at android.app.Activity.performCreate(Activity.java:7335)
at android.app.Activity.performCreate(Activity.java:7326)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1275)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3121)
So the problem was occured on this line:
viewFinder = findViewById(R.id.previewView)
Here is the full code of what I was trying to do:
MainActivity.kt and underneath the MainActivity code is the other class with another activity to show the bitmap in the ImageView, I added this way is because I don't want to separate them and making them confusing:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewFinder = findViewById(R.id.previewView)
//Permissions
if (allPermissions()) {
startCamera()
} else {
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
}
//Capture button
val captureBtn: Button = findViewById(R.id.captureButton)
captureBtn.setOnClickListener {
takePhoto()
}
outputDirectory = outputDirectoryFolder()
cameraExecutor = Executors.newSingleThreadExecutor()
}
private fun takePhoto() {
Toast.makeText(baseContext, "Processing ..", Toast.LENGTH_SHORT).show()
//Directly to open the new Activity
val intent = Intent(this, VirtualPreview::class.java)
startActivity(intent)
}
fun getBitmap(): Bitmap? {
//Preview to Bitmap
viewFinder = findViewById(R.id.previewView)
val source = viewFinder.bitmap
val newWidth = 200
val newHeight = 200
val bitmapWidth = source?.width
val bitmapHeight = source?.height
//Matrix
val matrix = Matrix()
val scaleWidth = newWidth.toFloat() / bitmapWidth!!
val scaleHeight = newHeight.toFloat() / bitmapHeight!!
matrix.postScale(scaleWidth, scaleHeight)
return Bitmap.createBitmap(source, 0, 0, newWidth, newHeight, matrix, true)
}
}
class VirtualPreview : AppCompatActivity() {
private lateinit var acceptButton: Button
private lateinit var denyButton: Button
private lateinit var imageView: ImageView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_virtual_preview)
val bitmapPreview = MainActivity().getBitmap()
val drawableBitmap = BitmapDrawable(resources, bitmapPreview)
imageView = findViewById(R.id.imagePreview)
imageView.setImageDrawable(drawableBitmap)
acceptButton = findViewById(R.id.acceptButton)
acceptButton.setOnClickListener {
}
denyButton = findViewById(R.id.denyButton)
denyButton.setOnClickListener {
//delete the matrix and returns to the main activity
finish()
}
}
}
val bitmapPreview = MainActivity().getBitmap() - This way you are creating a new instance of MainActivity and the new instance do not have any thing in preview view, also this method is not recommended. Better store bitmap inside MainActivity and then pass that bitmap to VirtualPreview activity in constructor (in bundle it won't work). It won't be a problem for your case, as you're scaling the bitmap to 200x200. and for large bitmap, store in file, and use that file. And for your case, you can create another imageview in mainactivity and show the bitmap in that imageview instead of creating another activity.
I have a simple Composable as below
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Testing()
}
}
}
#Composable
fun Testing(modifier: Modifier = Modifier) {
var height = 0f
Column(modifier = modifier.onGloballyPositioned {
height = it.size.height.toFloat()
}) {
if (height == 0f) return
// Do something
}
}
It will crash with
2021-04-06 20:09:14.132 8383-8383/com.example.jetpackcomposeanimationspec E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.jetpackcomposeanimationspec, PID: 8383
java.lang.IllegalStateException: Start/end imbalance
at androidx.compose.runtime.ComposerImpl.finalizeCompose(Composer.kt:2890)
at androidx.compose.runtime.ComposerImpl.endRoot(Composer.kt:1149)
at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:2602)
at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:348)
at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:693)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:304)
But if I change Testing to
#Composable
fun Testing(modifier: Modifier = Modifier) {
var height = 0f
Column(modifier = modifier.onGloballyPositioned {
height = it.size.height.toFloat()
}) {
if (height != 0f) {
// Do something
}
}
}
It no longer crash. Why?
I have this issue on Compose version 1.1.1. But if I type for example return#Column instead of return there will not be a crash.
Column {
return // will crash
}
Column {
return#Column // works for me
}
UPD! This works stable only in debug mode. If I build release it may crash with ArrayIndexOutOfBoundsException in ComposerImpl:
java.lang.ArrayIndexOutOfBoundsException: length=163; index=-1
at java.util.ArrayList.remove(ArrayList.java:506)
at androidx.compose.runtime.Stack.pop(Stack.kt:26)
at androidx.compose.runtime.ComposerImpl.exitGroup(Composer.kt:2131)
at androidx.compose.runtime.ComposerImpl.end(Composer.kt:2293)
at androidx.compose.runtime.ComposerImpl.endGroup(Composer.kt:1494)
at androidx.compose.runtime.ComposerImpl.endRoot(Composer.kt:1387)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3199)
at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:3140)
at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:722)
at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:876)
at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:107)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:485)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:454)
at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1035)
at android.view.Choreographer.doCallbacks(Choreographer.java:845)
at android.view.Choreographer.doFrame(Choreographer.java:775)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1022)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
In compose version '1.2.0-beta01' this issue still exists
I also had this exception and my code had no return statement. So what I did to fix it is downgrading kotlinCompilerExtensionVersion from 1.3.2 to 1.1.1
In my application i want to upload an image to server but i want to convert it to gray scale before i do that.< br />
So i found a function that takes a bitmap and returns a bitmap as Gray scale.
fun getGrayScale(src: Bitmap): Bitmap {
//Custom color matrix to convert to GrayScale
val matrix = floatArrayOf(
0.3f,
0.59f,
0.11f,
0f,
0f,
0.3f,
0.59f,
0.11f,
0f,
0f,
0.3f,
0.59f,
0.11f,
0f,
0f,
0f,
0f,
0f,
1f,
0f
)
val dest = Bitmap.createBitmap(src.width, src.height, Bitmap.Config.RGB_565)
val canvas = Canvas(dest)
val paint = Paint()
val filter = ColorMatrixColorFilter(matrix)
paint.colorFilter = filter
canvas.drawBitmap(src, 0.toFloat(), 0.toFloat(), paint)
return dest
}
That runs successfully but NOT in Android 10, in which i get the following exception
java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Software rendering doesn't support hardware bitmaps
at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:516)
at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:475)
at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:298)
at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.lang.IllegalArgumentException: Software rendering doesn't support hardware bitmaps
at android.graphics.BaseCanvas.onHwBitmapInSwMode(BaseCanvas.java:632)
at android.graphics.BaseCanvas.throwIfHwBitmapInSwMode(BaseCanvas.java:639)
at android.graphics.BaseCanvas.throwIfCannotDraw(BaseCanvas.java:73)
at android.graphics.BaseCanvas.drawBitmap(BaseCanvas.java:113)
at android.graphics.Canvas.drawBitmap(Canvas.java:1540)
at com.example.utilities.ImageUtils.getGrayScale(ImageUtils.kt:64)
at com.example.utilities.FileUtils.imageRefactor(FileUtils.kt:98)
at com.example.workmanager.FileSplitterWorker.doWork(FileSplitterWorker.kt:54)
at androidx.work.CoroutineWorker$startWork$1.invokeSuspend(CoroutineWorker.kt:68)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
I have tried to add hardwareAccelerated as true in my manifest but same happens.
Can i do this with Glide, or with another way?
In Android O they have introduced new Bitmap.Config the Bitmap.Config.HARDWARE which is an actual optimization when it comes to draw the Bitmap to the screen. So since you are using Software rendering that is why you get the error.
Try this:
fun getGrayScaleBitmap(original: Bitmap): Bitmap {
// You have to make the Bitmap mutable when changing the config because there will be a crash
// That only mutable Bitmap's should be allowed to change config.
val bmp = original.copy(Bitmap.Config.ARGB_8888, true)
val bmpGrayscale = Bitmap.createBitmap(bmp.width, bmp.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bmpGrayscale)
val paint = Paint()
val colorMatrix = ColorMatrix()
colorMatrix.setSaturation(0f)
val colorMatrixFilter = ColorMatrixColorFilter(colorMatrix)
paint.colorFilter = colorMatrixFilter
canvas.drawBitmap(bmp, 0F, 0F, paint)
return bmpGrayscale
}
This will replace the Bitmap.Config from Bitmap.Config.HARDWARE to Bitmap.Config.ARGB_8888.
Hope it helps!!!
I am building an AR Android app where I want to spawn an arrow whenever the position of the user changes. However I get a NotTrackingException when I try to create an anchor. How can I know that ARCore detected a plane so that I can add my anchor?
The only thing I found is this, but there is not much I could get out of it.
fun onLocationChanged(location: Location) {
val session = arFragment.arSceneView.session
var arrowViewRenderable:ViewRenderable
val pos = floatArrayOf(0f,0f,-1f)
val rotation = floatArrayOf(0f,0f,0f,1f)
val anchor = session!!.createAnchor(Pose(pos,rotation))
val anchorNode = AnchorNode(anchor)
anchorNode.setParent(arFragment.arSceneView.scene)
ViewRenderable.builder()
.setView(this, R.layout.arrow)
.setSizer(DpToMetersViewSizer(400 ))
.build()
.thenAccept { renderable -> arrowViewRenderable = renderable
anchorNode.renderable = arrowViewRenderable
}
}
status.cc:156 ArStatusErrorSpace::AR_ERROR_NOT_TRACKING: Cannot create anchors while the camera is not tracking.
2019-06-12 14:58:37.369 29685-29685/com.carmeq.carfind E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.carmeq.carfind, PID: 29685
com.google.ar.core.exceptions.NotTrackingException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at com.google.ar.core.Session.throwExceptionFromArStatus(Session.java:134)
at com.google.ar.core.Session.nativeCreateAnchor(Native Method)
at com.google.ar.core.Session.createAnchor(Session.java:93)
at com.carmeq.carfind.MainActivity.onLocationChanged(MainActivity.kt:282)
at com.carmeq.carfind.MainActivity$mLocationCallback$1.onLocationResult(MainActivity.kt:223)
at com.google.android.gms.internal.zzbzq.zzq(Unknown Source:4)
at com.google.android.gms.common.api.internal.zzcj.zzb(Unknown Source:8)
at com.google.android.gms.common.api.internal.zzck.handleMessage(Unknown Source:16)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:6981)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
You can retrieve the TrackingState from the Camera of the current Frame.
val frame = session.update()
if (frame.camera.trackingState == TrackingState.tracking) {
// place anchor
}