1
Fork 0

Add composite image rendering

This commit is contained in:
Joshua Goins 2020-03-11 23:31:42 -04:00 committed by redstrate
parent 2134cbc6a8
commit 39a0de2c75
3 changed files with 84 additions and 18 deletions

View file

@ -246,13 +246,16 @@ DQ
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ipM-NH-wUM">
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ipM-NH-wUM">
<rect key="frame" x="20" y="20" width="440" height="201"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="chN-IE-x52"/>
</imageView>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ifc-N4-GCF">
<popUpButton verticalHuggingPriority="750" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ifc-N4-GCF">
<rect key="frame" x="18" y="226" width="101" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<constraints>
<constraint firstAttribute="width" constant="96" id="Csg-An-ug2"/>
</constraints>
<popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" id="P5l-BO-Pd1">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -262,9 +265,11 @@ DQ
<action selector="selectLayerAction:" target="5gI-5U-AMq" id="nzQ-6F-mUw"/>
</connections>
</popUpButton>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vY4-dQ-JOJ">
<popUpButton verticalHuggingPriority="750" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vY4-dQ-JOJ">
<rect key="frame" x="122" y="226" width="101" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<constraints>
<constraint firstAttribute="width" constant="96" id="FeE-01-aTL"/>
</constraints>
<popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" id="IVG-g2-g5C">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -276,10 +281,9 @@ DQ
</popUpButton>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="ipM-NH-wUM" secondAttribute="bottom" constant="20" symbolic="YES" id="9wh-iS-c9w"/>
<constraint firstAttribute="trailing" secondItem="ipM-NH-wUM" secondAttribute="trailing" constant="20" symbolic="YES" id="H7s-2P-Zaq"/>
<constraint firstItem="ipM-NH-wUM" firstAttribute="leading" secondItem="ERx-hH-rdd" secondAttribute="leading" constant="20" symbolic="YES" id="aib-B6-dBu"/>
<constraint firstItem="ipM-NH-wUM" firstAttribute="top" secondItem="ERx-hH-rdd" secondAttribute="top" constant="20" symbolic="YES" id="xk9-1v-JRt"/>
<constraint firstItem="Ifc-N4-GCF" firstAttribute="top" secondItem="ERx-hH-rdd" secondAttribute="top" constant="20" symbolic="YES" id="BmT-9r-weG"/>
<constraint firstItem="vY4-dQ-JOJ" firstAttribute="leading" secondItem="Ifc-N4-GCF" secondAttribute="trailing" constant="8" symbolic="YES" id="hgm-Np-cYB"/>
<constraint firstItem="vY4-dQ-JOJ" firstAttribute="baseline" secondItem="Ifc-N4-GCF" secondAttribute="baseline" id="uHT-fd-ze3"/>
</constraints>
</view>
<connections>

View file

