2017-03-24 13 views
4

画像を16分割して(マトリックスで)作成しようとしています。私はスイフト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) 

     } 
    } 

これは機能しますが、返される画像は元の画像の一部に過ぎません。私は検索してきましたが、私はそれがUIImageとは異なるサイズを持っているCGImageを作成するので、私はそれを修正する方法がわからないので、知っている。変数cellSizeをUIImageの代わりにCGImageの高さで作ることができたら、それを修正すると思いますが、CGImageの高さを得ることはできません。

ありがとうございました!

+0

ええと、それはスケールでなければなりませんが、それはちょうどget-onlyです。どうすればそれを検討できますか? – JJdip

答えて

2

根本的な問題は、彼らのsizeをどう解釈するかUIImageCGImageとの間の差です。 UIImageは「ポイント」を使用し、CGImageはピクセルを使用します。換算係数はscaleです。例えば

UIImageが、任意の所与の方向UIImage内のすべての「点」を3のscaleを有する場合、基礎となるCGImageにおけるその方向に3個の画素が存在します。だから、3のscaleを持っており、100×100ポイントのsizeUIImageのために、基礎となるCGImageは300×300ピクセルの大きさを持っています。

(配列内の9枚の画像があるだろう、3ですnは場合など)N X のnでスライス画像の単純な配列を返すには、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 
} 

あるいは、スウィフト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ポイントの高さの画像に対して3枚のタイルを作成すると、最初の2枚は245ポイントになりますが、最後の2枚は246ポイントになります)。

これは(完全に)正常に処理しないことが1つの例外があります。つまり、UIImage.up以外の何かのimageOrientationがある場合、画像が取得される順序は、画像の左上隅ではなく、その向きに対応します。

+0

答えのおかげで、あなたは問題を解決した。ありがとう! – JJdip

0

これを使ってイメージをマトリックスにスライスしました。行列は1次元配列として表されます。

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

お返事ありがとうございます。それは私にエラーが表示されます: "タイプの値 'UIImage'は、imageRefを作成するとき、スナップショットの楽しみにメンバー 'cgImage'を持っていません。 – JJdip

+0

スイフト2または3を使用していますか?おそらく2私はAppStore Xcode 8.2.1 –

+0

から新しい(既に古い)Swift 3をダウンロードすることをお勧めしますが、私のコードはどうなりますか?私はそれを変更する必要がありますか? – JJdip

3

あなたは二つの部分垂直方向と水平方向あなたの画像IMを分割することができ、必要に応じてサブの結果を分割:

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 
+0

答えをありがとう。問題は、おそらく将来、5x5と6x6のマトリックスでスライスする必要があるということです。私は主な質問にそれを書いていないことを知っている、私はそれのために謝罪、私はこの場合は考えていない – JJdip