2012-07-05 100 views
5

我想在NSImage中添加十字架,這裏是我的代碼:NSImage中和視網膜顯示混亂

-(NSSize)convertPixelSizeToPointSize:(NSSize)px 
{ 
    CGFloat displayScale = [[NSScreen mainScreen] backingScaleFactor]; 
    NSSize res; 
    res.width = px.width/displayScale; 
    res.height = px.height/displayScale; 
    return res; 
} 

-(void)awakeFromNib 
{ 
    CGFloat scale = [[NSScreen mainScreen] backingScaleFactor]; 

    NSLog(@"backingScaleFactor : %f",scale); 

    NSImage *img = [[[NSImage alloc]initWithContentsOfFile:@"/Users/support/Pictures/cat.JPG"] autorelease]; 


    NSBitmapImageRep *imgRep = [NSBitmapImageRep imageRepWithData:[img TIFFRepresentation]]; 
    NSSize imgPixelSize = NSMakeSize([imgRep pixelsWide],[imgRep pixelsHigh]); 
    NSSize imgPointSize = [self convertPixelSizeToPointSize:imgPixelSize]; 
    [img setSize:imgPointSize]; 

    NSLog(@"imgPixelSize.width: %f , imgPixelSize.height:%f",imgPixelSize.width,imgPixelSize.height); 
    NSLog(@"imgPointSize.width: %f , imgPointSize.height:%f",imgPointSize.width,imgPointSize.height); 

    [img lockFocus]; 
    NSAffineTransform *trans = [[[NSAffineTransform alloc] init] autorelease]; 
    [trans scaleBy:1.0/scale]; 
    [trans set]; 

    NSBezierPath *path = [NSBezierPath bezierPath];  
    [[NSColor redColor] setStroke]; 
    [path moveToPoint:NSMakePoint(0.0, 0.0)]; 
    [path lineToPoint:NSMakePoint(imgPixelSize.width, imgPixelSize.height)]; 
    [path moveToPoint:NSMakePoint(0.0, imgPixelSize.height)]; 
    [path lineToPoint:NSMakePoint(imgPixelSize.width, 0.0)]; 

    [path setLineWidth:1]; 
    [path stroke]; 
    [img unlockFocus]; 

    [imageView setImage:img]; 

    imgRep = [NSBitmapImageRep imageRepWithData:[img TIFFRepresentation]]; 
    NSData *imageData = [imgRep representationUsingType:NSJPEGFileType properties:nil]; 
    [imageData writeToFile:@"/Users/support/Pictures/11-5.JPG" atomically:NO]; 
} 

非視網膜顯示的結果是: enter image description here

和顯示控制檯:

2012-07-06 00:53:09.889 RetinaTest[8074:403] backingScaleFactor : 1.000000 
2012-07-06 00:53:09.901 RetinaTest[8074:403] imgPixelSize.width: 515.000000 , imgPixelSize.height:600.000000 
2012-07-06 00:53:09.902 RetinaTest[8074:403] imgPointSize.width: 515.000000 , imgPointSize.height:600.000000 

但在視網膜顯示器上(我沒有使用真正的視網膜顯示器但是使用了hidpi模式): enter image description here

控制檯:

2012-07-06 00:56:05.071 RetinaTest[8113:403] backingScaleFactor : 2.000000 
2012-07-06 00:56:05.083 RetinaTest[8113:403] imgPixelSize.width: 515.000000 , imgPixelSize.height:600.000000 
2012-07-06 00:56:05.084 RetinaTest[8113:403] imgPointSize.width: 257.500000 , imgPointSize.height:300.000000 

如果我省略這些行:

NSAffineTransform *trans = [[[NSAffineTransform alloc] init] autorelease]; 
      [trans scaleBy:1.0/scale]; 
      [trans set]; 

enter image description here

然而如果我改變[NSAffineTransform scaleBy]〜1.0的結果是正確的

NSAffineTransform *trans = [[[NSAffineTransform alloc] init] autorelease]; 
     [trans scaleBy:1.0]; 
     [trans set]; 

enter image description here

控制檯:

2012-07-06 01:01:03.420 RetinaTest[8126:403] backingScaleFactor : 2.000000 
2012-07-06 01:01:03.431 RetinaTest[8126:403] imgPixelSize.width: 515.000000 , imgPixelSize.height:600.000000 
2012-07-06 01:01:03.432 RetinaTest[8126:403] imgPointSize.width: 257.500000 , imgPointSize.height:300.000000 

誰能給個說法嗎?是不同於視網膜顯示的hidpi模式?

回答

4

我想我找到了答案。如果NSAffineTransform設置爲NSImage的上下文,它會將座標系轉換爲像素尺寸,即2 x點尺寸。即使它是空的是這樣的:

NSAffineTransform *trans = [[[NSAffineTransform alloc] init] autorelease]; 
[trans set]; 

我不知道這是否是一個bug或者是它的工作原理雖然方式。

0

重置轉換沒有錯誤(指您自己的答案)。使用hidpi可以使默認轉換成爲可以讓大多數高級代碼保持原樣的狀態。重置爲標識變換將取消此操作以使座標系1:1與像素對齊。

儘管如此,人們應該很少需要這樣做。簡化你的代碼取出形象代表和變換的變化讓你得到這樣的:

NSImage *img = [[[NSImage alloc]initWithContentsOfFile:@"/Users/support/Pictures/cat.JPG"] autorelease]; 
NSSize size = img.size; 

NSBezierPath *path = [NSBezierPath bezierPath];  
[[NSColor redColor] setStroke]; 
[path moveToPoint:NSMakePoint(0.0, 0.0)]; 
[path lineToPoint:NSMakePoint(size.width, size.height)]; 
[path moveToPoint:NSMakePoint(0.0, size.height)]; 
[path lineToPoint:NSMakePoint(size.width, 0.0)]; 

[path setLineWidth:1]; 
[path stroke]; 
[img unlockFocus]; 

[imageView setImage:img]; 
... 

這應該只是行工作將改爲2個物理像素寬(但當然類似的寬度對圖像定期屏幕)。試試這個更簡單的特殊情況來解決這個問題:

[path setLineWidth:(img.scale > 1) ? 0.5 : 1.0];