[apk][mod] Lcamera with longer exposure times for crazy night pictures

Search This thread

enryea123

Senior Member
May 10, 2011
191
276
Milan

Hey everyone!

As some of you might know, the nexus 5x and nexus 6p cameras have a maximum exposure time in manual mode of 1/4.3 seconds, which is a real shame. Somebody suggested that Google made this choice because of the bigger size of the pixels, nonetheless the resulting pictures in very low light are not satisfying and none of the apps on the play store overrides the limit of 1/4.3 seconds.

So, I managed to unlock longer exposure times (up to 5 seconds) on the nexus 5x camera to take some truly unbelievable night pictures. Since the sensor is the same, this app should work also on the nexus 6p and it might work even on other devices with at least android 5.0. It also probably works on the nexus 5, but doesn't appear to be working on the nexus 6.

A big thank to PkmX for developing the original app Lcamera and to CazeW for his suggestions.

Notice that the photos will be upside down, because the sensor is mounted upside down (at least in the nexus 5x). Just rotate them with your favorite photos editor. Also notice that the "screen refresh time" is the one of the exposure, so when you set an exposure of e.g. 3 seconds, the app will look like if it's stuck and refresh every 3s.

I am not responsible for any damage that your phone might report. I've been using this app for a long time and everything works fine.
You can download the .apk file and the source code at the bottom. To install the app you only need the .apk file, the source code is for developers who wish to improve the code.

Check the difference between a manual camera downloaded from the play store and my app (the pics are resized here).
Click on the images to enlarge.

before.jpgafter.jpg

How did I do it?
I exploited the fact that the older versions of Lcamera by PkmX allowed up to 1/1.2 seconds of exposure time (probably because the nexus 5x wasn't supported yet), so I downloaded the source of lcamera 0.3 by PkmX, modified a few lines of code and compiled it.
The exposure times of my modded app are: 5s, 4s, 3s, 2s, 1.5s, 1s, 0.5s, 0.23 s, ... and so on, up to 1/120000 s (the default minimum value) and you can change them in the settings of the app.

Why not more than 5 seconds?
Because the app gets really unstable, since those exposure times are not officially "hardware" supported.
EDIT: a user suggested here that the app might be stable for even longer exposures with a longer kernel readahead.
Beware that the app can be unstable even with exposure times longer than 3 seconds: if it starts crashing, just terminate it in the settings. I usually set the exposure time back to 1/10 s every time I close the app, otherwise the following times it might just crash when entering in it.
Therefore, with this app you can get some beautiful night pictures, the drawback is that sometimes it might be unstable (because those exposures are not hardware supported).

What did I modify?
In src/pkmx/lcamera/MainActivity.scala I've modified lines 417, 419, 693 and deleted the line 1083. You can download my source code at the bottom, the original source code from github and compare them, to see in more detail which are the differences.
I've also modified the app icon with one that I've personally designed.

Thank you and have fun :)

 

Attachments

  • Lcamera1_enryea123.apk
    546.6 KB · Views: 29,537
  • source_code_for_developers.zip
    75.7 KB · Views: 2,093
Last edited:

TW1ST3D1NS4N3

Senior Member
Oct 20, 2014
400
204
The first one is Google camera and the second is from your app:confused::confused:
 

Attachments

  • IMG_20161209_130851.jpg
    IMG_20161209_130851.jpg
    249.9 KB · Views: 9,794
  • IMG_20161209_130913.jpg
    IMG_20161209_130913.jpg
    262.5 KB · Views: 9,781

enryea123

Senior Member
May 10, 2011
191
276
Milan
Thanks for this.
Is it possible to force ISO to a lower value than 60?

Sent from my Nexus 5X using Tapatalk

Well, in the app the lowest possible iso is set to 40, but the camera doesn't go below 60, so I think it's not possible. Anyway 60 is already very low and the noise shouldn't be much, so I don't know if an even lower iso would actually bring some benefits.
 

CazeW

Senior Member
Nov 14, 2008
867
456
Good job. Some questions and tips for your code. Haven't tried the app though as my phone is getting repaired.

