首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >图像阵列中的快速分割

图像阵列中的快速分割
EN

Stack Overflow用户
提问于 2017-03-24 19:56:05
回答 3查看 3.8K关注 0票数 5

我试图把一个图像分割出来(在一个矩阵中),创建16个图像。我用的是斯威夫特2.1。下面是代码:

代码语言:javascript
运行
复制
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不同,但我不知道如何修复它。如果我能够使变量cellSize与CGImage的高度而不是UIImage的高度相对应,我想我会修复它,但不能得到CGImage的高度。

谢谢你的帮助!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-03-24 22:18:25

根本的问题是UIImageCGImage如何解释他们的size之间的区别。UIImage使用“点”,CGImage使用像素。转换因子是scale

例如,如果UIImagescale为3,任何给定方向的“点”-- UIImage --都有三个像素在基础CGImage中。因此,对于UIImagescale为3,size为100 x100点,底层CGImage的大小为300×300像素。

若要返回由n切片的图像的简单数组(例如,如果n为3,数组中将有9幅图像),您可以在Swift 3中执行如下操作:

代码语言:javascript
运行
复制
/// 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
}

或者,在Swift 2.3中:

代码语言:javascript
运行
复制
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中(这就是为什么上面的图像在“点”中跨出并乘以在CGImage中获得正确的像素)。这也是,如果以“点”为单位的尺寸不能被n整除,它将分别弥补该行或列的最后图像中的差异。例如,当你为一个高度为736点的图像制作三个瓷砖时,前两个是245个点,而最后一个是246个点)。

有一个例外,这不能(完全)优雅地处理。也就是说,如果UIImageimageOrientation不是.up,那么检索图像的顺序对应于该方向,而不是在您查看图像的左上角。

票数 6
EN

Stack Overflow用户

发布于 2017-03-24 20:55:39

您可以将图像分割为垂直和水平两部分,并根据需要将结果拆分:

代码语言:javascript
运行
复制
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
    }
}

将图像按列和行拆分:

代码语言:javascript
运行
复制
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
    }
}
代码语言:javascript
运行
复制
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
票数 3
EN

Stack Overflow用户

发布于 2017-03-24 20:35:28

我用这个把图像分割成矩阵。矩阵表示为一维数组。

代码语言:javascript
运行
复制
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
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43008098

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档