样本图像和保留质量(swift 3)

样本图像和保留质量(swift 3),swift,macos,appkit,Swift,Macos,Appkit,我写了一个NSImage扩展,允许我对图像进行随机采样。我希望这些样品保持与原始图像相同的质量。但是,它们似乎有别名或有点模糊。下面是一个示例-右侧绘制的原始样本和左侧的随机样本: 我现在正在SpriteKit中玩这个。以下是我创建原始图像的方式: let bg = NSImage(imageLiteralResourceName: "ref") let tex = SKTexture(image: bg) let sprite = SKSpriteNode(textu

我写了一个NSImage扩展,允许我对图像进行随机采样。我希望这些样品保持与原始图像相同的质量。但是,它们似乎有别名或有点模糊。下面是一个示例-右侧绘制的原始样本和左侧的随机样本:

我现在正在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)
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
}
以下是创建示例的NSImage扩展名(和randomNumber func):

    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)
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
}
扩展NSImage{
///返回当前图像的高度。
变量高度:CGFloat{
返回self.size.height
}
///返回当前图像的宽度。
变量宽度:CGFloat{
返回self.size.width
}
func样本(大小:NSSize)->NSImage{
//调整当前图像的大小,同时保留纵横比。
让源=自
//确保我们在合适的范围内
var checkedSize=大小
checkedSize.width=地板(最小值(checkedSize.width,source.size.width*0.9))
checkedSize.height=地板(最小值(checkedSize.height,source.size.height*0.9))
//获取作物的随机点。
设x=randomNumber(范围:0…(Int(source.width)-Int(checkedSize.width)))
设y=randomNumber(范围:0…(Int(source.height)-Int(checkedSize.height)))
//创建裁剪帧。
var frame=NSRect(x:x,y:y,宽度:Int(checkedSize.width),高度:Int(checkedSize.height))
//let ref=source.cgImage.crapping(到:帧)
let ref=source.cgImage(forProposedRect:&frame,上下文:nil,提示:nil)
let rep=NSBitmapImageRep(cgImage:ref!)
//创建具有新大小的新图像
让img=NSImage(大小:checkedSize)
//设置图形上下文
img.lockFocus()
延迟{img.unlockFocus()}
//填写示例图像
如果rep.draw(in:NSMakeRect(0,0,checkedSize.width,checkedSize.height),
发件人:frame,
操作:nscompositionOperation.copy,
分数:1.0,
被尊重的人:错,
提示:[NSImageHintInterpolation:NSImageInterpolation.high.rawValue]){
//返回裁剪后的图像。
返回img
}
//如果出现任何故障,则返回nil。
归零
}
}
func随机数(范围:ClosedRange=0…100)->Int{
设最小值=range.lowerBound
设max=range.upperBound
返回Int(arc4random_uniform(UInt32(1+max-min)))+min
}
我试过10种不同的方法,结果总是有点模糊。我甚至检查了屏幕上的污迹


如何创建保留原始源图像部分准确质量的NSImage样本?

将插值模式切换为
NSIMAGEINTERROPERSOTION。在这种情况下,没有一个
显然是足够的


正确处理绘图目标rect也很重要。由于
cgImage(forProposedRect:…)
可能会更改建议的rect,因此应该使用基于它的目标rect。基本上,您应该使用偏移量为(-x,-y)的
帧的副本,使其相对于(0,0)而不是(x,y)。

尝试
NSImageInterpolation。无
。另外,如果
cgImage(forProposedRect:…)
更改了帧,那么您应该更改您绘制到的
中的
。基本上,你应该使用一个偏移量为(-x,-y)的
帧的副本,因此它相对于(0,0)而不是(x,y)。谢谢@kenthomass<代码>NSImageInterpolation。没有一个
成功。我想我已经尝试过了除此之外的所有价值观。如果你想添加一个答案,我会把它标记为正确。