2012-07-29 10 views
7

içinde bir NSImage sınırının alınması Bir pencerenin tüm boyutunu kaplayan bir NSImageView var. Görüntü görünümüne kenarlık yok ve sol altta gösterilecek ayar var. Yani bu, pencerenin nasıl yeniden boyutlandırıldığına bakılmaksızın, görüntünün kökeninin gerçek görüntünün kökü ile eşleştiği anlamına gelir. Ayrıca, görüntü, ekranda tam olarak sığabileceğim boyuttan çok daha büyüktür. Bu yüzden, görüntünün boyutunu küçültmek için görüntü ayarına sahibim. Ancak, bu ölçek faktörünü hiçbir yerde bulamıyorum.NSImageView

Amacım, bir fare aşağı olayı gerçek görüntü koordinatlarına eşlemektir. Bunu yapmak için bence daha fazla bilgiye ihtiyacım var ... görüntülenen NSImage'ın gerçekte ne kadar büyük olduğu.

[imageView bounds]'a bakarsanız, genellikle resimden daha büyük olacak şekilde resim görünümünün sınırlayıcı dikdörtgeni alırım.

+0

Bunu denedim. Çerçeveler ve sınırlar ve diğerleri, NSView/NSWindow tipi nesnelere göre geçerlidir. Bu yüzden, görüşün veya pencerenin sınırlayıcı çerçevesini alabilirim ... sorun, NSImageView'in tüm sınırlarını çizmemesidir. Görünümün bir kısmı boş. Ve ihtiyacım olan şey ya NSImageView'in görüntüsünü küçültme miktarı ya da ImageView'ın gerçekte çizdiği sınırın dikdörtgeni (sahip olduklarının aksine) – wrjohns

+0

Şu an için bir geçici çözüm ile gidiyorum. Yeniden boyutlandırılacak pencereyi engelleme ve pencereden diğer tüm UI öğelerini kaldırma (başlık çubuğu gibi), böylece süper görüntü sınırlarını biliyorum = NSImageView sınırları = gerçek görüntünün boyutu. – wrjohns

+0

NSImages'de çerçeve yok. ** ** 'nin boyutları var, ancak boyutları tam olarak çizildikleri boyut değil, tam ölçekli görüntüdür. – wrjohns

cevap

2

bu ihtiyacın olanı verir düşünüyorum:

görünümü içinde görüntünün kökenli ofset döndürür ve boyutu nedir
NSRect imageRect = [imageView.cell drawingRectForBounds: imageView.bounds]; 

.

Ve sen çalışması gerektiğini Özel görünüm sınıfına böyle bir şey fare koordinatlarını yeniden eşleme hedefi sonuna için

...

- (void)mouseUp:(NSEvent *)event 
{ 
    NSPoint eventLocation = [event locationInWindow];  
    NSPoint location = [self convertPoint: eventLocation fromView: nil]; 

    NSRect drawingRect = [self.cell drawingRectForBounds:self.bounds]; 

    location.x -= drawingRect.origin.x; 
    location.y -= drawingRect.origin.y; 

    NSSize frameSize = drawingRect.size; 
    float frameAspect = frameSize.width/frameSize.height; 

    NSSize imageSize = self.image.size; 
    float imageAspect = imageSize.width/imageSize.height; 

    float scaleFactor = 1.0f; 

    if(imageAspect > frameAspect) { 

     ///in this case image.width == frame.width 
     scaleFactor = imageSize.width/frameSize.width; 

     float imageHeightinFrame = imageSize.height/scaleFactor; 

     float imageOffsetInFrame = (frameSize.height - imageHeightinFrame)/2; 

     location.y -= imageOffsetInFrame; 

    } else { 
     ///in this case image.height == frame.height 
     scaleFactor = imageSize.height/frameSize.height; 

     float imageWidthinFrame = imageSize.width/scaleFactor; 

     float imageOffsetInFrame = (frameSize.width - imageWidthinFrame)/2; 

     location.x -= imageOffsetInFrame; 
    } 

    location.x *= scaleFactor; 
    location.y *= scaleFactor; 

    //do something with you newly calculated mouse location  
} 
+0

Üzgünüz ... ilk satır işe yaramadı. Ben hesaplanmış rect I NSLog'ed ve pencere boyutu yeniden boyutlandırma gibi (ama imagecell orantılı çekmek için ayarlanır), yeniden boyutlandırıldı, görüntülenen görüntü değil, görüntülerin sınırlarını, pencerenin sınırlarını eşleşti. Bunun için bir API çağrısı olmadığını düşünmeye başladım. Yapabileceğim şey, orijinal, ölçeklendirilmemiş görüntünün en boy oranını hesaplamaktır ... ve yeniden boyutlandırılan pencerede görüntü boyutunu hesaplamak için bunu kullanın. – wrjohns

