2012-10-02 6 views
8

@ 2xイメージを通常のサイズに再スケーリングする方法があるクイックアプリを開発しています。問題は、それがNSImageが縮尺変更されていません

をなぜ?:(しないということである

あなたはNSImageではのサイズ属性の非常に警戒する必要があります。それは必ずしもbitmapRepresentationのピクセル寸法を参照していない
-(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; 
} 
+0

ここで*は*動作しませんソリューションです。以前はこれをどのようにしていたのですが、Snow Leopard以来廃止され、ライオンのようには機能しません。 –

+0

あなたはちょうどそれを小さな矩形で描くことはできませんか?または、ヒントとしてNSAffineTransformを渡しますか? –

+0

@RamyAlZuhouri:アプリケーションが2倍のアセットを作成し、同じアセットから1倍のアセットを作成するために、イメージの解像度を下げて結果を保存することが目的のようです。 –

答えて

10

、それ例えば、表示サイズを参照することができます。NSImageでは、異なる出力サイズで使用するためbitmapRepresentationsの数を有することができる。

を同様に、何もbitmapRepresentationsを変えないためにないNSImageではのサイズ属性を変更

だから何をあなたは、あなたの出力イメージが欲しいサイズを探し出し、ソースNSImageからbitmapRepresentationを使ってそのサイズで新しいイメージを描画する必要があります。

このサイズを取得する方法は、入力イメージの取得方法とその知識についてです。たとえば、あなたが入力画像が一つだけbitmapImageRepを持っているあなたは(NSImageでは上のカテゴリとして)事のこのタイプを使用することができると確信していた場合

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

あなたがbitmapImageRepsの数を持っている場合でも、最初の1があるべきそれがあなたの網膜画像が作成されたサイズであれば、それは後の網膜サイズでなければなりません。

、あなたの最終的なサイズを働いていたとき、あなたは画像を作ることができます。

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

}

ここで更新

は、ピクセル、サイズのより精巧なバージョンです。 NSImageでカテゴリを取得します...画像について何も仮定しません。画像の数はどれくらいですか? bitmapImageReps ...これは最大のピクセル寸法を返します。i見つけることができます。 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"は、それがアクセスできるようにするでしょう。この画像カテゴリとリサイズして

:方法、あなたは、このようにあなたの方法を変更します:

//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]; 

あなたのための(条件を:私はあなたのコードでそれをテストしていない)ものを修正する必要があることを

`setScalesWhenResized::` は
+0

3つの場所すべてで 'bestRepresentationForRect:context:hints:'を使わないのはなぜですか? –

+1

私はそれが質問を懇願するかもしれないと思う... BestRepresentationForRect:私達が後である最終的なサイズを知っていることを示唆している - この場合、私達は網膜のサイズを半分にすることを望んでいる。また、NSImageがどのようにぶら下がっているかを学習する練習として、さまざまなimageRepsが実際にどのように関係しているかを把握することは悪い考えではありません。 – foundry

+0

rectはソースイメージのユーザー空間にあるので、円形ではありません。画像全体が必要な場合は、画像内の表現のピクセル解像度(またはその欠如)に関係なく、または希望のスケーリングされたサイズの(またはその欠如)にかかわらず、rectは '(NSRect){NSZeroPoint、image.size}解決。私は、代理人の性質を理解することが良いことに同意します。しかし、最初の担当者をつかんで、それがあなたが望むものになると仮定することは、その目的のための良い手段ではありません。 –

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; 
} 
関連する問題