Re: Concurrent loading of images ?
> I’m not sure if you can create and manipulate a CALayer on a background > thread, all UI code must be run on main thread. Yes, that's what I was suspecting, too. Interestingly, when I create a layer in the background, and add it to the main layer *in the background thread* , it helps a lot. The stuttering is much much better now! not 100% perfect, but OK to distribute, IMHO. Code is attached, just for reference, should someone else stumble in here. > > It’s worth noting that I’m using Lanczos scaling with cpu renderer because > I’m scaling relatively low-resolution images for print output so I need the > highest quality scaling regardless of performance. Do you scale up? or down? (I'm only scaling down, if any.) > According to this NSHipster guide (https://nshipster.com/image-resizing/) > simply getting an appropriate size via CGImageSourceCreateThumbnailAtIndex > should be your best option. You’re already doing this, so maybe you don’t > need CIImage at all? Yes, I have just removed CIImage functions completely. > > The CALayer animation should be using the GPU. Yes, I think, it does. > If loading the new image at the same time you’re starting the animation of > the current image causes a stutter, you could try delaying execution of your > block by a little (using dispatch_after instead of dispatch_async). Good idea ! I tried that and it seems to help a bit further against stuttering. So, thanks a million to you (and everyone else who chimed in)! You kept me experimenting. Best regards, Gabriel Encl.: This is my solution to the stuttering problem, at the moment. (Let's hope, Apple doesn't change the semantics of all the API's, LOL.) NSDictionary * imageOpts = @{ (id)kCGImageSourceCreateThumbnailWithTransform: (id)kCFBooleanTrue, // takes care of EXIF orientation, too (id)kCGImageSourceCreateThumbnailFromImageIfAbsent: (id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageAlways: (id)kCFBooleanTrue, (id)kCGImageSourceShouldCacheImmediately: (id)kCFBooleanTrue, (id)kCGImageSourceThumbnailMaxPixelSize: @(8192)}; CGImageRef newImageRef = CGImageSourceCreateThumbnailAtIndex( new_image, 0, (__bridge CFDictionaryRef) imageOpts ); if ( prefetchLayer_ ) [prefetchLayer_ removeFromSuperlayer]; prefetchLayer_ = [CALayer layer]; prefetchLayer_.contents = (__bridge id)(newImageRef); prefetchLayer_.delegate= nil; prefetchLayer_.minificationFilter = kCAFilterTrilinear; // kCAFilterLinear is faster prefetchLayer_.magnificationFilter = imgLayer.minificationFilter; prefetchLayer_.bounds = NSRectToCGRect( drawRect_ ); prefetchLayer_.zPosition = -10.0; prefetchLayer_.opacity = 0.0; // hopefully, Apple never optimizes layers away b/c of zero opacity! [mainLayer_ addSublayer: prefetchLayer_]; smime.p7s Description: S/MIME cryptographic signature ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
Thanks a lot for your response! I have tried the CILanczosScaleTransform filter for downsizing. I have computed the scale factor exactly such that the new image has an extent not larger than the view. (Below is my code) But the performance was worse, at least with the software renderer. With the hardware renderer (kCIContextUseSoftwareRenderer: @NO), performance was as before, but visual artifacts were still much worse than without any downsizing. If you are curious: here is a video showing the performance https://owncloud.informatik.uni-bremen.de/index.php/s/wJRkK8Ek2HTp32a (The video was made with the software renderer.) So, right now, I am using this code: NSDictionary * imageOpts = @{ (id)kCGImageSourceCreateThumbnailWithTransform: (id)kCFBooleanTrue, // takes care of EXIF orientation, too (id)kCGImageSourceCreateThumbnailFromImageIfAbsent: (id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageAlways: (id)kCFBooleanTrue, (id)kCGImageSourceShouldCacheImmediately: (id)kCFBooleanTrue, (id)kCGImageSourceThumbnailMaxPixelSize: @(8192) }; CGImageRef newImageRef = CGImageSourceCreateThumbnailAtIndex( new_image, 0, (__bridge CFDictionaryRef) imageOpts ); There is still a bit of stuttering. Maybe, it would help to create the CALayer for the new images in the background thread and add it to the layer hierarchy, but I haven't explored this option yet. Maybe it would not help, because, maybe, at that point some process in the foreground would kick in again, over which I would not have control. Best regards, Gabriel Encl.: Just for your reference, this is my code for downsizing using the Lanczos filter: CIContext * ciContext = [CIContext contextWithOptions: @{kCIContextUseSoftwareRenderer: @NO} ]; // TODO: als inst.var. machen! // TODO: evtl im context kCIContextPriorityRequestLow und useSoftwareRenderer=FALSE angeben? CIFilter * resizeFilter = [CIFilter filterWithName: @"CILanczosScaleTransform" ]; [resizeFilter setValue: orientedimage forKey: kCIInputImageKey]; [resizeFilter setValue: @(scale) forKey: kCIInputScaleKey ]; [resizeFilter setValue: @(aspect) forKey:kCIInputAspectRatioKey ]; CIImage * resizedImage = resizeFilter.outputImage; CGImageRef newImageRef = [ciContext createCGImage: resizedImage fromRect: resizedImage.extent]; > > Since this stutter does not occur when cycling back through images that have > already been assigned to the layer, it’s possible that if the size of the > CGImageRef does not match the size of the CALayer, there may be some kind of > render occuring, especially if the image is being scaled to fit the layer. > Do images much larger than the CALayer stutter more? > > Also, if you’re resizing, you’ll want to use CIImage’s > CILanczosScaleTransform filter. Simply scaling a using a transform will give > you a much blurrier image. > > Jim Crate > ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
On May 14, 2020, at 11:13 AM, Gabriel Zachmann via Cocoa-dev wrote: > > I thought i'm doing that with this code: > > -animateOneframe: > // essentially, this gets called when the next image is to be displayed > current_image_ = prefetched_image_; // these are CGImageRef's > dispatch_async( prefetch_queue_, ^{ > [self loadNextImage];// stores next image in > prefetched_image_ > } ); > create a new CALayer, > assign the current_image_ as content, > create an animation for the layer, > add the layer to the layer hierarchy Since this stutter does not occur when cycling back through images that have already been assigned to the layer, it’s possible that if the size of the CGImageRef does not match the size of the CALayer, there may be some kind of render occuring, especially if the image is being scaled to fit the layer. Do images much larger than the CALayer stutter more? Also, if you’re resizing, you’ll want to use CIImage’s CILanczosScaleTransform filter. Simply scaling a using a transform will give you a much blurrier image. Jim Crate ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> > Ahh, there’s a jitter when moving. Right. Sometimes it's a really lengthy stutter. > > Try creating an async dispatch to a background thread in a block. I thought i'm doing that with this code: -animateOneframe: // essentially, this gets called when the next image is to be displayed current_image_ = prefetched_image_;// these are CGImageRef's dispatch_async( prefetch_queue_, ^{ [self loadNextImage];// stores next image in prefetched_image_ } ); create a new CALayer, assign the current_image_ as content, create an animation for the layer, add the layer to the layer hierarchy Am I not? Best regards, Gabriel ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
One cheap option would be to ease the sliding in to a stop position and have a nice little pause where you swap images. Of course, that’s cheating. > On May 13, 2020, at 3:34 PM, Gabriel Zachmann wrote: > >> >> Care to post a video on a Google drive so that we can see it? > > Good idea - here is the video: > > https://owncloud.informatik.uni-bremen.de/index.php/s/TTGG6bKCMFLqY4g > > (encoded in H265/HEVC for saving file size) > > I think, you can see clearly the stuttering. Sometimes it is more subtle, > sometimes, the stuttering pauses the animation for a second. > Sometimes, it occurs when the background thread is prefetching the next image > (usually happens directly after the switch to a new image), sometimes, it > happens when the new image is beginning to show (i.e., when it's CALayer is > added to the layer hierarchy). > > I made another experiment, which puzzles me even more. > I am storing a history of the CGImageRef's that had been displayed so far. > When I go back through that history, I use those stored CGImageRef's to > create new CALayers which I then add to the layer hierarchy (the image that > had been shown until then is just removed from the layer hierarchy, or rather > its CALayer). > The funny thing is that when I do that (using older CGImageRef's) the switch > from one image to the next one is instantaneous and there is no stuttering at > all. > > You can see that in the video starting at 1:19. > > It seems as if some more processing is going on when a CGImage is assigned to > a CALayer, > which CGImageSourceCreateThumbnailAtIndex() and all the other functions I > listed below do not do. > Or it happens at the point when an animation is added. > And the result of that is stored inside the CGImage! > But how can I force that in the background thread? > (without making the animation of the foreground thread stutter.) > > I made another little experiment. > I keep (kinetically) scrolling through the source code in Xcode with high > velocity while my app is running in the foreground. > And when it switches images there is sometimes even a stuttering in that > scrolling. > >> >> One of my tricks (not just mine) is to have a 3 slots of for images, not >> just 2. When a new image loads, take the foreground one that is blended in >> to 100%, put an identical one ahead of it. Make the changes to the new and >> old images behind it, then hide that foreground image. > > Sorry, I didn't get how that would work with my animations. > Maybe, you can describe it again once you've seen the video. > > > > Best, Gab. > > ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
Ahh, there’s a jitter when moving. Try creating an async dispatch to a background thread in a block. > On May 13, 2020, at 3:34 PM, Gabriel Zachmann wrote: > >> >> Care to post a video on a Google drive so that we can see it? > > Good idea - here is the video: > > https://owncloud.informatik.uni-bremen.de/index.php/s/TTGG6bKCMFLqY4g > > (encoded in H265/HEVC for saving file size) > > I think, you can see clearly the stuttering. Sometimes it is more subtle, > sometimes, the stuttering pauses the animation for a second. > Sometimes, it occurs when the background thread is prefetching the next image > (usually happens directly after the switch to a new image), sometimes, it > happens when the new image is beginning to show (i.e., when it's CALayer is > added to the layer hierarchy). > > I made another experiment, which puzzles me even more. > I am storing a history of the CGImageRef's that had been displayed so far. > When I go back through that history, I use those stored CGImageRef's to > create new CALayers which I then add to the layer hierarchy (the image that > had been shown until then is just removed from the layer hierarchy, or rather > its CALayer). > The funny thing is that when I do that (using older CGImageRef's) the switch > from one image to the next one is instantaneous and there is no stuttering at > all. > > You can see that in the video starting at 1:19. > > It seems as if some more processing is going on when a CGImage is assigned to > a CALayer, > which CGImageSourceCreateThumbnailAtIndex() and all the other functions I > listed below do not do. > Or it happens at the point when an animation is added. > And the result of that is stored inside the CGImage! > But how can I force that in the background thread? > (without making the animation of the foreground thread stutter.) > > I made another little experiment. > I keep (kinetically) scrolling through the source code in Xcode with high > velocity while my app is running in the foreground. > And when it switches images there is sometimes even a stuttering in that > scrolling. > >> >> One of my tricks (not just mine) is to have a 3 slots of for images, not >> just 2. When a new image loads, take the foreground one that is blended in >> to 100%, put an identical one ahead of it. Make the changes to the new and >> old images behind it, then hide that foreground image. > > Sorry, I didn't get how that would work with my animations. > Maybe, you can describe it again once you've seen the video. > > > > Best, Gab. > > ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> > Care to post a video on a Google drive so that we can see it? Good idea - here is the video: https://owncloud.informatik.uni-bremen.de/index.php/s/TTGG6bKCMFLqY4g (encoded in H265/HEVC for saving file size) I think, you can see clearly the stuttering. Sometimes it is more subtle, sometimes, the stuttering pauses the animation for a second. Sometimes, it occurs when the background thread is prefetching the next image (usually happens directly after the switch to a new image), sometimes, it happens when the new image is beginning to show (i.e., when it's CALayer is added to the layer hierarchy). I made another experiment, which puzzles me even more. I am storing a history of the CGImageRef's that had been displayed so far. When I go back through that history, I use those stored CGImageRef's to create new CALayers which I then add to the layer hierarchy (the image that had been shown until then is just removed from the layer hierarchy, or rather its CALayer). The funny thing is that when I do that (using older CGImageRef's) the switch from one image to the next one is instantaneous and there is no stuttering at all. You can see that in the video starting at 1:19. It seems as if some more processing is going on when a CGImage is assigned to a CALayer, which CGImageSourceCreateThumbnailAtIndex() and all the other functions I listed below do not do. Or it happens at the point when an animation is added. And the result of that is stored inside the CGImage! But how can I force that in the background thread? (without making the animation of the foreground thread stutter.) I made another little experiment. I keep (kinetically) scrolling through the source code in Xcode with high velocity while my app is running in the foreground. And when it switches images there is sometimes even a stuttering in that scrolling. > > One of my tricks (not just mine) is to have a 3 slots of for images, not just > 2. When a new image loads, take the foreground one that is blended in to > 100%, put an identical one ahead of it. Make the changes to the new and old > images behind it, then hide that foreground image. Sorry, I didn't get how that would work with my animations. Maybe, you can describe it again once you've seen the video. Best, Gab. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> > Actually, can’t you disable screen updating while you’re swapping images? Would that mean that the animations are not .. animating during that time? That would defeat the whole purpose of the exercise . If I am mistaken: how would I disable screen updates? Best regards, Gabriel ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
Actually, can’t you disable screen updating while you’re swapping images? > On May 12, 2020, at 3:35 PM, Alex Zavatone via Cocoa-dev > wrote: > > Care to post a video on a Google drive so that we can see it? > > One of my tricks (not just mine) is to have a 3 slots of for images, not just > 2. When a new image loads, take the foreground one that is blended in to > 100%, put an identical one ahead of it. Make the changes to the new and old > images behind it, then hide that foreground image. > > You’re actually using a copy of the foreground image as a mask and you > perform the swap behind it, then update the screen, then remove the top level > one and refresh again. > > This is if I’m understanding what you’re going properly. > > I’d expect that Apple’s video system to actually handle this if it still > triple buffers, but it’s been 25 years since I read the docs on the Mac’s > video subsystem. > > > In the mean time, add logging code that you can put breatpoints on and take a > screen grab when you log. That should help. > > Cheers, > Alex Zavatone > >> On May 12, 2020, at 3:27 PM, Gabriel Zachmann via Cocoa-dev >> wrote: >> >> Thanks a million to everyone who has shared insights, hints, and advice on >> this. >> >> I have restructured my code, so now I do the heavy lifting of loading images >> in a serial dispatch queue. >> However, there is still sometimes some stuttering visible in the animation >> of the images. >> Does anyone have an idea what might be causing it? >> >> Here is the current structure of my code, given in sort of a pseudo-code: >> >> -animateOneframe: >> // essentially, this gets called when the next image is to be displayed >> current_image_ = prefetched_image_; // these are CGImageRef's >> dispatch_async( prefetch_queue_, ^{ >> [self loadNextImage]; >> } ); >> create a new CALayer, >> assign the current_image_ as content, >> create an animation for the layer, >> add the layer to the layer hierarchy >> >> In -loadNextImage, I am doing all the heavy lifting of loading images >> (and the not-so-heavy), such as: >> prefetched_image_ = nil; >> CGImageSourceGetStatus >> CGImageSourceCopyPropertiesAtIndex >> CGImageSourceCreateThumbnailAtIndex >> imageByApplyingOrientation >> createCGImage >> prefetched_image_ = new image >> >> (I know there is some potential race condition here, but that is not of >> concern to me right now.) >> >> Overall, I get the impression that it is "better" (less stuttering), >> but sometimes there is still a stuttering in the animation when the app >> makes a transition from one image to the next one. >> >> How could that be? >> >> Using Instruments, I can see this in the "heaviest stack trace" when CPU >> usage is high in the main thread: >> >> 41 CoreFoundation 3897.0 __CFRunLoopDoObservers >> 40 CoreFoundation 3897.0 >> __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ >> 39 QuartzCore 3896.0 >> CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, >> void*) >> 38 QuartzCore 3896.0 CA::Transaction::commit() >> 37 QuartzCore 3895.0 CA::Context::commit_transaction(CA::Transaction*, >> double) >> 36 QuartzCore 3895.0 CA::Layer::prepare_commit(CA::Transaction*) >> 35 QuartzCore 3895.0 CA::Render::prepare_image(CGImage*, CGColorSpace*, >> unsigned int, double) >> 34 QuartzCore 3895.0 CA::Render::copy_image(CGImage*, CGColorSpace*, >> unsigned int, double, double) >> 33 QuartzCore 3895.0 CA::Render::(anonymous >> namespace)::create_image_by_rendering(CGImage*, CGColorSpace*, unsigned int, >> double, CA::Render::ImageCopyType) >> >> Are these functions the culprits? How can I make them get executed in the >> background? >> >> >> All insights will be highly appreciated. >> >> Best regards, Gabriel >> >> ___ >> >> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) >> >> Please do not post admin requests or moderator comments to the list. >> Contact the moderators at cocoa-dev-admins(at)lists.apple.com >> >> Help/Unsubscribe/Update your Subscription: >> https://lists.apple.com/mailman/options/cocoa-dev/zav%40mac.com >> >> This email sent to z...@mac.com > > ___ > > Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) > > Please do not post admin requests or moderator comments to the list. > Contact the moderators at cocoa-dev-admins(at)lists.apple.com > > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/cocoa-dev/zav%40mac.com > > This email sent to z...@mac.com ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to
Re: Concurrent loading of images ?
Care to post a video on a Google drive so that we can see it? One of my tricks (not just mine) is to have a 3 slots of for images, not just 2. When a new image loads, take the foreground one that is blended in to 100%, put an identical one ahead of it. Make the changes to the new and old images behind it, then hide that foreground image. You’re actually using a copy of the foreground image as a mask and you perform the swap behind it, then update the screen, then remove the top level one and refresh again. This is if I’m understanding what you’re going properly. I’d expect that Apple’s video system to actually handle this if it still triple buffers, but it’s been 25 years since I read the docs on the Mac’s video subsystem. In the mean time, add logging code that you can put breatpoints on and take a screen grab when you log. That should help. Cheers, Alex Zavatone > On May 12, 2020, at 3:27 PM, Gabriel Zachmann via Cocoa-dev > wrote: > > Thanks a million to everyone who has shared insights, hints, and advice on > this. > > I have restructured my code, so now I do the heavy lifting of loading images > in a serial dispatch queue. > However, there is still sometimes some stuttering visible in the animation of > the images. > Does anyone have an idea what might be causing it? > > Here is the current structure of my code, given in sort of a pseudo-code: > > -animateOneframe: > // essentially, this gets called when the next image is to be displayed > current_image_ = prefetched_image_; // these are CGImageRef's > dispatch_async( prefetch_queue_, ^{ >[self loadNextImage]; > } ); > create a new CALayer, > assign the current_image_ as content, > create an animation for the layer, > add the layer to the layer hierarchy > > In -loadNextImage, I am doing all the heavy lifting of loading images > (and the not-so-heavy), such as: > prefetched_image_ = nil; > CGImageSourceGetStatus > CGImageSourceCopyPropertiesAtIndex > CGImageSourceCreateThumbnailAtIndex > imageByApplyingOrientation > createCGImage > prefetched_image_ = new image > > (I know there is some potential race condition here, but that is not of > concern to me right now.) > > Overall, I get the impression that it is "better" (less stuttering), > but sometimes there is still a stuttering in the animation when the app > makes a transition from one image to the next one. > > How could that be? > > Using Instruments, I can see this in the "heaviest stack trace" when CPU > usage is high in the main thread: > > 41 CoreFoundation 3897.0 __CFRunLoopDoObservers > 40 CoreFoundation 3897.0 > __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ > 39 QuartzCore 3896.0 > CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) > 38 QuartzCore 3896.0 CA::Transaction::commit() > 37 QuartzCore 3895.0 CA::Context::commit_transaction(CA::Transaction*, > double) > 36 QuartzCore 3895.0 CA::Layer::prepare_commit(CA::Transaction*) > 35 QuartzCore 3895.0 CA::Render::prepare_image(CGImage*, CGColorSpace*, > unsigned int, double) > 34 QuartzCore 3895.0 CA::Render::copy_image(CGImage*, CGColorSpace*, > unsigned int, double, double) > 33 QuartzCore 3895.0 CA::Render::(anonymous > namespace)::create_image_by_rendering(CGImage*, CGColorSpace*, unsigned int, > double, CA::Render::ImageCopyType) > > Are these functions the culprits? How can I make them get executed in the > background? > > > All insights will be highly appreciated. > > Best regards, Gabriel > > ___ > > Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) > > Please do not post admin requests or moderator comments to the list. > Contact the moderators at cocoa-dev-admins(at)lists.apple.com > > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/cocoa-dev/zav%40mac.com > > This email sent to z...@mac.com ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
Thanks a million to everyone who has shared insights, hints, and advice on this. I have restructured my code, so now I do the heavy lifting of loading images in a serial dispatch queue. However, there is still sometimes some stuttering visible in the animation of the images. Does anyone have an idea what might be causing it? Here is the current structure of my code, given in sort of a pseudo-code: -animateOneframe: // essentially, this gets called when the next image is to be displayed current_image_ = prefetched_image_; // these are CGImageRef's dispatch_async( prefetch_queue_, ^{ [self loadNextImage]; } ); create a new CALayer, assign the current_image_ as content, create an animation for the layer, add the layer to the layer hierarchy In -loadNextImage, I am doing all the heavy lifting of loading images (and the not-so-heavy), such as: prefetched_image_ = nil; CGImageSourceGetStatus CGImageSourceCopyPropertiesAtIndex CGImageSourceCreateThumbnailAtIndex imageByApplyingOrientation createCGImage prefetched_image_ = new image (I know there is some potential race condition here, but that is not of concern to me right now.) Overall, I get the impression that it is "better" (less stuttering), but sometimes there is still a stuttering in the animation when the app makes a transition from one image to the next one. How could that be? Using Instruments, I can see this in the "heaviest stack trace" when CPU usage is high in the main thread: 41 CoreFoundation 3897.0 __CFRunLoopDoObservers 40 CoreFoundation 3897.0 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ 39 QuartzCore 3896.0 CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) 38 QuartzCore 3896.0 CA::Transaction::commit() 37 QuartzCore 3895.0 CA::Context::commit_transaction(CA::Transaction*, double) 36 QuartzCore 3895.0 CA::Layer::prepare_commit(CA::Transaction*) 35 QuartzCore 3895.0 CA::Render::prepare_image(CGImage*, CGColorSpace*, unsigned int, double) 34 QuartzCore 3895.0 CA::Render::copy_image(CGImage*, CGColorSpace*, unsigned int, double, double) 33 QuartzCore 3895.0 CA::Render::(anonymous namespace)::create_image_by_rendering(CGImage*, CGColorSpace*, unsigned int, double, CA::Render::ImageCopyType) Are these functions the culprits? How can I make them get executed in the background? All insights will be highly appreciated. Best regards, Gabriel ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> On May 8, 2020, at 2:53 PM, Gabriel Zachmann wrote: > > But in my case, I really have just one task, so the queue would - at most - > contain one task at a time. You have to consider the case where the user is flipping through images faster than you can load them. In that case you do get multiple tasks piling up, or else you have to be able to abort the current task. I don't think you can abort a CoreGraphics call, though, so the best you could do is check for an abort in between two calls. —Jens ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
The last time I used layers to draw images it made a HUGE difference if the image was pixel perfect matching the size of the layer. If the image needed scaling, it was quite slow (I had really tiny images, but a lot of them). g > Am 9. May 2020 um 19:16 schrieb Steve Mills via Cocoa-dev > : > >> On May 9, 2020, at 12:13, Gabriel Zachmann via Cocoa-dev >> wrote: >> >> Would that really make the background (worker) thread execute all that >> internal copying/decoding of images in the *background* thread? >> >> I am asking because, currently, all this stuff gets executed in the main >> thread invoked by some observer. >> And, after all, even a background thread eventually has to put the new image >> in the layer hierarchy, which, I fear, will cause the heavy lifting to be >> done by the main thread, again. > > The point is, yes, the worker thread would be handling the image manipulation > to resize it to something that lets the main drawing thread work more > efficiently. > > Steve via iPad > > ___ > > Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) > > Please do not post admin requests or moderator comments to the list. > Contact the moderators at cocoa-dev-admins(at)lists.apple.com > > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/cocoa-dev/georg.seifert%40gmx.de > > This email sent to georg.seif...@gmx.de ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> On May 9, 2020, at 07:41, Gabriel Zachmann wrote: > > >> Also, if you’re already getting a CGImageRef using >> CGImageSourceCreateImageAtIndex, why not just set imgLayer.contents to the >> CGImageRef? > > sorry, my previous response regarding this was incomplete. What I am doing is > this, in order to get the EXIF orientation right: > > CIImage * image = [CIImage imageWithCGImage: imageRef]; > CIImage * orientedimage = [image imageByApplyingOrientation: > (CGImagePropertyOrientation) img_orientation]; > NSCIImageRep * nsimgrep = [NSCIImageRep imageRepWithCIImage: > orientedimage]; > NSImage * nsImage = [[NSImage alloc] initWithSize: nsimgrep.size]; > [nsImage addRepresentation: nsimgrep]; > CALayer * imgLayer= [CALayer layer]; > imgLayer.contents = nsImage; > > Still, is there a better way? > > Best regards, Gabriel I’m not at my computer now, but if you load the image using the thumbnail option it will give you a properly oriented image. I’ll check the specific options when I get home and can look at the code. If you’re using CIImage anyway, you can render it back to a CGImageRef with a bitmap context, and that can be done in a separate thread as well. Then you have a rendered bitmap ready to assign to your CALayer contents property. Jim Crate ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> On May 9, 2020, at 12:13, Gabriel Zachmann via Cocoa-dev > wrote: > > Would that really make the background (worker) thread execute all that > internal copying/decoding of images in the *background* thread? > > I am asking because, currently, all this stuff gets executed in the main > thread invoked by some observer. > And, after all, even a background thread eventually has to put the new image > in the layer hierarchy, which, I fear, will cause the heavy lifting to be > done by the main thread, again. The point is, yes, the worker thread would be handling the image manipulation to resize it to something that lets the main drawing thread work more efficiently. Steve via iPad ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> Time to learn some more about the frameworks you’re using then :) :-) > People have long dealt with this on iOS by doing tricks like first drawing > that image to a 1x1 bitmap on a worker thread before sending it on to the UI. Would that really make the background (worker) thread execute all that internal copying/decoding of images in the *background* thread? I am asking because, currently, all this stuff gets executed in the main thread invoked by some observer. And, after all, even a background thread eventually has to put the new image in the layer hierarchy, which, I fear, will cause the heavy lifting to be done by the main thread, again. Can you point me to some resources ? or examples that have solved this issue? Best regards, Gabriel > You have to do something along these lines (as far as I’m aware) to prompt > the first decode of the image to happen. After that, drawing it will be much > faster. > > Mike. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> On May 9, 2020, at 08:51, Gabriel Zachmann via Cocoa-dev > wrote: > > >> >> >> Try Instruments. Apple have written a measuring tool for a reason :) > > Thanks for the hint. > > I've done that. > In the Heaviest Stack Trace, I am seeing functions like > CA::Transcation::commit() > CA::Render::copy_image(..) > CI::recursive_tile(..) > etc If an image is huge and/or highres, it’s naturally going to take more time to render. I’d experiment and see if pre-sizing images before passing them onto the layer will be more efficient. Probably not, but it seems like some parts of the various Mac image frameworks do a better job of scaling than others. Steve via iPad ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> > Try Instruments. Apple have written a measuring tool for a reason :) Thanks for the hint. I've done that. In the Heaviest Stack Trace, I am seeing functions like CA::Transcation::commit() CA::Render::copy_image(..) CI::recursive_tile(..) etc None of these functions seems to get invoked (indirectly) by any of my code. Instead, they all seem to be called (indirectly) by _CFRunLoopDoObservers (in the main thread). So, I feel a bit stumped. What can I do? It seems that somehow I need to make all this stuff happen in the background - but how? ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
Have you profiled this? The first thing I would to is run that in Instruments. Georg > Am 9. May 2020 um 14:44 schrieb Gabriel Zachmann via Cocoa-dev > : > > Again, thanks a lot for all the helpful hints. > > Before restructuring my code, I did a few timings, using a set of test images > ranging in size from 30 through 300 MB. > I used mach_absolute_time() for this experiment. > And now, I am confused. > > These are the execution times I have found for some of the methods that I > invoke in the process of loading and displaying the next image: > > CGImageSourceCreateWithURL: 0.4-1.4 millisec > CGImageSourceGetStatus: 10-600 microsec > CGImageSourceCopyPropertiesAtIndex: 0.8-9 millisec > CGImageSourceCreateImageAtIndex:15 microsec > convertToNSImage (*): 25 microsec > imgLayer.contents = nsimage:1-5 microsec > removeFromSuperlayer: 0.1 microsec > addSublayer:5-10microsec > > (*): this is a wrapper method of mine that does a few calls to > CIImage/NSImage/NSCIImageRep methods. > > Overall, none of the methods I invoke seems to incur a long execution time. > Yet, there is a noticeable lag when my app switches from one image to the > next one. > I can tell because all layers have an animation assigned. > Sometimes , there is even a stutter in the animation itself. > > But it doesn't seem like it makes sense at this point to load images in a > concurrent/background dispatch queue, does it? > > So, I am confused: where is the lag coming from? > > Any ideas how I might be able to prevent the lag/stutter when loading and > switching to big images? > > > Best, G. > > ___ > > Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) > > Please do not post admin requests or moderator comments to the list. > Contact the moderators at cocoa-dev-admins(at)lists.apple.com > > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/cocoa-dev/georg.seifert%40gmx.de > > This email sent to georg.seif...@gmx.de ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
Again, thanks a lot for all the helpful hints. Before restructuring my code, I did a few timings, using a set of test images ranging in size from 30 through 300 MB. I used mach_absolute_time() for this experiment. And now, I am confused. These are the execution times I have found for some of the methods that I invoke in the process of loading and displaying the next image: CGImageSourceCreateWithURL: 0.4-1.4 millisec CGImageSourceGetStatus: 10-600 microsec CGImageSourceCopyPropertiesAtIndex: 0.8-9 millisec CGImageSourceCreateImageAtIndex:15 microsec convertToNSImage (*): 25 microsec imgLayer.contents = nsimage:1-5 microsec removeFromSuperlayer: 0.1 microsec addSublayer:5-10microsec (*): this is a wrapper method of mine that does a few calls to CIImage/NSImage/NSCIImageRep methods. Overall, none of the methods I invoke seems to incur a long execution time. Yet, there is a noticeable lag when my app switches from one image to the next one. I can tell because all layers have an animation assigned. Sometimes , there is even a stutter in the animation itself. But it doesn't seem like it makes sense at this point to load images in a concurrent/background dispatch queue, does it? So, I am confused: where is the lag coming from? Any ideas how I might be able to prevent the lag/stutter when loading and switching to big images? Best, G. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> Also, if you’re already getting a CGImageRef using > CGImageSourceCreateImageAtIndex, why not just set imgLayer.contents to the > CGImageRef? sorry, my previous response regarding this was incomplete. What I am doing is this, in order to get the EXIF orientation right: CIImage * image = [CIImage imageWithCGImage: imageRef]; CIImage * orientedimage = [image imageByApplyingOrientation: (CGImagePropertyOrientation) img_orientation]; NSCIImageRep * nsimgrep = [NSCIImageRep imageRepWithCIImage: orientedimage]; NSImage * nsImage = [[NSImage alloc] initWithSize: nsimgrep.size]; [nsImage addRepresentation: nsimgrep]; CALayer * imgLayer= [CALayer layer]; imgLayer.contents = nsImage; Still, is there a better way? Best regards, Gabriel ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> > Also, if you’re already getting a CGImageRef using > CGImageSourceCreateImageAtIndex, why not just set imgLayer.contents to the > CGImageRef? Good point . What I am doing right now is: NSImage * nsimage = [self convertToNSImage: img withOrientation: img_orientation]; CALayer * imgLayer= [CALayer layer]; imgLayer.contents = nsimage; The reason for that is that otherwise (IIRC) the EXIF orientation flags would not be heeded correctly by the CALayer. Is there a better way to achieve this? Best, G. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> I would add, that for a long running process, open ended work, or task, I > would favor a thread. But for short and finite items I would favor > GCD/NSOperationQueue. > > Are you going to only load one image, the next image, in this concurrent > loading scenario? Or, will you be loading many images and caching them? No, just one (next) image. That will then get displayed about a minute later, at which point the image after that should get prefetched. > > I would imaging looking one or two ahead would be the choice. Yes, I am planning to look ahead just one image. That's why I thought a whole queue might be overdoing it for just one task that takes usually just a few milliseconds, and occasionally 1-2 seconds. But if you say that for such one-off tasks, an NSOperationQueue is better, I'll go with that approach. And thanks a lot to everybody for sharing their insights and hints. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
On May 8, 2020, at 6:00 PM, Gabriel Zachmann via Cocoa-dev wrote: > >> Sure. Just be aware that if you're using NSImage, simply loading an NSImage >> does not rasterize it; the class tries to be 'lazy' about doing work. So >> your background task should explicitly render it, e.g. into an >> NSBitmapImageRep. > > I am using CGImageSourceCreateImageAtIndex and related functions. > But I am still unclear which function actually takes the time. > Maybe it is only when I create the CALayer like this? > > CALayer * imgLayer= [CALayer layer]; > imgLayer.contents = nsimage; Reading a 50MB image will definitely take some time, so preloading the image will definitely help. I’ve usually used an NSOperationQueue but my apps working with images can sometimes be loading hundreds of images and NSOperationQueue has an option to limit the number of operations run concurrently. Since you’ll only be loading the next image then a single GCD dispatch would work just as well. Also, if you’re already getting a CGImageRef using CGImageSourceCreateImageAtIndex, why not just set imgLayer.contents to the CGImageRef? Jim Crate ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
Using a queue is part of GCD. You should probably not use the main queue since that is analogous to the main thread and the main thread is meant for updating the UI. The good thing here is that you can sort of preload the next image in a queue after your last one has displayed. With a dispatchQueue, the idea here is that you have lots of tasks that you want to get done and you want the previous task to complete, then start the next one and so on and so on. You probably don’t need to do that for this application. If I were doing this in Objective-C, I’d fire off a “preload” on an async dispatch to a block. Something like this. // create a queue to load the image dispatch_group_t d_group = dispatch_group_create(); dispatch_queue_t bg_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_async(d_group, bg_queue, ^{ NSLog(@“preloading"); Do that image loading here }); If you did want to do something on the main queue, you can do it like this. dispatch_async(dispatch_get_main_queue(), ^{ Do your main thread updates here } If you want to use a serial queue that doesn’t block the main thread you can do it like this. // Dispatch the rest of session setup to the sessionQueue so that the main queue isn't blocked. dispatch_queue_t sessionQueue = dispatch_queue_create("session queue", DISPATCH_QUEUE_SERIAL); [self setSessionQueue:sessionQueue]; dispatch_async(sessionQueue, ^{ Do stuff here, but you want to read up on dipatch queues to see the best approach. } There’s lots of fun that you can have using these queues and GCD. The trick is finding the approaches that suit your needs. Hope these help. > On May 8, 2020, at 4:53 PM, Gabriel Zachmann via Cocoa-dev > wrote: > >> I second the use of GCD. Its also considerably simpler than NSThread, >> NSOperationQueue/NSOperation et al. This is the kind of operation that GCD >> was invented for. > > Thanks a lot for your response(s). > > To me a queue suggests that you have lots and lots of tasks arriving from the > producer , which you need to buffer in queue, so that the consumer can work > on it one task at a time. > > But in my case, I really have just one task, so the queue would - at most - > contain one task at a time. > So, why not start the task right away using NSThread or NSOperation? > > > ___ > > Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) > > Please do not post admin requests or moderator comments to the list. > Contact the moderators at cocoa-dev-admins(at)lists.apple.com > > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/cocoa-dev/zav%40mac.com > > This email sent to z...@mac.com ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> On May 8, 2020, at 15:13, Rob Petrovec via Cocoa-dev > wrote: > > > >>> On May 8, 2020, at 12:19 PM, Jens Alfke via Cocoa-dev >>> wrote: >>> >>> >>> On May 8, 2020, at 9:53 AM, Gabriel Zachmann via Cocoa-dev wrote: >>> >>> So, I was thinking, maybe it helps to load the next image concurrently, >>> while the current one is still being displayed. >> >> Sure. Just be aware that if you're using NSImage, simply loading an NSImage >> does not rasterize it; the class tries to be 'lazy' about doing work. So >> your background task should explicitly render it, e.g. into an >> NSBitmapImageRep. >> >>> I also read about the GCD's dispatch queues, but it seems to me that this >>> would not be the suitable approach since I always only have one task >>> running concurrently to the main thread. >> >> Why not? Dispatch queues are always available. (The main thread is simply a >> special queue.) You can run the background task by creating a single >> dispatch queue and then using dispatch_async to call a block that does the >> work. The end of the block would call dispatch_async back to the main queue >> and pass the image as a parameter. >I second the use of GCD. Its also considerably simpler than NSThread, > NSOperationQueue/NSOperation et al. This is the kind of operation that GCD > was invented for. I would add, that for a long running process, open ended work, or task, I would favor a thread. But for short and finite items I would favor GCD/NSOperationQueue. Are you going to only load one image, the next image, in this concurrent loading scenario? Or, will you be loading many images and caching them? I would imaging looking one or two ahead would be the choice. I’m just trying to understand the need/use case. If there’s lots of overhead that can be reduced to a one time effort than maybe a thread is better. If not maybe a one-off throw-it-in-a-queue and be done with it approach is better? Sandor > > —Rob > > > ___ > > Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) > > Please do not post admin requests or moderator comments to the list. > Contact the moderators at cocoa-dev-admins(at)lists.apple.com > > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/cocoa-dev/admin.szatmari.net%40gmail.com > > This email sent to admin.szatmari@gmail.com ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> Sure. Just be aware that if you're using NSImage, simply loading an NSImage > does not rasterize it; the class tries to be 'lazy' about doing work. So your > background task should explicitly render it, e.g. into an NSBitmapImageRep. I am using CGImageSourceCreateImageAtIndex and related functions. But I am still unclear which function actually takes the time. Maybe it is only when I create the CALayer like this? CALayer * imgLayer= [CALayer layer]; imgLayer.contents = nsimage; > > Why not? Dispatch queues are always available. (The main thread is simply a > special queue.) You can run the background task by creating a single dispatch > queue and then using dispatch_async to call a block that does the work. The > end of the block would call dispatch_async back to the main queue and pass > the image as a parameter. Could you give a few more specific hints? Best regards, Gabriel ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> I second the use of GCD. Its also considerably simpler than NSThread, > NSOperationQueue/NSOperation et al. This is the kind of operation that GCD > was invented for. Thanks a lot for your response(s). To me a queue suggests that you have lots and lots of tasks arriving from the producer , which you need to buffer in queue, so that the consumer can work on it one task at a time. But in my case, I really have just one task, so the queue would - at most - contain one task at a time. So, why not start the task right away using NSThread or NSOperation? ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images?
> I also read about the GCD's dispatch queues, but it seems to me that this would not be the suitable approach since I always only have one task running concurrently to the main thread. > > Why not? Dispatch queues are always available. (The main thread is simply > a special queue.) You can run the background task by creating a single > dispatch queue and then using dispatch_async to call a block that does the > work. The end of the block would call dispatch_async back to the main queue > and pass the image as a parameter. I could not agree more with Jens. Great Central Dispatch has been a big boon. Before GCD, I would not touch multithreaded code with a ten-foot pole. Now I use it everyday and I can increase responsiveness as never before. I would definitely take a look at it. You can load images with a background thread and then when the loading is done you can dispatch it to the main queue for display. It has never been so easy to do that. João > > ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> On May 8, 2020, at 12:19 PM, Jens Alfke via Cocoa-dev > wrote: > > > >> On May 8, 2020, at 9:53 AM, Gabriel Zachmann via Cocoa-dev >> wrote: >> >> So, I was thinking, maybe it helps to load the next image concurrently, >> while the current one is still being displayed. > > Sure. Just be aware that if you're using NSImage, simply loading an NSImage > does not rasterize it; the class tries to be 'lazy' about doing work. So your > background task should explicitly render it, e.g. into an NSBitmapImageRep. > >> I also read about the GCD's dispatch queues, but it seems to me that this >> would not be the suitable approach since I always only have one task running >> concurrently to the main thread. > > Why not? Dispatch queues are always available. (The main thread is simply a > special queue.) You can run the background task by creating a single dispatch > queue and then using dispatch_async to call a block that does the work. The > end of the block would call dispatch_async back to the main queue and pass > the image as a parameter. I second the use of GCD. Its also considerably simpler than NSThread, NSOperationQueue/NSOperation et al. This is the kind of operation that GCD was invented for. —Rob ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
> On May 8, 2020, at 9:53 AM, Gabriel Zachmann via Cocoa-dev > wrote: > > So, I was thinking, maybe it helps to load the next image concurrently, while > the current one is still being displayed. Sure. Just be aware that if you're using NSImage, simply loading an NSImage does not rasterize it; the class tries to be 'lazy' about doing work. So your background task should explicitly render it, e.g. into an NSBitmapImageRep. > I also read about the GCD's dispatch queues, but it seems to me that this > would not be the suitable approach since I always only have one task running > concurrently to the main thread. Why not? Dispatch queues are always available. (The main thread is simply a special queue.) You can run the background task by creating a single dispatch queue and then using dispatch_async to call a block that does the work. The end of the block would call dispatch_async back to the main queue and pass the image as a parameter. (Or you could use NSOperationQueue and NSOperation, although I've always found those classes unnecessarily complicated for simple tasks.) —Jens ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
Does this seem related? https://9to5mac.com/2020/04/28/new-bug-found-in-macos-can-quickly-fill-up-storage-when-importing-photos-with-image-capture/ "The problem discovered by the NeoFinder team is that the Mac adds 1.5MB of empty data to each converted photo, making the imported files larger for no reason. By looking inside these photos through a Hex-Editor, you can find a section full of zeroes, which results in unnecessarily larger files.” I know you’re not capturing images, just loading them, but It’s pretty suspiciously similar. > On May 8, 2020, at 11:53 AM, Gabriel Zachmann via Cocoa-dev > wrote: > > Sometimes, when it switches from one image to the next, there is a noticeable > lag when the file size of the next image is very big, say, 50 MB or more. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
Thanks for the question: MacOS. > > iOS or MacOS? ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Concurrent loading of images ?
iOS or MacOS? > On May 8, 2020, at 11:53 AM, Gabriel Zachmann via Cocoa-dev > wrote: > > I have kind of a slide-show app. > > Sometimes, when it switches from one image to the next, there is a noticeable > lag when the file size of the next image is very big, say, 50 MB or more. > Sometimes, it seems that loading the image takes 1-2 seconds. > > So, I was thinking, maybe it helps to load the next image concurrently, while > the current one is still being displayed. > > My question is: should I spawn a thread (using NSThreads' > detachNewThreadSelector), load the image in that thread, then exit the > thread? (no run loop) > > Or should I use NSObject's performSelectorInBackground ? > > I also read about the GCD's dispatch queues, but it seems to me that this > would not be the suitable approach since I always only have one task running > concurrently to the main thread. > > What do you think? > > Best regards, Gabriel > > ___ > > Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) > > Please do not post admin requests or moderator comments to the list. > Contact the moderators at cocoa-dev-admins(at)lists.apple.com > > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/cocoa-dev/zav%40mac.com > > This email sent to z...@mac.com ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com