Why use a base of 60s? Wouldn't it have been easier to just use a 10s base instead of 60s for val exposureTime? Then you would only have needed to multiply the values by 10 in exposureTimeMap instead of 60 (and also add your values, 2 for 5s, 2.5 for 4s and so on). You also seem to be missing the base 1/60s exposure, don't know if that matters though.

Remove the line prefs.exposureTimeIndex = exposureTimeIndex() from onStop(), this will stop the manual exposure getting saved when closing the app (hence you don't need to change it back before closing).

Try replacing the line (not sure if this code will work but you probably notice what I'm trying to do)
Code:
observe { exposureTimeIndex foreach { v => text = s"60/${new DecimalFormat("#.#").format(exposureTimeMap(v))}" } }
with
Code:
observe { exposureTimeIndex foreach { v => text = if (v > 5) s"1/${new DecimalFormat("#.#").format(exposureTimeMap(v)/60)}" else s"${new DecimalFormat("#.#").format(60/exposureTimeMap(v))}s" } }
for a nicer display of the exposure times. Obviously change the value of 60 if you decide to change the base value.

EDIT: You should also be able to fix the rotation by implementing this commit in your code. Might also know how to "fix" the preview as well so the refresh rate doesn't go below a certain rate, but don't want to take away all the fun from you. ;)
 
Last edited:

enryea123

Senior Member
May 10, 2011
191
276
Milan
Why use a base of 60s? Wouldn't it have been easier to just use a 10s base instead of 60s for val exposureTime? Then you would only have needed to multiply the values by 10 in exposureTimeMap instead of 60 (and also add your values, 2 for 5s, 2.5 for 4s and so on). You also seem to be missing the base 1/60s exposure, don't know if that matters though.

Remove the line prefs.exposureTimeIndex = exposureTimeIndex() from onStop(), this will stop the manual exposure getting saved when closing the app (hence you don't need to change it back before closing).

Try replacing the line (not sure if this code will work but you probably notice what I'm trying to do)
Code:
observe { exposureTimeIndex foreach { v => text = s"60/${new DecimalFormat("#.#").format(exposureTimeMap(v))}" } }
with
Code:
observe { exposureTimeIndex foreach { v => text = if (v > 5) s"1/${new DecimalFormat("#.#").format(exposureTimeMap(v)/60)}" else s"${new DecimalFormat("#.#").format(60/exposureTimeMap(v))}s" } }
for a nicer display of the exposure times. Obviously change the value of 60 if you decide to change the base value.

EDIT: You should also be able to fix the rotation by implementing this commit in your code. Might also know how to "fix" the preview as well so the refresh rate doesn't go below a certain rate, but don't want to take away all the fun from you. ;)
Thank you for the suggestions! Well I choose a base 60 because it is divisible by 5,4,3,2,1, so I could avoid using "double" values for the exposures and I didn't have to worry about the digit precision, but yes I've modified the code as you suggested to have a better looking exposure time in the app, with some small differences; now it's like 5 s, 4 s, ..., 1/2 s, 1/4.3 s, ... and I've also modified a bit the shorter exposures and added back the 1/60 one.
I've also deleted the line that saves the exposure preference.
I've checked the rotation commit but it is for a newer version of Lcamera, so there are many differences in the code.
Of course any suggestion on how to fix it in my app or how to change the "screen refresh rate" is welcome :), as long as it doesn't imply to modify more than a few (let's say 30) lines of code, unless you want to do it yourself.

Nice, should be great for shooting auroras.
Yes, also to shoot the night sky. Nice picture by the way!
Source is the sourcecode of the apk...
You don't have to flash anything,
Exactly
 
Last edited:
  • Like
Reactions: f3r.and0

CazeW

Senior Member
Nov 14, 2008
867
456
Thank you for the suggestions! Well I choose a base 60 because it is divisible by 5,4,3,2,1, so I could avoid using "double" values for the exposures and I didn't have to worry about the digit precision, but yes I've modified the code as you suggested to have a better looking exposure time in the app, with some small differences; now it's like 5 s, 4 s, ..., 1/2 s, 1/4.3 s, ... and I've also modified a bit the shorter exposures and added back the 1/60 one.
I've also deleted the line that saves the exposure preference.
I've checked the rotation commit but it is for a newer version of Lcamera, so there are many differences in the code.
Of course any suggestion on how to fix it in my app or how to change the "screen refresh rate" is welcome :), as long as it doesn't imply to modify more than a few (let's say 30) lines of code, unless you want to do it yourself.
Looked closer at the commit and you're right, would take a bit of work to implement it in the older version.
I'm not sure but this might be the part that handles the refresh rate of the screen.
Code:
val startPreview =
    for { (cameraOpt, previewSurfaceOpt, previewSessionOpt, autoFocus, focusDistance, autoExposure, iso, exposureTime, metering)
          <- Rx {(this.camera(), this.previewSurface(), this.previewSession(),
                  this.autoFocus(), this.focusDistance(),
                  this.autoExposure(), this.iso(), this.exposureTime(), this.metering())}
Inside that for you could put in an if that checks if this.exposureTime() is less than for example 1/5s, then use a constant of 1/5s instead of this.exposureTime().

I also might have found a way to get the newer version to be able to use slower shutter speeds. The problem I think is this code on line 699.
Code:
val validExposureTimes = Rx { lcamera().toList flatMap { camera => exposureTimes filter { camera.exposureTimeRange contains _ }} }
Which is a list of exposure times the sensor supports. Now, if we set this equal to the var exposureTimes, I think we should be able to use the longer exposure times. I don't know if straight val validExposureTimes = exposureTimes works or if you have to convert the Vector to a List first, haven't programmed in scala before. I would try this out myself if I had a phone to test it on.
 
  • Like
Reactions: gsutton

enryea123

Senior Member
May 10, 2011
191
276
Milan
Looked closer at the commit and you're right, would take a bit of work to implement it in the older version.
I'm not sure but this might be the part that handles the refresh rate of the screen.
Code:
val startPreview =
    for { (cameraOpt, previewSurfaceOpt, previewSessionOpt, autoFocus, focusDistance, autoExposure, iso, exposureTime, metering)
          <- Rx {(this.camera(), this.previewSurface(), this.previewSession(),
                  this.autoFocus(), this.focusDistance(),
                  this.autoExposure(), this.iso(), this.exposureTime(), this.metering())}
Inside that for you could put in an if that checks if this.exposureTime() is less than for example 1/5s, then use a constant of 1/5s instead of this.exposureTime().
Well, I managed to set the preview to be updated every 1/10s by creating another variable "exposureTimePreview", BUT this way on the screen you don't see the actual brightness that the picture is going to have, but the one that it would have if the exposure time was actually 1/10, so it is not very handy and it's better to just leave it how it is now.

I also might have found a way to get the newer version to be able to use slower shutter speeds. The problem I think is this code on line 699.
Code:
val validExposureTimes = Rx { lcamera().toList flatMap { camera => exposureTimes filter { camera.exposureTimeRange contains _ }} }
Which is a list of exposure times the sensor supports. Now, if we set this equal to the var exposureTimes, I think we should be able to use the longer exposure times. I don't know if straight val validExposureTimes = exposureTimes works or if you have to convert the Vector to a List first, haven't programmed in scala before. I would try this out myself if I had a phone to test it on.
That line of code only exists in the latest source code on github, I'm using an older version, which in fact doesn't have that line (this missing line is probably the reason I could select longer exposures). I can even set exposures longer than 5 seconds, if they are between 6 and 9 the phone is likely to crash, but if they are 10s or longer the camera just seems to get crazy and some weird "moving purple shapes" are displayed on the screen.
 

CazeW

Senior Member
Nov 14, 2008
867
456
Well, I managed to set the preview to be updated every 1/10s by creating another variable "exposureTimePreview", BUT this way on the screen you don't see the actual brightness that the picture is going to have, but the one that it would have if the exposure time was actually 1/10, so it is not very handy and it's better to just leave it how it is now.

That line of code only exists in the latest source code on github, I'm using an older version, which in fact doesn't have that line (this missing line is probably the reason I could select longer exposures). I can even set exposures longer than 5 seconds, if they are between 6 and 9 the phone is likely to crash, but if they are 10s or longer the camera just seems to get crazy and some weird "moving purple shapes" are displayed on the screen.

That's why I suggested to use an if, so that when the exposure time becomes unreasonably long (like 1s or more) you use a constant refresh rate which would at least help with the framing. When the exposure time is faster, you of course use that as your refresh rate.

EDIT: You could also then bump up the ISO sensitivity for the preview so that you would still see the actual brightness of the picture (or at least close to it). For example, you want to take a picture that uses ISO 100 and 1s exposure. You lock the refresh rate at 1/4s and bump the ISO for the preview to 400 to compensate for the 2 stops slower refresh rate, and you should end up with an equally bright preview as what the picture will look like. (I think this is what most cameras do.)

I know that line of code only exists in the latest source code. What I meant is that if you edit that line, you might be able to use that version for your mod.
 
Last edited:
  • Like
Reactions: flatpedals

enryea123

Senior Member
May 10, 2011
191
276
Milan
That's why I suggested to use an if, so that when the exposure time becomes unreasonably long (like 1s or more) you use a constant refresh rate which would at least help with the framing. When the exposure time is faster, you of course use that as your refresh rate.

EDIT: You could also then bump up the ISO sensitivity for the preview so that you would still see the actual brightness of the picture (or at least close to it). For example, you want to take a picture that uses ISO 100 and 1s exposure. You lock the refresh rate at 1/4s and bump the ISO for the preview to 400 to compensate for the 2 stops slower refresh rate, and you should end up with an equally bright preview as what the picture will look like. (I think this is what most cameras do.)

I know that line of code only exists in the latest source code. What I meant is that if you edit that line, you might be able to use that version for your mod.
Thank you, I didn't understand what you meant. Those are some interesting improvements, I will consider them in the future for sure (right now I don't have much free time to spend on this project).
 
Last edited:

daniyal62

Senior Member
Nov 15, 2013
63
25
great job well done i was waiting for this
it would be great to add timer future to this app
 

Attachments

  • IMG_20161210_221630.jpg
    IMG_20161210_221630.jpg
    233.8 KB · Views: 1,963
Last edited:
  • Like
Reactions: LazerL0rd

Travisdroidx2

Senior Member
Sep 9, 2011
3,699
976
Bay Area California
In my app, tap on the magenta settings button, then on exposure and then de-select "Auto Exposure" and decrease the value of shooting time from 60/1000 to something like 60/60, you will see what a difference.

Sorry for the noob question. When turning off auto exposure you have two options to change. The s and iso, what do you recommend for both? I do not get the 60/60. Thank you for the mods. I am sure when I get it set correctly it will work great.
 

enryea123

Senior Member
May 10, 2011
191
276
Milan
Sorry for the noob question. When turning off auto exposure you have two options to change. The s and iso, what do you recommend for both? I do not get the 60/60. Thank you for the mods. I am sure when I get it set correctly it will work great.
Let's first make sure of a couple things: do you have the nexus 5x? have you downloaded the last version of my app? To make sure you did, download it again now. (you get the "60/60" only in the old app, in the new one it is written as "1 s").
The "s" is the exposure time, which is the time the shutter will stay opened to capture the light (in fact the "s" stands for seconds). The iso is the sensitivity of the camera but it is directly related to noise (higher iso = higher noise).

So, I recommend to keep the exposure time as long as possible (like 3-4-5 seconds) and lower the iso until you get the right photo brightess.
 
  • Like
Reactions: Travisdroidx2

Travisdroidx2

Senior Member
Sep 9, 2011
3,699
976
Bay Area California
Let's first make sure of a couple things: do you have the nexus 5x? have you downloaded the last version of my app? To make sure you did, download it again now. (you get the "60/60" only in the old app, in the new one it is written as "1 s").
The "s" is the exposure time, which is the time the shutter will stay opened to capture the light (in fact the "s" stands for seconds). The iso is the sensitivity of the camera but it is directly related to noise (higher iso = higher noise).

So, I recommend to keep the exposure time as long as possible (like 3-4-5 seconds) and lower the iso until you get the right photo brightess.

Thank you for explaining this. And yes I have the 5x and it is the new version of the app. Thank you for explaining this!
 

Top Liked Posts

  • There are no posts matching your filters.
  • 67

    Hey everyone!

    As some of you might know, the nexus 5x and nexus 6p cameras have a maximum exposure time in manual mode of 1/4.3 seconds, which is a real shame. Somebody suggested that Google made this choice because of the bigger size of the pixels, nonetheless the resulting pictures in very low light are not satisfying and none of the apps on the play store overrides the limit of 1/4.3 seconds.

    So, I managed to unlock longer exposure times (up to 5 seconds) on the nexus 5x camera to take some truly unbelievable night pictures. Since the sensor is the same, this app should work also on the nexus 6p and it might work even on other devices with at least android 5.0. It also probably works on the nexus 5, but doesn't appear to be working on the nexus 6.

    A big thank to PkmX for developing the original app Lcamera and to CazeW for his suggestions.

    Notice that the photos will be upside down, because the sensor is mounted upside down (at least in the nexus 5x). Just rotate them with your favorite photos editor. Also notice that the "screen refresh time" is the one of the exposure, so when you set an exposure of e.g. 3 seconds, the app will look like if it's stuck and refresh every 3s.

    I am not responsible for any damage that your phone might report. I've been using this app for a long time and everything works fine.
    You can download the .apk file and the source code at the bottom. To install the app you only need the .apk file, the source code is for developers who wish to improve the code.

    Check the difference between a manual camera downloaded from the play store and my app (the pics are resized here).
    Click on the images to enlarge.

    before.jpgafter.jpg

    How did I do it?
    I exploited the fact that the older versions of Lcamera by PkmX allowed up to 1/1.2 seconds of exposure time (probably because the nexus 5x wasn't supported yet), so I downloaded the source of lcamera 0.3 by PkmX, modified a few lines of code and compiled it.
    The exposure times of my modded app are: 5s, 4s, 3s, 2s, 1.5s, 1s, 0.5s, 0.23 s, ... and so on, up to 1/120000 s (the default minimum value) and you can change them in the settings of the app.

    Why not more than 5 seconds?
    Because the app gets really unstable, since those exposure times are not officially "hardware" supported.
    EDIT: a user suggested here that the app might be stable for even longer exposures with a longer kernel readahead.
    Beware that the app can be unstable even with exposure times longer than 3 seconds: if it starts crashing, just terminate it in the settings. I usually set the exposure time back to 1/10 s every time I close the app, otherwise the following times it might just crash when entering in it.
    Therefore, with this app you can get some beautiful night pictures, the drawback is that sometimes it might be unstable (because those exposures are not hardware supported).

    What did I modify?
    In src/pkmx/lcamera/MainActivity.scala I've modified lines 417, 419, 693 and deleted the line 1083. You can download my source code at the bottom, the original source code from github and compare them, to see in more detail which are the differences.
    I've also modified the app icon with one that I've personally designed.

    Thank you and have fun :)

    8
    If you still moddying it's should be possible reach 30sec + I recently got a Moto g5p which kept crashing at 2sec in Hal lib there is a timeout value and well as liboemcamera there is sof timeout I removed this can now preview 21sec+

    The advertised shutter value is calculated from a value found in libmmcamera_imx377.so

    That would be awesome if you could share how to find the values in the libs and how to modify them!


    Edit: I modified enryea123s source a bit...
    I added a toggle to select how many pictures are taken in burst mode (default was 7). I think I also fixed the orientation issue (at least for the JPEGs). The source code and the apk are attached.
    4
    The first one is Google camera and the second is from your app:confused::confused:
    In my app, tap on the magenta settings button, then on exposure and then de-select "Auto Exposure" and decrease the value of shooting time from 1/10 to something like 1-2, you will see what a difference.
    4
    Can you add a 30 seconds option in exposure or tell me please the ide that you used for compile the source? many thanks.
    I haven't used any ide, only the terminal. You have to download SBT and scala, it's a bit messy because the apk is old so it takes some time to fix all the broken libraries, but you can do it. The source code in the first post should already have all the libraries fixed, so use that one.

    Anyway, with a 30 seconds exposure time the app just crashes immediately, so it's not worth it