2010-02-22 151 views
4

我有一個1600x1600 1.2MB的圖像,調整到320x320縮小到404KB。 我需要更進一步,減少字節大小而不減少圖像方面的大小。用Cocoa減少圖像字節大小

當前我使用 - TIFFRepresentationUsingCompression:factor: NSImage方法NSTIFFCompressionJPEG以及似乎不影響圖像尺寸/質量的因素。

我該如何解決?

馬爾科

+0

你說的是降低內存或磁盤上的圖像的大小? – 2010-02-22 21:40:44

+0

在磁盤上。 1.2MB和404KB是磁盤大小 – Marco 2010-02-22 22:05:17

回答

7

如果你需要壓縮和你不介意丟失的圖像質量然後將該文件保存爲JPEG。要做到這一點,你需要讓圖像的NSBitmapImageRep,然後得到一個JPEG表示:

//yourImage is an NSImage object 

NSBitmapImageRep* myBitmapImageRep; 

if(useActualSize) 
{ 
    //this will produce an image the full size of the NSImage's backing bitmap, which may not be what you want 
    myBitmapImageRep = [NSBitmapImageRep imageRepWithData: [yourImage TIFFRepresentation]]; 
} 
else 
{ 
    //this will get a bitmap from the image at 1 point == 1 pixel, which is probably what you want 
    NSSize imageSize = [yourImage size]; 
    [yourImage lockFocus]; 
    NSRect imageRect = NSMakeRect(0, 0, imageSize.width, imageSize.height); 
    myBitmapImageRep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:imageRect] autorelease]; 
    [yourImage unlockFocus]; 
} 

CGFloat imageCompression = 0.7; //between 0 and 1; 1 is maximum quality, 0 is maximum compression 

// set up the options for creating a JPEG 
NSDictionary* jpegOptions = [NSDictionary dictionaryWithObjectsAndKeys: 
       [NSNumber numberWithDouble:imageCompression], NSImageCompressionFactor, 
       [NSNumber numberWithBool:NO], NSImageProgressive, 
       nil]; 

// get the JPEG encoded data 
NSData* jpegData = [myBitmapImageRep representationUsingType:NSJPEGFileType properties:jpegOptions]; 
//write it to disk 
[jpegData writeToFile:[NSHomeDirectory() stringByAppendingPathComponent:@"foo.jpg"] atomically:YES]; 
+0

我不介意圖像質量,但不是你的代碼相同 -TIFFRepresentationUsingCompression:factor:method? – Marco 2010-02-22 22:23:49

+1

否。該方法創建一個具有內部JPEG壓縮的TIFF文件。但是,文檔聲明「不支持TIFF文件中的JPEG壓縮,並且忽略因素。」我的代碼創建了一個實際的JPEG文件。 – 2010-02-22 22:28:43

+0

感謝您提取缺少的'autorelease',彼得,我從GC項目中的一個類別中複製了該行,所以在我的情況下沒有必要。 – 2010-02-24 05:07:25

0
#import "UIImage+Compress.h" 

#define MAX_IMAGEPIX 200.0   // max pix 200.0px 
#define MAX_IMAGEDATA_LEN 50000.0 // max data length 5K 

@implementation UIImage (Compress) 

- (UIImage *)compressedImage { 
    CGSize imageSize = self.size; 
    CGFloat width = imageSize.width; 
    CGFloat height = imageSize.height; 

    if (width <= MAX_IMAGEPIX && height <= MAX_IMAGEPIX) { 
     // no need to compress. 
     return self; 
    } 

    if (width == 0 || height == 0) { 
     // void zero exception 
     return self; 
    } 

    UIImage *newImage = nil; 
    CGFloat widthFactor = MAX_IMAGEPIX/width; 
    CGFloat heightFactor = MAX_IMAGEPIX/height; 
    CGFloat scaleFactor = 0.0; 

    if (widthFactor > heightFactor) 
     scaleFactor = heightFactor; // scale to fit height 
    else 
     scaleFactor = widthFactor; // scale to fit width 

    CGFloat scaledWidth = width * scaleFactor; 
    CGFloat scaledHeight = height * scaleFactor; 
    CGSize targetSize = CGSizeMake(scaledWidth, scaledHeight); 

    UIGraphicsBeginImageContext(targetSize); // this will crop 

    CGRect thumbnailRect = CGRectZero; 
    thumbnailRect.size.width = scaledWidth; 
    thumbnailRect.size.height = scaledHeight; 

    [self drawInRect:thumbnailRect]; 

    newImage = UIGraphicsGetImageFromCurrentImageContext(); 

    //pop the context to get back to the default 
    UIGraphicsEndImageContext(); 

    return newImage; 

} 

- (NSData *)compressedData:(CGFloat)compressionQuality { 
    assert(compressionQuality <= 1.0 && compressionQuality >= 0); 

    return UIImageJPEGRepresentation(self, compressionQuality); 
} 

- (CGFloat)compressionQuality { 
    NSData *data = UIImageJPEGRepresentation(self, 1.0); 
    NSUInteger dataLength = [data length]; 

    if(dataLength > MAX_IMAGEDATA_LEN) { 
     return 1.0 - MAX_IMAGEDATA_LEN/dataLength; 
    } else { 
     return 1.0; 
    } 
} 

- (NSData *)compressedData { 
    CGFloat quality = [self compressionQuality]; 

    return [self compressedData:quality]; 
} 

@end