JPImageresizerview

repository·master·Indexed 21 days ago

https://github.com/rogue24/jpimageresizerview

A comprehensive iOS library for cropping images, GIFs, and videos. It supports adaptive scaling, rotation, mirroring, and circular crops. Key features include N-grid image splitting, video frame extraction, GIF processing with custom playback settings, and the ability to convert video segments to GIFs. Compatible with Swift and SwiftUI, it provides highly customizable UI parameters for borders, masks, and blur effects.

Tokens
17.1K
Snippets
46
Records
50
Agent score
69%

What's inside JPImageresizerview

  1. Overview of JPImageresizerView

    master

    JPImageresizerView is a versatile tool for cropping images, GIFs, and videos. It provides high freedom in parameter settings, supporting rotation, mirroring, masks, and compression. It is designed to meet most cropping requirements with a rich feature set.

    Key Features:

    • Adaptive Scaling: Automatically adjusts the cropping area scale.
    • High Customization: Control cropping area margins, aspect ratios, and adaptive scaling.
    • Flexible Interaction: Supports up to 8 drag directions for the cropping area.
    • Transformations: Supports rotation (top, left, bottom, right) and horizontal/vertical mirroring.
    • Visual Styles: Two border styles, circular cropping, customizable corner radii, and custom border images.
    • Visual Effects: Customizable blur effects, border colors, background colors, and mask transparency.
    • Media Support:
      • GIFs: Supports cropping GIFs with customizable background colors, corner radii, borders, outlines, and margins.
      • Videos: Supports cropping entire videos or specific frames, as well as extracting specific time segments or converting them to GIFs.
    • Advanced Layout: Supports N-grid cropping for images and dynamic modification of view/cropping area margins (including orientation changes).
    • Compatibility: Works in Swift and SwiftUI environments.

    Important Note: The library currently uses frame layout instead of AutoLayout because AutoLayout is not ideal for gesture control.

  2. Important considerations for saving and restoring configuration

    master

    When working with saved configurations in JPImageresizerView, be aware of the following limitations:

    1. View Frame Consistency: If the saved savedConfigure.history.viewFrame does not match the current viewFrame, the interface may become corrupted or behave erratically. You must manually verify if the frames are consistent before attempting to reopen a saved configuration.
    2. Persistence: Currently, configurations can only be saved during the active App session. Persistent caching (saving to disk across app restarts) is not yet implemented.
  3. Initialize and Add JPImageresizerView to your View Hierarchy

    master

    Once configured, create the JPImageresizerView instance. The initializer provides two important callbacks to manage your UI state:

    • imageresizerIsCanRecovery: Returns YES if the user can reset the current transformations (rotation, zoom, mirror). Use this to enable/disable your 'Reset' button.
    • imageresizerIsPrepareToScale: Returns YES while the crop frame is calculating/scaling. Use this to disable user interaction with operation buttons to prevent conflicts.

    Swift Usage Example:

    let imageresizerView = JPImageresizerView(configure: configure) { [weak self] isCanRecovery in
        self?.recoveryBtn.isEnabled = isCanRecovery
    } imageresizerIsPrepareToScale: { [weak self] isPrepareToScale in
        self?.operationView.isUserInteractionEnabled = !isPrepareToScale
    }
    view.insertSubview(imageresizerView, at: 0)
    // Objective-C Usage
    JPImageresizerView *imageresizerView = [JPImageresizerView imageresizerViewWithConfigure:configure imageresizerIsCanRecovery:^(BOOL isCanRecovery) {
        // Handle reset button state
    } imageresizerIsPrepareToScale:^(BOOL isPrepareToScale) {
        // Handle operation button state
    }];
    [self.view addSubview:imageresizerView];
    self.imageresizerView = imageresizerView;
  4. Handle Video Orientation Fixes during Initialization

    master

    Videos from the Photos app may have orientation transforms that cause incorrect cropping. You can handle this in two ways:

    1. Fix during Initialization

    When using defaultConfigureWithVideoURL: or defaultConfigureWithVideoAsset:, provide callbacks to handle the orientation correction process automatically.

    2. Fix before Initialization using JPImageresizerTool

    Manually fix the video orientation using JPImageresizerTool before creating the JPImageresizerView. This is recommended for more control.

    Note: If no orientation fix is required, fixStartBlock, fixProgressBlock, and fixErrorBlock will not be called, and fixCompleteBlock will be called directly with the original path.

    // Fix orientation before initializing the cropper
    [JPImageresizerTool fixOrientationVideoWithAsset:videoAsset fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
        // Error callback
    } fixStartBlock:^(AVAssetExportSession *exportSession) {
        // Start callback; observe exportSession for progress/cancel
    } fixCompleteBlock:^(NSURL *cacheURL) {
        // Completion callback; cacheURL is the final exported path
        // Use this path to initialize the cropper
        JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoAsset:[AVURLAsset assetWithURL:cacheURL] make:nil ...];
    }];
  5. Initialize JPImageresizerView with Videos and Handle Orientation

    master

    Videos from the system album may have orientation metadata that causes cropping issues. You can handle this in two ways:

    1. Automatic Correction during Initialization

    When initializing with a videoURL or videoAsset, provide callback blocks to handle the orientation correction process. The view will automatically attempt to fix the orientation before presenting the cropping interface.

    2. Manual Correction using JPImageresizerTool

    For more control, use JPImageresizerTool to fix the video orientation before initializing the JPImageresizerView. This is recommended if you want to handle the export process yourself.

    Important Notes:

    • If the video does not require correction, fixStartBlock, fixProgressBlock, and fixErrorBlock will not be called; fixCompleteBlock will be called immediately with the original path.
    • If you are certain no correction is needed, pass nil to the fix... blocks.
    • When using the corrected video, use the cacheURL returned in fixCompleteBlock to initialize the JPImageresizerView.
    // 1. Automatic correction via URL
    JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoURL:videoURL make:^(JPImageresizerConfigure *configure) {
        // configuration
    } fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
        // error handling
    } fixStartBlock:^{ 
        // start callback
    } fixProgressBlock:^(float progress) {
        // progress callback
    } fixCompleteBlock:^(NSURL *cacheURL) {
        // completion callback
    }];
    
    // 2. Manual correction using JPImageresizerTool
    [JPImageresizerTool fixOrientationVideoWithAsset:videoAsset fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
        // error
    } fixStartBlock:^(AVAssetExportSession *exportSession) {
        // start (can monitor exportSession)
    } fixCompleteBlock:^(NSURL *cacheURL) {
        // Use this cacheURL to initialize the view
        JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoAsset:[AVURLAsset assetWithURL:cacheURL] make:nil ...];
    }];
  6. Create and Add JPImageresizerView to a View Hierarchy

    master

    Once configured, instantiate JPImageresizerView using imageresizerViewWithConfigure:. The initializer provides two important callbacks for UI management:

    • imageresizerIsCanRecovery: Notifies you if the user can reset changes (rotation, scale, mirror). Use this to enable/disable a reset button.
    • imageresizerIsPrepareToScale: Notifies you when the cropping area is preparing to scale to fit the bounds. During this state, cropping, rotation, and mirroring are unavailable. Use this to disable relevant UI buttons.

    Note for iOS < 11: Set automaticallyAdjustsScrollViewInsets = NO on the parent controller to prevent layout offsets caused by navigation bars or status bars.

    Swift Usage:

    let imageresizerView = JPImageresizerView(configure: configure) { isCanRecovery in
        self?.recoveryBtn.isEnabled = isCanRecovery
    } imageresizerIsPrepareToScale: { isPrepareToScale in
        self?.operationView.isUserInteractionEnabled = !isPrepareToScale
    }
    view.insertSubview(imageresizerView, at: 0)
    // Objective-C
    JPImageresizerView *imageresizerView = [JPImageresizerView imageresizerViewWithConfigure:configure imageresizerIsCanRecovery:^(BOOL isCanRecovery) {
        // Handle reset button state
    } imageresizerIsPrepareToScale:^(BOOL isPrepareToScale) {
        // Handle operation button state
    }];
    [self.view addSubview:imageresizerView];
    
    // Dynamic updates
    self.imageresizerView.image = [UIImage imageNamed:@
  7. Install JPImageresizerView via Swift Package Manager

    master

    To install JPImageresizerView using Swift Package Manager (requires Xcode 11 or later), you can either add the repository URL directly in Xcode or update your Package.swift file.

    Via Xcode:

    1. Select File -> Swift Packages -> Add Package Dependency.
    2. Enter the repository URL: https://github.com/Rogue24/JPImageresizerView.git.
    3. Choose your version requirement (e.g., a specific version, branch, or commit).
    4. Add JPImageresizerView to your target dependencies.

    Via Package.swift: Add the package to your dependencies array using .upToNextMajor(from: "1.14.0") or your preferred version constraint.

    .dependencies: [
        .package(url: "https://github.com/Rogue24/JPImageresizerView.git", .upToNextMajor(from: "1.14.0"))
    ]
  8. Manage history clearing in JPImageresizerView

    master

    You can control whether the view's history is automatically cleared after initialization by setting the isCleanHistoryAfterInitial property on JPImageresizerConfigure.

    • Default behavior: YES (history is cleared after initialization).
    • Manual clearing: You can call cleanHistory directly to clear the history at any time.
    // Set to YES to auto-clear history after initialization (default is YES)
    JPImageresizerConfigure.isCleanHistoryAfterInitial = YES;
    
    // Or call cleanHistory directly
    [self.imageresizerView cleanHistory];
  9. Initialize JPImageresizerView with Local Videos

    master

    Videos require special handling because orientation metadata (from the Photos app) can cause incorrect cropping. You have two options:

    Option 1: Fix orientation during initialization

    Use the fix... blocks to handle the orientation correction process automatically.

    JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoURL:videoURL make:^(JPImageresizerConfigure *configure) { 
        // Configuration
    } fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
        // Error callback
    } fixStartBlock:^{ 
        // Start callback
    } fixProgressBlock:^(float progress) {
        // Progress callback
    } fixCompleteBlock:^(NSURL *cacheURL) {
        // Completion callback
    }];

    Option 2: Fix orientation manually before initialization

    Use JPImageresizerTool to export a corrected video first, then initialize with the new URL.

    [JPImageresizerTool fixOrientationVideoWithAsset:videoAsset fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
        // Error callback
    } fixStartBlock:^(AVAssetExportSession *exportSession) {
        // Start callback
    } fixCompleteBlock:^(NSURL *cacheURL) {
        // Use the new cacheURL to initialize the view
        JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoAsset:[AVURLAsset assetWithURL:cacheURL] make:nil ...];
    }];
    JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithVideoURL:videoURL make:^(JPImageresizerConfigure *configure) { ...... } fixErrorBlock:^(NSURL *cacheURL, JPImageresizerErrorReason reason) {
        // Error callback for orientation fix during initialization
    } fixStartBlock:^{
        // Start callback for orientation fix during initialization
    } fixProgressBlock:^(float progress) {
        // Progress callback for orientation fix during initialization
    } fixCompleteBlock:^(NSURL *cacheURL) {
        // Completion callback for orientation fix during initialization
    }];
  10. Install JPImageresizerView via Swift Package Manager or CocoaPods

    master

    You can integrate JPImageresizerView into your iOS project using either Swift Package Manager (SPM) or CocoaPods.

    Swift Package Manager

    In Xcode, go to File -> Swift Packages -> Add Package Dependency and enter the repository URL: https://github.com/Rogue24/JPImageresizerView.git

    Alternatively, add it directly to your Package.swift:

    .dependencies: [
        .package(url: "https://github.com/Rogue24/JPImageresizerView.git", .upToNextMajor(from: "1.14.0"))
    ]

    CocoaPods

    Add the following line to your Podfile:

    pod 'JPImageresizerView'

    Then run pod update --no-repo-update.

  11. Initialize JPImageresizerView with JPImageresizerConfigure

    master

    To use the view, you must first create a JPImageresizerConfigure object. You must provide exactly one of the following source types (cannot be nil):

    • image: A UIImage (for images or GIFs).
    • imageData: NSData (for images or GIFs).
    • videoURL: An NSURL (for local videos).
    • videoAsset: An AVURLAsset (for local videos).

    You can use a block-based configuration pattern to set parameters like strokeColor, bgColor, maskAlpha, and frameType using chainable methods.

    Note: The view uses frame layout and does not support AutoLayout due to gesture control requirements.

    // Example: Initializing with a UIImage
    JPImageresizerConfigure *configure = [JPImageresizerConfigure defaultConfigureWithImage:image make:^(JPImageresizerConfigure *configure) {
        configure
        .jp_maskAlpha(0.5)
        .jp_strokeColor([UIColor yellowColor])
        .jp_frameType(JPClassicFrameType)
        .jp_contentInsets(contentInsets)
        .jp_bgColor([UIColor orangeColor])
        .jp_isClockwiseRotation(YES)
        .jp_animationCurve(JPAnimationCurveEaseOut);
    }];