Is this the correct translation from Objective-C code to Swift?

Hi all,
In AVCameraCalibrationData.h there is reference implementation on how to correct images for lens distortion. I am using this code to undistort the AVDepthData.
I was wondering whether I did the "translation" from Objective-C to Swift correct?
Thank you.
This is objective-c:

- (CGPoint)lensDistortionPointForPoint:(CGPoint)point
                           lookupTable:(NSData *)lookupTable
               distortionOpticalCenter:(CGPoint)opticalCenter
                             imageSize:(CGSize)imageSize
{
    // The lookup table holds the relative radial magnification for n linearly spaced radii.
    // The first position corresponds to radius = 0
    // The last position corresponds to the largest radius found in the image.

    // Determine the maximum radius.
    float delta_ocx_max = MAX( opticalCenter.x, imageSize.width  - opticalCenter.x );
    float delta_ocy_max = MAX( opticalCenter.y, imageSize.height - opticalCenter.y );
    float r_max = sqrtf( delta_ocx_max * delta_ocx_max + delta_ocy_max * delta_ocy_max );

    // Determine the vector from the optical center to the given point.
    float v_point_x = point.x - opticalCenter.x;
    float v_point_y = point.y - opticalCenter.y;

    // Determine the radius of the given point.
    float r_point = sqrtf( v_point_x * v_point_x + v_point_y * v_point_y );

    // Look up the relative radial magnification to apply in the provided lookup table
    float magnification;
    const float *lookupTableValues = lookupTable.bytes;
    NSUInteger lookupTableCount = lookupTable.length / sizeof(float);

    if ( r_point < r_max ) {
        // Linear interpolation
        float val   = r_point * ( lookupTableCount - 1 ) / r_max;
        int   idx   = (int)val;
        float frac  = val - idx;

        float mag_1 = lookupTableValues[idx];
        float mag_2 = lookupTableValues[idx + 1];

        magnification = ( 1.0f - frac ) * mag_1 + frac * mag_2;
    }
    else {
        magnification = lookupTableValues[lookupTableCount - 1];
    }

    // Apply radial magnification
    float new_v_point_x = v_point_x + magnification * v_point_x;
    float new_v_point_y = v_point_y + magnification * v_point_y;

    // Construct output
    return CGPointMake( opticalCenter.x + new_v_point_x, opticalCenter.y + new_v_point_y );
}


this is my swift 4.2 code:


func lensDistortionPointForPoint(point: CGPoint, lookupTable: Data, opticalCenter: CGPoint, imageSize: CGSize) -> CGPoint{
        // The lookup table holds the relative radial magnification for n linearly spaced radii.
        // The first position corresponds to radius = 0
        // The last position corresponds to the largest radius found in the image.
       
        // Determine the maximum radius.
        let delta_ocx_max = max( opticalCenter.x, imageSize.width  - opticalCenter.x );
        let delta_ocy_max = max( opticalCenter.y, imageSize.height - opticalCenter.y );
        let r_max = sqrtf( Float(delta_ocx_max * delta_ocx_max + delta_ocy_max * delta_ocy_max));
       
        // Determine the vector from the optical center to the given point.
        let v_point_x = point.x - opticalCenter.x;
        let v_point_y = point.y - opticalCenter.y;
       
        // Determine the radius of the given point.
        let r_point = sqrtf( Float( v_point_x * v_point_x + v_point_y * v_point_y ));
       
        // Look up the relative radial magnification to apply in the provided lookup table
       
        return lookupTable.withUnsafeBytes { (bytes: UnsafePointer) in
            var magnification:Float
            let lookupTableValues = bytes
            let lookupTableCount = lookupTable.count;
           
            if ( r_point < r_max ) {
                // Linear interpolation
                let val   = r_point * ( Float(lookupTableCount) - 1 ) / r_max;
                let idx   = val;
                let frac  = val - idx;
               
                let mag_1 = lookupTableValues[Int(idx)];
                let mag_2 = lookupTableValues[Int(idx) + 1];
               
                magnification = ( 1.0 - frac ) * mag_1 + frac * mag_2;
            }
            else {
                magnification = lookupTableValues[lookupTableCount - 1];
            }
           
            // Apply radial magnification
            let new_v_point_x = v_point_x + CGFloat(magnification) * v_point_x;
            let new_v_point_y = v_point_y + CGFloat(magnification) * v_point_y;
           
            // Construct output
            return CGPoint( x: opticalCenter.x + new_v_point_x, y: opticalCenter.y + new_v_point_y );
        };
    }