@ -2,14 +2,29 @@ import Cocoa
import ZIPFoundation
import CoreFoundation
struct SilicaChunk {
init() {
x = 0
y = 0
image = NSImage()
}
var x: Int
var y: Int
var image: NSImage
}
struct SilicaLayer {
var chunks: [NSImage] = []
var chunks: [SilicaChunk] = []
}
struct SilicaDocument {
var trackedTime: Int = 0
var tileSize: Int = 0
var width: Int = 0
var height: Int = 0
var layers: [SilicaLayer] = []
}
@ -27,6 +42,7 @@ class Document: NSDocument {
let TrackedTimeKey = "SilicaDocumentTrackedTimeKey"
let LayersKey = "layers"
let TileSizeKey = "tileSize"
let SizeKey = "size"
let LayerClassName = "SilicaLayer"
@ -78,11 +94,20 @@ class Document: NSDocument {
}
}
layer.chunks = Array(repeating: NSImage(), count: chunkPaths.count)
layer.chunks = Array(repeating: SilicaChunk(), count: chunkPaths.count)
DispatchQueue.concurrentPerform(iterations: chunkPaths.count) { (i: Int) in
let entry = chunkPaths[i]
let pathURL = URL(fileURLWithPath: entry.path)
let pathComponents = pathURL.lastPathComponent.replacingOccurrences(of: ".chunk", with: "").components(separatedBy: "~")
let x = Int(pathComponents[0])
let y = Int(pathComponents[1])
layer.chunks[i].x = x!
layer.chunks[i].y = y!
guard let archive = Archive(data: self.data!, accessMode: Archive.AccessMode.read) else {
return
}
@ -109,15 +134,16 @@ class Document: NSDocument {
let render: CGColorRenderingIntent = CGColorRenderingIntent.defaultIntent
let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue)
.union(.byteOrder32Little)
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.last.rawValue)
.union(.byteOrder32Big)
let providerRef: CGDataProvider? = CGDataProvider(data: image_data as CFData)
let cgimage: CGImage? = CGImage(width: info.tileSize, height: info.tileSize, bitsPerComponent: 8, bitsPerPixel: 32, bytesPerRow: info.tileSize * 4, space: rgbColorSpace, bitmapInfo: bitmapInfo, provider: providerRef!, decode: nil, shouldInterpolate: true, intent: render)
let cgimage: CGImage? = CGImage(width: info.tileSize, height: info.tileSize, bitsPerComponent: 8, bitsPerPixel: 32, bytesPerRow: info.tileSize * 4, space: rgbColorSpace, bitmapInfo: bitmapInfo, provider: providerRef!, decode: nil, shouldInterpolate: false, intent: render)
if cgimage != nil {
let image = NSImage(cgImage: cgimage!, size: NSZeroSize)
layer.chunks[i] = image
layer.chunks[i].image = image
}
}
@ -132,6 +158,17 @@ class Document: NSDocument {
info.trackedTime = (dict[TrackedTimeKey] as! NSNumber).intValue
info.tileSize = (dict[TileSizeKey] as! NSNumber).intValue
let sizeClassKey = dict[SizeKey]
let sizeClassID = objectRefGetValue(sizeClassKey as CFTypeRef)
let sizeString = objectsArray[Int(sizeClassID)] as! String
let sizeComponents = sizeString.replacingOccurrences(of: "{", with: "").replacingOccurrences(of: "}", with: "").components(separatedBy: ", ")
let width = Int(sizeComponents[0])
let height = Int(sizeComponents[1])
info.width = width!
info.height = height!
let layersClassKey = dict[LayersKey]
let layersClassID = objectRefGetValue(layersClassKey as CFTypeRef)
let layersClass = objectsArray[Int(layersClassID)] as! NSDictionary
@ -218,5 +255,30 @@ class Document: NSDocument {
parseDocument(archive: archive, dict: dict)
}
func makeComposite() -> NSImage {
let image = NSImage(size: NSSize(width: info.width, height: info.height))
image.lockFocus()
let rows = Int(ceil(Float(info.height) / Float(info.tileSize)))
for layer in info.layers.reversed() {
for chunk in layer.chunks {
let x = chunk.x
var y = chunk.y
if y == rows {
y = 0
}
let rect = NSRect(x: info.tileSize * x, y: info.height - (info.tileSize * y), width: info.tileSize, height: info.tileSize)
chunk.image.draw(in: rect)
}
}
image.unlockFocus()
return image
}
}

View file

@ -21,7 +21,7 @@ class ViewController: NSViewController {
func loadCanvas() {
let document = self.view.window?.windowController?.document as? Document
imageView.image = document?.info.layers[selectedLayer].chunks[selectedChunk]
imageView.image = document?.info.layers[selectedLayer].chunks[selectedChunk].image
}
@IBAction func selectLayerAction(_ sender: Any) {
@ -45,14 +45,14 @@ class ViewController: NSViewController {
chunkPopup.removeAllItems()
for (i, chunk) in (document?.info.layers[selectedLayer].chunks.enumerated())! {
chunkPopup.addItem(withTitle: "Chunk " + String(i))
chunkPopup.addItem(withTitle: "Chunk " + String(chunk.x) + " " + String(chunk.y))
}
}
override func viewWillAppear() {
let document = self.view.window?.windowController?.document as? Document
imageView.image = document?.thumbnail
imageView.image = document?.makeComposite()
for (i, layer) in (document?.info.layers.enumerated())! {
layerPopup.addItem(withTitle: "Layer " + String(i))