11

I am trying to create a custom camera app. I followed the Android Developer example from here with minor tweaks. However, my camera preview turns out to be rather dark. On the other hand, the stock camera gives a much brighter preview.

I have tried several settings to make it work better but it seems none of them are having any impact. Relevant code is posted here.

CameraActivity (Main)

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camera);
    if(CameraHelper.checkCameraHardware(this)) {
        mHelper = new CameraHelper(this, getWindowManager().getDefaultDisplay());
    }

    FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
    mPreview = new CameraPreview(this, CameraHelper.camera);
    mPreview.setLayoutParams(new LayoutParams(CameraHelper.mSize.width, CameraHelper.mSize.height, Gravity.CENTER));

    preview.addView(mPreview);

}

CameraHelper class (initialize the camera and set the default parameters)

    public CameraHelper(CameraListener listener, Display display){
        mListener = listener;
        camera = getCameraInstance();

        mParameters = camera.getParameters();
        initCameraParameters();

        mSize = getPreviewSize(display);
        mParameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);
        mParameters.setPictureSize(2560, 1920);

        mParameters.setAutoExposureLock(false);
        mParameters.setAutoWhiteBalanceLock(false);
        mParameters.set("iso", "ISO800"); //Tried with 400, 800, 600 (values obtained from flatten())
        mParameters.setColorEffect("none");
        mParameters.setPictureSize(2560, 1920);
        mParameters.setPreviewFrameRate(20);
        mParameters.set("scene-mode", "auto");
        mParameters.setFocusMode("auto");
        mParameters.setExposureCompensation(4);     
        camera.setParameters(mParameters);
    }

The Camera sends the frames to SurfaceHolder.Surface from the example linked from developer pages above.

See the difference here: Stock Camera App Stock Camera Preview My Camera App My Camera app

Tried setting the ISO, etc based on upack parameters from the camera as posted here. It still didn't work.

Parameters(16369): effect-values=none,mono,negative,sepia,aqua,sharpen,purple,green-tint,blue-tint,pink,yellow,red-tint,mono,antique;exposure-compensation-step=0.5;focal-length=3.43;focus-areas=(0,0,0,0,0);focus-distances=0.10,1.20,Infinity;focus-mode-values=auto,macro,facedetect;gps-altitude=0;gps-latitude=0;gps-longitude=0;gps-processing-method=GPS;gps-timestamp=0;horizontal-view-angle=51.2;iso=auto;iso-values=auto,ISO50,ISO100,ISO200,ISO400,ISO800,ISO1600;jpeg-quality=1;jpeg-thumbnail-height=480;jpeg-thumbnail-size-values=640x480,0x0;jpeg-thumbnail-width=640;max-exposure-compensation=4;max-num-focus-areas=1;max-zoom=12;min-exposure-compensation=-4;picture-format=jpeg;picture-format-values=jpeg;picture-size-values=2560x1920,2560x1536,2048x1536,2048x1232,1600x1200,1600x960,800x480,640x480;preview-format=yuv420sp;preview-format-values=yuv420sp;preview-fps-range=15000,30000;preview-fps-range-values=(15000,30000);preview-frame-rate=30;preview-frame-rate-values=30;preview-size=640x480;preview-size-values=1280x720,800x480,720x480,640x480,352x288;rotation=0;scene-mode=auto;scene-mode-values=auto,portrait,landscape,night,beach,snow,sunset,fireworks,sports,party,candlelight,asd,backlight,dusk-dawn,text,fall-color;vertical-view-angle=39.4;video-frame-format=yuv422i-yuyv;whitebalance-values=auto,incandescent,fluorescent,daylight,cloudy-daylight;zoom=0;zoom-ratios=100,125,150,175,200,225,250,275,300,325,350,375,400;zoom-supported=true;focus-mode=auto;picture-size=2560x1920;exposure-compensation=4;

