首页 文章

NSImage无法扩展

提问于
浏览
8

我正在开发一个快速应用程序,其中我有一个方法应该将@ 2x图像重新缩放为常规图像 . 问题是它没有:(

为什么?

-(BOOL)createNormalImage:(NSString*)inputRetinaImagePath {

    NSImage *inputRetinaImage = [[NSImage alloc] initWithContentsOfFile:inputRetinaImagePath];



    NSSize size = NSZeroSize;
    size.width = inputRetinaImage.size.width*0.5;
    size.height = inputRetinaImage.size.height*0.5;

    [inputRetinaImage setSize:size];


    NSLog(@"%f",inputRetinaImage.size.height);


    NSBitmapImageRep *imgRep = [[inputRetinaImage representations] objectAtIndex: 0];

    NSData *data = [imgRep representationUsingType: NSPNGFileType properties: nil];

    NSString *outputFilePath = [[inputRetinaImagePath substringToIndex:inputRetinaImagePath.length - 7] stringByAppendingString:@".png"];

    NSLog([@"Normal version file path: " stringByAppendingString:outputFilePath]);
    [data writeToFile:outputFilePath atomically: NO];
    return true;
}

2 回答

  • 10

    你必须非常警惕NSImage的size属性 . 它不一定是指bitmapRepresentation的像素尺寸,它可以参考显示的尺寸 . NSImage可以具有多个位图表示,以用于不同的输出大小 .

    同样,更改NSImage的size属性不会改变bitmapRepresentations

    因此,您需要做的是计算出您想要输出图像的大小,然后使用源NSImage中的bitmapRepresentation以该大小绘制新图像 .

    获得该大小取决于您获得输入图像的方式以及您对它的了解 . 例如,如果您确信输入图像只有一个bitmapImageRep,则可以使用此类事物(作为NSImage上的类别)

    - (NSSize) pixelSize
    {
        NSBitmapImageRep* bitmap = [[self representations] objectAtIndex:0];
        return NSMakeSize(bitmap.pixelsWide,bitmap.pixelsHigh);
    }
    

    即使您有多个bitmapImageReps,第一个应该是最大的一个,如果这是您创建Retina图像的大小,它应该是您所追求的Retina大小 .

    当您计算出最终尺寸后,您可以制作图像:

    - (NSImage*) resizeImage:(NSImage*)sourceImage size:(NSSize)size
    {
    
        NSRect targetFrame = NSMakeRect(0, 0, size.width, size.height);     
        NSImage* targetImage = nil;
        NSImageRep *sourceImageRep =
        [sourceImage bestRepresentationForRect:targetFrame
                                       context:nil
                                         hints:nil];
    
        targetImage = [[NSImage alloc] initWithSize:size];
    
        [targetImage lockFocus];
        [sourceImageRep drawInRect: targetFrame];
        [targetImage unlockFocus];
    
    return targetImage;
    

    }

    update

    这是NSImage上像素大小获取类别的更精细版本...让我们不假设图像,它有多少imageReps,是否有任何bitmapImageReps ...这将返回它可以找到的最大像素尺寸 . 如果它找不到bitMapImageRep像素尺寸,它将使用它可以获得的任何其他东西,这很可能是边界框尺寸(由eps和pdfs使用) .

    NSImage PixelSize.h

    #import <Cocoa/Cocoa.h>
    #import <QuartzCore/QuartzCore.h>
    
    @interface NSImage (PixelSize)
    
    - (NSInteger) pixelsWide;
    - (NSInteger) pixelsHigh;
    - (NSSize) pixelSize;
    
    @end
    

    NSImage PixelSize.m

    #import "NSImage+PixelSize.h"
    
    @implementation NSImage (Extensions)
    
    - (NSInteger) pixelsWide
    {
        /*
         returns the pixel width of NSImage.
         Selects the largest bitmapRep by preference
         If there is no bitmapRep returns largest size reported by any imageRep.
         */
        NSInteger result = 0;
        NSInteger bitmapResult = 0;
    
        for (NSImageRep* imageRep in [self representations]) {
            if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
                if (imageRep.pixelsWide > bitmapResult)
                    bitmapResult = imageRep.pixelsWide;
            } else {
                if (imageRep.pixelsWide > result)
                    result = imageRep.pixelsWide;
            }
        }
        if (bitmapResult) result = bitmapResult;
        return result;
    
    }
    
    - (NSInteger) pixelsHigh
    {
        /*
         returns the pixel height of NSImage.
         Selects the largest bitmapRep by preference
         If there is no bitmapRep returns largest size reported by any imageRep.
         */
        NSInteger result = 0;
        NSInteger bitmapResult = 0;
    
        for (NSImageRep* imageRep in [self representations]) {
            if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
                if (imageRep.pixelsHigh > bitmapResult)
                    bitmapResult = imageRep.pixelsHigh;
            } else {
                if (imageRep.pixelsHigh > result)
                    result = imageRep.pixelsHigh;
            }
        }
        if (bitmapResult) result = bitmapResult;
        return result;
    }
    
    - (NSSize) pixelSize
    {
        return NSMakeSize(self.pixelsWide,self.pixelsHigh);
    }
    
    @end
    

    您可以在当前文件中使用 #import "NSImage+PixelSize.h" 以使其可访问 .

    使用此图像类别和resize:方法,您可以修改您的方法:

    //size.width = inputRetinaImage.size.width*0.5;
    //size.height = inputRetinaImage.size.height*0.5;
    size.width  = inputRetinaImage.pixelsWide*0.5;
    size.height = inputRetinaImage.pixelsHigh*0.5;
    
    //[inputRetinaImage setSize:size];
    NSImage* outputImage = [self resizeImage:inputRetinaImage size:size];
    
    //NSBitmapImageRep *imgRep = [[inputRetinaImage representations] objectAtIndex: 0];
    NSBitmapImageRep *imgRep = [[outputImage representations] objectAtIndex: 0];
    

    这应该为你解决问题(附带条件:我没有在你的代码上测试它)

  • 2

    我修改了我用来缩小图像的脚本:)

    -(BOOL)createNormalImage:(NSString*)inputRetinaImagePath {
    
        NSImage *inputRetinaImage = [[NSImage alloc] initWithContentsOfFile:inputRetinaImagePath];
    
        //determine new size
        NSBitmapImageRep* bitmapImageRep = [[inputRetinaImage representations] objectAtIndex:0];
        NSSize size = NSMakeSize(bitmapImageRep.pixelsWide * 0.5,bitmapImageRep.pixelsHigh * 0.5);
    
        NSLog(@"size = %@", NSStringFromSize(size));
    
        //get CGImageRef
        CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)[inputRetinaImage TIFFRepresentation], NULL);
        CGImageRef oldImageRef =  CGImageSourceCreateImageAtIndex(source, 0, NULL);
        CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(oldImageRef);
        if (alphaInfo == kCGImageAlphaNone) alphaInfo = kCGImageAlphaNoneSkipLast;
    
        // Build a bitmap context
        CGContextRef bitmap = CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, CGImageGetColorSpace(oldImageRef), alphaInfo);
    
        // Draw into the context, this scales the image
        CGContextDrawImage(bitmap, CGRectMake(0, 0, size.width, size.height), oldImageRef);
    
        // Get an image from the context
        CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
    
        //this does not work in my test.
        NSString *outputFilePath = [[inputRetinaImagePath substringToIndex:inputRetinaImagePath.length - 7] stringByAppendingString:@".png"];
    
        //but this does!
        NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString* docsDirectory = [paths objectAtIndex:0];
        NSString *newfileName = [docsDirectory stringByAppendingFormat:@"/%@", [outputFilePath lastPathComponent]];
    
        CFURLRef url = (__bridge CFURLRef)[NSURL fileURLWithPath:newfileName];
        CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL);
        CGImageDestinationAddImage(destination, newImageRef, nil);
    
        if (!CGImageDestinationFinalize(destination)) {
            NSLog(@"Failed to write image to %@", newfileName);
        }
    
        CFRelease(destination);
    
        return true;
    }
    

相关问题