2012-02-29 74 views
24

Tôi muốn nén hình ảnh (thư viện ảnh/thư viện ảnh) và sau đó gửi hình ảnh đến máy chủ. Tôi biết tôi có thể nén theo chiều cao và chiều rộng, nhưng tôi muốn nén hình ảnh theo kích thước thành kích thước cố định (200 KB) chỉ và giữ nguyên chiều cao và chiều rộng ban đầu. Yếu tố tỷ lệ trong JPEGRepresentation không đại diện cho kích thước và chất lượng nén duy nhất. Làm thế nào tôi có thể đạt được điều này (nén đến một kích thước cố định) mà không cần sử dụng bất kỳ thư viện của bên thứ ba? Cảm ơn bạn đã giúp đỡ.nén hình ảnh theo kích cỡ - iPhone SDK

+0

Không có API cho nó trong SDK. Khi bạn phát hiện ra, bạn có thể thay đổi kích thước theo độ phân giải hoặc chất lượng. Chúng tôi đã có cùng một vấn đề và cuối cùng chúng tôi quyết định thay đổi kích thước để hiển thị màn hình và nén 85% làm giảm kích thước tập tin đáng kể nhưng vẫn cung cấp một chất lượng hình ảnh rất tốt. –

Trả lời

62

Heres một số mã ví dụ mà sẽ cố gắng để nén hình ảnh cho bạn để nó không vượt quá hoặc là một nén tối đa hoặc kích thước tập tin tối đa

CGFloat compression = 0.9f; 
CGFloat maxCompression = 0.1f; 
int maxFileSize = 250*1024; 

NSData *imageData = UIImageJPEGRepresentation(yourImage, compression); 

while ([imageData length] > maxFileSize && compression > maxCompression) 
{ 
    compression -= 0.1; 
    imageData = UIImageJPEGRepresentation(yourImage, compression); 
} 
+2

Các mã viết trên hoạt động tuyệt vời :). Nhưng tôi muốn hình ảnh của tôi nén tối đa 20 kb, tôi đã cố gắng phát bằng mã của bạn. Nhưng chỉ có thể để có được kích thước khoảng 200 kb, bạn có thể hướng dẫn cho tôi một cách làm thế nào tôi có thể đạt được 20 kb. –

+0

@DeepK Giải pháp trên là gì để nén hình ảnh gốc. Nén tối đa có thể không giúp bạn có được giải pháp mong đợi. Vì vậy, tạo ra hình ảnh từ các dữ liệu nén và sau đó một lần nữa nén hình ảnh cho đến khi bạn nhận được những gì bạn muốn. chỉ là một ý tưởng. – CodetrixStudio

+0

@Codetrix Cảm ơn bạn đã đề xuất giải pháp. –

3

Một cách để thực hiện, là nén lại tệp trong một vòng lặp cho đến khi bạn tìm thấy kích thước mong muốn. Đầu tiên bạn có thể tìm chiều cao và chiều rộng, và đoán hệ số nén (nén ảnh lớn hơn) sau đó sau khi bạn nén nó, kiểm tra kích thước và phân chia lại sự khác biệt.

Tôi biết điều này không phải là siêu hiệu quả, nhưng tôi không tin rằng có một cuộc gọi duy nhất để đạt được hình ảnh có kích thước cụ thể.

1

Ở đây, JPEGRepresentation khá bộ nhớ tiêu thụ và nếu chúng tôi sử dụng trong Loop vì vậy nó tiêu thụ bộ nhớ cực kỳ cao. Vì vậy, sử dụng mã bên dưới & ImageSize sẽ không nhiều hơn 200KB.

UIImage* newImage = [self captureView:yourUIView]; 


