2017-03-24 1 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) 

     } 
    } 

이 방법은 작동하지만 반환되는 이미지는 원본 이미지의 일부입니다. 저는 검색을 해왔습니다. CGImage를 만들 때 UIImage와는 다른 크기를 가지기 때문에 그 문제를 해결할 방법을 모르겠습니다. 내가 UIImage 대신 CGImage 높이로 변수 cellSize를 만들 수 있다면 고칠 수 있다고 생각하지만 CGImage 높이를 얻을 수 없습니다.

도움 주셔서 감사합니다.

+0

네, 척도가되어야합니다.하지만 제대로 얻는 것입니다. 어떻게 생각합니까? – JJdip

답변

2

근본적인 문제는 UIImageCGImage이 어떻게 size을 해석하는지의 차이입니다. UIImage은 "점"을 사용하고 CGImage은 픽셀을 사용합니다. 그리고 전환율은 scale입니다. UIImagescale (3)가있는 경우

는 예를 들어, 임의의 주어진 방향 UIImage 모든 "포인트"기본 CGImage에서 그 방향으로 3 개 개의 화소가있다. 따라서 scale이 3이고 size이 100x100 포인트 인 UIImage의 경우 기본이되는 CGImage의 크기는 300x300 픽셀입니다.

에 의해 슬라이스 이미지의 간단한 배열을 반환하려면 N X N, 당신은 스위프트 3에 다음과 같은 작업을 수행 할 수 있습니다 ( N 세의 경우, 배열의 9 개 개의 이미지가있을 것입니다 예) : 스위프트 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 
} 

또는 : 결과 이미지가 올바른 scale (t에서

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 
} 

이 확실하게 있음 그 이유는 위의 "점"의 이미지와 곱하기를 통해 CGImage의 올바른 픽셀을 얻는 것입니다. 또한 "포인트"로 측정 된 치수)가 n으로 균등하게 나눌 수없는 경우, 해당 행 또는 열의 마지막 이미지에서 차이를 보입니다. 예 : 높이가 736 인 이미지의 타일을 세 개 만들면 처음 두 개는 245 포인트가되지만 마지막 타일은 246 포인트가됩니다.

예외적으로 (완전히) 정상적으로 처리하지 못합니다.즉, UIImage의 이미지가 .up이 아닌 imageOrientation 인 경우 이미지를 검색하는 순서는 이미지의 왼쪽 위 모서리가 아니라 해당 방향과 일치합니다.

+0

대답 해 주셔서 감사합니다. 문제가 해결되었습니다. 감사! – JJdip

0

이미지를 매트릭스로 분할하는 데 사용했습니다. 행렬은 1D 배열로 표현됩니다.

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

답변 해 주셔서 감사합니다. 그것은 나에게 오류를 준다 : imageRef를 생성 할 때 "UIImage 타입의 값은 스냅 샷 재미에서"cgImage "멤버가 없다. – JJdip

+0

스위프트 2 또는 3을 사용하고 있습니까? 아마도 2 AppStore Xcode 8.2.1 –

+0

Ok에서 새로운 (이미 오래된) Swift 3을 다운로드하는 것이 좋습니다.하지만 내 코드는 어떻게됩니까? 내가 그것을 변경해야합니까? – JJdip

3

당신은 두 부분으로 수직 및 수평 이미지 메신저를 나눌 수 및 하위 필요에 따라 결과 분할 :

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 
    } 
} 
: 열과 행으로

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 
    } 
} 

분할 이미지를


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