A thread safe, performant, feature rich image fetcher

Overview

PINRemoteImage

Fast, non-deadlocking parallel image downloader and cache for iOS

CocoaPods compatible Carthage compatible Build status

PINRemoteImageManager is an image downloading, processing and caching manager. It uses the concept of download and processing tasks to ensure that even if multiple calls to download or process an image are made, it only occurs one time (unless an item is no longer in the cache). PINRemoteImageManager is backed by GCD and safe to access from multiple threads simultaneously. It ensures that images are decoded off the main thread so that animation performance isn't affected. None of its exposed methods allow for synchronous access. However, it is optimized to call completions on the calling thread if an item is in its memory cache.

PINRemoteImage supports downloading many types of files. It, of course, supports both PNGs and JPGs. It also supports decoding WebP images if Google's library is available. It even supports GIFs and Animated WebP via PINAnimatedImageView.

PINRemoteImage also has two methods to improve the experience of downloading images on slow network connections. The first is support for progressive JPGs. This isn't any old support for progressive JPGs though: PINRemoteImage adds an attractive blur to progressive scans before returning them.

Progressive JPG with Blur

PINRemoteImageCategoryManager defines a protocol which UIView subclasses can implement and provide easy access to PINRemoteImageManager's methods. There are built-in categories on UIImageView, PINAnimatedImageView and UIButton, and it's very easy to implement a new category. See [UIImageView+PINRemoteImage](/Pod/Classes/Image Categories/UIImageView+PINRemoteImage.h) of the existing categories for reference.

Download an image and set it on an image view:

Objective-C

UIImageView *imageView = [[UIImageView alloc] init];
[imageView pin_setImageFromURL:[NSURL URLWithString:@"http://pinterest.com/kitten.jpg"]];

Swift

let imageView = UIImageView()
imageView.pin_setImage(from: URL(string: "https://pinterest.com/kitten.jpg")!)

Download a progressive jpeg and get attractive blurred updates:

Objective-C

UIImageView *imageView = [[UIImageView alloc] init];
[imageView setPin_updateWithProgress:YES];
[imageView pin_setImageFromURL:[NSURL URLWithString:@"http://pinterest.com/progressiveKitten.jpg"]];

Swift

let imageView = UIImageView()
imageView.pin_updateWithProgress = true
imageView.pin_setImage(from: URL(string: "https://pinterest.com/progressiveKitten.jpg")!)

Download a WebP file

Objective-C

UIImageView *imageView = [[UIImageView alloc] init];
[imageView pin_setImageFromURL:[NSURL URLWithString:@"http://pinterest.com/googleKitten.webp"]];

Swift

let imageView = UIImageView()
imageView.pin_setImage(from: URL(string: "https://pinterest.com/googleKitten.webp")!)

Download a GIF and display with PINAnimatedImageView

Objective-C

PINAnimatedImageView *animatedImageView = [[PINAnimatedImageView alloc] init];
[animatedImageView pin_setImageFromURL:[NSURL URLWithString:@"http://pinterest.com/flyingKitten.gif"]];

Swift

let animatedImageView = PINAnimatedImageView()
animatedImageView.pin_setImage(from: URL(string: "http://pinterest.com/flyingKitten.gif")!)

Download and process an image

Objective-C

UIImageView *imageView = [[UIImageView alloc] init];
[self.imageView pin_setImageFromURL:[NSURL URLWithString:@"https://i.pinimg.com/736x/5b/c6/c5/5bc6c5387ff6f104fd642f2b375efba3.jpg"] processorKey:@"rounded" processor:^UIImage *(PINRemoteImageManagerResult *result, NSUInteger *cost)
 {
     CGSize targetSize = CGSizeMake(200, 300);
     CGRect imageRect = CGRectMake(0, 0, targetSize.width, targetSize.height);
     UIGraphicsBeginImageContext(imageRect.size);
     UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:7.0];
     [bezierPath addClip];

     CGFloat sizeMultiplier = MAX(targetSize.width / result.image.size.width, targetSize.height / result.image.size.height);

     CGRect drawRect = CGRectMake(0, 0, result.image.size.width * sizeMultiplier, result.image.size.height * sizeMultiplier);
     if (CGRectGetMaxX(drawRect) > CGRectGetMaxX(imageRect)) {
         drawRect.origin.x -= (CGRectGetMaxX(drawRect) - CGRectGetMaxX(imageRect)) / 2.0;
     }
     if (CGRectGetMaxY(drawRect) > CGRectGetMaxY(imageRect)) {
         drawRect.origin.y -= (CGRectGetMaxY(drawRect) - CGRectGetMaxY(imageRect)) / 2.0;
     }

     [result.image drawInRect:drawRect];

     UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();
     return processedImage;
 }];

