Move class extensions into their own file
This commit is contained in:
parent
441c353c41
commit
cea81a2221
5 changed files with 128 additions and 125 deletions
|
@ -11,6 +11,7 @@
|
||||||
030F700E2415C6B500A43F01 /* PreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030F700D2415C6B500A43F01 /* PreviewViewController.swift */; };
|
030F700E2415C6B500A43F01 /* PreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030F700D2415C6B500A43F01 /* PreviewViewController.swift */; };
|
||||||
030F70112415C6B500A43F01 /* PreviewViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 030F700F2415C6B500A43F01 /* PreviewViewController.xib */; };
|
030F70112415C6B500A43F01 /* PreviewViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 030F700F2415C6B500A43F01 /* PreviewViewController.xib */; };
|
||||||
030F70162415C6B500A43F01 /* QuickLook.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 030F70082415C6B500A43F01 /* QuickLook.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
030F70162415C6B500A43F01 /* QuickLook.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 030F70082415C6B500A43F01 /* QuickLook.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
03328514285A2AB700AEEBF3 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03328513285A2AB700AEEBF3 /* Extensions.swift */; };
|
||||||
035D1A0426F0927200B332BE /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035D19F826F0927200B332BE /* ViewController.swift */; };
|
035D1A0426F0927200B332BE /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035D19F826F0927200B332BE /* ViewController.swift */; };
|
||||||
035D1A0526F0927200B332BE /* cbridge.c in Sources */ = {isa = PBXBuildFile; fileRef = 035D19FA26F0927200B332BE /* cbridge.c */; };
|
035D1A0526F0927200B332BE /* cbridge.c in Sources */ = {isa = PBXBuildFile; fileRef = 035D19FA26F0927200B332BE /* cbridge.c */; };
|
||||||
035D1A0626F0927200B332BE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 035D19FB26F0927200B332BE /* Assets.xcassets */; };
|
035D1A0626F0927200B332BE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 035D19FB26F0927200B332BE /* Assets.xcassets */; };
|
||||||
|
@ -101,6 +102,7 @@
|
||||||
030F70102415C6B500A43F01 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PreviewViewController.xib; sourceTree = "<group>"; };
|
030F70102415C6B500A43F01 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PreviewViewController.xib; sourceTree = "<group>"; };
|
||||||
030F70122415C6B500A43F01 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
030F70122415C6B500A43F01 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
030F70132415C6B500A43F01 /* Quicklook.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Quicklook.entitlements; sourceTree = "<group>"; };
|
030F70132415C6B500A43F01 /* Quicklook.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Quicklook.entitlements; sourceTree = "<group>"; };
|
||||||
|
03328513285A2AB700AEEBF3 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
|
||||||
035D19F826F0927200B332BE /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
035D19F826F0927200B332BE /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||||
035D19F926F0927200B332BE /* SilicaViewer.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = SilicaViewer.entitlements; sourceTree = "<group>"; };
|
035D19F926F0927200B332BE /* SilicaViewer.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = SilicaViewer.entitlements; sourceTree = "<group>"; };
|
||||||
035D19FA26F0927200B332BE /* cbridge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cbridge.c; sourceTree = "<group>"; };
|
035D19FA26F0927200B332BE /* cbridge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cbridge.c; sourceTree = "<group>"; };
|
||||||
|
@ -245,6 +247,7 @@
|
||||||
035D1A0326F0927200B332BE /* Info.plist */,
|
035D1A0326F0927200B332BE /* Info.plist */,
|
||||||
0371996627BACD8700EE1DFD /* ExportAccessoryView.xib */,
|
0371996627BACD8700EE1DFD /* ExportAccessoryView.xib */,
|
||||||
0371996827BACDE800EE1DFD /* ExportAccessoryView.swift */,
|
0371996827BACDE800EE1DFD /* ExportAccessoryView.swift */,
|
||||||
|
03328513285A2AB700AEEBF3 /* Extensions.swift */,
|
||||||
);
|
);
|
||||||
path = SilicaViewer;
|
path = SilicaViewer;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -509,6 +512,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
035D1A0A26F0927200B332BE /* AppDelegate.swift in Sources */,
|
035D1A0A26F0927200B332BE /* AppDelegate.swift in Sources */,
|
||||||
|
03328514285A2AB700AEEBF3 /* Extensions.swift in Sources */,
|
||||||
035D1A0B26F0927200B332BE /* TimelapseViewController.swift in Sources */,
|
035D1A0B26F0927200B332BE /* TimelapseViewController.swift in Sources */,
|
||||||
035D1A0426F0927200B332BE /* ViewController.swift in Sources */,
|
035D1A0426F0927200B332BE /* ViewController.swift in Sources */,
|
||||||
035D1A0526F0927200B332BE /* cbridge.c in Sources */,
|
035D1A0526F0927200B332BE /* cbridge.c in Sources */,
|
||||||
|
|
|
@ -305,36 +305,3 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension CGImage {
|
|
||||||
// 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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -806,85 +806,3 @@ class Document: NSDocument {
|
||||||
return NSImage(data: thumbnailData)
|
return NSImage(data: thumbnailData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public 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 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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -22,13 +22,3 @@ class ExportAccessoryView : NSView {
|
||||||
savePanel?.allowedFileTypes?.append((typeBox.titleOfSelectedItem?.lowercased())!)
|
savePanel?.allowedFileTypes?.append((typeBox.titleOfSelectedItem?.lowercased())!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
124
SilicaViewer/Extensions.swift
Normal file
124
SilicaViewer/Extensions.swift
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue