Skip to content

Commit

Permalink
Merge pull request #31 from IdeasOnCanvas/bugfix/alpha-channel-in-exp…
Browse files Browse the repository at this point in the history
…orted-images

Disable Alpha channel in exported images
  • Loading branch information
Patrick-Kladek authored Feb 8, 2022
2 parents 66dbf50 + cd969c2 commit b76b96a
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 67 deletions.
5 changes: 4 additions & 1 deletion Screenshot Framer CLI/Export.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ extension Export {
let fileCapsule = FileCapsule()
fileCapsule.projectURL = project.deletingLastPathComponent()

guard let layerStateHistory = self.layerStateHistory(for: project) else { return }
guard let layerStateHistory = self.layerStateHistory(for: project) else {
ConsoleIO.writeMessage("Could not open file: \(project.lastPathComponent)", to: .error)
return
}

let fileController = FileController(fileCapsule: fileCapsule)
let languageController = LanguageController(fileCapsule: fileCapsule)
Expand Down
1 change: 1 addition & 0 deletions Screenshot Framer CLI/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct ScreenshotFramer: ParsableCommand {

static let configuration = CommandConfiguration(
abstract: "A Swift command-line tool to frame localised screenshots for the AppStore",
version: "2.0"
subcommands: [Export.self, Website.self])

init() { }
Expand Down
2 changes: 2 additions & 0 deletions Screenshot Framer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.ideasoncanvas.ScreenshotFramer;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand All @@ -787,6 +788,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.ideasoncanvas.ScreenshotFramer;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ final class ContentViewController: NSViewController, NSMenuItemValidation {
@IBOutlet private var tableView: SSFTableView!
@IBOutlet private var addMenu: NSMenu!
@IBOutlet private var layoutWarningButton: NSButton!
@IBOutlet private var transparencyCheckbox: NSButton!
@IBOutlet private var textFieldOutput: NSTextField!
@IBOutlet private var textFieldFromImageNumber: NSTextField!
@IBOutlet private var textFieldToImageNumber: NSTextField!
Expand Down Expand Up @@ -183,7 +184,7 @@ final class ContentViewController: NSViewController, NSMenuItemValidation {
}

@IBAction func outputConfigDidChange(_ sender: AnyObject?) {
guard let sender = sender as? NSTextField else { return }
guard let sender = sender as? NSView else { return }

switch sender {
case self.textFieldOutput:
Expand All @@ -209,6 +210,11 @@ final class ContentViewController: NSViewController, NSMenuItemValidation {
let operation = UpdateToImageNuberOperation(layerStateHistory: self.layerStateHistory, toImageNumber: self.textFieldToImageNumber.integerValue)
operation.apply()

case self.transparencyCheckbox:
let transparent = self.transparencyCheckbox.state == .on ? true : false
let operation = UpdateTransparencyOperation(layerStateHistory: self.layerStateHistory, transparent: transparent)
operation.apply()

default:
return
}
Expand Down Expand Up @@ -303,6 +309,7 @@ final class ContentViewController: NSViewController, NSMenuItemValidation {
self.scrollView.documentView = self.layoutController.layoutHierarchy(layers: self.lastLayerState.layers)
self.layoutWarningButton.isHidden = self.layoutController.layoutErrors.isEmpty

self.transparencyCheckbox.state = self.lastLayerState.outputConfig.transparent ? .on : .off
self.textFieldOutput.stringValue = self.lastLayerState.outputConfig.output
self.textFieldFromImageNumber.integerValue = self.lastLayerState.outputConfig.fromImageNumber
self.textFieldToImageNumber.integerValue = self.lastLayerState.outputConfig.toImageNumber
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@ protocol ExportControllerDelegate: AnyObject {

final class ExportController {

private var shouldCancel: Bool = false

// MARK: - Properties

private var shouldCancel: Bool = false
let fileController: FileController
let languageController: LanguageController
let layerStateHistory: LayerStateHistory
weak var delegate: ExportControllerDelegate?

var lastLayerState: LayerState { return self.layerStateHistory.currentLayerState }

var lastLayerState: LayerState {
return self.layerStateHistory.currentLayerState
}

// MARK: - Lifecycle

Expand All @@ -49,7 +51,7 @@ final class ExportController {
guard let url = self.fileController.outputURL(for: self.lastLayerState, viewState: viewState) else { return [.noOutputFile] }

try? fileManager.createDirectory(at: url.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil)
if let data = view.pngData() {
if let data = view.pngData(transparent: self.lastLayerState.outputConfig.transparent) {
try? data.write(to: url, options: .atomic)
}

Expand All @@ -69,16 +71,33 @@ final class ExportController {

for language in self.languageController.allLanguages(prefered: language) {
viewStateController.newViewState(language: language)
guard let lower = self.lastLayerState.outputConfig.prefered(from: start) else { continue }
guard let upper = self.lastLayerState.outputConfig.prefered(end: end) else { continue }

var lower: Int
var upper: Int

if let start = start {
guard let _lower = self.lastLayerState.outputConfig.prefered(from: start) else { continue } // swiftlint:disable:this identifier_name

lower = _lower
} else {
lower = self.lastLayerState.outputConfig.fromImageNumber
}

if let end = end {
guard let _upper = self.lastLayerState.outputConfig.prefered(end: end) else { continue } // swiftlint:disable:this identifier_name

upper = _upper
} else {
upper = self.lastLayerState.outputConfig.toImageNumber
}

for index in lower...upper {
viewStateController.newViewState(imageNumber: index)
guard let view = layoutController.layoutHierarchy(layers: self.lastLayerState.layers) else { continue } // TODO: is called from a background thread
guard let url = self.fileController.outputURL(for: self.lastLayerState, viewState: viewStateController.viewState) else { return [.noOutputFile] }

try? fileManager.createDirectory(at: url.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil)
if let data = view.pngData() {
if let data = view.pngData(transparent: self.lastLayerState.outputConfig.transparent) {
try? data.write(to: url, options: .atomic)
}

Expand Down Expand Up @@ -119,7 +138,7 @@ final class ExportController {
let tempURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("Preview \(name).png")

do {
try view.pngData()?.write(to: tempURL)
try view.pngData(transparent: self.lastLayerState.outputConfig.transparent)?.write(to: tempURL)
} catch {
let alert = NSAlert(error: error)
alert.runModal()
Expand Down Expand Up @@ -156,7 +175,7 @@ final class ExportController {
let tempURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("Preview Languages of \(name).png")

do {
try view.pngData()?.write(to: tempURL)
try view.pngData(transparent: self.lastLayerState.outputConfig.transparent)?.write(to: tempURL)
} catch {
let alert = NSAlert(error: error)
alert.runModal()
Expand Down
11 changes: 8 additions & 3 deletions Screenshot Framer/Model/LayerState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,20 +127,25 @@ struct LayerState: Codable {
// MARK: - Output Config

func updating(output: String) -> LayerState {
let newConfig = OutputConfig(output: output, fromImageNumber: self.outputConfig.fromImageNumber, toImageNumber: self.outputConfig.toImageNumber)
let newConfig = OutputConfig(transparent: self.outputConfig.transparent, output: output, fromImageNumber: self.outputConfig.fromImageNumber, toImageNumber: self.outputConfig.toImageNumber)
return LayerState(title: "Updating Export Output", layers: self.layers, outputConfig: newConfig)
}

func updating(fromImageNumber: Int) -> LayerState {
let newConfig = OutputConfig(output: self.outputConfig.output, fromImageNumber: fromImageNumber, toImageNumber: self.outputConfig.toImageNumber)
let newConfig = OutputConfig(transparent: self.outputConfig.transparent, output: self.outputConfig.output, fromImageNumber: fromImageNumber, toImageNumber: self.outputConfig.toImageNumber)
return LayerState(title: "Updating Export From Image Number", layers: self.layers, outputConfig: newConfig)
}

func updating(toImageNumber: Int) -> LayerState {
let newConfig = OutputConfig(output: self.outputConfig.output, fromImageNumber: self.outputConfig.fromImageNumber, toImageNumber: toImageNumber)
let newConfig = OutputConfig(transparent: self.outputConfig.transparent, output: self.outputConfig.output, fromImageNumber: self.outputConfig.fromImageNumber, toImageNumber: toImageNumber)
return LayerState(title: "Updating Export To Image Number", layers: self.layers, outputConfig: newConfig)
}

func updating(transparency: Bool) -> LayerState {
let newConfig = OutputConfig(transparent: transparency, output: self.outputConfig.output, fromImageNumber: self.outputConfig.fromImageNumber, toImageNumber: self.outputConfig.toImageNumber)
return LayerState(title: "Updating Export Transparency", layers: self.layers, outputConfig: newConfig)
}


// MARK: - Private

Expand Down
3 changes: 2 additions & 1 deletion Screenshot Framer/Model/LayerStateHistory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ final class LayerStateHistory {
// MARK: - Lifecycle

init() {
let initialState = LayerState(title: "Initial Operation", layers: [], outputConfig: OutputConfig(output: "", fromImageNumber: 1, toImageNumber: 5))
let config = OutputConfig(transparent: false, output: "", fromImageNumber: 1, toImageNumber: 5)
let initialState = LayerState(title: "Initial Operation", layers: [], outputConfig: config)
self.append(initialState)
}

Expand Down
18 changes: 18 additions & 0 deletions Screenshot Framer/Model/Operations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,24 @@ final class UpdateToImageNuberOperation: OperationProtocol {
}


final class UpdateTransparencyOperation: OperationProtocol {

let layerStateHistory: LayerStateHistory
let transparent: Bool

init(layerStateHistory: LayerStateHistory, transparent: Bool) {
self.layerStateHistory = layerStateHistory
self.transparent = transparent
}

func apply() {
let lastLayerState = self.layerStateHistory.currentLayerState
let newLayerState = lastLayerState.updating(transparency: self.transparent)
self.layerStateHistory.append(newLayerState)
}
}


final class UpdateFrameOperation: OperationProtocol {

let layerStateHistory: LayerStateHistory
Expand Down
1 change: 1 addition & 0 deletions Screenshot Framer/Model/OutputConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ struct OutputConfig: Codable {

// MARK: - Properties

let transparent: Bool
let output: String
let fromImageNumber: Int
let toImageNumber: Int
Expand Down
18 changes: 2 additions & 16 deletions Screenshot Framer/Supporting Files/Code/SSFView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,29 +46,15 @@ final class SSFView: NSView {

extension NSView {

func pngData() -> Data? {
func pngData(transparent: Bool) -> Data? {
let imageSize = self.bounds.size
guard let rep = self.bitmapImageRepForCachingDisplay(in: self.bounds) else { return nil }

rep.size = imageSize
rep.pixelsHigh = Int(imageSize.height)
rep.pixelsWide = Int(imageSize.width)
rep.hasAlpha = transparent
self.cacheDisplay(in: self.bounds, to: rep)
return rep.representation(using: .png, properties: [:])
}
}

extension NSView {
var snapshot: NSImage {
guard let bitmapRep = self.bitmapImageRepForCachingDisplay(in: bounds) else { return NSImage() }
bitmapRep.size = self.frame.size
self.cacheDisplay(in: bounds, to: bitmapRep)
let image = NSImage(size: bounds.size)
image.addRepresentation(bitmapRep)
return image
}

func imageData() -> Data? {
return self.snapshot.tiffRepresentation
}
}
2 changes: 1 addition & 1 deletion Screenshot Framer/Supporting Files/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>5</string>
<key>LSMinimumSystemVersion</key>
Expand Down

0 comments on commit b76b96a

Please sign in to comment.