Swift

let imageView = FLAnimatedImageView()
imageView.pin_setImage(from: URL(string: "https://i.pinimg.com/736x/5b/c6/c5/5bc6c5387ff6f104fd642f2b375efba3.jpg")!, processorKey: "rounded")  { (result, unsafePointer) -> UIImage? in

    guard let image = result.image else { return nil }

    let radius : CGFloat = 7.0
    let targetSize = CGSize(width: 200, height: 300)
    let imageRect = CGRect(x: 0, y: 0, width: targetSize.width, height: targetSize.height)

    UIGraphicsBeginImageContext(imageRect.size)

    let bezierPath = UIBezierPath(roundedRect: imageRect, cornerRadius: radius)
    bezierPath.addClip()

    let widthMultiplier : CGFloat = targetSize.width / image.size.width
    let heightMultiplier : CGFloat = targetSize.height / image.size.height
    let sizeMultiplier = max(widthMultiplier, heightMultiplier)

    var drawRect = CGRect(x: 0, y: 0, width: image.size.width * sizeMultiplier, height: image.size.height * sizeMultiplier)
    if (drawRect.maxX > imageRect.maxX) {
        drawRect.origin.x -= (drawRect.maxX - imageRect.maxX) / 2
    }
    if (drawRect.maxY > imageRect.maxY) {
        drawRect.origin.y -= (drawRect.maxY - imageRect.maxY) / 2
    }

    image.draw(in: drawRect)

    UIColor.red.setStroke()
    bezierPath.lineWidth = 5.0
    bezierPath.stroke()

    let ctx = UIGraphicsGetCurrentContext()
    ctx?.setBlendMode(CGBlendMode.overlay)
    ctx?.setAlpha(0.5)

    let logo = UIImage(named: "white-pinterest-logo")
    ctx?.scaleBy(x: 1.0, y: -1.0)
    ctx?.translateBy(x: 0.0, y: -drawRect.size.height)

    if let coreGraphicsImage = logo?.cgImage {
        ctx?.draw(coreGraphicsImage, in: CGRect(x: 90, y: 10, width: logo!.size.width, height: logo!.size.height))
    }

    let processedImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return processedImage

}

Handle Authentication

Objective-C

