用swift划分图像阵列中的图像

时间:2017-03-24 19:56:06

标签: ios swift swift2 uiimage

我试图将图像分割成16个(在矩阵中)。我使用的是swift 2.1。这是代码:

let cellSize = Int(originalImage.size.height) / 4

for i in 0...4 {
        for p in 0...4 {
            let tmpImgRef: CGImage = originalImage.CGImage!

            let rect: CGImage = CGImageCreateWithImageInRect(tmpImgRef, CGRectMake(CGFloat(i * cellSize), CGFloat(p * cellSize), CGFloat(cellSize), CGFloat(cellSize)))!

            gameCells.append(cell)

        }
    }

这有效,但返回的图像只是原始图像的一部分。我一直在搜索,我知道这是因为当我创建一个CGImage时,它的大小与UIImage不同,但我不知道如何解决它。如果我可以使用CGImage的高度而不是UIImage来制作变量cellSize,我想我会修复它,但我无法获得CGImage高度。

感谢您的帮助!

3 个答案:

答案 0 :(得分:4)

根本问题是UIImageCGImage解释其size的方式之间的区别。 UIImage使用“点数”,CGImage使用像素。转换因子是scale

例如,如果UIImage的{​​{1}}为3,则scale在任何给定方向上的每个“点”,底层UIImage中的该方向上有三个像素1}}。因此对于CGImage为3和UIImage为100x100点的scale,基础size的大小为300x300像素。

要返回由 n x n 切割的简单图像数组(例如,如果 n 为3,则会有9个图像数组),您可以在Swift 3中执行以下操作:

CGImage

或者,在Swift 2.3中:

/// Slice image into array of tiles
///
/// - Parameters:
///   - image: The original image.
///   - howMany: How many rows/columns to slice the image up into.
///
/// - Returns: An array of images.
///
/// - Note: The order of the images that are returned will correspond
///         to the `imageOrientation` of the image. If the image's
///         `imageOrientation` is not `.up`, take care interpreting 
///         the order in which the tiled images are returned.

func slice(image: UIImage, into howMany: Int) -> [UIImage] {
    let width: CGFloat
    let height: CGFloat

    switch image.imageOrientation {
    case .left, .leftMirrored, .right, .rightMirrored:
        width = image.size.height
        height = image.size.width
    default:
        width = image.size.width
        height = image.size.height
    }

    let tileWidth = Int(width / CGFloat(howMany))
    let tileHeight = Int(height / CGFloat(howMany))

    let scale = Int(image.scale)
    var images = [UIImage]()

    let cgImage = image.cgImage!

    var adjustedHeight = tileHeight

    var y = 0
    for row in 0 ..< howMany {
        if row == (howMany - 1) {
            adjustedHeight = Int(height) - y
        }
        var adjustedWidth = tileWidth
        var x = 0
        for column in 0 ..< howMany {
            if column == (howMany - 1) {
                adjustedWidth = Int(width) - x
            }
            let origin = CGPoint(x: x * scale, y: y * scale)
            let size = CGSize(width: adjustedWidth * scale, height: adjustedHeight * scale)
            let tileCgImage = cgImage.cropping(to: CGRect(origin: origin, size: size))!
            images.append(UIImage(cgImage: tileCgImage, scale: image.scale, orientation: image.imageOrientation))
            x += tileWidth
        }
        y += tileHeight
    }
    return images
}

这可确保生成的图像位于正确的func slice(image image: UIImage, into howMany: Int) -> [UIImage] { let width: CGFloat let height: CGFloat switch image.imageOrientation { case .Left, .LeftMirrored, .Right, .RightMirrored: width = image.size.height height = image.size.width default: width = image.size.width height = image.size.height } let tileWidth = Int(width / CGFloat(howMany)) let tileHeight = Int(height / CGFloat(howMany)) let scale = Int(image.scale) var images = [UIImage]() let cgImage = image.CGImage! var adjustedHeight = tileHeight var y = 0 for row in 0 ..< howMany { if row == (howMany - 1) { adjustedHeight = Int(height) - y } var adjustedWidth = tileWidth var x = 0 for column in 0 ..< howMany { if column == (howMany - 1) { adjustedWidth = Int(width) - x } let origin = CGPoint(x: x * scale, y: y * scale) let size = CGSize(width: adjustedWidth * scale, height: adjustedHeight * scale) let tileCgImage = CGImageCreateWithImageInRect(cgImage, CGRect(origin: origin, size: size))! images.append(UIImage(CGImage: tileCgImage, scale: image.scale, orientation: image.imageOrientation)) x += tileWidth } y += tileHeight } return images } 中(这就是为什么上面的图像在“点”中跨越图像并且乘以获得scale中的正确像素)。同样,如果尺寸(以“点”为单位)不能被 n 整除,则它将分别构成该行或列的最后一个图像的差异。例如。当你为一个高度为736点的图像制作三个图块时,前两个将是245个点,但最后一个将是246个点。

有一个例外,它没有(完全)优雅地处理。也就是说,如果CGImage的{​​{1}}不是UIImage,则检索图像的顺序对应于该方向,而不是您查看时图像的左上角它

