2013-05-15 7 views
5

Chiến lược lấy UIImage với nền trong suốt là gì và xác định hình chữ nhật nhỏ nhất để cắt để chỉ có dữ liệu hình ảnh có thể nhìn thấy được (cùng với nền trong suốt bổ sung nếu hình ảnh dữ liệu không phải là hình chữ nhật của khóa học)?Phát hiện hình chữ nhật cắt xén cho UIImage với nền trong suốt

Tôi đã tìm thấy rất nhiều thông tin về việc cắt xén UIImage thành CGRect, nhiều trình điều khiển chế độ xem cắt xén yêu cầu sự can thiệp của người dùng và một số thư viện nguồn mở với các lớp và danh mục xử lý hình ảnh (bao gồm MGImageUtilities và NYXImagesKit). giải quyết vấn đề cụ thể của tôi.

Ứng dụng hiện tại của tôi đang nhắm mục tiêu iOS 5.0, do đó khả năng tương thích với ứng dụng đó sẽ tối ưu. EDIT: Bằng cách này, tôi hy vọng rằng có một cách tốt hơn so với lực lượng vũ phu nhìn vào mỗi điểm ảnh trong kịch bản trường hợp xấu nhất của dữ liệu hình ảnh trong các hàng và cột tìm kiếm các ranh giới cạnh.

Trả lời

9

Bạn đã có cơ hội để xem https://gist.github.com/spinogrizz/3549921?

có vẻ như đó chính xác là những gì bạn cần.

chỉ vì vậy nó không bị mất, một dán bản sao & từ trang đó:

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

Đó là một chút xấu xí, nhưng nó hoạt động tốt đủ. Cảm ơn. –

+0

Làm việc cho tôi (Y) – Xeieshan

+1

Không làm việc cho tôi - nhưng hy vọng có một phiên bản khác nổi về… – Benjohn

-5

Tham khảo CoreImage Slides trên WWDC. Câu trả lời của bạn là trực tiếp.

0

ở đây nó là trong Swift 4

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

}