Edit: Upon further testing based on comments below, it appears that its just the preview that is turning out darker than it should be. The actual captured image is well lit and exposure compensatiion seems to be working fine. Its just the preview that is giving me a headache. Tested on i9003 running CM11 and Nexus 10 running stock android.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Puneet
  • 653
  • 1
  • 7
  • 18
  • You might wanna try to "play around"/increase the exposure compenstation in your settings. Does it change anything? – Florian Barth Nov 17 '14 at 07:51
  • I have it at maximum supported exposure compensation, i.e. 4 (mParameters.setExposureCompensation(4)) for the phone I am using. That picture is taken with max exposure compensation. – Puneet Nov 17 '14 at 07:54
  • Did you get the max/min value for expo-compensation from "params.getMinExposureCompensation()" and "params.getMaxExposureCompensation()"? – Florian Barth Nov 17 '14 at 12:58
  • Yes, initially I set the max exposure using params.getMaxExposureCompensation() but when it had no effect, I tried to set it manually based on the dump received from params.unpack() (ranges from 4 to -4). See unpack dump above. – Puneet Nov 17 '14 at 13:03
  • I tested it further. It turns out that the exposure settings are having no effect on the preview but the actual image is well lit. Now, how do I sync the preview with the actual image. Any suggestions? (Edit: I will edit the question with new information). – Puneet Nov 17 '14 at 13:20
  • And just as I see it: Your parameters say "exposure-compensation=0;" You might wanna try getting the feasible values from the calls mentioned above. – Florian Barth Nov 17 '14 at 13:20
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/65078/discussion-between-florian-barth-and-puneet). – Florian Barth Nov 17 '14 at 13:22
  • I'm experiencing the same problem. Did you find a solution for it? – PerracoLabs Nov 29 '14 at 18:17
  • Nope. I couldn't spare the time to go through the source of aosp camera. There has to be some post processing going on. – Puneet Nov 29 '14 at 18:22
  • Notice that your code tries to set frame rate to 20, but the parameters shows that only 30 is supported. Such inconsistency can cause big troubles on some devices. – Alex Cohn Jan 03 '15 at 18:59
  • I have the same issue...setting frame rate and scene mode doesn't work for me either, so it's not your imagination :-( – kenyee May 31 '16 at 18:44
  • One other weird thing is it works fine on Galaxy S6/S7 phones – kenyee May 31 '16 at 19:05

3 Answers3

14

There appears to be a bug with certain cameras reporting the supported preview FPS range incorrectly. You can identify the offending devices by those that return the same value for min and max when calling

getPreviewFpsRange (int[] range)

In my case I saw this issue with devices that reported (15000, 15000) and (30000, 30000), but not with devices where the values were different, like (7000, 30000).

The best solution I could find was to identify the supported FPS range that had different values for min and max, and set that:

Camera.Parameters params = camera.getParameters();
final int[] previewFpsRange = new int[2];
params.getPreviewFpsRange(previewFpsRange);
if (previewFpsRange[0] == previewFpsRange[1]) {
    final List<int[]> supportedFpsRanges = params.getSupportedPreviewFpsRange();
    for (int[] range : supportedFpsRanges) {
        if (range[0] != range[1]) {
            params.setPreviewFpsRange(range[0], range[1]);
            break;
        }
    }
}
camera.setParameters(params);

This works because the ranges reported seem to only have 1 item with the actual range. Eg:

BLU Vivo XL:

preview-fps-range=30000,30000
preview-fps-range-values=(15000,15000),(20000,20000),(24000,24000),(5000,30000),(30000,30000)

Pixel:

preview-fps-range=7000,30000
preview-fps-range-values=(15000,15000),(24000,24000),(7000,30000),(30000,30000)

A more robust approach would be to set the min and max by comparing all those available.

Paul Burke
  • 25,496
  • 9
  • 66
  • 62
Praveena
  • 6,340
  • 2
  • 40
  • 53
  • This could easily be the issue with the original problem: as I noted in a comment, the code there set FPS=20 while the camera reported support for range (15-30) fps. – Alex Cohn Jan 25 '15 at 09:54
  • In my nexus 7 I can change the scene mode but not able to show color effects in preview even though taken picture gets effects.. I can see color effects for fraction of second while pressing shutter button. I tried all combination of FPS range but no use. Any idea? – Praveena Jan 25 '15 at 10:02
  • Let me try the FPS tweak(correction) and get back to you on this. I did try a lot of settings so I am keeping my fingers crossed. – Puneet Jan 26 '15 at 06:49
  • @Praveen: no, I don't know why color effects do not stick. I don't have a Nexus 7 device here to check. – Alex Cohn Jan 27 '15 at 07:48
  • Thanks a lot, it fixes the issue on a lot of devices for us as well ! – Viish Mar 28 '18 at 09:03
  • Kindle Fire HD 2018 running Android 9.0. This fixed it for me. Thanks! – anonymous-one Apr 14 '21 at 22:01
4

In addition to the previous answers, this can happen with Camera2 if you are doing

createCaptureRequest(CameraDevice.TEMPLATE_RECORD)

change to

createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)

