muukii/Pixel
An image editor and engine using CoreImage
repo name | muukii/Pixel |
repo link | https://github.com/muukii/Pixel |
homepage | https://twitter.com/muukii0803/status/1056866874560937986 |
language | Swift |
size (curr.) | 104059 kB |
stars (curr.) | 1928 |
created | 2018-10-08 |
license | MIT License |
Pixel - Engine • Editor
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.