有没有最好的方法来将NSImage的大小调整为最大文件大小?

时间:2009-10-13 22:46:36

标签: cocoa image-manipulation nsimage nsimagerep

这是我到目前为止所得到的:

NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:
               [file.image TIFFRepresentation]];
// Resize image to 200x200
CGFloat maxSize = 200.0;
NSSize imageSize = imageRep.size;
if (imageSize.height>maxSize || imageSize.width>maxSize) {
    // Find the aspect ratio
    CGFloat aspectRatio = imageSize.height/imageSize.width;
    CGSize newImageSize;
    if (aspectRatio > 1.0) {
        newImageSize = CGSizeMake(maxSize / aspectRatio, maxSize);
    } else if (aspectRatio < 1.0) {
        newImageSize = CGSizeMake(maxSize, maxSize * aspectRatio);
    } else {
        newImageSize = CGSizeMake(maxSize, maxSize);
    }
    [imageRep setSize:NSSizeFromCGSize(newImageSize)];
}


NSData *imageData = [imageRep representationUsingType:NSPNGFileType properties:nil];
NSString *outputFilePath = [@"~/Desktop/output.png" stringByExpandingTildeInPath];
[imageData writeToFile:outputFilePath atomically:NO];

代码假设200x200 PNG将小于128K,这是我的大小限制。 200x200足够大,但我希望尽可能最大化。

以下是我的两个问题:

  1. 代码不起作用。我检查导出文件的大小,它与原始文件的大小相同。
  2. 在我导出之前有没有办法预测输出文件的大小,所以我可以最大化尺寸,但仍然可以获得小于128K的图像?

  3. 这是工作代码。它非常草率,可能会使用一些优化,但在这一点上它运行得足够快,我不在乎。对于大多数图片,它迭代超过100倍,并且它在几毫秒内完成。此外,此方法在NSImage上的类别中声明。

    - (NSData *)resizeImageWithBitSize:(NSInteger)size 
                          andImageType:(NSBitmapImageFileType)fileType {
    
        CGFloat maxSize = 500.0;
        NSSize originalImageSize = self.size;
        NSSize newImageSize;
        NSData *returnImageData;
        NSInteger imageIsTooBig = 1000;
    
        while (imageIsTooBig > 0) {
                if (originalImageSize.height>maxSize || originalImageSize.width>maxSize) {
                // Find the aspect ratio
                CGFloat aspectRatio = originalImageSize.height/originalImageSize.width;
                if (aspectRatio > 1.0) {
                    newImageSize = NSMakeSize(maxSize / aspectRatio, maxSize);
                } else if (aspectRatio < 1.0) {
                    newImageSize = NSMakeSize(maxSize, maxSize * aspectRatio);
                } else {
                    newImageSize = NSMakeSize(maxSize, maxSize);
                }
            } else {
                newImageSize = originalImageSize;
            }
    
            NSImage *resizedImage = [[NSImage alloc] initWithSize:newImageSize];
    
            [resizedImage lockFocus];
            [self drawInRect:NSMakeRect(0, 0, newImageSize.width, newImageSize.height)
                    fromRect: NSMakeRect(0, 0, originalImageSize.width, originalImageSize.height) 
                   operation: NSCompositeSourceOver 
                    fraction: 1.0];
            [resizedImage unlockFocus];
    
            NSData *tiffData = [resizedImage TIFFRepresentation];
            [resizedImage release];
    
            NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithData:tiffData];
            NSDictionary *imagePropDict = [NSDictionary 
                                           dictionaryWithObject:[NSNumber numberWithFloat:0.85] 
                                                         forKey:NSImageCompressionFactor];
    
            returnImageData = [imageRep representationUsingType:fileType properties:imagePropDict];
            [imageRep release];
    
            if ([returnImageData length] > size) {
                maxSize = maxSize * 0.99;
                imageIsTooBig--;
            } else {
                imageIsTooBig = 0;
            }
    
        }
    
        return returnImageData;
    }
    

2 个答案:

答案 0 :(得分:0)

[imageData length]应该给你NSData内容的长度,我理解这是写入磁盘时的最终文件大小。这应该让你有机会在实际编写之前最大化文件的大小。

根据the docs for setSize

,至于为什么图像没有缩小或增长
  

图像表示的大小与图像数据的物理尺寸相结合决定了图像的分辨率。

所以可能是通过设置大小而不是改变分辨率而不修改任何像素,只需要解释像素的方式。

答案 1 :(得分:0)

1。

正如另一张海报所提到的,setSize只会改变图像的显示尺寸,而不会改变底层图像文件的实际像素数据。

要调整大小,您可能需要将源图像重绘到另一个NSImageRep上,然后将其写入文件。

此博客文章包含一些示例代码,介绍如何以这种方式调整大小。

How to Resize an NSImage

2。

我不认为你至少可以在内存中创建对象并检查图像的长度。使用的实际字节将取决于图像类型。使用ARGB的位图很容易预测它们的大小,但PNG和JPEG会更难。