Ich habe eine NSImage-Erweiterung geschrieben, mit der ich Stichproben eines Bildes aufnehmen kann. Ich möchte, dass diese Samples die gleiche Qualität wie das Originalbild behalten. Sie erscheinen jedoch als Alias oder leicht verschwommen. Hier ist ein Beispiel - das Original auf der rechte Seite und eine Stichprobe auf der linken Seite gezogen:Sample NSBeispiel und Qualität beibehalten (swift 3)
Ich spiele um mit diesem in SpriteKit im Moment. Hier ist, wie ich das Originalbild erstellen:
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)
Und hier ist, wie ich die Probe zu erstellen:
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)
Hier ist die NSImage Erweiterung (und random func), der die Probe erzeugt:
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
}
Ich habe dies über 10 verschiedene Möglichkeiten versucht und die Ergebnisse scheinen immer eine leicht unscharfe Probe zu sein. Ich habe sogar nach Flecken auf meinem Bildschirm gesucht. :)
Wie kann ich ein Beispiel eines NSMag erstellen, das die genauen Eigenschaften des Abschnitts des ursprünglichen Quellbildes beibehält?
Versuchen Sie 'NSImageInterpolation.none'. Wenn 'cgImage (forProposedRect: ...)' 'den Frame geändert hat, sollten Sie das' in: 'rect ändern, zu dem Sie zeichnen. Sie sollten grundsätzlich eine Kopie von 'frame' verwenden, die um (-x, -y) versetzt ist, so dass sie relativ zu (0, 0) statt (x, y) ist. –
Danke @KenThomases! 'NSImageInterpolation.none' hat es geschafft. Ich glaube, ich habe alle anderen Werte ausprobiert. Wenn Sie eine Antwort hinzufügen möchten, markiere ich sie korrekt. – Clay