GithubHelp home page GithubHelp logo

congnd / fmphotopicker Goto Github PK

View Code? Open in Web Editor NEW
760.0 26.0 127.0 4 MB

A modern, simple and zero-dependency photo picker with an elegant and customizable image editor

License: MIT License

Swift 99.71% Ruby 0.29%
image effects filter crop photos video picker ios swift image-editor

fmphotopicker's Introduction

FMPhotoPicker

MIT licensed Carthage compatible Pod Compatible Build

FMPhotoPicker is a modern, simple and zero-dependency photo picker with an elegant and customizable image editor

Quick demo

Batch select/deselect
Smooth transitions
Filter
Crop
FMPhotoPicker FMPhotoPicker FMPhotoPicker FMPhotoPicker

Features

  • Support both single and multiple selection
  • Support batch selection/deselection by swipe gesture
  • Support preview
  • Support simple image editor with filter and cropping functions
  • Support force crop mode
  • Support rounded image preview
  • Support adding self-define cropping
  • Support adding self-define filter
  • Support video player
  • Support custom confirmation view
  • Support language customization

Requirements

  • iOS 9.0+

Installation

SwiftPM

dependencies: [
  .package(url: "https://github.com/congnd/FMPhotoPicker.git", .exact("1.3.0")),
]

Carthage

Insert the following line in your Carthfile:

git "[email protected]:congnd/FMPhotoPicker.git"

and run carthage update FMPhotoPicker

CocoaPods

FMPhotoPicker is now available in CocoaPods
You want to add pod 'FMPhotoPicker', '~> 1.3.0' similar to the following to your Podfile:

target 'MyApp' do
  pod 'FMPhotoPicker', '~> 1.3.0'
end

Then run a pod install inside your terminal.

Usage

Create a configuration object

var config = FMPhotoPickerConfig()

For details, see Configuration

Picker

let picker = FMPhotoPickerViewController(config: config)
picker.delegate = self
self.present(picker, animated: true)

From iOS 10, you have to add the Privacy - Photo Library Usage Description into your Info.plist file.

Editor

let editor = FMImageEditorViewController(config: config, sourceImage: image)
editor.delegate = self
self.present(editor, animated: true)

Delegation methods

  • Implement FMPhotoPickerViewControllerDelegate protocol to handle selected photos.
func fmPhotoPickerController(_ picker: FMPhotoPickerViewController, didFinishPickingPhotoWith photos: [UIImage])
func fmPhotoPickerController(_ picker: FMPhotoPickerViewController, didFinishPickingPhotoWith assets: [PHAsset])

If you prefer to receive selected photos in type of PHAsset instead of UIImage then don't forget to set the shouldReturnAsset to true and implement the corresponding delegation method.

  • Implement FMImageEditorViewControllerDelegate protocol to handle ouput image
func fmImageEditorViewController(_ editor: FMImageEditorViewController, didFinishEdittingPhotoWith photo: UIImage)

Configuration

The configuration supports the following parameters:

Reference

  • mediaTypes
    An array that indicates the media types to be accessed by the picker controller.
    Type: [FMMediaType]
    Default: [.image, .video]

  • selectMode
    Photo selection mode that can be in single or multiple mode.
    Type: : FMSelectMode
    Default is multiple

  • maxImage
    The maximum number of images can be selected. Type: Int
    Default: 10

  • maxVideo
    The maximum number of videos can be selected.
    Type: Int
    Default is 10

  • availableFilters
    Filter options that are used in editor. Set this parameter to nil to make the filter menu be unavailable in the editor FMPhotoEditor provides some default filters that will be fit to you.
    Type: [FMFilterable]?
    Default: all filters are provided by FMPhotoPicker.

  • availableCrops
    Crop options that is used in editor. Set this parameter to nil to make the cropping menu be unavailable in the editor FMPhotoEditor provides some default crops that will be fit to you.
    Type: [FMCroppable]? Default: all crops provided by FMPhotoPicker.

You are not allowed to use the editor without giving it at least one crop option or one filter option

  • useCropFirst
    An option that indicates whether the crop menu should be selected by default in the FMImageEditorViewController.
    Type: Bool
    Default: false

  • alertController
    An alert controller to show the confirmation view to an user with 2 options: Ok or Cancel.
    Type: FMAlertable
    Default: FMAlert

  • shouldReturnAsset
    Whether you want FMPhotoPicker returns PHAsset instead of UIImage. FMPhotoPicker chooses a proper delegation method to be invoked when user finishes picking based on this configuration Type: Bool Default: false

  • forceCropEnabled
    A bool value that indicates whether force mode is enabled.
    If true is set, only the first crop in the availableCrops is used in the editor.
    And that crop's ration becomes force crop ratio.
    Type: FMAlertable
    Default: false

  • eclipsePreviewEnabled
    A bool value that indicates whether the preview of image should be displayed in rounded image.
    Type: Bool Default: false

  • strings
    A dictionary that allows you to customize language for your app.
    For details, see FMPhotoPickerConfig.swift
    Type: Dictionary