UPDATE: I have also begun to see a dark preview on some newer Pixel devices and this happens if you don't set the fps in the capture request or if you set the fps to something that the device can't handle BUT not on Samsung devices like the Note 10 and S10

Machine Tribe
  • 871
  • 9
  • 13
  • This fixed it for me. But I wonder what i'm losing with this template (probably video quality) – Vlad May 01 '18 at 09:11
  • Works for me too and have same concern as @Vlad – prex Mar 24 '20 at 05:43
  • 1
    You should be using the 'CameraDevice.TEMPLATE_PREVIEW' while you are in a preview state. Then, once you are ready to record, you switch to 'TEMPLATE_RECORD' for your capture request. – Machine Tribe May 04 '20 at 14:06
1

From my experiments, scene-mode setting can change the preview (unlike ISO or exposure-compensation, which both work for captured pictures). Don't use auto. Try scene-mode-values=night or scene-mode=dusk-dawn.

The problem with scenes is that the supported values are not standardized across devices. But some kind of night is usually present.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • 1
    I have tested this on Nexus 7(Android L) and front camera works fine but back camera showing dark preview. I tried setting night mode but no use. I tried other popular camera apps and I found out that even they failed doing it. Only camera working fine is google camera. Is there anything to do with color effects? – Praveena Jan 18 '15 at 08:24
  • @Praveen: I have not done reverse engineering on the [GoogleCamera](https://play.google.com/store/apps/details?id=com.google.android.GoogleCamera), but judging from its requirements (4.4 and higher) and extra attention to Nexus devices, I may suppose that they tuned it to the less-than-wonderful back camera on Nexus 7. – Alex Cohn Jan 19 '15 at 08:46
  • Scene modes like night or party will activate the camera - this is the case for Nexus 5 at least. What I did was to measure the light and then gradually change the exposure value based on that. This resulted in a nice result. – slott Jan 19 '15 at 08:48
  • 1
    @AlexCohn Thanks for your reply. Somehow I think that it is mandatory to use Camera2 api's rather than deprecated Camera apis. Just now I worked on Camera2 api's on my Nexus 7 and surprisingle evrything works fine. But only problem I have is, my app has lot of customization and it is too much work to port into Camera2.. – Praveena Jan 19 '15 at 08:56
  • @Praveen: thanks for this info. It is not very surprising that Camera2 works better on Nexus 7(Androoid L) than the deprecated API. Me wonders, if the older ROM would behave same way. Unfortunately, I have encountered 4.4+ stock ROMs without Camera2 support (_inspite of this being mandatory_), and it will take a while until the old API will phase out business-wise. – Alex Cohn Jan 19 '15 at 09:18
  • Sorry for a late reply. I sort of stopped following the issue after a month of no solution (was a trial project anyway). Unfortunately, setting scenes manually did not solve the problem. – Puneet Jan 26 '15 at 06:47
  • so any solution for this? – Tomero Indonesia Aug 04 '20 at 03:15
  • @TomeroIndonesia this requires delicate device-dependent tuning. The other answers here seem to improve situation on some devices. – Alex Cohn Aug 04 '20 at 07:11