Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a7beefcc authored by Eino-Ville Talvala's avatar Eino-Ville Talvala
Browse files

DngCreator: Use new LENS_DISTORTION result field if available.

Also move coefficient adjustment code to this level to account for
different scaling for the older LENS_RADIAL_DISTORTION and new
LENS_DISTORTION fields.

Test: DngCreator CTS tests continue to pass, inspecting saved DNGs shows expected values.
Bug: 74641761
Change-Id: I29eb0c463eb4bde1ca8b03104b29d95bc48cd755
parent 5a36c134
Loading
Loading
Loading
Loading
+68 −9
Original line number Diff line number Diff line
@@ -1770,15 +1770,73 @@ static sp<TiffWriter> DngCreator_setup(JNIEnv* env, jobject thiz, uint32_t image
        status_t err = OK;

        // Set up rectilinear distortion correction
        camera_metadata_entry entry3 =
                results.find(ANDROID_LENS_RADIAL_DISTORTION);
        float distortion[6] {1.f, 0.f, 0.f, 0.f, 0.f, 0.f};
        bool gotDistortion = false;

        camera_metadata_entry entry4 =
                results.find(ANDROID_LENS_INTRINSIC_CALIBRATION);

        if (entry3.count == 6 && entry4.count == 5) {
        if (entry4.count == 5) {
            float cx = entry4.data.f[/*c_x*/2];
            float cy = entry4.data.f[/*c_y*/3];
            err = builder.addWarpRectilinearForMetadata(entry3.data.f, preWidth, preHeight, cx,
            // Assuming f_x = f_y, or at least close enough.
            // Also assuming s = 0, or at least close enough.
            float f = entry4.data.f[/*f_x*/0];

            camera_metadata_entry entry3 =
                    results.find(ANDROID_LENS_DISTORTION);
            if (entry3.count == 5) {
                gotDistortion = true;
                float m_x = std::fmaxf(preWidth - cx, cx);
                float m_y = std::fmaxf(preHeight - cy, cy);
                float m_sq = m_x*m_x + m_y*m_y;
                float m = sqrtf(m_sq); // distance to farthest corner from optical center
                float f_sq = f * f;
                // Conversion factors from Camera2 K factors for new LENS_DISTORTION field
                // to DNG spec.
                //
                //       Camera2 / OpenCV assume distortion is applied in a space where focal length
                //       is factored out, while DNG assumes a normalized space where the distance
                //       from optical center to the farthest corner is 1.
                //       Scale from camera2 to DNG spec accordingly.
                //       distortion[0] is always 1 with the new LENS_DISTORTION field.
                const double convCoeff[5] = {
                    m_sq / f_sq,
                    pow(m_sq, 2) / pow(f_sq, 2),
                    pow(m_sq, 3) / pow(f_sq, 3),
                    m / f,
                    m / f
                };
                for (size_t i = 0; i < entry3.count; i++) {
                    distortion[i+1] = convCoeff[i] * entry3.data.f[i];
                }
            } else {
                entry3 = results.find(ANDROID_LENS_RADIAL_DISTORTION);
                if (entry3.count == 6) {
                    gotDistortion = true;
                    // Conversion factors from Camera2 K factors to DNG spec. K factors:
                    //
                    //      Note: these are necessary because our unit system assumes a
                    //      normalized max radius of sqrt(2), whereas the DNG spec's
                    //      WarpRectilinear opcode assumes a normalized max radius of 1.
                    //      Thus, each K coefficient must include the domain scaling
                    //      factor (the DNG domain is scaled by sqrt(2) to emulate the
                    //      domain used by the Camera2 specification).
                    const double convCoeff[6] = {
                        sqrt(2),
                        2 * sqrt(2),
                        4 * sqrt(2),
                        8 * sqrt(2),
                        2,
                        2
                    };
                    for (size_t i = 0; i < entry3.count; i++) {
                        distortion[i] = entry3.data.f[i] * convCoeff[i];
                    }
                }
            }
            if (gotDistortion) {
                err = builder.addWarpRectilinearForMetadata(distortion, preWidth, preHeight, cx,
                        cy);
                if (err != OK) {
                    ALOGE("%s: Could not add distortion correction.", __FUNCTION__);
@@ -1786,6 +1844,7 @@ static sp<TiffWriter> DngCreator_setup(JNIEnv* env, jobject thiz, uint32_t image
                    return nullptr;
                }
            }
        }

        size_t listSize = builder.getSize();
        uint8_t opcodeListBuf[listSize];