0

I am trying to develop an application which crops an image. The rectangle to crop is created by touching two times on the image (topLeft point, bottomRight point). When the user has tapped, a red rectangle is displayed on the screen to see the crop area.

Then with this rectangle, I would like to crop the image. But I am facing to an issue, the crop does not work and give me bad result.

Below my code :

@objc
func tap(_ sender: UITapGestureRecognizer) {
    let location = sender.location(in: sourceImageView)

    print(#function + ":: location: \(location)")

    if location1 == nil {
        location1 = location
    } else if location2 == nil {
        location2 = location

        print("Processing to crop the image...")
        guard let _topLeft = location1,
            let _bottomRight = location2 else {
                fatalError("Processing failed...")
        }
        let _topRight = CGPoint(x: _bottomRight.x, y: _topLeft.y)
        let _bottomLeft = CGPoint(x: _topLeft.x, y: _bottomRight.y)
        let _width = _topLeft.distance(point: _topRight)
        let _height = _topLeft.distance(point: _bottomLeft)
        let cropArea = CGRect(origin: _topLeft, size: CGSize(width: _width, height: _height))

        // Displaying red rectangle on the source image          
        let outline = CALayer()
        outline.frame = cropArea
        outline.borderWidth = 2.0
        outline.borderColor = UIColor.red.cgColor
        sourceImageView.layer.addSublayer(outline)

        guard let sourceImage = sourceImageView.image,
            let sourceCGImage = sourceImage.cgImage else {
            fatalError("Cannot get CG Image from source img")
        }

        let viewSize = self.view.frame.size

        let imageViewScaleWidth = viewSize.width / CGFloat(sourceCGImage.width)
        let imageViewScaleHeight = viewSize.height / CGFloat(sourceCGImage.height)

        let scale = 1 / min(imageViewScaleWidth, imageViewScaleHeight)
        let scaleWidth = 1 / imageViewScaleWidth
        let scaleHeight = 1 / imageViewScaleHeight


        let newWidth = cropArea.height * scale
        let newHeight = cropArea.width * scale
        let newXCord = (cropArea.topLeft.x * scale) + newHeight
        let newYCord = (cropArea.topLeft.y * scale)


        let newCropArea = CGRect(origin: CGPoint(x: newXCord,
                                                 y: newYCord),
                                 size: CGSize(width: newHeight,
                                              height: newWidth))

        guard let croppedSourceImage = sourceCGImage.cropping(to: newCropArea) else {
            print("Cannot crop the current image.")
            return
        }
    }
}

I think my issue comes from the rectangle projection on the source image.

Thanks

EDIT :

public extension CGPoint {
    /// Distance between two points.
    ///
    /// - Parameter point: A `CGPoint` instance.
    public func distance(point p: CGPoint) -> CGFloat {
        return sqrt(pow((p.x - x), 2) + pow((p.y - y), 2))
    }
}
YMonnier
  • 1,384
  • 2
  • 19
  • 30
  • What is _topLeft.distance(point: _topRight)? That's not a built-in CGPoint method. If you implemented that yourself it may be what's causing trouble. – Dalton Sweeney Jun 12 '18 at 17:28
  • @DaltonSweeney I edited my post. It is just a function to calculate a distance between two points. – YMonnier Jun 12 '18 at 17:31
  • @matt the content mode is Scale To Fill – YMonnier Jun 12 '18 at 18:00
  • The first duplicate answer shows you what to do to read a crop rect from the image view onto the original image and crop it for aspect fill. Scale to fill can stretch the image out of its aspect ratio; you really should not be using that, as it distorts the image. – matt Jun 12 '18 at 18:14
  • @matt thank you for your answer, posts helped me. However, I am trying to make another application with Vision and SwiftOCR, I am trying to crop the text detected by Vision to inject it to OCR function. It seems to be not working with your solutions. I obtain incoherent result. – YMonnier Jun 20 '18 at 12:29
  • But none of that is in your question. All you said is “crops an image”, and I’ve told you how to do that. And “the crop does not work and give me bad result“ is meaningless. To get better help, ask a better question, describing the real issue, with enough detail to allow us to reproduce the problem. – matt Jun 20 '18 at 12:58
  • Above all, I’ve shown you the technique for finding “the rectangle projection on the source image”, which is what you said was the problem. – matt Jun 20 '18 at 13:18

0 Answers0