Android camera preview is dark

11.9k views Asked by At

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.

3

There are 3 answers

8
Alex Cohn On BEST ANSWER

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.

3
Machine Tribe On

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

6
Praveena On

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.