Brightroom

使用 Core Image 和 Metal 的可组合图像编辑器。「📷 A composable image editor using Core Image and Metal.」

Github星跟蹤圖

Pixel - Engine • Editor

CocoaPods FOSSA Status
Engine

CocoaPods Editor

Image editor and engine using CoreImage

⚠️ Currently, API is not stable. It may change in the future.

Features

Currently accepting PRs that impement these features.

Performance

  • ✈️Pretty Good
  • ?Blazing Fast (?Anyone help us!)

Adjustment

  • Crop
  • Straighten (?Anyone help us!)
  • Perspective (?Anyone help us!)

Filter

Presets

  • ColorCube (Look Up Table)
    • Intensity

⚠️ Currently, Pixel does not contain LUT.
Demo app has sample LUTs.

And also, here is interesting article

Edits

  • Brightness
  • Contrast
  • Saturation
  • Highlights
  • Shadows
  • Temperature
  • GaussianBlur
  • Vignette
  • Color (Shadows / Highlights)
  • Fade
  • Sharpen
  • Clarity
  • HLS (?Anyone help us!)

Other

Requirements

  • Swift 4.2 (Xcode10+)
  • iOS 10+

Getting Started

Demo.app contains the sample code.
Please check out Sources/Demo/EditorViewController.swift.

Create instance of PixelEditViewController

let image: UIImage

let controller = PixelEditViewController(image: image)

Show

  • as Modal

⚠️ Currently
We need to wrap the controller with UINavigationController.
Because, PixelEditViewController needs UINavigationBar.

let controller: PixelEditViewController

let navigationController = UINavigationController(rootViewController: controller)

self.present(navigationController, animated: true, completion: nil)
  • as Push

We can push the controller in UINavigationController.

let controller: PixelEditViewController
self.navigationController.push(controller, animated: true)

Setup Delegate

PixelEditViewController has delegate protocol called PixelEditViewControllerDelegate.

public protocol PixelEditViewControllerDelegate : class {
  func pixelEditViewController(_ controller: PixelEditViewController, didEndEditing editingStack: SquareEditingStack)
  func pixelEditViewControllerDidCancelEditing(in controller: PixelEditViewController)
}

?PixelEditViewController does not know how to dismiss or pop by itself.
So we need to control PixelEditViewController outside.

Basically, it's like following code, recommend dismiss or pop in methods of delegate.

extension EditorViewController : PixelEditViewControllerDelegate {

  func pixelEditViewController(_ controller: PixelEditViewController, didEndEditing editingStack: SquareEditingStack) {

    self.navigationController?.popToViewController(self, animated: true)
  }

  func pixelEditViewControllerDidCancelEditing(in controller: PixelEditViewController) {
  
    self.navigationController?.popToViewController(self, animated: true)
  }

}

Render Image

let editingStack: SquareEditingStack

let image = editingStack.makeRenderer().render(resolution: .full)

Restore editing

We can take current editing as instance of EditingStack from PixelEditViewController.editingStack.

If we want to restore editing after closed PixelEditViewController, we use this.

let editingStack = controller.editingStack
// close editor

// and then when show editor again
let controller = PixelEditViewController(editingStack: editingStack)

Add ColorCubeFilters

We can use LUT(LookUpTable) with CIColorCubeFilter.

LUT is like this (Dimension is 64)

import PixelEngine

let lutImage: UIImage

let filter = FilterColorCube(
  name: "Filter Name",
  identifier: "Filter Identifier",
  lutImage: lutImage,
  dimension: 64
)

let storage = ColorCubeStorage(filters: [filter])
let controller = PixelEditViewController(image: image, colorCubeStorage: storage)

And also, if we don't specify colorCubeStorage, use default.

// set
ColorCubeStorage.default.filters = filters

// get
ColorCubeStorage.default.filters

Customize Control-UI

We can customize UI for control area.

Customize Built-In Control-UI using override

