2015-01-03 1 views
1

NSImage를 비례 적으로 크기를 조절하고 90도 회전했지만 그 결과 이미지가 잘린 상태로 유지하려고합니다.drawInRect의 NSImage를 비례 적으로 비율 조정 및 회전

- (void) drawRect:(NSRect)dirtyRect 
{ 
    [super drawRect:dirtyRect]; 

    NSImage* image = /* get image */; 

    CGRect drawRect = dirtyRect; 
    CGRect imageRect = [self proportionallyScale:image.size toSize:drawRect.size]; 

    NSAffineTransform* rotation = [[NSAffineTransform alloc] init]; 
    [rotation translateXBy:NSWidth(drawRect)/2 yBy:NSHeight(drawRect)/2]; 
    [rotation rotateByDegrees:90]; 
    [rotation translateXBy:-NSWidth(drawRect)/2 yBy:-NSHeight(drawRect)/2]; 

    NSGraphicsContext* context = [NSGraphicsContext currentContext]; 
    [context saveGraphicsState]; 
    [rotation concat]; 
    [image drawInRect:imageRect fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0]; 
    [context restoreGraphicsState]; 
} 

그리고 스케일링 로직 : 다음 NSView의 서브 클래스에서

가, 여기에 내가 현재하는 일이다 여기

- (CGRect) proportionallyScale:(CGSize)fromSize toSize:(CGSize)toSize 
{ 
    CGPoint origin = CGPointZero; 
    CGFloat width = fromSize.width, height = fromSize.height; 
    CGFloat targetWidth = toSize.width, targetHeight = toSize.height; 

    float widthFactor = targetWidth/width; 
    float heightFactor = targetHeight/height; 

    CGFloat scaleFactor = std::min(widthFactor, heightFactor); 

    CGFloat scaledWidth = width * scaleFactor; 
    CGFloat scaledHeight = height * scaleFactor; 

    if (widthFactor < heightFactor) 
     origin.y = (targetHeight - scaledHeight)/2.0; 
    else if (widthFactor > heightFactor) 
     origin.x = (targetWidth - scaledWidth)/2.0; 
    return {origin, {scaledWidth, scaledHeight}}; 
} 

이 적용되지 않은 회전 결과입니다 (이미지는 빨강, 사각형이 배경은도 임) 표시하도록 표현된다

No rotation applied

그리고 난 [rotation concat] 있도록하여 변환을 적용했을 때

Current code with 90 deg rotation applied

되는 문제가 그 이미지의 스케일링 및 회전 뷰포트의 크기가 아닌 입력 뷰 경계로 오프셋하여 계산한다 상대. 그러나 나는 이것을 올바르게 계산하는 논리를 생각해 낼 수 없다.

스케일링 된 이미지와 회전 된 이미지의 정확한 이미지 그리기 rect를 올바르게 계산하는 논리를 가진 사람이라면 누구든지 도와 주실 수 있습니까? 아니면 전체적인 문제에 대해 더 나은 접근법이 있습니까?

답변

4

짧은 버전

추가 : drawRect

긴에서 proportionallyScale 호출 버전

내가 두 단계로이를 이끌어 냈습니다

imageRect.origin.x += NSWidth(drawRect)/2 - NSHeight(drawRect)/2; 
imageRect.origin.y += NSHeight(drawRect)/2 - NSWidth(drawRect)/2; 

: 경계하고 이미지를 확장하고, 그런 다음 뷰포트 내에서 위치를 변경합니다. 당신이 모든 공상을 원한다면 아마 그들을 결합 할 수 있습니다. 나는 이것이 다양한 뷰 크기에서 작동해야한다고 생각한다.

이 우리의 원래보기를하자 :
******************** 
*     * 
*  View  * 6 
*     * 
*     * 
X******************* 
     20 

왼쪽 하단에있는 출처

X을 표시됩니다.

이미지가 6 x 8 (회전되기 전)이라고 가정 해 봅시다.

첫 번째 부분은 간단합니다. 회전 할 때 이미지를 얼마나 크게 그리는 지 결정하십시오.이것은 RECT 결과

CGRect imageRect = [self 
    proportionallyScale:image.size 
    toSize:CGSizeMake(
     drawRect.size.height, // 6 
     drawRect.size.width) // 20 
]; 

을 : : 그냥 proportionallyScale에 이성을 상실 차원에서 통과

imageRect = { origin=(x=0, y=6) size=(width=6, height=8) }; 

을하지만이 순간에 많은 이해가되지 않습니다 : 수행 다음

6 
$$$$$$ 
$ $ 
$ $ 
$ IM $ 8 
$ $ 
$ $ 
$ $ 
X$$$$$************** 
*     * 
*  View  * 6 
*     * 
*     * 
X******************* 
     20 

중심에 대한 시계의 시계 방향 90도 회전 :

     8 
       X++++X$$$$$$$$  - 
       + +  $  | 
Rot'd View >-- + $ IM $  | 
       + +  $ 6  | 7 
       + $  $  | 
       + +$$$$$$$$  | 
     *******+****+*******  - 
     * VP + +  *  | 
     *  + +  *  | 6 
     *  + +  *  | 
     *  + +  *  | 
     X******+****+*******  - 
       + +    | 
       + +    | 
       + +    | 
       + +    | 7 
       + +    | 
       ++++++    - 

     |------|----|------| 
      7  6  7 

VP가 원래보기의 위치입니다. 원점을 회전 된 공간에서 원래의 뷰포트 공간으로 변환해야합니다.

imageRect.origin.x += transX; 
imageRect.origin.y += transY; 

이 변환이 생산 : 우리는 현재 이미지 변환을 적용 그래서

// note that drawRect hasn't been flipped here 
CGFloat transX = NSWidth(drawRect)/2 - NSHeight(drawRect)/2 == 7; 
CGFloat transY = NSHeight(drawRect)/2 - NSWidth(drawRect)/2 == -7 

로 :이 변환

계산할 수있다

   X++++X 
       + + 
       + + 
       + + 
       + + 
       + + 
     ******$+$$$$+$****** 
     * VP $+ +$  * 
     *  $+ +$  * 
     *  $+ +$  * 
     *  $+ +$  * 
     X*****$+$$$$+$****** 
       + + 
       + + 
       + + 
       + + 
       + + 
       ++++++ 

이제 모든이다 잘 배치되고 크기 조정 됨 :

  6  8  6 
     |-----|------|-----| 

     ******$$$$$$$$****** - 
     *  $  $  * | 
     *  $  $  * | 6 
     *  $  $  * | 
     *  $  $  * | 
     X*****$$$$$$$$****** - 

적어도 다음 Vile Force of Darkness가 도착할 때까지 ...

관련 문제