+0

Doğru ayarlanmış olan şeylerin nasıl oluşturulduğuna dair açıkladığınıza göre.Yukarıdaki kodun geri kalanı, ofsetin görüntüye kendisini hesaplar. Kodun kalanını denedin mi? Görüşüm ve pencerenin sınırlarının benim sınırım olmadığı gibi eşleşmesi dışında size çok benzer bir şey yapıyorum. Final * = scaleFactor'a ihtiyacınız olmayabilir çünkü görüntü alanındaki koordinatları (yani görüntünün gerçek boyutuna göre) istiyorum. – combinatorial

+0

Kodun kalanını denedim. Fakat drawingRect'in kapalı olmasıyla, hesaplanan son koordinat da kapalıydı. İstediğim şeye 2 yönlü bir yaklaşım üzerinde karar verdim: NSWindowDelegate'den birkaç yöntem uygulamak ve en boy oranını korumak için herhangi bir manuel yeniden boyutlandırmayı zorlamak ve sonra mouseUp: yöntemimde, görüntü boyutunun pencere boyutu – wrjohns

0

Bir yukarıdaki yorumunda belirtildiği gibi, burada aldı yaklaşım:

// the view that mouseUp: is part of doesnt draw anything. I'm layering it 
// in the window hierarchy to intercept mouse events. I suppose I could have 
// subclassed NSImageView instead, but I went this route. isDragging is 
// an ivar...its cleared in mouseDown: and set in mouseDragged: 
// this view has no idea what the original unscaled image size is, so 
// rescaling is done by caller 
- (void)mouseUp:(NSEvent *)theEvent 
{ 

    if (!isDragging) 
    { 
     NSPoint rawPoint = [theEvent locationInWindow]; 
     NSImageView *view = self.subviews.lastObject; 

     point = [self convertPoint:rawPoint fromView:view]; 
     point.x /= view.bounds.size.width; 
     point.y /= view.bounds.size.height; 

     [owner mouseClick:point]; 

    } 
} 

Ve fare görünümü için penceremin temsilci benim NSWindowController, içinde , var:

static int resizeMode=-1; 

- (void)windowDidEndLiveResize:(NSNotification *)notification 
{ 
    if ([notification object]==frameWindow) 
     self.resizeFrameSelection=0; 
    resizeMode = -1; 
} 

- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize 
{ 

    if (sender==frameWindow) 
    { 
     float imageAspectRatio = (float)movie.movieSize.width/(float)movie.movieSize.height; 
     float newH = frameSize.height; 
     float newW = frameSize.width; 
     float currH = sender.frame.size.height; 
     float currW = sender.frame.size.width; 
     float deltaH = abs(newH-currH); 
     float deltaW = abs(newW-currW); 

     // lock onto one dimension to key off of, per drag. 
     if (resizeMode==1 || (resizeMode==-1 && deltaW<deltaH)) 
     { 
      // adjust width to match aspect ratio 
      frameSize.width = frameSize.height * imageAspectRatio; 
      resizeMode=1; 
     } 
     else 
     { 
      // adjust height to match aspect ratio 
      frameSize.height = frameSize.width/imageAspectRatio; 
      resizeMode=2; 
     } 
    } 

    return frameSize; 
} 
0

Henüz NSImageView içindeki gerçek görüntü çerçevesini elde etmek için herhangi bir çözüm bulamadığımdan, tüm özelliklerini (ölçekleme, hizalama ve kenarlık) dikkate alarak, görüntü hesaplamalarını manuel olarak yaptım. Bu, en verimli kod olmayabilir ve gerçek görüntüden 0,5-1 piksel arasında küçük sapmalar olabilir ancak orijinal görüntüye oldukça yakın geliyor (Bu sorunun oldukça eski olduğunu biliyorum ancak çözüm diğerlerine yardımcı olabilir):

@implementation NSImageView (ImageFrame) 

