2016-12-21 1 views
1

이미지의 임의 샘플을 가져올 수 있도록 NSImage 확장 프로그램을 작성했습니다. 샘플을 원본 이미지와 동일한 품질로 유지하고 싶습니다. 그러나 별칭이 있거나 약간 흐리게 보입니다.샘플 NSImage 및 품질 유지 (빠른 3)

sample

나는 순간에 SpriteKit이와 장난 해요 : 오른쪽 왼쪽에 무작위 표본에 그려진 원래는 - 여기 예입니다. 여기가 원래의 이미지를 만드는 방법은 다음과 같습니다

let bg = NSImage(imageLiteralResourceName: "ref") 
    let tex = SKTexture(image: bg) 
    let sprite = SKSpriteNode(texture: tex) 
    sprite.position = CGPoint(x: size.width/2, y:size.height/2) 
    addChild(sprite) 

을 그리고 여기 샘플을 만드는 방법은 다음과 같습니다

let sample = bg.sample(size: NSSize(width: 100, height: 100)) 
    let sampletex = SKTexture(image:sample!) 
    let samplesprite = SKSpriteNode(texture:sampletex) 
    samplesprite.position = CGPoint(x: 60, y:size.height/2) 
    addChild(samplesprite) 

여기 NSImage 확장 (그리고 난수 FUNC) 샘플 작성

extension NSImage { 

    /// Returns the height of the current image. 
    var height: CGFloat { 
     return self.size.height 
    } 

    /// Returns the width of the current image. 
    var width: CGFloat { 
     return self.size.width 
    } 

    func sample(size: NSSize) -> NSImage? { 
     // Resize the current image, while preserving the aspect ratio. 
     let source = self 

     // Make sure that we are within a suitable range 
     var checkedSize = size 
     checkedSize.width = floor(min(checkedSize.width,source.size.width * 0.9)) 
     checkedSize.height = floor(min(checkedSize.height, source.size.height * 0.9)) 

     // Get random points for the crop. 
     let x = randomNumber(range: 0...(Int(source.width) - Int(checkedSize.width))) 
     let y = randomNumber(range: 0...(Int(source.height) - Int(checkedSize.height))) 

     // Create the cropping frame. 
     var frame = NSRect(x: x, y: y, width: Int(checkedSize.width), height: Int(checkedSize.height)) 

     // let ref = source.cgImage.cropping(to:frame) 
     let ref = source.cgImage(forProposedRect: &frame, context: nil, hints: nil) 
     let rep = NSBitmapImageRep(cgImage: ref!) 

     // Create a new image with the new size 
     let img = NSImage(size: checkedSize) 

     // Set a graphics context 
     img.lockFocus() 
     defer { img.unlockFocus() } 

     // Fill in the sample image 
     if rep.draw(in: NSMakeRect(0, 0, checkedSize.width, checkedSize.height), 
        from: frame, 
        operation: NSCompositingOperation.copy, 
        fraction: 1.0, 
        respectFlipped: false, 
        hints: [NSImageHintInterpolation:NSImageInterpolation.high.rawValue]) { 
      // Return the cropped image. 
      return img 
     } 

     // Return nil in case anything fails. 
     return nil 
    } 

} 

func randomNumber(range: ClosedRange<Int> = 0...100) -> Int { 
    let min = range.lowerBound 
    let max = range.upperBound 
    return Int(arc4random_uniform(UInt32(1 + max - min))) + min 
} 

나는 이것을 약 10 가지 방법으로 시도해 왔으며 결과는 항상 약간 흐린 샘플로 보입니다. 나는 심지어 화면에 얼룩이 있는지 확인했다. :)

원본 원본 이미지의 섹션의 정확한 품질을 유지하는 NSImage 샘플을 만들려면 어떻게해야합니까?

+0

'NSImageInterpolation.none'을 사용해보세요. 또한,'cgImage (forProposedRect : ...)'가 프레임을 변경했다면 draw 할'in :'rect를 변경해야한다. 당신은 기본적으로 (-x, -y)에 의해 오프셋 된'frame'의 복사본을 사용해야합니다. 그래서 (x, y) 대신에 (0, 0)에 상대적입니다. –

+0

감사합니다. @KenThomases! 'NSImageInterpolation.none'이 트릭을했습니다. 나는 그것 이외의 모든 가치들을 시도했다고 생각한다. 답변을 추가하려면 올바른 것으로 표시하겠습니다. – Clay

답변

1

이 경우 보간 모드를 NSImageInterpolation.none으로 전환하는 것으로 충분했습니다.

그리기 대상 rect를 올바르게 처리하는 것도 중요합니다. cgImage(forProposedRect:...)은 제안 된 rect를 변경할 수 있으므로이를 기반으로하는 대상 rect를 사용해야합니다. 기본적으로 (-x, -y)로 오프셋 된 frame 사본을 사용해야하므로 (x, y) 대신 (0, 0)에 상대적입니다.