Customization

Custom filter

You can freely create your own filter by implementing the FMFilterable protocol.

public protocol FMFilterable {
    func filter(image: UIImage) -> UIImage
    func filterName() -> String
}

Be careful that the filterName is used to determine whether the two filters are the same.
Make sure that your filter's names are not duplicated, especially with the default filters that you want to use.

Custom cropping

Similar as filter function, FMPhotoPicker provides the capability to use your own cropping by implementing the FMCroppable protocol.

public protocol FMCroppable {
    func crop(image: UIImage, toRect rect: CGRect) -> UIImage
    func name(string: [String: String]) -> String
    func icon() -> UIImage
    func ratio() -> FMCropRatio?
}

The func name(strings: [String: String]) -> String will receive the strings configuration from configuration object. It allows you customize the cropping while keeping all your language setting in only one place.

The name() method is also used as identifier for the cropping.
Thus, make sure you do not have any duplicate of the cropping name.

Custom alert view controller

You can use your own view style for the confirmation view by implementing the FMAlertable protocol.

public protocol FMAlertable {
    func show(in viewController: UIViewController, ok: @escaping () -> Void, cancel: @escaping () -> Void)
}

Contact

Follow and contact me on Twitter. If you find an issue, just open a ticket. Pull requests are warmly welcome as well.

License

FMPhotoPicker is released under the MIT license. See LICENSE for details.

fmphotopicker's People

Contributors

congnd avatar congndrkt avatar engsulta avatar hoalp2404 avatar i-tengfei avatar ibinh avatar n-cong avatar stakada7 avatar unixb0y avatar vdeep avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fmphotopicker's Issues

Offer a option for filter and cropper

Hi. The library is awesome! But Someone, like me, only need cropper, or someone only need filter, or others don't need both. Maybe you can offer a option as FMPhotoPickerConfig. I mean it's easy to do this. Thx.

CocoaPods installing error

Version of my iOS project is 13.5 and Swift 5.

I am getting attached error when I try to install dependency with CocoaPods.

I also tried to install dependency with Carthage and it is working.

Cocoapods

Swift Package Manager

I am trying to add this dependency with Swift Package Manager and I am getting attached error.

I tried to add with all version rules (up to next major, up to next minor, range, exact) in Xcode

Screen Shot 2020-08-30 at 20 14 06

A suggestion to avoid confusion

Your use of the term ForceCrop was not what I expected. In my use case I am having a user pick a profile pic that will be circular, so I need to force them to edit their selected photo with a circle crop. It took me awhile to understand why turning on forceCrop didn't result in that behavior, but rather forces a single crop option. IMHO ForceCrop should be named CropChoice or CropDefault.

This is an amazing framework, thank you for open sourcing it.

Package Resolution Found

Screenshot 2020-09-13 at 13 20 11

I got this error while trying to add a package manager dependencies on my project. I am using Xcode 11.7 .

SDK crashes while showing warning

When a user selects more than max allowed images, the app crashes while fetching rootViewController to present warning at line 28 in FMWarningView.swift. See screenshot for reference:
Screenshot 2021-11-03 at 3 33 37 PM

Implementing FMFilterable

Hi,

I really appreciate the tremendous work you did. I have couple of extra filters to be added on the slider. However I'm not sure how to add them using FMFilterable. I tried several things but truly speaking couldn't manage smoothly.

If you can support with an example, I really appreciate for that.
Thank you,
Baris

select More photos

second time when open the app its not asking keep the current selection or select more photos ,permission

Hide Edit Button

How to hide Edit Button , disable photo edit ,just show origin image

edit multiple photos simultaneously bug

When I select multiple photos, then edit them, sometimes FMLoadingView can't hide and delegate method "didFinishPickingPhotoWith" can't response after tapping done button.Then, I set a breakpoint in DispatchQueue.main.async, and I found sometimes the code didn't enter into.
ps: my device is iPhone6,iOS12.2.

` private func processDetermination() {
FMLoadingView.shared.show()

    var dict = [Int:UIImage]()
    
    DispatchQueue.global(qos: .userInitiated).async {
        let multiTask = DispatchGroup()
        for (index, element) in self.dataSource.getSelectedPhotos().enumerated() {
            multiTask.enter()
            element.requestFullSizePhoto(cropState: .edited, filterState: .edited) {
                guard let image = $0 else { return }
                dict[index] = image
                multiTask.leave()
            }
        }
        multiTask.wait()

        let result = dict.sorted(by: { $0.key < $1.key }).map { $0.value }
        DispatchQueue.main.async { 
            FMLoadingView.shared.hide() // set a breakpoint
            self.delegate?.fmPhotoPickerController(self, didFinishPickingPhotoWith: result)
        }
    }
}`

