快速将图像划分为图像阵列 [英] Divide image in array of images with swift
问题描述
我正在尝试将图像划分为16个图像(以矩阵形式).我正在使用Swift 2.1.这是代码:
I'm trying to divide an image to create 16 out of it (in a matrix). I'm using swift 2.1. Here's the code:
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的高度.
This works but the images that returns are only part of the original image. I've been searching and I know that's because when I create a CGImage it has a size different than the UIImage, but I don't know how to fix it. If I could make the variable cellSize with the height of the CGImage instead of the UIImage I suppose I would fix it but I can't get the CGImage height.
感谢您的帮助!
推荐答案
基本问题是UIImage
和CGImage
解释其size
的方式之间的区别. UIImage
使用点",而CGImage
使用像素.转换因子为 scale
.
The fundamental issue is the difference between how UIImage
and CGImage
interpret their size
. UIImage
uses "points" and CGImage
uses pixels. And the conversion factor is the scale
.
例如,如果UIImage
的scale
为3,则在UIImage
的任何给定方向上的每个点"都在基础CGImage
中的该方向上有三个像素.因此,对于UIImage
的scale
为3,size
的像素为100x100点,基础CGImage
的大小为300x300像素.
For example, if a UIImage
has a scale
of 3, every "point" in any given direction the UIImage
, there are three pixels in that direction in the underlying CGImage
. So for a UIImage
that has a scale
of 3 and a size
of 100x100 points, the underlying CGImage
has a size of 300x300 pixels.
要返回由 n x n 切成的简单图像数组(例如,如果 n 为3,则在数组),您可以在Swift 3中执行以下操作:
To return a simple array of images sliced by n x n (e.g. if n is three, there will be nine images in the array), you can do something like the following in Swift 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
}
或者,在Swift 2.3中:
Or, in Swift 2.3:
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点).
This makes sure that the resulting images are in the correct scale
(this is why the above strides through the image in "points" and the multiplies to get the correct pixels in the CGImage
). This also, if the dimensions, measured in "points") are not evenly divisible by n, it will making up the difference in the last image for that row or column, respectively. E.g. when you make three tiles for an image with a height of 736 points, the first two will be 245 points, but the last one will be 246 points).
有一个例外,那就是它不能(完全)优雅地处理.也就是说,如果UIImage
的imageOrientation
不同于.up
,则检索图像的顺序对应于该方向,而不是查看时图像的左上角.
There is one exception that this does not (entirely) handle gracefully. Namely, if the UIImage
has an imageOrientation
of something other than .up
, the order in which the images is retrieved corresponds to that orientation, not the upper left corner of the image as you view it.
这篇关于快速将图像划分为图像阵列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!