1
Fork 0
This repository has been archived on 2025-04-12. You can view files and clone it, but cannot push or open issues or pull requests.
silica-viewer/SilicaViewer/Extensions.swift

125 lines
4.4 KiB
Swift
Raw Normal View History

import Foundation
import AppKit
extension CGImage {
func toGrayscale() -> CGImage? {
let rect = CGRect(x: 0, y: 0, width: width, height: height)
let grayColorSpace = CGColorSpaceCreateDeviceGray()
let maskBitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue).union(.byteOrder16Big)
let ccgContext = CGContext(data: nil, width: width, height: height, bitsPerComponent: 16, bytesPerRow: width * 2, space: grayColorSpace, bitmapInfo: maskBitmapInfo.rawValue)
ccgContext?.setFillColor(.black)
ccgContext?.fill(rect)
ccgContext?.draw(self, in: rect)
return ccgContext?.makeImage()
}
// we really only handle 90 degree turns, which is totally fine
func rotate(angle : CGFloat, flipHorizontally : Bool, flipVertically : Bool) -> CGImage? {
let newWidth: CGFloat = CGFloat(height)
let newHeight: CGFloat = CGFloat(width)
let ctx = CGContext(data: nil,
width: Int(newWidth),
height: Int(newHeight),
bitsPerComponent: bitsPerComponent,
bytesPerRow: bytesPerRow,
space: colorSpace!,
bitmapInfo: bitmapInfo.rawValue)!
ctx.translateBy(x: newWidth / 2, y: newHeight / 2)
ctx.rotate(by: -angle)
if flipVertically {
ctx.scaleBy(x: 1.0, y: -1.0)
}
if flipHorizontally {
ctx.scaleBy(x: -1.0, y: 1.0)
}
let dstRect = CGRect(x: -width / 2, y: -height / 2, width: width, height: height)
ctx.draw(self, in: dstRect)
return ctx.makeImage()
}
}
extension NSImage {
func imageRotatedByDegreess(degrees:CGFloat) -> NSImage {
var imageBounds = NSMakeRect(0.0, 0.0, size.width, size.height)
let pathBounds = NSBezierPath(rect: imageBounds)
var transform = NSAffineTransform()
transform.rotate(byDegrees: degrees)
pathBounds.transform(using: transform as AffineTransform)
let rotatedBounds:NSRect = NSMakeRect(NSZeroPoint.x, NSZeroPoint.y, pathBounds.bounds.size.width, pathBounds.bounds.size.height )
let rotatedImage = NSImage(size: rotatedBounds.size)
imageBounds.origin.x = NSMidX(rotatedBounds) - (NSWidth(imageBounds) / 2)
imageBounds.origin.y = NSMidY(rotatedBounds) - (NSHeight(imageBounds) / 2)
transform = NSAffineTransform()
transform.translateX(by: +(NSWidth(rotatedBounds) / 2 ), yBy: +(NSHeight(rotatedBounds) / 2))
transform.rotate(byDegrees: degrees)
transform.translateX(by: -(NSWidth(rotatedBounds) / 2 ), yBy: -(NSHeight(rotatedBounds) / 2))
rotatedImage.lockFocus()
transform.concat()
self.draw(in: imageBounds, from: .zero, operation: .copy, fraction: 1.0)
rotatedImage.unlockFocus()
return rotatedImage
}
func flipHorizontally() -> NSImage {
let flipedImage = NSImage(size: size)
flipedImage.lockFocus()
let transform = NSAffineTransform()
transform.translateX(by: size.width, yBy: 0.0)
transform.scaleX(by: -1.0, yBy: 1.0)
transform.concat()
let rect = NSMakeRect(0, 0, size.width, size.height)
self.draw(at: .zero, from: rect, operation: .sourceOver, fraction: 1.0)
flipedImage.unlockFocus()
return flipedImage
}
func flipVertically() -> NSImage {
let flipedImage = NSImage(size: size)
flipedImage.lockFocus()
let transform = NSAffineTransform()
transform.translateX(by: 0.0, yBy: size.height)
transform.scaleX(by: 1.0, yBy: -1.0)
transform.concat()
let rect = NSMakeRect(0, 0, size.width, size.height)
self.draw(at: .zero, from: rect, operation: .sourceOver, fraction: 1.0)
flipedImage.unlockFocus()
return flipedImage
}
}
extension NSView {
class func fromNib<T: NSView>() -> T? {
var topLevelObjects : NSArray?
guard Bundle.main.loadNibNamed("\(self)", owner: nil, topLevelObjects: &topLevelObjects) else {
return nil
}
return topLevelObjects!.first(where: { $0 is T }) as? T
}
}