{"id":13465773,"url":"https://github.com/congnd/FMPhotoPicker","last_synced_at":"2025-03-25T16:32:51.319Z","repository":{"id":37391153,"uuid":"120398479","full_name":"congnd/FMPhotoPicker","owner":"congnd","description":"A modern, simple and zero-dependency photo picker with an elegant and customizable image editor","archived":false,"fork":false,"pushed_at":"2023-06-27T16:29:30.000Z","size":4099,"stargazers_count":801,"open_issues_count":22,"forks_count":131,"subscribers_count":26,"default_branch":"master","last_synced_at":"2025-02-28T16:12:22.103Z","etag":null,"topics":["crop","effects","filter","image","image-editor","image-procesing","ios","photopicker","photos","picker","swift","video"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/congnd.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null},"funding":{"patreon":"congnguyen","custom":["https://paypal.me/conngnd"]}},"created_at":"2018-02-06T03:47:25.000Z","updated_at":"2025-02-27T02:41:34.000Z","dependencies_parsed_at":"2022-08-01T00:08:19.944Z","dependency_job_id":"bdf369d3-7ee8-4486-a8d5-ce837c47cbb9","html_url":"https://github.com/congnd/FMPhotoPicker","commit_stats":{"total_commits":257,"total_committers":13,"mean_commits":19.76923076923077,"dds":0.2645914396887159,"last_synced_commit":"3086dee89138da826f551155745cf08768a28965"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/congnd%2FFMPhotoPicker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/congnd%2FFMPhotoPicker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/congnd%2FFMPhotoPicker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/congnd%2FFMPhotoPicker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/congnd","download_url":"https://codeload.github.com/congnd/FMPhotoPicker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245500472,"owners_count":20625587,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crop","effects","filter","image","image-editor","image-procesing","ios","photopicker","photos","picker","swift","video"],"created_at":"2024-07-31T15:00:35.238Z","updated_at":"2025-03-25T16:32:50.869Z","avatar_url":"https://github.com/congnd.png","language":"Swift","funding_links":["https://patreon.com/congnguyen","https://paypal.me/conngnd"],"categories":["Libs","Images [🔝](#readme)","Swift"],"sub_categories":["Images"],"readme":"![FMPhotoPicker](https://i.imgur.com/xrIZy0S.jpg)\n\n[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](/LICENSE)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![Pod Compatible](https://img.shields.io/cocoapods/v/FMPhotoPicker.svg)](https://cocoapods.org/pods/FMPhotoPicker)\n[![Build](https://github.com/congnd/FMPhotoPicker/workflows/Build/badge.svg)](https://github.com/congnd/FMPhotoPicker/actions)\n\nFMPhotoPicker is a modern, simple and zero-dependency photo picker with an elegant and customizable image editor\n\n## Quick demo\n|\u003cdiv style=\"width:200px\"\u003eBatch select/deselect\u003c/div\u003e|\u003cdiv style=\"width:200px\"\u003eSmooth transitions\u003c/div\u003e|\u003cdiv style=\"width:200px\"\u003eFilter\u003c/div\u003e|\u003cdiv style=\"width:200px\"\u003eCrop\u003c/div\u003e|\n|---|---|---|---|\n|![FMPhotoPicker](https://media.giphy.com/media/If0vqiG78Tg6RSvncL/giphy.gif)| ![FMPhotoPicker](https://media.giphy.com/media/JPm6sAGyGhTV8rGXxs/giphy.gif)|![FMPhotoPicker](https://media.giphy.com/media/eJ3klNWDqWem69SbLT/giphy.gif)|![FMPhotoPicker](https://media.giphy.com/media/XBQITkEgzUv0GefK9F/giphy.gif)|\n\n## Features\n- [x] Support both single and multiple selection\n- [x] Support batch selection/deselection by swipe gesture\n- [x] Support preview\n- [x] Support simple image editor with filter and cropping functions\n- [x] Support force crop mode\n- [x] Support rounded image preview\n- [x] Support adding self-define cropping\n- [x] Support adding self-define filter\n- [x] Support video player\n- [x] Support custom confirmation view\n- [x] Support language customization\n \n## Requirements\n- iOS 9.0+\n\n## Installation\n### SwiftPM\n```\ndependencies: [\n  .package(url: \"https://github.com/congnd/FMPhotoPicker.git\", .exact(\"1.3.0\")),\n]\n```\n\n### Carthage\nInsert the following line in your Carthfile:\n```\ngit \"git@github.com:congnd/FMPhotoPicker.git\"\n```\nand run `carthage update FMPhotoPicker`\n\n### CocoaPods\nFMPhotoPicker is now available in [CocoaPods](https://cocoapods.org/pods/FMPhotoPicker)  \nYou want to add pod 'FMPhotoPicker', '~\u003e 1.3.0' similar to the following to your Podfile:\n```\ntarget 'MyApp' do\n  pod 'FMPhotoPicker', '~\u003e 1.3.0'\nend\n```\nThen run a `pod install` inside your terminal.\n\n## Usage\n#### Create a configuration object\n```swift\nvar config = FMPhotoPickerConfig()\n```\nFor details, see [Configuration](#configuration)\n\n### Picker\n```swift\nlet picker = FMPhotoPickerViewController(config: config)\npicker.delegate = self\nself.present(picker, animated: true)\n```\n*From iOS 10, you have to add the `Privacy - Photo Library Usage Description` into your Info.plist file.*\n\n### Editor\n```swift\nlet editor = FMImageEditorViewController(config: config, sourceImage: image)\neditor.delegate = self\nself.present(editor, animated: true)\n```\n\n## Delegation methods\n- Implement FMPhotoPickerViewControllerDelegate protocol to handle selected photos.  \n```swift\nfunc fmPhotoPickerController(_ picker: FMPhotoPickerViewController, didFinishPickingPhotoWith photos: [UIImage])\nfunc fmPhotoPickerController(_ picker: FMPhotoPickerViewController, didFinishPickingPhotoWith assets: [PHAsset])\n```\n\n***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.***\n\n- Implement FMImageEditorViewControllerDelegate protocol to handle ouput image\n```swift\nfunc fmImageEditorViewController(_ editor: FMImageEditorViewController, didFinishEdittingPhotoWith photo: UIImage)\n```\n\n## Configuration\n#### The configuration supports the following parameters:\n- [`mediaTypes`](#ref-media-types)\n- [`selectMode`](#ref-select-mode)\n- [`maxImage`](#ref-max-image)\n- [`maxVideo`](#ref-max-video)\n- [`availableFilters`](#ref-available-filters)\n- [`availableCrops`](#ref-available-crops)\n- [`useCropFirst`](#ref-use-crop-first)\n- [`alertController`](#ref-alert-controller)\n- [`shouldReturnAsset`](#ref-should-return-asset)\n- [`forceCropEnabled`](#ref-force-crop-enabled)\n- [`eclipsePreviewEnabled`](#ref-eclipse-preview-enabled)\n- [`strings`](#ref-strings)\n\n#### Reference\n- \u003ca name=\"ref-media-types\"\u003e\u003c/a\u003e`mediaTypes`   \nAn array that indicates the media types to be accessed by the picker controller.  \nType: `[FMMediaType]`  \nDefault: `[.image, .video]`\n\n- \u003ca name=\"ref-select-mode\"\u003e\u003c/a\u003e`selectMode`    \nPhoto selection mode that can be in `single` or `multiple` mode.  \nType: : `FMSelectMode`  \nDefault is `multiple`\n\n- \u003ca name=\"ref-max-image\"\u003e\u003c/a\u003e`maxImage`    \nThe maximum number of images can be selected. \nType: `Int`  \nDefault: `10`\n\n- \u003ca name=\"ref-max-video\"\u003e\u003c/a\u003e`maxVideo`    \nThe maximum number of videos can be selected.  \nType: `Int`   \nDefault is `10`\n\n- \u003ca name=\"ref-available-filters\"\u003e\u003c/a\u003e`availableFilters`    \nFilter options that are used in editor. **Set this parameter to `nil` to make the filter menu be unavailable in the editor**\nFMPhotoEditor provides some default filters that will be fit to you.  \nType: `[FMFilterable]?`  \nDefault: all filters are provided by FMPhotoPicker.\n\n- \u003ca name=\"ref-available-crops\"\u003e\u003c/a\u003e`availableCrops`    \nCrop options that is used in editor. **Set this parameter to `nil` to make the cropping menu be unavailable in the editor**\nFMPhotoEditor provides some default crops that will be fit to you.  \nType: `[FMCroppable]?` \nDefault: all crops provided by FMPhotoPicker.\n\n***You are not allowed to use the editor without giving it at least one crop option or one filter option***\n\n- \u003ca name=\"ref-use-crop-first\"\u003e\u003c/a\u003e`useCropFirst`    \nAn option that indicates whether the crop menu should be selected by default in the `FMImageEditorViewController`.  \nType: `Bool`  \nDefault: `false`\n\n- \u003ca name=\"ref-alert-controller\"\u003e\u003c/a\u003e`alertController`    \nAn alert controller to show the confirmation view to an user with 2 options: Ok or Cancel.  \nType: `FMAlertable`   \nDefault: `FMAlert`\n\n- \u003ca name=\"ref-should-return-asset\"\u003e\u003c/a\u003e`shouldReturnAsset`    \nWhether you want FMPhotoPicker returns PHAsset instead of UIImage.\n***FMPhotoPicker chooses a proper delegation method to be invoked when user finishes picking based on this configuration***\nType: `Bool`\nDefault: `false`\n\n- \u003ca name=\"ref-forc-crop-enabled\"\u003e\u003c/a\u003e`forceCropEnabled`    \nA bool value that indicates whether force mode is enabled.  \nIf `true` is set, only the first crop in the `availableCrops` is used in the editor.  \nAnd that crop's ration becomes force crop ratio.  \nType: `FMAlertable`  \nDefault: `false`\n\n- \u003ca name=\"ref-eclipse-preview-enabled\"\u003e\u003c/a\u003e`eclipsePreviewEnabled`    \nA bool value that indicates whether the preview of image should be displayed in rounded image.  \nType: `Bool`\nDefault: `false`\n\n- \u003ca name=\"ref-strings\"\u003e\u003c/a\u003e`strings`    \nA dictionary that allows you to customize language for your app.    \nFor details, see `FMPhotoPickerConfig.swift`   \nType: `Dictionary`\n\n## Customization\n### Custom filter\nYou can freely create your own filter by implementing the `FMFilterable` protocol.\n```swift\npublic protocol FMFilterable {\n    func filter(image: UIImage) -\u003e UIImage\n    func filterName() -\u003e String\n}\n```\nBe careful that the filterName is used to determine whether the two filters are the same.  \nMake sure that your filter's names are not duplicated, especially with the default filters that you want to use.\n\n### Custom cropping \nSimilar as filter function, FMPhotoPicker provides the capability to use your own cropping by implementing the `FMCroppable` protocol.\n```swift\npublic protocol FMCroppable {\n    func crop(image: UIImage, toRect rect: CGRect) -\u003e UIImage\n    func name(string: [String: String]) -\u003e String\n    func icon() -\u003e UIImage\n    func ratio() -\u003e FMCropRatio?\n}\n```\nThe `func name(strings: [String: String]) -\u003e String` will receive the strings configuration from configuration object.\nIt allows you customize the cropping while keeping all your language setting in only one place.\n\nThe `name()` method is also used as identifier for the cropping.  \nThus, make sure you do not have any duplicate of the cropping name.\n\n### Custom alert view controller\nYou can use your own view style for the confirmation view by implementing the `FMAlertable` protocol.\n```swift\npublic protocol FMAlertable {\n    func show(in viewController: UIViewController, ok: @escaping () -\u003e Void, cancel: @escaping () -\u003e Void)\n}\n```\n\n## Contact\nFollow and contact me on [Twitter](https://twitter.com/congndcom). \nIf you find an issue, just [open a ticket](https://github.com/congnd/FMPhotoPicker/issues/new). \nPull requests are warmly welcome as well.\n\n## License\nFMPhotoPicker is released under the MIT license. See LICENSE for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcongnd%2FFMPhotoPicker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcongnd%2FFMPhotoPicker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcongnd%2FFMPhotoPicker/lists"}