Any comments or remarks are highly appreciated, as I am still a noob in iOS development.
Thank you

That will not compile.


How is lookUpTable defined ?

You should add the type for UnsafePointer:

lookupTable.withUnsafeBytes { (bytes: UnsafePointer) in


A few comments:

- Swift names do not usually use underscore. So v_point should be vPoint for instance


In the same way, names like

lensDistortionPointForPoint(point: CGPoint

are objc style

They are now more usually

lensDistortionPoint(forPoint point: CGPoint

Accepted Answer

I have tried to translate your Objective-C into Swift by myself and got this:

func lensDistortionPoint(for point: CGPoint, lookupTable: Data, distortionOpticalCenter opticalCenter: CGPoint, imageSize: CGSize) -> CGPoint {
    // The lookup table holds the relative radial magnification for n linearly spaced radii.
    // The first position corresponds to radius = 0
    // The last position corresponds to the largest radius found in the image.

    // Determine the maximum radius.
    let delta_ocx_max = Float(max(opticalCenter.x, imageSize.width  - opticalCenter.x))
    let delta_ocy_max = Float(max(opticalCenter.y, imageSize.height - opticalCenter.y))
    let r_max = sqrt(delta_ocx_max * delta_ocx_max + delta_ocy_max * delta_ocy_max)

    // Determine the vector from the optical center to the given point.
    let v_point_x = Float(point.x - opticalCenter.x)
    let v_point_y = Float(point.y - opticalCenter.y)

    // Determine the radius of the given point.
    let r_point = sqrt(v_point_x * v_point_x + v_point_y * v_point_y)

    // Look up the relative radial magnification to apply in the provided lookup table
    let magnification: Float = lookupTable.withUnsafeBytes { (lookupTableValues: UnsafePointer<Float>) in
        let lookupTableCount = lookupTable.count / MemoryLayout<Float>.size

        if r_point < r_max {
            // Linear interpolation
            let val   = r_point * Float(lookupTableCount - 1) / r_max
            let idx   = Int(val)
            let frac  = val - Float(idx)

            let mag_1 = lookupTableValues[idx]
            let mag_2 = lookupTableValues[idx + 1]

            return (1.0 - frac) * mag_1 + frac * mag_2
        } else {
            return lookupTableValues[lookupTableCount - 1]
        }
    }

    // Apply radial magnification
    let new_v_point_x = v_point_x + magnification * v_point_x
    let new_v_point_y = v_point_y + magnification * v_point_y

    // Construct output
    return CGPoint(x: opticalCenter.x + CGFloat(new_v_point_x), y: opticalCenter.y + CGFloat(new_v_point_y))
}

Check some significant differences (ignoring subtle things such as spacing or semicolons).


1. I would choos the method name consistent with the way how Swift compiler imports Objective-C methods.


This can be important when you migrate your Objective-C project into Swift. Your existing Swift code may be calling the imported method still in Objective-C.


2. The Objective-C code uses `float` for most intermediate variables, so I would choose `Float` for these variables.


In your Swift code, some of such variable are of type `CGFloat`. So the calculation result may be slightly different than in Ojective-C.


3. I would try to make the range of closure passed to `withUnsafeBytes`, as narrow as possible.


I believe this may help the compiler to optimize the code. (Though, in a short code like this, the difference may be very little.)


So, if such three things are not important for your usage, your code seems to be a perfect translation that I wonder if I really understand the word noob.


Just that the line 20. in your posted code lacks type parameter:

    return lookupTable.withUnsafeBytes { (bytes: UnsafePointer<Float>) in

I'm afraid that may be lost while posting your code.

How exactly would you apply this function to the captured image? I am relatively new to this but I am trying to re-create the straighten up app from WWDC 2017. I can't find that sample app anywhere either..


I have downloaded the AVCam sample code but I am not sure which inputs this function should take after I have captured the image. Any ideas on how to implement? Any help would be greatly appreciated!

To get better responses...

- Better start your own thread. Not many readers would have attention the a new comment on the SOLVED thread.

(You can include the links to the related threads.)

- Please clarify what you want to do, show your code or at least try to find what session of WWDC 2017 you are referring.

Is this the correct translation from Objective-C code to Swift?
 
 
Q