2012-07-05 16 views
5

Quiero añadir cruces en una NSImage, aquí está mi código:NSImage y la retina confusión pantalla

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

en la no-Retina Display, el resultado es: enter image description here

y la consola mostrará:

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 

pero en la pantalla Retina (no usé la pantalla retina real pero el modo hidpi):

consola:

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 

Si omito estas líneas:

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

enter image description here

Sin embargo si cambio [NSAffineTransform Scaleby] a 1,0 el resultado es correcto

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

enter image description here

Consola:

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 

Podría alguien dar una explicación por favor? ¿Es el modo hidpi diferente de la pantalla retina?

Respuesta

4

Creo que he encontrado la respuesta. Si NSAffineTransform se establece en el contexto de NSImage, transforma el sistema de coordenadas en dimensión de píxel, que es 2 x dimensión de punto. Incluso si está vacío así:

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

No sé si se trata de un error o de la forma en que funciona sin embargo.

0

Restablecer la transformación no es ningún error (se refiere a su propia respuesta). El uso de hidpi hace que la transformación predeterminada sea la que permite que la mayoría del código de alto nivel funcione bien tal como está. Restablecer a la transformación de identidad deshace esto para alinear el sistema de coordenadas 1: 1 con píxeles.

Sin embargo, rara vez se necesita hacer esto. La simplificación de su código de sacar las repeticiones de imagen y la transformación de cambio da a obtener esto:

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

esto debería funcionar, excepto la línea sería en cambio ser de 2 píxeles físicos amplia (pero por supuesto similares anchura de la imagen en un habitual pantalla). Pruebe este caso especial más simple para arreglar eso:

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