[[PINRemoteImageManager sharedImageManager] setAuthenticationChallenge:^(NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, PINRemoteImageManagerAuthenticationChallengeCompletionHandler aCompletion) {
aCompletion(NSURLSessionAuthChallengePerformDefaultHandling, nil)];

Swift

PINRemoteImageManager.shared().setAuthenticationChallenge { (task, challenge, completion) in
  completion?(.performDefaultHandling, nil)
}

Support for high resolution images

Currently there are two ways PINRemoteImage is supporting high resolution images:

  1. If the URL contains an _2x. or an _3x. postfix it will be automatically handled by PINRemoteImage and the resulting image will be returned at the right scale.
  2. If it's not possible to provide an URL with an _2x. or _3x. postfix, you can also handle it with a completion handler:
NSURL *url = ...;
__weak UIImageView *weakImageView = self.imageView;
[self.imageView pin_setImageFromURL:url completion:^(PINRemoteImageManagerResult * _Nonnull result) {
  CGFloat scale = UIScreen.mainScreen.scale;
  if (scale > 1.0) {
    UIImage *image = result.image;
    weakImageView.image = [UIImage imageWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
    }
}];

Set some limits

// cache is an instance of PINCache as long as you haven't overridden defaultImageCache
PINCache *cache = (PINCache *)[[PINRemoteImageManager sharedImageManager] cache];
// Max memory cost is based on number of pixels, we estimate the size of one hundred 600x600 images as our max memory image cache.
[[cache memoryCache] setCostLimit:600 * [[UIScreen mainScreen] scale] * 600 * [[UIScreen mainScreen] scale] * 100];

// ~50 MB
[[cache diskCache] setByteLimit:50 * 1024 * 1024];
// 30 days
[[cache diskCache] setAgeLimit:60 * 60 * 24 * 30];

Installation

CocoaPods

Add PINRemoteImage to your Podfile and run pod install.

If you'd like to use WebP images, add PINRemoteImage/WebP to your Podfile and run pod install.

Carthage

Add github "pinterest/PINRemoteImage" to your Cartfile . See Carthage's readme for more information on integrating Carthage-built frameworks into your project.

Manually

Download the latest tag and drag the Pod/Classes folder into your Xcode project. You must also manually link against PINCache.

Install the docs by double clicking the .docset file under docs/, or view them online at cocoadocs.org

Git Submodule

You can set up PINRemoteImage as a submodule of your repo instead of cloning and copying all the files into your repo. Add the submodule using the commands below and then follow the manual instructions above.

git submodule add https://github.com/pinterest/PINRemoteImage.git
git submodule update --init

Requirements

PINRemoteImage requires iOS 7.0 or greater.

Contact

Garrett Moon @garrettmoon Pinterest

License

Copyright 2015 Pinterest, Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Comments
  • Images loaded from Disk Cache occasionally display artifacts / corruption.

    Images loaded from Disk Cache occasionally display artifacts / corruption.

    I'm currently using AsyncDisplayKit + PINRemoteImage libraries in my app. The PINRemoteImage version is 3.0.0-beta.3 (due to some constraint using in AsyncDisplayKit)

    This library is awesome, however, sometimes the cached images look not fully downloaded as the image below: broken

    The function I'm using is

    UIImageView *imageView = [[UIImageView alloc] init];
    [imageView setPin_updateWithProgress:YES];
    [imageView pin_setImageFromURL:[NSURL URLWithString:@"$(my_image_link)"]];
    
    bug 
    opened by nghuiqin 41
  • Unable to submit my app

    Unable to submit my app

    Guys, I am unable to submit my app on your website: https://developers.pinterest.com/apps/ I have already authorized my app and when i am trying to submit the app for review process, i am not able to submit it and i am getting โ€œ502 Bad Gatewayโ€ response and error message is: The MySQL server is running with theโ€Šโ€”โ€Šread-only option so it cannot execute this statement. This is not expected from reputed service like Pinterest. Please fix it as it is hampering our Business.

    opened by vishal2647 20
  •  Crashed: PINURLSessionManager Operation Queue :: NSOperation (QOS: LEGACY)

    Crashed: PINURLSessionManager Operation Queue :: NSOperation (QOS: LEGACY)

    We have a similar issue to #91 I thought I'd create a new ticket as it isnt on the exact same line. I'm running the latest code with commit 65d9c582fbaed691940cf4c550054535e4b84246

    The issue happens on ios 8/9 only. I can link you to the crashlytics issue if more info is required.

    Thread : Crashed: PINURLSessionManager Operation Queue :: NSOperation 0x149041870 (QOS: LEGACY)
    0  libdispatch.dylib              6850538312 dispatch_async + 76
    1  libdispatch.dylib              6850538304 dispatch_async + 68
    2  PaigeeWorld                    4297916584 -[PINURLSessionManager URLSession:task:didReceiveChallenge:completionHandler:] (PINURLSessionManager.m:79)
    3  Foundation                     6509364084 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 16
    4  Foundation                     6508655008 -[NSBlockOperation main] + 96
    5  Foundation                     6508590056 -[__NSOperationInternal _start:] + 604
    6  Foundation                     6509373288 __NSOQSchedule_f + 224
    7  libdispatch.dylib              6850533032 _dispatch_client_callout + 16
    8  libdispatch.dylib              6850582252 _dispatch_queue_drain + 864
    9  libdispatch.dylib              6850548140 _dispatch_queue_invoke + 464
    10 libdispatch.dylib              6850590140 _dispatch_root_queue_drain + 728
    11 libdispatch.dylib              6850589404 _dispatch_worker_thread3 + 112
    12 libsystem_pthread.dylib        6852760688 _pthread_wqthread + 1092
    

    I've had no luck trying to reproduce it. If you have any thoughts on how I can give it a shot.

    opened by farhanpatel 20
  • Added support for tvOS

    Added support for tvOS

    Added tvOS to the podspec, plus an example project with similar scenarios as the iOS example. Things seem to be working well, but there are two exceptions:

    1. FLAnimatedImage does not yet support tvOS. I opened a pull request to add it, but in the meantime, you can run the tvOS example by adding pod "FLAnimatedImage", :git => "https://github.com/ioveracker/FLAnimatedImage", :branch => "tvos" to the Podfile in Example-tvOS, above the line for PINRemoteImage.
    2. WebP doesn't seem to work--could be a limitation of the platform, or libwebp may need to be updated.
    opened by ioveracker 19
  • add handling for image returned with 404 http response (fixes #399)

    add handling for image returned with 404 http response (fixes #399)

    There are cases when image is returned along with 404 HttpResponse, this pr will handle the edge case from within framework. Since we manage cache any way, may be not necessary to expose api to client to handle this case? Side Notes: NSUrlSession can handle this case correctly in NSURLSessionDataDelegate.

    opened by wsdwsd0829 18
  • Add KVO to NSURLSessionTask may cause crash.

    Add KVO to NSURLSessionTask may cause crash.

    The crashes are here: http://crashes.to/s/45830cf8ec3

    I found the same issue discussed about AFNetworking. https://github.com/AFNetworking/AFNetworking/issues/1477

    I searched all the code in my project that the category NSURLSessionTask+Timing with the observer on the property of NSURLSessionTask may cause the crash.

    opened by zjmdp 17
  • [PINProgressiveImage] Use CoreImage Rather than vImage for Blurring

    [PINProgressiveImage] Use CoreImage Rather than vImage for Blurring

    Since this uses the GPU directly, the performance running on iOS Simulator is very bad.

    But on my iPhone 6, this performed more consistently and slightly faster in the example app than the prior Accelerate-based approach. Under accelerate, I saw between 125-600 ms per progressive render. With this approach, the range was 120-240ms.

    I haven't tested this under OS X yet. Is there an OS X project in the repo?

    opened by Adlai-Holler 17
  • Animated webp support

    Animated webp support

    This PR switches our technique for GIF handling to keeping in memory frames instead of trying to decode the entire GIF and memory mapping it. That technique was fraught with peril for devices without disk space left and had longer 'startup' costs. In addition there was a pesky race condition I never tracked down.

    While I think the former solution has a place, it'll be best used in a hybrid scenario along with the solution introduced here.

    Oh, this also adds animated webP support.

    opened by garrettmoon 16
  • App crashes due to Out of Memory Exception with PINRemote

    App crashes due to Out of Memory Exception with PINRemote

    I am using PINRemoteImage to download images and cached them in my app. My app uses lots of images, just like instagram so the images memory increases all the time. And I have lots of crashes due to out of memory.

    Is there a way to set a limit of MB to store in cache? Is there a way to free memory once it's full before the app crashes?

    Thanks!

    opened by rmato 15
  • Fast scrolling with a lot of images causes excessive memory usage

    Fast scrolling with a lot of images causes excessive memory usage

    Hi,

    I have an iPad app where I show rows of 4 (relatively large: width: 920px; height: 1380px;) images on an iPad inside a collection view. This leads to, when scrolling moderately rapid, excessive memory usage and eventually a crash (on physical devices). An example instruments call tree:

    pasted_image_at_2015_09_28_16_57_720

    An example of memory usage over time:

    pasted_image_at_2015_09_28_16_57_720-1

    Here is a device log from the crash:

    Incident Identifier: 9C9452D1-8376-4E06-8F2F-8E6F26080653
    CrashReporter Key:   34a30a2fec33ac19197705866e1020fc84df87bf
    Hardware Model:      iPad2,5
    OS Version:          iPhone OS 7.0.4 (11B554a)
    Kernel Version:      Darwin Kernel Version 14.0.0: Fri Sep 27 23:00:49 PDT 2013; root:xnu-2423.3.12~1/RELEASE_ARM_S5L8942X
    Date:                2015-09-30 12:45:46 +0100
    Time since snapshot: 125 ms
    
    Free pages:                              1182
    Active pages:                            3665
    Inactive pages:                          1845
    Speculative pages:                       266
    Throttled pages:                         102067
    Purgeable pages:                         0
    Wired pages:                             19868
    File-backed pages:                       5433
    Anonymous pages:                         343
    Compressions:                            0
    Decompressions:                          0
    Compressor Size:                         0
    Uncompressed Pages in Compressor:        0
    Largest process:   PINRemoteTest
    
    Processes
         Name                    <UUID>                       rpages       recent_max   fds      [reason]          (state)
    
       wirelessproxd <46066fc432663d45ab7e055082fe0bd6>          139              139  200   [vm-pageshortage]  (daemon) (idle)
          MobileMail <b3574f4bded1315cb2e50e5de205be48>         1137             1137  200   [vm-pageshortage]  (resume) (continuous)
                tccd <1fea8c5a71943151b5cd304c7eb0fd8c>          160              160  100   [vm-pageshortage]  (daemon)
       PINRemoteTest <8aac78eadffc37b0ac68272860f87788>        74944            74944  200   [vm-pageshortage]  (frontmost) (resume)
                ptpd <db9048c36f6c3c18a7330fc96d93a0cf>          647              647   50                      (daemon)
    identityservices <18cc20db2e4739a782cc8e38e03eff52>          364              364  100                      (daemon)
               wifid <a5cf99e5a0f032a69bc2f65050b44291>          379              379   25                      (daemon)
             syslogd <6539f4cf4dcf34daadf1d99991926680>          155              166   50                      (daemon)
           locationd <c31643022d833911b8b7461fd3964bd5>          955              955  100                      (daemon)
              powerd <0a253ac2a99236809422214be1700bc0>          118              118  100                      (daemon)
             imagent <bef102e1faef39209926fb25f428a71e>          240              240  100                      (daemon)
       iaptransportd <42faa147f61a314bb735e239f445efaf>          205              205   50                      (daemon)
        mediaserverd <71101024312538ccae5799b88681e38d>          667              667  100                      (daemon)
       mDNSResponder <8922e9954d893eb9a1ab27ca4723bbab>          210              280  100                      (daemon)
                apsd <0dd1fd7c2edc3cf9899a4830541c1bac>          437              437  100                      (daemon)
         dataaccessd <5da732b6ce6935f2928461a022101aba>          941              941  100                      (daemon)
            sharingd <a95c2cea41b43cc69b0bbe9a03730d45>          448              448   50                      (daemon)
               timed <abc20e52e7ce3cb9832590652d21e7d1>          199              199   50                      (daemon)
              voiced <2823988f691e3715a6e23959590f3c00>          215              215  200                      (daemon)
          calaccessd <77a5672f2f653f64acf7367126a8d173>          219              219  200                      (daemon)
         SpringBoard <3c0e305139b331c6b37d2e9516f5804f>        10476            10476   50                     
          backboardd <d61df126c4673b25bbfe5d9024be1d48>         7615             7615   50                      (daemon)
          aggregated <a5dda46586ba3a3cbb298bd8aa545e50>          454              454   50                      (daemon)
           lockdownd <6f28a28a0025348aa5361078e41914e3>          193              193  100                      (daemon)
        fairplayd.A2 <6cae0c124e1830598a43f6b4d790917f>          132              132  100                      (daemon)
             configd <c57db43e53a73f8a9360f4d0d9001704>          446              446  100                      (daemon)
           fseventsd <5c909a70b62f33c8856e3158834ba071>          242              242  100                      (daemon)
            BTServer <3933a8148924316b9f19dd3d10a23f00>          254              254  100                      (daemon)
           distnoted <38616bd8864034e7bc741f8bd7313349>          117              117  100                      (daemon)
      UserEventAgent <a3c7e56924ec3690a994a75a0ea79ee8>          502              502   50                      (daemon)
            networkd <84dfdb49c24132fa8dd10520deb16645>          423              423  100                      (daemon)
         eapolclient <534b8549294d384c9bec206a272a29cd>          141              141  100                      (daemon)
    notification_pro <852af3fe832e3cc3a3f31d05511a5482>          114              114  100                      (daemon)
                 ubd <ca1400009326346db54f834cc8b740d2>          491              491  100                      (daemon)
              cplogd <148e9e2ff86130ecb63423c183f68da5>          130              130  200                      (daemon)
         touchsetupd <02780826b4263a7498bda167721b5f8c>          153              153  200                      (daemon)
         debugserver <4f8d671c17be36d2bb9d3b30da9dd947>          164              167  200                      (daemon)
          DTMobileIS <cd97740bdfd833b69d543b3044065d20>          186              186  200                      (daemon)
    CommCenterClassi <b836b786e0cb3785a18a94e9b13c9991>          314              314   50                      (daemon)
             notifyd <35afacabfed73771889e72a017479709>          183              183  100                      (daemon)
    
    **End**
    

    I have also created a test project where I can reproduce the issue:

    https://github.com/kerrmarin/PINRemoteTest

    Is there any way to prevent this crash while maintaining performance? Initially, we thought about setting PINRemoteImageManagerDownloadOptionsSkipDecode as one of the options for the manager, but that limits the scroll performance.

    Thanks

    opened by kerrmarin 15
  • Progressive Jpeg Not Working

    Progressive Jpeg Not Working

    I've tried the following code to iOS 9.3, 10.3.1 and 11.0:

     imageView.pin_updateWithProgress = true
     imageView.pin_setImage(from: URL(string: "http://www.pooyak.com/p/progjpeg/jpegload.cgi?o=1")!)
    

    However, the image doesn't load progressively. Instead it loads after the image is fully downloaded. Is there anything i done wrongly or it is a bug?

    opened by tengfoung 14
  • Need a new release

    Need a new release

    I need an SPM package of PINRemoteImage that includes this commit (93428e8b6e797d27d1f57425937c0e094d0f4ad8)

    If you could tag and release 3.0.4 (or call it anything you like), it would be appreciated.

    opened by mr-fixit 2
  • Add support for Querying and Setting the Playback Timestamp in PINAnimatedImageView

    Add support for Querying and Setting the Playback Timestamp in PINAnimatedImageView

    If you have GIFs in a table view or collection view and you want to let them scroll off screen, then back on screen, and resume playback from the same frame, as if they were never unloaded you need to be able to save the current playback timestamp and then resume playback from that timestamp.

    Added 3 new public methods to PINAnimatedImageView to achieve this.

    @property (nonatomic, readonly) CFTimeInterval lastDisplayedTimestamp;
    -(void)setCurrentTimestamp:(CFTimeInterval)newTimestamp;
    
    -(void)setAnimatedImage:(PINCachedAnimatedImage*)image atTimestamp:(CFTimeInterval)newTimestamp
    
    opened by kylehowells 0
  • PINRemoteImageWeakTask memory leak

    PINRemoteImageWeakTask memory leak

    We're seeing some PINRemoteImageWeakTask leaks in the memory graph debugger. Looking at the PINRemoteImage code, we store this weak task using [NSURLProtocol setProperty: forKey: inRequest:] method. But we never seem to be removing this task through the corresponding removePropertyForKey method call.

    Is this expected? Or is the leak due to some other issue?

    Thanks!

    Screen Shot 2022-06-08 at 3 50 17 PM
    opened by rounak 0
  • Project future/roadmap, slow response times

    Project future/roadmap, slow response times

    hey @garrettmoon , is PINRemoteImage is still relevant to you and Pinterest? You are very passive here and it makes a felling that project is dead or almost dead. Maybe you can transition the project to someone else in that case or please let us know what you think about it ? We use it and all PRs and suggestions hanging and waiting months or years to your response.

    Sorry if I sound offending, I just want to understand can we make project to move faster. I know we can make fork and all that, just let us know what you think.

    opened by hovox 4
  • Issue with cache cost calculation for UIImage created from Core Image

    Issue with cache cost calculation for UIImage created from Core Image

    We are using PINRemoteImage's processorBlock to download an image from a URL, and then processing it using Core Image. We return UIImage(ciImage: processedCoreImage) in the processorBlock.

    However we're hitting an NSAssert in PINRemoteImage during cache cost calculation:

    NSAssert(container.image == nil || imageRef != NULL, @"We only cache a decompressed image if we decompressed it ourselves. In that case, it should be backed by a CGImageRef.");
    

    It seems like this only supports UIImage that is CGImage backed, which is not the case with Core Image. Any help or guidance would be appreciated, thanks!

    opened by rounak 0
Releases(3.0.3)
Owner
Pinterest
Pinterest's Open Source Projects
Pinterest
๐Ÿš€SwiftUI Image downloader with performant LRU mem/disk cache.

Progressive concurrent image downloader for SwiftUI, with neat API and performant LRU mem/disk cache.

Cheng Zhang 42 Sep 24, 2022
Essential Feed App โ€“ Image Feed Feature

Essential Feed App โ€“ Image Feed Feature

Alexandre Gravelle 0 Jan 9, 2022
A simple, performant, and lightweight SVG parser

Key Features Parsing performance that meets or beats other popular SVG Frameworks A simple architecture, optimized for extension, flexibility and deve

Michael Choe 1.8k Dec 29, 2022
XAnimatedImage is a performant animated GIF engine for iOS written in Swift based on FLAnimatedImage

XAnimatedImage is a performant animated GIF engine for iOS written in Swift based on FLAnimatedImage. An illustration is shown below: Features Plays m

Khaled Taha 561 Sep 9, 2022
A photo gallery for iOS with a modern feature set. Similar features as the Facebook photo browser.

EBPhotoPages โ€A photo gallery can become a pretty complex component of an app very quickly. The EBPhotoPages project demonstrates how a developer coul

Eddy Borja 1.7k Dec 8, 2022
๐Ÿ“ท A composable image editor using Core Image and Metal.

Brightroom - Composable image editor - building your own UI Classic Image Editor PhotosCrop Face detection Masking component ?? v2.0.0-alpha now open!

Muukii 2.8k Jan 3, 2023
An image download extension of the image view written in Swift for iOS, tvOS and macOS.

Moa, an image downloader written in Swift for iOS, tvOS and macOS Moa is an image download library written in Swift. It allows to download and show an

Evgenii Neumerzhitckii 330 Sep 9, 2022
๐Ÿ“ท A composable image editor using Core Image and Metal.

Brightroom - Composable image editor - building your own UI Classic Image Editor PhotosCrop Face detection Masking component ?? v2.0.0-alpha now open!

Muukii 2.8k Jan 2, 2023
AsyncImage before iOS 15. Lightweight, pure SwiftUI Image view, that displays an image downloaded from URL, with auxiliary views and local cache.

URLImage URLImage is a SwiftUI view that displays an image downloaded from provided URL. URLImage manages downloading remote image and caching it loca

Dmytro Anokhin 1k Jan 4, 2023
AYImageKit is a Swift Library for Async Image Downloading, Show Name's Initials and Can View image in Separate Screen.

AYImageKit AYImageKit is a Swift Library for Async Image Downloading. Features Async Image Downloading. Can Show Text Initials. Can have Custom Styles

Adnan Yousaf 11 Jan 10, 2022
A complete Mac App: drag an image file to the top section and the bottom section will show you the text of any QRCodes in the image.

QRDecode A complete Mac App: drag an image file to the top section and the bottom section will show you the text of any QRCodes in the image. QRDecode

David Phillip Oster 2 Oct 28, 2022
Convert the image to hexadecimal to send the image to e-paper

ConvertImageToHex Convert the image to hexadecimal to send the image to e-paper Conversion Order // 0. hex๋กœ ๋ณ€ํ™˜ํ•  ์ด๋ฏธ์ง€ var image = UIImage(named: "sample

Hankyeol Park 0 Feb 26, 2022
Image-cropper - Image cropper for iOS

Image-cropper Example To run the example project, clone the repo, and run pod in

Song Vuthy 0 Jan 6, 2022
An instagram-like image editor that can apply preset filters passed to it and customized editings to a binded image.

CZImageEditor CZImageEditor is an instagram-like image editor with clean and intuitive UI. It is pure swift and can apply preset filters and customize

null 8 Dec 16, 2022
SwiftGen is a tool to automatically generate Swift code for resources of your projects (like images, localised strings, etc), to make them type-safe to use.

SwiftGen is a tool to automatically generate Swift code for resources of your projects (like images, localised strings, etc), to make them type-safe to use.

null 8.3k Jan 5, 2023
Agrume - ๐Ÿ‹ An iOS image viewer written in Swift with support for multiple images.

Agrume An iOS image viewer written in Swift with support for multiple images. Requirements Swift 5.0 iOS 9.0+ Xcode 10.2+ Installation Use Swift Packa

Jan Gorman 601 Dec 26, 2022
AlamofireImage is an image component library for Alamofire

AlamofireImage AlamofireImage is an image component library for Alamofire. Features Image Response Serializers UIImage Extensions for Inflation / Scal

Alamofire 3.9k Dec 29, 2022
Image slide-show viewer with multiple predefined transition styles, with ability to create new transitions with ease.

ATGMediaBrowser ATGMediaBrowser is an image slide-show viewer that supports multiple predefined transition styles, and also allows the client to defin

null 200 Dec 19, 2022
FMPhotoPicker is a modern, simple and zero-dependency photo picker with an elegant and customizable image editor

FMPhotoPicker is a modern, simple and zero-dependency photo picker with an elegant and customizable image editor Quick demo Batch select/deselect Smoo

Cong Nguyen 648 Dec 27, 2022