image

Finally, I found the code "guard let image = $0 else { return }" has a bug.Because sometimes image is nil after call back , it leads to that enter() and leave() don't match, and "multiTask.wait()" will not work.

crash when preview a video asset

When I use FMPhotoPicker select video asset, this method func requestAVAsset(asset: PHAsset, complete: @escaping (AVAsset?) -> Void) always return a nil asset and the player won't be initialized, tap play button and nothing happends , a fews seconds later the app crash because some UI modifications performed from a background thread, I try to fix first problem by adding an option to PHImageManager and it works:

            let manager = PHImageManager.default()
            let option = PHVideoRequestOptions()
            option.isNetworkAccessAllowed = true
            
            manager.requestAVAsset(forVideo: asset, options: option) { asset, audioMix, _ in
                DispatchQueue.main.async {
                    complete(asset)
                }
            }

hope help, and the other problem I took a screenshot for your reference,hope useful:
截屏2023-04-16 00 11 20

Survey about Open Source Image editors for Master's thesis

Dear Mr. Nguyen,

My name is Anupama Nedungadi and I am a Master’s student at the University of Geneva. For my thesis, I am looking at internationalization and localization practices in open source image editors, meaning how and why (or why not) the software has been translated into another language.
I have curated a list of image editors, graphic editors and the likes hosted on SourceForge, GitHub and GitLab, and this list includes your software congnd/FMPhotoPicker.

I am contacting you to ask for your participation in a survey. This is a key element of my Master’s thesis. I am aware of the fact that we don't know each other and that you don't owe me anything, but I am really dependent on your help since my topic is quite niche. I also believe we should shine a spotlight on open source software and its translation in particular, as little research has been done in this area recently.

The survey will be open until the 16th of June 2021, and it should only take you around 10 minutes as most questions are multiple choice. Your answers will be anonymous.

https://formulaire.unige.ch/outils/limesurveyfac/traduction-interpretation/index.php/697247?lang=en

Again, thank you for taking the time to read this email and helping a slightly stressed student out!

Best regards,
Anupama Nedungadi

Could not load NIB in bundle

When trying to present FMPhotoPickerViewController got an error

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </private/var/containers/Bundle/Application/3AFB974F-E9E0-4678-864B-5716806E8E46/Tuja.app> (loaded)' with name 'FMPhotoPickerViewController''
*** First throw call stack:
(0x1aeb8d5f0 0x1ae8afbcc 0x1aea83b28 0x1b28ccd5c 0x1b25f686c 0x1b25f72e4 0x1b25f759c 0x1b25f7ca0 0x1b260d31c 0x1b260610c 0x1b2607b08 0x1b260a014 0x1b260a51c 0x1b2609f64 0x1b260a1d0 0x102743f94 0x102746240 0x102740e30 0x1e605712c 0x1e6140924 0x1e633fdec 0x1e61b62ac 0x1e61b62c8 0x1e61b62ac 0x1e61a9cfc 0x1e61a98a8 0x1e61e6068 0x1e64a25b8 0x1e64a2800 0x1e64a2e14 0x1b2815380 0x1b2cb8bf0 0x1b280ae5c 0x1b280af6c 0x1b280add4 0x1b2c749fc 0x1b2c506a0 0x1b2cd0d84 0x1b2cd38bc 0x1b2ccb8d0 0x1aeb0bb64 0x1aeb0babc 0x1aeb0b244 0x1aeb06274 0x1aeb05c34 0x1b8c4f38c 0x1b2c3822c 0x10273e2cc 0x1ae98d800)
libc++abi.dylib: terminating with uncaught exception of type NSException 

Xcode 11.5
Installed via SPM

Change Owner

Hi.

Tribal Media House(@tribalmedia) decide owner change to Cong Nguyen(@congnd).
please keep maintaining this repository.

thanks a looooooooooooooooot!!!!!

How to disable photo Editing mode.

config = FMPhotoPickerConfig()
config.selectMode = .multiple
config.mediaTypes = [.image]
config.maxImage = 20
config.maxVideo = 0

there is no option for disable edit photo in FMPhotoPickerViewController

Pagination for loading assets?

When I present the picker, the UI loads up very slowly, and if I tap on the top bar it immediately goes to the very first photo of my photo library, which makes me believe it loaded up the entire library's thumbnails upon opening, and that's probably the major cause of the slowless. Could we make the load paginated and only load more as we scroll up?

No way to know the editing was cancelled.

Is there a way to know the editing was cancelled? There is only a FMImageEditorViewControllerDelegate method to notify editing finish event, but not editing cancel event with the delegate methods.

