2013-05-15 5 views
5

투명한 배경을 가진 UIImage를 가져 와서 자르기 할 최소 사각형을 결정하는 전략은 무엇입니까? (이미지가 보이면 여분의 투명한 배경과 함께 표시되는 이미지 데이터 만 남게됩니다. 데이터는 직사각형이 아닙니다.)투명 배경이있는 UIImage의 자르기 사각형 감지

나는 사용자 개입이 필요한 뷰 컨트롤러를 많이 자르고, 이미지 처리 클래스와 카테고리 (MGImageUtilities 및 NYXImagesKit 포함)가있는 오픈 소스 라이브러리를 많이 가지고 있지만 아직 아무것도 아니지만, CGRect에 UIImage를 자르기에 대한 많은 정보를 발견했다. 내 특별한 문제를 해결합니다.

현재 앱이 iOS 5.0을 대상으로하므로이 앱과의 호환성이 최적입니다.

편집 : 그런데 가장자리 경계를 찾는 행과 열의 이미지 데이터의 최악의 시나리오에서 모든 픽셀을 바라 보는 무력보다 더 나은 방법이 있기를 바랍니다.

답변

9

https://gist.github.com/spinogrizz/3549921을 볼 기회가 있었습니까?

정확히 필요한 것 같습니다. 분실하지 그냥 때문에

, 해당 페이지에서 복사 & 붙여 넣기 :

- (UIImage *) imageByTrimmingTransparentPixels { 
    int rows = self.size.height; 
    int cols = self.size.width; 
    int bytesPerRow = cols*sizeof(uint8_t); 

    if (rows < 2 || cols < 2) { 
     return self; 
    } 

    //allocate array to hold alpha channel 
    uint8_t *bitmapData = calloc(rows*cols, sizeof(uint8_t)); 

    //create alpha-only bitmap context 
    CGContextRef contextRef = CGBitmapContextCreate(bitmapData, cols, rows, 8, bytesPerRow, NULL, kCGImageAlphaOnly); 

    //draw our image on that context 
    CGImageRef cgImage = self.CGImage; 
    CGRect rect = CGRectMake(0, 0, cols, rows); 
    CGContextDrawImage(contextRef, rect, cgImage); 

    //summ all non-transparent pixels in every row and every column 
    uint16_t *rowSum = calloc(rows, sizeof(uint16_t)); 
    uint16_t *colSum = calloc(cols, sizeof(uint16_t)); 

    //enumerate through all pixels 
    for (int row = 0; row < rows; row++) { 
     for (int col = 0; col < cols; col++) 
     { 
      if (bitmapData[row*bytesPerRow + col]) { //found non-transparent pixel 
       rowSum[row]++; 
       colSum[col]++; 
      } 
     } 
    } 

    //initialize crop insets and enumerate cols/rows arrays until we find non-empty columns or row 
    UIEdgeInsets crop = UIEdgeInsetsMake(0, 0, 0, 0); 

    for (int i = 0; i<rows; i++) {  //top 
     if (rowSum[i] > 0) { 
      crop.top = i; break; 
     } 
    } 

    for (int i = rows; i >= 0; i--) {  //bottom 
     if (rowSum[i] > 0) { 
      crop.bottom = MAX(0, rows-i-1); break; 
     } 
    } 

    for (int i = 0; i<cols; i++) {  //left 
     if (colSum[i] > 0) { 
      crop.left = i; break; 
     } 
    } 

    for (int i = cols; i >= 0; i--) {  //right 
     if (colSum[i] > 0) { 
      crop.right = MAX(0, cols-i-1); break; 
     } 
    } 

    free(bitmapData); 
    free(colSum); 
    free(rowSum); 

    if (crop.top == 0 && crop.bottom == 0 && crop.left == 0 && crop.right == 0) { 
     //no cropping needed 
     return self; 
    } 
    else { 
     //calculate new crop bounds 
     rect.origin.x += crop.left; 
     rect.origin.y += crop.top; 
     rect.size.width -= crop.left + crop.right; 
     rect.size.height -= crop.top + crop.bottom; 

     //crop it 
     CGImageRef newImage = CGImageCreateWithImageInRect(cgImage, rect); 

     //convert back to UIImage 
     return [UIImage imageWithCGImage:newImage]; 
    } 
} 
+0

스위프트 4이지만, 충분히 잘 작동합니다. 감사. –

+0

나를 위해 일했습니다 (Y) – Xeieshan

+1

저를 위해 일하지 않습니다 -하지만 잘하면 거기에 대해 다른 버전이 떠돌아 다니고 있습니다 ... – Benjohn

-5

는 WWDC에 CoreImage 슬라이드를 참조하십시오. 귀하의 답변은 직접적인 것입니다.

0

여기 그것은 조금 추한

extension UIImage { 

func cropAlpha() -> UIImage { 

    let cgImage = self.cgImage!; 

    let width = cgImage.width 
    let height = cgImage.height 

    let colorSpace = CGColorSpaceCreateDeviceRGB() 
    let bytesPerPixel:Int = 4 
    let bytesPerRow = bytesPerPixel * width 
    let bitsPerComponent = 8 
    let bitmapInfo: UInt32 = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Big.rawValue 

    guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo), 
     let ptr = context.data?.assumingMemoryBound(to: UInt8.self) else { 
      return self 
    } 

    context.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: width, height: height)) 

    var minX = width 
    var minY = height 
    var maxX: Int = 0 
    var maxY: Int = 0 

    for x in 1 ..< width { 
     for y in 1 ..< height { 

      let i = bytesPerRow * Int(y) + bytesPerPixel * Int(x) 
      let a = CGFloat(ptr[i + 3])/255.0 

      if(a>0) { 
       if (x < minX) { minX = x }; 
       if (x > maxX) { maxX = x }; 
       if (y < minY) { minY = y}; 
       if (y > maxY) { maxY = y}; 
      } 
     } 
    } 

    let rect = CGRect(x: CGFloat(minX),y: CGFloat(minY), width: CGFloat(maxX-minX), height: CGFloat(maxY-minY)) 
    let imageScale:CGFloat = self.scale 
    let croppedImage = self.cgImage!.cropping(to: rect)! 
    let ret = UIImage(cgImage: croppedImage, scale: imageScale, orientation: self.imageOrientation) 

    return ret; 
} 

}

관련 문제