rnboi05
rnboi05

Reputation: 113

Camera preview is dark using Camera2

I am trying to use Camera2 to allow an app to take a simple picture. I managed to get a working sample using android-Camera2Basic sample code, the problem is that the camera preview is very dark (same problem as this other question), following some answers i did get a proper FPS range [15, 15], setting this in the lockFocus() method allows the app to great a clear picture with correct brightness and fixes the preview from the camera:

private void lockFocus() {
    try {
        // This is how to tell the camera to lock focus.
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, Range.create(15, 15));

        // Tell #mCaptureCallback to wait for the lock.
        mState = STATE_WAITING_LOCK;
        mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

But the preview before taking the pic is still very dark. I tried to set up the same line of code in other parts of the sample but is not working. How can i fix it in order to ge the same results in the preview? I am working with a Samsung SM-P355M tablet.

Upvotes: 1

Views: 757

Answers (2)

Perraco
Perraco

Reputation: 17340

Using an FPS range with equal lower and upper bounds, such as [15,15], [30,30], [etc...], will put a constrain to the AE algorithm about how much it can adjust to light changes, which therefore may produce dark results. Such type of ranges are meant for video recording to maintain a constant FPS. For photos you need to find a range with a wide spread between the lower and upper bound, such as [7,30], [15,25], [etc...]

The next method can help you to find the optimal FPS range. Take into account that it is meant for photos and not video recording as it discards FPS ranges with equal lower and upper bounds.

(Adjust MIN_FPS_RANGE and MAX_FPS_RANGE to your requirements)

@Nullable
public static Range<Integer> getOptimalFpsRange(@NonNull final CameraCharacteristics characteristics) {
    final int MIN_FPS_RANGE = 0;
    final int MAX_FPS_RANGE = 30;

    final Range<Integer>[] rangeList = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);

    if ((rangeList == null) || (rangeList.length == 0)) {
        Log.e(TAG, "Failed to get FPS ranges.");
        return null;
    }

    Range<Integer> result = null;

    for (final Range<Integer> entry : rangeList) {
        int candidateLower = entry.getLower();
        int candidateUpper = entry.getUpper();

        if (candidateUpper > 1000) {
            Log.w(TAG,"Device reports FPS ranges in a 1000 scale. Normalizing.");
            candidateLower /= 1000;
            candidateUpper /= 1000;
        }

        // Discard candidates with equal or out of range bounds
        final boolean discard = (candidateLower == candidateUpper)
                || (candidateLower < MIN_FPS_RANGE)
                || (candidateUpper > MAX_FPS_RANGE);

        if (discard == false) {
            // Update if none resolved yet, or the candidate
            // has a >= upper bound and spread than the current result
            final boolean update = (result == null)
                    || ((candidateUpper >= result.getUpper()) && ((candidateUpper - candidateLower) >= (result.getUpper() - result.getLower())));

            if (update == true) {
                result = Range.create(candidateLower, candidateUpper);
            }
        }
    }

    return result;
}

Upvotes: 2

rnboi05
rnboi05

Reputation: 113

After lots of reseach it seams there is no easy fix for this (at least not with our same hardware), so we implemented a new version of the camera activities this time using the deprecated Camera Api and everything works as espected. Not really a clean solution but so far works for me.

Upvotes: 0

Related Questions