There is an existing issue with UIImagePickerController when the a view is present and dismissed from over it. Below are the steps to reproduce it.

  1. Present UIImagePickerContoller's camera screen,
  2. capture image, use FMImageEditorView to edit the object, hit cancel and click yes on the alert modal
  3. User lands back on the UIImagePickerContoller's camera screen.
  4. The Retake/Use Photo options are not clickable

To work around this issue, I would like to dismiss the camera screen and present a fresh instance when editing is cancelled, but there is no way to know this from the library.

Video support

Do you plan to add support for picking video like in system picker?
I mean smth like this:
func fmPhotoPickerController(_ picker: FMPhotoPickerViewController, didFinishPickingVideoWith videos: [URL]) { }

Pod

'Could not load NIB in bundle: 'NSBundle </var/containers/Bundle/Application/.app/Frameworks/FMPhotoPicker.framework> (loaded)' with name 'FMPhotoPickerViewController''

Image rotation functionality when we edit the image.

Hello Team,
I need an Image rotation functionality along with the filter and crop functionalities.
I found the rotation function created inside the FMCropView.swift but it is empty(Screenshot below).

So could you please help me to achieve the desired result.

Screenshot 2021-02-03 at 5 07 48 PM

Thanks in advance.

Dark mode support

Hi,

Is adding Dark Mode a possibility for the picker? I've had a few of my app's users ask about this, and just wanted to check if there's a way I can enable this (or if you're able to add it in an update).

Thanks in advance, and I hope you're well :)

Carthage build error

Hello, I get the following error when building with carthage update --platform iOS and having git "[email protected]:congnd/FMPhotoPicker.git" in Cartfile:

Module compiled with Swift 5.2.4 cannot be imported by the Swift 5.3 compiler

I use Xcode version 12.0.

crash in FMLoadingView

crash fix replace old init method with this one
private init() {
if let rootVC = (UIApplication.shared.windows.first?.rootViewController) {
self.transparentView = UIView(frame: rootVC.view.frame)

    } else {
        let windowFrame = UIApplication.shared.keyWindow?.frame
        self.transparentView = UIView(frame: windowFrame ?? .zero)
    }
    
    self.transparentView.backgroundColor = UIColor(white: 0, alpha: 0.4)
    
    self.indicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
    self.indicator.center = self.transparentView.center
    self.indicator.color = .white
    
    self.transparentView.addSubview(self.indicator)
}

Need to dismiss twice to dismiss the picker

func openPicker() {
            var config = FMPhotoPickerConfig()
            config.selectMode = .single
            config.mediaTypes = [.image]
            config.forceCropEnabled = true
            config.availableCrops = [FMCrop.ratioSquare]
       
            let picker = FMPhotoPickerViewController(config: config)
            picker.delegate = self
            self.present(picker, animated: true)
}

func fmPhotoPickerController(_ picker: FMPhotoPickerViewController, didFinishPickingPhotoWith photos: [UIImage]) {
        
        picker.dismiss(animated: true, completion: nil)
        picker.dismiss(animated: true, completion: nil)
        if photos.count > 0 {
            upload(image: photos.first!)
        }
    }

I want to dismiss the picker after I didFinishPicking, it will call didFinishPicking delegate after I edited my picture, and the dismiss can not dismiss the picker. It's still in the picker page where to select an image.

And then I tap the finish in the first page of the picker, it will call didFinishPicking delegate and then dismiss the picker.

It will call twice didFinishPicking delegate method in my one select and edit. And I can not dismiss the picker with one dismiss.
So I use two dismiss to dismiss the picker.

No localized cancel alert

It would great localize this alert, title and buttons :)

let alert = UIAlertController(title: "Are you sure you want to cancel?", message: nil, preferredStyle: .alert)

[Feature Request] Configurable Fonts & Colors

First of all, thanks for this repo! Great job overall, and very useful.

This is more of a request than an issue, but it'd be nice for the fonts and colors used throughout FMPhotoPicker to be configurable. The kBlackColor, kRedColor, etc. could be exposed to the Config object, perhaps? Not sure the best way to go about the fonts, however.

Use case: utilizing FMPhotoPicker in another app that doesn't necessarily conform to UI fonts and colors. Also, the kRedColor isn't the best UI color, since it's more of an "error" color than a state color, if that makes sense.

How could I custom the showDialog?

static func showDialog(in viewController: UIViewController,
                           ok: (() -> Void)? = nil,
                           cancel: (() -> Void)? = nil,
                           title: String = "FMPhotoPicker",
                           message: String = "FMPhotoPicker want to access Photo Library") {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in ok?() }))
        alertController.addAction(UIAlertAction(title: "キャンセル", style: .cancel, handler: { _ in cancel?() }))

        viewController.present(alertController, animated: true)
    }

Not support video?

it's detail said support video, but it's delegate just return photos: [UIImage], i hope it's support images and videos

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.