Skip to content

Commit

Permalink
Wide-color
Browse files Browse the repository at this point in the history
  • Loading branch information
muukii committed Mar 27, 2021
1 parent cb1fb5c commit 550f7ab
Show file tree
Hide file tree
Showing 16 changed files with 215 additions and 211 deletions.
8 changes: 4 additions & 4 deletions Brightroom.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
4B0BDCA1217D663D001098B9 /* ClassicImageEditClarityControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B0BDCA0217D663D001098B9 /* ClassicImageEditClarityControl.swift */; };
4B0BDCA3217D676D001098B9 /* ClassicImageEditSharpenControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B0BDCA2217D676D001098B9 /* ClassicImageEditSharpenControl.swift */; };
4B112F15216C9B5400EF8E25 /* ImageTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B112F14216C9B5400EF8E25 /* ImageTool.swift */; };
4B1C5E9E260374F40021F2A8 /* TiledImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1C5E9D260374F40021F2A8 /* TiledImageView.swift */; };
4B1E94B12175FB5800E9DFB8 /* ClassicImageEditStepSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B9D456E216DEE95003A240A /* ClassicImageEditStepSlider.swift */; };
4B1E951C21764DE700E9DFB8 /* ClassicImageEditGaussianBlurControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1E951B21764DE700E9DFB8 /* ClassicImageEditGaussianBlurControl.swift */; };
4B1E951E21764E1800E9DFB8 /* FilterGaussianBlur.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1E951D21764E1800E9DFB8 /* FilterGaussianBlur.swift */; };
Expand Down Expand Up @@ -151,6 +150,7 @@
4BA8E73D217C716700940518 /* ClassicImageEditOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BA8E73C217C716700940518 /* ClassicImageEditOptions.swift */; };
4BB4B0F8260F55AC007617D7 /* EditingStack.CropModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4B0F7260F55AC007617D7 /* EditingStack.CropModifier.swift */; };
4BB4B0FD260F55D6007617D7 /* EditingStack.Edit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4B0FC260F55D6007617D7 /* EditingStack.Edit.swift */; };
4BB4B105260F8589007617D7 /* LUT_64_Neutral.png in Resources */ = {isa = PBXBuildFile; fileRef = 4BB4B104260F8589007617D7 /* LUT_64_Neutral.png */; };
4BB917E525F518EF00C446B8 /* _ImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB917E425F518EF00C446B8 /* _ImageView.swift */; };
4BB917EA25F5193C00C446B8 /* CIImageDisplaying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B9B02E4216BB7B5001593B9 /* CIImageDisplaying.swift */; };
4BB917EC25F5193C00C446B8 /* MetalImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B9B02E2216BB6F8001593B9 /* MetalImageView.swift */; };
Expand Down Expand Up @@ -264,7 +264,6 @@
4B0BDCA0217D663D001098B9 /* ClassicImageEditClarityControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClassicImageEditClarityControl.swift; sourceTree = "<group>"; };
4B0BDCA2217D676D001098B9 /* ClassicImageEditSharpenControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClassicImageEditSharpenControl.swift; sourceTree = "<group>"; };
4B112F14216C9B5400EF8E25 /* ImageTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageTool.swift; sourceTree = "<group>"; };
4B1C5E9D260374F40021F2A8 /* TiledImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TiledImageView.swift; sourceTree = "<group>"; };
4B1E94E8217634A800E9DFB8 /* FilterHue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilterHue.swift; sourceTree = "<group>"; };
4B1E94ED217634A800E9DFB8 /* FilterSaturation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilterSaturation.swift; sourceTree = "<group>"; };
4B1E94EE217634A800E9DFB8 /* FilterVignette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilterVignette.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -388,6 +387,7 @@
4BA8E73C217C716700940518 /* ClassicImageEditOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClassicImageEditOptions.swift; sourceTree = "<group>"; };
4BB4B0F7260F55AC007617D7 /* EditingStack.CropModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditingStack.CropModifier.swift; sourceTree = "<group>"; };
4BB4B0FC260F55D6007617D7 /* EditingStack.Edit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditingStack.Edit.swift; sourceTree = "<group>"; };
4BB4B104260F8589007617D7 /* LUT_64_Neutral.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LUT_64_Neutral.png; path = Resources/LUT_64_Neutral.png; sourceTree = SOURCE_ROOT; };
4BB917E425F518EF00C446B8 /* _ImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _ImageView.swift; sourceTree = "<group>"; };
4BB917F125F5211F00C446B8 /* CoreImageInspector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreImageInspector.swift; sourceTree = "<group>"; };
4BB9180B25F5460000C446B8 /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -528,6 +528,7 @@
4B1E95292176F52100E9DFB8 /* LUTs */ = {
isa = PBXGroup;
children = (
4BB4B104260F8589007617D7 /* LUT_64_Neutral.png */,
4B4C7C79260A69C50082240A /* LUT_64_X_2.jpg */,
4BD275FE260A48FF0044B3D8 /* LUT_64_MMM.png */,
);
Expand All @@ -550,7 +551,6 @@
4B9B02E4216BB7B5001593B9 /* CIImageDisplaying.swift */,
4B9B02E2216BB6F8001593B9 /* MetalImageView.swift */,
4B9D4576216E0694003A240A /* ImagePreviewView.swift */,
4B1C5E9D260374F40021F2A8 /* TiledImageView.swift */,
);
path = ImageViews;
sourceTree = "<group>";
Expand Down Expand Up @@ -1139,6 +1139,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4BB4B105260F8589007617D7 /* LUT_64_Neutral.png in Resources */,
4B600B2D216B7C9E001E1456 /* LaunchScreen.storyboard in Resources */,
4BA41C89260CE817005E6FA7 /* IMG_5533.HEIC in Resources */,
4BA41C86260CE817005E6FA7 /* IMG_5529.HEIC in Resources */,
Expand Down Expand Up @@ -1317,7 +1318,6 @@
4BA84F7E25EE94B700BAB430 /* CropView._InteractiveCropGuideView.swift in Sources */,
4B42A6AF2178E14E00F18208 /* ClassicImageEditHighlightsControl.swift in Sources */,
4B58DF662607100600D85F97 /* CanvasView.swift in Sources */,
4B1C5E9E260374F40021F2A8 /* TiledImageView.swift in Sources */,
4B1E951C21764DE700E9DFB8 /* ClassicImageEditGaussianBlurControl.swift in Sources */,
4BEC14BE2603ADDB009CE218 /* EditingCrop+.swift in Sources */,
4B1E94B12175FB5800E9DFB8 /* ClassicImageEditStepSlider.swift in Sources */,
Expand Down
File renamed without changes
5 changes: 4 additions & 1 deletion Sources/BrightroomEngine/Core/EditingCrop.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,18 @@ public struct EditingCrop: Equatable {
- TODO: Resizing cropping extent with keeping area by new aspect ratio.
*/
public mutating func updateCropExtent(by newAspectRatio: PixelAspectRatio) {

let maxSize = newAspectRatio.sizeThatFits(in: imageSize)

cropExtent = .init(
let proposed = CGRect(
origin: .init(
x: (imageSize.width - maxSize.width) / 2,
y: (imageSize.height - maxSize.height) / 2
),
size: maxSize
)

self.cropExtent = Self.fittingRect(rect: proposed, in: imageSize, respectingAspectRatio: newAspectRatio)
}

public mutating func updateCropExtentIfNeeded(by newAspectRatio: PixelAspectRatio) {
Expand Down
11 changes: 8 additions & 3 deletions Sources/BrightroomEngine/Core/EditingStack.Edit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ extension EditingStack {

func makeFilters() -> [Filtering] {
return ([

/**
Must be first filter since color-cube does not support wide range color.
*/
colorCube,

// Before
exposure,
brightness,
Expand All @@ -92,8 +98,7 @@ extension EditingStack {
shadows,
saturation,
contrast,
colorCube,


// After
sharpen,
unsharpMask,
Expand All @@ -104,7 +109,7 @@ extension EditingStack {
.compactMap { $0 }
}

func apply(to ciImage: CIImage) -> CIImage {
public func apply(to ciImage: CIImage) -> CIImage {
makeFilters().reduce(ciImage) { (image, filter) -> CIImage in
filter.apply(to: image, sourceImage: image)
}
Expand Down
90 changes: 10 additions & 80 deletions Sources/BrightroomEngine/Core/EditingStack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,84 +132,10 @@ open class EditingStack: Equatable, StoreComponentType {
currentEdit = history.popLast() ?? initialEditing
}

public func makeCroppedPreviewImage(previewMaxPixelSize: CGFloat, appliesFilter: Bool) -> CIImage {

/// Make an image that cropped and resized for previewing
func _createPreviewImage(
targetImage: CIImage,
crop: EditingCrop,
previewMaxPixelSize: CGFloat
) -> CIImage {

/**
Crop image
*/

let croppedImage = targetImage
.cropped(to: crop.scaled(maxPixelSize: max(targetImage.extent.width, targetImage.extent.height)))

/**
Remove the offset from cropping
*/

let fixedOriginImage = croppedImage.transformed(by: .init(
translationX: -croppedImage.extent.origin.x,
y: -croppedImage.extent.origin.y
))

assert(fixedOriginImage.extent.origin == .zero)

/**
Make the image small
*/

let targetSize = fixedOriginImage.extent.size.scaled(maxPixelSize: previewMaxPixelSize)

// FIXME: depending the scale, the scaled image includes alpha pixel in the edges.

let scale = max(
targetSize.width / croppedImage.extent.width,
targetSize.height / croppedImage.extent.height
)

let zoomedImage = croppedImage
.transformed(
by: .init(
scaleX: scale,
y: scale
),
highQualityDownsample: true
)

/**
Remove the offset from transforming
Plus insert intermediate
*/

let translated = zoomedImage
.transformed(by: .init(
translationX: zoomedImage.extent.origin.x,
y: zoomedImage.extent.origin.y
))

// EngineLog.debug("[Preview-Crop] \(crop.cropExtent) -> \(translated.extent)")

return translated
}

let image = _createPreviewImage(
targetImage: editingSourceImage,
crop: currentEdit.crop,
previewMaxPixelSize: previewMaxPixelSize
)

if appliesFilter {
return currentEdit.filters.apply(to: image)
} else {
return image
}

public func makeCroppedImage() -> CIImage {
editingSourceImage.cropped(to: currentEdit.crop.scaled(maxPixelSize: max(editingSourceImage.extent.width, editingSourceImage.extent.height)))
}

}

public fileprivate(set) var hasStartedEditing = false
Expand Down Expand Up @@ -314,13 +240,17 @@ open class EditingStack: Equatable, StoreComponentType {

switch image {
case let .editable(image, metadata):


let cgImage = image.loadThumbnailCGImage(maxPixelSize: self.editingImageMaxPixelSize)
assert(cgImage.colorSpace != nil)
/// resized
let editingSourceImage = CIImage(
cgImage: image.loadThumbnailCGImage(maxPixelSize: self.editingImageMaxPixelSize)
let _editingSourceImage = CIImage(
cgImage: cgImage
)
.oriented(metadata.orientation)

let editingSourceImage = _editingSourceImage

self.adjustCropExtent(
image: editingSourceImage,
imageSize: metadata.imageSize,
Expand Down
24 changes: 20 additions & 4 deletions Sources/BrightroomEngine/Engine/ImageRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,23 +110,39 @@ public final class ImageRenderer {

return UIGraphicsImageRenderer.init(size: targetSize, format: format)
.image { c in

let cgContext = c.cgContext
let ciContext = CIContext(
cgContext: cgContext,
options: [
.workingColorSpace: effectedCIImage.colorSpace as Any,
.outputColorSpace: effectedCIImage.colorSpace as Any,
.workingFormat: CIFormat.RGBAh,
.highQualityDownsample: true,
// .workingColorSpace: effectedCIImage.colorSpace,
.useSoftwareRenderer: true,
.outputColorSpace: CGColorSpace(name: CGColorSpace.extendedSRGB)!,
]
)


#if false
cgContext.detached {
let cgImage = ciContext.createCGImage(
effectedCIImage,
from: effectedCIImage.extent,
format: .RGBAh,
colorSpace: effectedCIImage.colorSpace ?? CGColorSpace(name: CGColorSpace.sRGB)!
)!

cgContext.draw(cgImage, in: CGRect(origin: .zero, size: targetSize))
}
#else
cgContext.detached {
ciContext.draw(
effectedCIImage,
in: CGRect(origin: .zero, size: targetSize),
from: effectedCIImage.extent
)
}
#endif

/**
Render drawings
Expand Down
7 changes: 4 additions & 3 deletions Sources/BrightroomEngine/Filter/FilterColorCube.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,13 @@ public struct FilterColorCube : Filtering, Equatable {
return f.outputImage!

#else


let colorSpace = CGColorSpace(name: CGColorSpace.extendedSRGB)!
let f: CIFilter = ColorCubeHelper.makeColorCubeFilter(
lutImage: lutImage,
dimension: dimension,
colorSpace: image.colorSpace ?? CGColorSpace(name: CGColorSpace.sRGB)!,
cacheKey: identifier
colorSpace: colorSpace,
cacheKey: "\(identifier),\(colorSpace)"
)

f.setValue(image, forKeyPath: kCIInputImageKey)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,65 @@

import UIKit

#if !COCOAPODS
import BrightroomEngine
#endif

public protocol CIImageDisplaying : class {
func display(image: CIImage?)
var postProcessing: (CIImage) -> CIImage { get set }
}

extension CIImageDisplaying {

func downsample(image: CIImage, bounds: CGRect, contentMode: UIView.ContentMode) -> CIImage {

let targetRect: CGRect

switch contentMode {
case .scaleAspectFill:
targetRect = Geometry.rectThatAspectFill(
aspectRatio: image.extent.size,
minimumRect: bounds
)
case .scaleAspectFit:
targetRect = Geometry.rectThatAspectFit(
aspectRatio: image.extent.size,
boundingRect: bounds
)
default:
targetRect = Geometry.rectThatAspectFit(
aspectRatio: image.extent.size,
boundingRect: bounds
)
assertionFailure("ContentMode:\(contentMode) is not supported.")
}

let scaleX = targetRect.width / image.extent.width
let scaleY = targetRect.height / image.extent.height
let scale = min(scaleX, scaleY)

let resolvedImage: CIImage

#if targetEnvironment(simulator)
// Fixes geometry in Metal
resolvedImage = image
.transformed(
by: CGAffineTransform(scaleX: 1, y: -1)
.concatenating(.init(translationX: 0, y: image.extent.height))
.concatenating(.init(scaleX: scale, y: scale))
.concatenating(.init(translationX: targetRect.origin.x, y: targetRect.origin.y))
)

#else
resolvedImage = image
.transformed(by: CGAffineTransform(scaleX: scale, y: scale))
.transformed(by: CGAffineTransform(translationX: targetRect.origin.x, y: targetRect.origin.y))

#endif

return resolvedImage
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ public final class ImagePreviewView: PixelEditorCodeBasedView {
// MARK: - Properties

#if false
private let imageView = _ImageView()
private let originalImageView = _ImageView()
private let imageView = _ImageView(resizesOnDisplay: true)
private let originalImageView = _ImageView(resizesOnDisplay: true)
#else
private let imageView = MetalImageView()
private let originalImageView = MetalImageView()
Expand Down Expand Up @@ -126,12 +126,12 @@ public final class ImagePreviewView: PixelEditorCodeBasedView {
}

private func requestPreviewImage(state: EditingStack.State.Loaded) {

let pixelSize = max(self.bounds.width, self.bounds.height) * UIScreen.main.scale

imageView.display(image: state.makeCroppedPreviewImage(previewMaxPixelSize: pixelSize, appliesFilter: true))
originalImageView.display(image: state.makeCroppedPreviewImage(previewMaxPixelSize: pixelSize, appliesFilter: false))

let croppedImage = state.makeCroppedImage()
imageView.display(image: croppedImage)
imageView.postProcessing = state.currentEdit.filters.apply
originalImageView.display(image: croppedImage)
}

private func updateLoadingOverlay(displays: Bool) {
Expand Down
Loading

0 comments on commit 550f7ab

Please sign in to comment.