- (UIImage*)captureView:(UIView *)view { 
CGRect rect = view.bounds; 
UIGraphicsBeginImageContext(rect.size); 
CGContextRef context = UIGraphicsGetCurrentContext(); 

[view.layer renderInContext:context]; 
UIImage* img = [UIImage alloc]init]; 
img = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
NSLog(@"img=%@",img); 
return img; 
} 
-1
- (UIImage *)resizeImageToSize:(CGSize)targetSize 
{ 
    UIImage *sourceImage = captureImage; 
    UIImage *newImage = nil; 

    CGSize imageSize = sourceImage.size; 
    CGFloat width = imageSize.width; 
    CGFloat height = imageSize.height; 

    CGFloat targetWidth = targetSize.width; 
    CGFloat targetHeight = targetSize.height; 

    CGFloat scaleFactor = 0.0; 
    CGFloat scaledWidth = targetWidth; 
    CGFloat scaledHeight = targetHeight; 

    CGPoint thumbnailPoint = CGPointMake(0.0,0.0); 

    if (CGSizeEqualToSize(imageSize, targetSize) == NO) { 

     CGFloat widthFactor = targetWidth/width; 
     CGFloat heightFactor = targetHeight/height; 

     if (widthFactor < heightFactor) 
      scaleFactor = widthFactor; 
     else 
      scaleFactor = heightFactor; 

     scaledWidth = width * scaleFactor; 
     scaledHeight = height * scaleFactor; 

     // make image center aligned 
     if (widthFactor < heightFactor) 
     { 
      thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
     } 
     else if (widthFactor > heightFactor) 
     { 
      thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5; 
     } 
    } 

    UIGraphicsBeginImageContext(targetSize); 
    CGRect thumbnailRect = CGRectZero; 
    thumbnailRect.origin = thumbnailPoint; 
    thumbnailRect.size.width = scaledWidth; 
    thumbnailRect.size.height = scaledHeight; 

    [sourceImage drawInRect:thumbnailRect]; 
    newImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    if(newImage == nil) 
     NSLog(@"could not scale image"); 

    return newImage ; 
} 
+0

Câu hỏi đặt ra là dành riêng cho _file size_, không phải kích thước hình ảnh – bengoesboom

0

Sau khi thực hiện một vài thử nghiệm, tôi đã có thể tìm A relationship between image size and compression value. Vì mối quan hệ này là tuyến tính cho tất cả các giá trị trong đó nén nhỏ hơn 1, tôi đã tạo một thuật toán để cố gắng luôn nén hình ảnh thành một giá trị nhất định.

//Use 0.99 because at 1, the relationship between the compression and the file size is not linear 
NSData *image = UIImageJPEGRepresentation(currentImage, 0.99); 
float maxFileSize = MAX_IMAGE_SIZE * 1024; 

//If the image is bigger than the max file size, try to bring it down to the max file size 
if ([image length] > maxFileSize) { 
    image = UIImageJPEGRepresentation(currentImage, maxFileSize/[image length]); 
} 
+2

Câu trả lời này là không chính xác và gây hiểu nhầm. Vui lòng xem xét xóa nó – ikbal

0

tôi lấy câu trả lời của @kgutteridge và thực hiện một giải pháp tương tự cho Swift 3.0 sử dụng đệ quy:

extension UIImage { 
    static func compress(image: UIImage, maxFileSize: Int, compression: CGFloat = 1.0, maxCompression: CGFloat = 0.4) -> Data? { 

     if let data = UIImageJPEGRepresentation(image, compression) { 

      let bcf = ByteCountFormatter() 
      bcf.allowedUnits = [.useMB] // optional: restricts the units to MB only 
      bcf.countStyle = .file 
      let string = bcf.string(fromByteCount: Int64(data.count)) 
      print("Data size is: \(string)") 

      if data.count > (maxFileSize * 1024 * 1024) && (compression > maxCompression) { 
       let newCompression = compression - 0.1 
       let compressedData = self.compress(image: image, maxFileSize: maxFileSize, compression: newCompression, maxCompression: maxCompression) 
       return compressedData 
      } 

      return data 
     } 

     return nil 
    } 
} 
Các vấn đề liên quan