Proposed 'correction' to focus.c

Issue #2719 resolved
Former user created an issue

The current method to calculate diffraction includes a magnification term, which, when coupled with the optical blur, has the impact of changing the HFD with focus.

This is considered 'confusing', as the magnification (f/(x-f), where f is focal length and x focus distance) impact on diffraction really does seriously impact non-macro photography; and an HFD doesn't have any meaning in macro photography.

Based on the above I propose we change the equation in focus.c, ie from:

const uint64_t diff = (244freqlens_info.aperture*(1+imag)/imag)/1000000; // Diffraction blur in microns

to

const uint64_t diff = (244freqlens_info.aperture/1000000; // Diffraction blur in microns

This will create a diffraction that is only dependent on aperture and will not vary as we vary focus.

Comments (4)

  1. Garry George

    A1ex sorry I forgot to log in when I posted the above.

    I strongly suggest the above gets implemented.

    Cheers

    Garry

  2. Garry George

    Damn: I forgot to say, that this change is ONLY needed when you calculate the HFD, ie calculate the HFD with a diffraction that is not dependent on focus, and let diffraction have an image magnification impact the rest of the time.

    I hope this clear?

    I'll post my suggested changes soon.

  3. Garry George

    A1ex, I'm not a C programmer, however, I think this is the changed code, ie to create a focus independent hyperfocal distance:

    // Total (defocus + diffraction) blur dia in microns
    uint64_t coc = dof_info_coc;

    const uint64_t  fd = lens_info.focus_dist * 10; // into mm
    const uint64_t  fl = lens_info.focal_len; // already in mm
    
    // If we have no aperture value then we can't compute any of this
    // Also not all lenses report the focus length or distance
    if (fl == 0 || lens_info.aperture == 0 || fd == 0)
    {
        lens_info.dof_near      = 0;
        lens_info.dof_far       = 0;
        lens_info.hyperfocal    = 0;
        return;
    }
    
    // Set up some dof info
    const uint64_t  freq = 550;         // mid vis diffraction freq in nm (use 850 if IR)
    const uint64_t  imag = (fd-fl)/fl;  // inverse of magnification (to keep as integer)
    const uint64_t  diff = (244*freq*lens_info.aperture*(1+imag)/imag)/1000000; // Diffraction blur in microns
    const uint64_t  diff2 = (244*freq*lens_info.aperture/1000000; // Focus indepedent diffraction blur in microns (used to estimate H)
    
    int dof_flags = 0;
    
    if (dof_info_formula == DOF_FORMULA_DIFFRACTION_AWARE)
    {
        // Test if large aperture diffraction limit reached 
        if (diff >= coc)
        {
            // note: in this case, DOF near and far will collapse to focus distance
            dof_flags |= DOF_DIFFRACTION_LIMIT_REACHED;
            coc = 0;
        }
        else
        {
            // calculate defocus only blur in microns
            const uint64_t sq = (coc*coc - diff*diff);
            coc = (int) sqrtf(sq); // Defocus only blur
        }
    }
    
    const uint64_t        fl2 = fl * fl;
    
    // Calculate hyperfocal distance H based on focus independent diffraction blur
        if (diff2 >= dof_info_coc)
        {
            // note: in this case, DOF near and far will collapse to focus distance
            dof_flags |= DOF_DIFFRACTION_LIMIT_REACHED;
            coc = 0;
        }
        else
        {
            // calculate defocus only blur in microns
            const uint64_t sq = (dof_info_coc*dof_info_coc - diff2*diff2);
            coc = (int) sqrtf(sq); // Defocus only blur
        }
    const uint64_t H = coc ? fl + ((10000 * fl2) / (lens_info.aperture  * coc)) : 1000 * 1000;
    lens_info.hyperfocal = H;
    
  4. Log in to comment