// ------------------------------------------------------------------------- 
// -imageFrame 
// ------------------------------------------------------------------------- 
- (NSRect)imageFrame 
{ 
    // Find the content frame of the image without any borders first 
    NSRect contentFrame = self.bounds; 
    NSSize imageSize = self.image.size; 
    NSImageFrameStyle imageFrameStyle = self.imageFrameStyle; 

    if (imageFrameStyle == NSImageFrameButton || 
     imageFrameStyle == NSImageFrameGroove) 
    { 
     contentFrame = NSInsetRect(self.bounds, 2, 2); 
    } 

    else if (imageFrameStyle == NSImageFramePhoto) 
    { 
     contentFrame = NSMakeRect(contentFrame.origin.x + 1, 
            contentFrame.origin.y + 2, 
            contentFrame.size.width - 3, 
            contentFrame.size.height - 3); 
    } 

    else if (imageFrameStyle == NSImageFrameGrayBezel) 
    { 
     contentFrame = NSInsetRect(self.bounds, 8, 8); 
    } 


    // Now find the right image size for the current imageScaling 
    NSImageScaling imageScaling = self.imageScaling; 
    NSSize drawingSize = imageSize; 

    // Proportionally scaling 
    if (imageScaling == NSImageScaleProportionallyDown || 
     imageScaling == NSImageScaleProportionallyUpOrDown) 
    { 
     NSSize targetScaleSize = contentFrame.size; 
     if (imageScaling == NSImageScaleProportionallyDown) 
     { 
      if (targetScaleSize.width > imageSize.width) targetScaleSize.width = imageSize.width; 
      if (targetScaleSize.height > imageSize.height) targetScaleSize.height = imageSize.height; 
     } 

     NSSize scaledSize = [self sizeByScalingProportionallyToSize:targetScaleSize fromSize:imageSize]; 
     drawingSize = NSMakeSize(scaledSize.width, scaledSize.height); 
    } 

    // Axes independent scaling 
    else if (imageScaling == NSImageScaleAxesIndependently) 
     drawingSize = contentFrame.size; 


    // Now get the image position inside the content frame (center is default) from the current imageAlignment 
    NSImageAlignment imageAlignment = self.imageAlignment; 
    NSPoint drawingPosition = NSMakePoint(contentFrame.origin.x + contentFrame.size.width/2.0 - drawingSize.width/2.0, 
              contentFrame.origin.y + contentFrame.size.height/2.0 - drawingSize.height/2.0); 

    // NSImageAlignTop/NSImageAlignTopLeft/NSImageAlignTopRight 
    if (imageAlignment == NSImageAlignTop || 
     imageAlignment == NSImageAlignTopLeft || 
     imageAlignment == NSImageAlignTopRight) 
    { 
     drawingPosition.y = contentFrame.origin.y+contentFrame.size.height - drawingSize.height; 

     if (imageAlignment == NSImageAlignTopLeft) 
      drawingPosition.x = contentFrame.origin.x; 
     else if (imageAlignment == NSImageAlignTopRight) 
      drawingPosition.x = contentFrame.origin.x + contentFrame.size.width - drawingSize.width; 
    } 

    // NSImageAlignBottom/NSImageAlignBottomLeft/NSImageAlignBottomRight 
    else if (imageAlignment == NSImageAlignBottom || 
      imageAlignment == NSImageAlignBottomLeft || 
      imageAlignment == NSImageAlignBottomRight) 
    { 
     drawingPosition.y = contentFrame.origin.y; 

     if (imageAlignment == NSImageAlignBottomLeft) 
      drawingPosition.x = contentFrame.origin.x; 
     else if (imageAlignment == NSImageAlignBottomRight) 
      drawingPosition.x = contentFrame.origin.x + contentFrame.size.width - drawingSize.width; 
    } 

    // NSImageAlignLeft/NSImageAlignRight 
    else if (imageAlignment == NSImageAlignLeft) 
     drawingPosition.x = contentFrame.origin.x; 

    // NSImageAlignRight 
    else if (imageAlignment == NSImageAlignRight) 
     drawingPosition.x = contentFrame.origin.x + contentFrame.size.width - drawingSize.width; 


    return NSMakeRect(round(drawingPosition.x), 
         round(drawingPosition.y), 
         ceil(drawingSize.width), 
         ceil(drawingSize.height)); 
} 

// ------------------------------------------------------------------------- 
// -sizeByScalingProportionallyToSize:fromSize: 
// ------------------------------------------------------------------------- 
- (NSSize)sizeByScalingProportionallyToSize:(NSSize)newSize fromSize:(NSSize)oldSize 
{ 
    CGFloat widthHeightDivision = oldSize.width/oldSize.height; 
    CGFloat heightWidthDivision = oldSize.height/oldSize.width; 

    NSSize scaledSize = NSZeroSize; 
    if (oldSize.width > oldSize.height) 
    { 
     if ((widthHeightDivision * newSize.height) >= newSize.width) 
     { 
      scaledSize = NSMakeSize(newSize.width, heightWidthDivision * newSize.width); 
     } else { 
      scaledSize = NSMakeSize(widthHeightDivision * newSize.height, newSize.height); 
     } 

    } else { 

     if ((heightWidthDivision * newSize.width) >= newSize.height) 
     { 
      scaledSize = NSMakeSize(widthHeightDivision * newSize.height, newSize.height); 
     } else { 
      scaledSize = NSMakeSize(newSize.width, heightWidthDivision * newSize.width); 
     } 
    } 

    return scaledSize; 
} 

@end