答案 1 :(得分:3)

您可以将图像纵向和横向分成两部分,然后根据需要进行子分割:

extension UIImage {
    var topHalf: UIImage? {
        guard let cgImage = cgImage, let image = cgImage.cropping(to: CGRect(origin: .zero, size: CGSize(width: size.width, height: size.height/2))) else { return nil }
        return UIImage(cgImage: image, scale: scale, orientation: imageOrientation)
    }
    var bottomHalf: UIImage? {
        guard let cgImage = cgImage, let image = cgImage.cropping(to: CGRect(origin: CGPoint(x: 0,  y: CGFloat(Int(size.height)-Int(size.height/2))), size: CGSize(width: size.width, height: CGFloat(Int(size.height) - Int(size.height/2))))) else { return nil }
        return UIImage(cgImage: image, scale: scale, orientation: imageOrientation)
    }
    var leftHalf: UIImage? {
        guard let cgImage = cgImage, let image = cgImage.cropping(to: CGRect(origin: .zero, size: CGSize(width: size.width/2, height: size.height))) else { return nil }
        return UIImage(cgImage: image, scale: scale, orientation: imageOrientation)
    }
    var rightHalf: UIImage? {
        guard let cgImage = cgImage, let image = cgImage.cropping(to: CGRect(origin: CGPoint(x: CGFloat(Int(size.width)-Int((size.width/2))), y: 0), size: CGSize(width: CGFloat(Int(size.width)-Int((size.width/2))), height: size.height)))
            else { return nil }
        return UIImage(cgImage: image, scale: scale, orientation: imageOrientation)
    }
    var splitedInFourParts: [UIImage] {
        guard case let topHalf = topHalf,
              case let bottomHalf = bottomHalf,
            let topLeft = topHalf?.leftHalf,
            let topRight = topHalf?.rightHalf,
            let bottomLeft = bottomHalf?.leftHalf,
            let bottomRight = bottomHalf?.rightHalf else{ return [] }
        return [topLeft, topRight, bottomLeft, bottomRight]
    }
    var splitedInSixteenParts: [UIImage] {
        var array = splitedInFourParts.flatMap({$0.splitedInFourParts})
        // if you need it in reading order you need to swap some image positions
        swap(&array[2], &array[4])
        swap(&array[3], &array[5])
        swap(&array[10], &array[12])
        swap(&array[11], &array[13])
        return array
    }
}

按列和行拆分图像:

extension UIImage {
    func matrix(_ rows: Int, _ columns: Int) -> [UIImage] {
        let y = (size.height / CGFloat(rows)).rounded()
        let x = (size.width / CGFloat(columns)).rounded()
        var images: [UIImage] = []
        images.reserveCapacity(rows * columns)
        guard let cgImage = cgImage else { return [] }
        (0..<rows).forEach { row in
            (0..<columns).forEach { column in
                var width = Int(x)
                var height = Int(y)
                if row == rows-1 && size.height.truncatingRemainder(dividingBy: CGFloat(rows)) != 0 {
                    height = Int(size.height - size.height / CGFloat(rows) * (CGFloat(rows)-1))
                }
                if column == columns-1 && size.width.truncatingRemainder(dividingBy: CGFloat(columns)) != 0 {
                    width = Int(size.width - (size.width / CGFloat(columns) * (CGFloat(columns)-1)))
                }
                if let image = cgImage.cropping(to: CGRect(origin: CGPoint(x: column * Int(x), y:  row * Int(x)), size: CGSize(width: width, height: height))) {
                    images.append(UIImage(cgImage: image, scale: scale, orientation: imageOrientation))
                }
            }
        }
        return images
    }
}
let myPicture = UIImage(data: try! Data(contentsOf: URL(string:"https://i.stack.imgur.com/Xs4RX.jpg")!))!

let images = myPicture.matrix(4, 4)

images.count   // 16

答案 2 :(得分:0)

我用它将图像切割成矩阵。矩阵表示为一维数组。

func snapshotImage(image: UIImage, rect: CGRect) -> UIImage {
        var imageRect: CGRect! = rect

        if image.scale > 1.0 {
            imageRect = CGRect(origin: CGPoint(x: rect.origin.x * image.scale, y: rect.origin.y * image.scale), size: CGSize(width: rect.size.width * image.scale, height: rect.size.height * image.scale))
        }


        let imageRef: CGImage = image.cgImage!.cropping(to: imageRect)!
        let result: UIImage = UIImage(cgImage: imageRef, scale: image.scale, orientation: image.imageOrientation)
        return result
    }

    func sliceImage(image: UIImage, size: CGSize) -> [UIImage] {
        var slices: [UIImage] = [UIImage]()
        var rect = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)


        var y: Float = 0.0
        let width: Int = Int(image.size.width / size.width)
        let height: Int = Int(image.size.height / size.height)

        for _ in 0...height {
            var x: Float = 0.0

            for _ in 0...width {
                rect.origin.x = CGFloat(x);
                slices.append(self.snapshotImage(image: image, rect: rect))

                x += Float(size.width)
            }

            y += Float(size.height)
            rect.origin.y = CGFloat(y)
        }

        return slices
    }