There is Options struct in PixelEditor.
We can create options that fit our usecases.

So, If we need to change ExposureControl, override ExposureControlBase class.
Then set that class to Options.

var options = Options.default
options.classes.control.brightnessControl = MyExposureControl.self

let picker = PixelEditViewController(image: image, options: options)

It's like using custom Cell in UICollectionView.
If you have any better idea for this, please tell us?.
And also Built-In UI may need expose some properties to customize from subclassing.

Customize whole Control-UI

We can also customize whole UI.

Override options.classes.control.rootControl, then build UI from scratch.

For example, if you don't need the filter section but only the edit mode, you may want to create a control like:

final class EditRootControl : RootControlBase {

   private let containerView = UIView()

   public let colorCubeControl: ColorCubeControlBase

   public lazy var editView = context.options.classes.control.editMenuControl.init(context: context)

   // MARK: - Initializers

   public required init(context: PixelEditContext, colorCubeControl: ColorCubeControlBase) {

       self.colorCubeControl = colorCubeControl

       super.init(context: context, colorCubeControl: colorCubeControl)

       backgroundColor = Style.default.control.backgroundColor

       layout: do {

           addSubview(containerView)

           containerView.translatesAutoresizingMaskIntoConstraints = false

           NSLayoutConstraint.activate([

               containerView.topAnchor.constraint(equalTo: containerView.superview!.topAnchor),
               containerView.leftAnchor.constraint(equalTo: containerView.superview!.leftAnchor),
               containerView.rightAnchor.constraint(equalTo: containerView.superview!.rightAnchor),
               containerView.bottomAnchor.constraint(equalTo: containerView.superview!.bottomAnchor)
           ])
       }
   }

   // MARK: - Functions

   override func didMoveToSuperview() {
       super.didMoveToSuperview()

       if superview != nil {
           editView.frame = containerView.bounds
           editView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

           containerView.addSubview(editView)
       }
   }
}

And use it this way:

var options = Options.default
options.classes.control.rootControl = EditRootControl.self

let picker = PixelEditViewController(image: image, options: options)

Filter some edit menu

If there are some edit options you don't need in your app, you can choose edit options you want to ignore:

var options = Options.default
options.classes.control.ignoredEditMenu = [.saturation, .gaussianBlur]
let controller = PixelEditViewController.init(image: UIImage(named: "large")!, options: options)

Localization

Strings in UI can be localized with L10n.

import PixelEditor

PixelEditor.L10n.done = "保存"

// or
PixelEditor.L10n.done = NSLocalizedString...

Installation

CocoaPods

Pixel is available through CocoaPods. To install
it, simply add the following line to your Podfile:

pod 'PixelEngine'
pod 'PixelEditor'

Carthage

For Carthage, add the following to your Cartfile:

github "muukii/Pixel"

Contributing

If you need more features, please open issue or submit PR!
Muukii may not know the approach to take for implementing them, So your PR will be very helpful.

Development

To develop Pixel, setup environment of development with following code.

$ pod install
$ open Pixel.xcworkspace

Author

Muukii (muukii.app@gmail.com)

License

Pixel is available under the MIT license. See the LICENSE file for more info.

FOSSA Status

主要指標

概覽
名稱與所有者FluidGroup/Brightroom
主編程語言Swift
編程語言Swift (語言數: 4)
平台
許可證MIT License
所有者活动
創建於2018-10-08 11:44:36
推送於2025-05-23 08:08:45
最后一次提交
發布數49
最新版本名稱3.1.1 (發布於 2025-04-02 16:16:44)
第一版名稱0.0.1 (發布於 )
用户参与
星數3.5k
關注者數63
派生數320
提交數638
已啟用問題?
問題數81
打開的問題數28
拉請求數155
打開的拉請求數4
關閉的拉請求數15
项目设置
已啟用Wiki?
已存檔?
是復刻?
已鎖定?
是鏡像?
是私有?