+{NSImage imageNamed:fromBundle:]?

  • NSImage's +imageNamed: is documented as searching the named images
    cache, the apps main bundle, and then the AppKit framework bundle.
    Unfortunately, I've got code in a private framework that wants to get
    the image stored that framework (which isn't thus searched).

    Is there some way to add a framework to this search path?  (Which
    would be best, because it will allow any object, such as a button,
    that has an image name to automatically work correctly) Or at least a
    way to explicitly pass a bundle to search (via a hypothetical
    +imageNamed:fromBundle:).  The fall back, of course, is to get all the
    possible file extensions from NSImage and manually try each and every
    one of them, but I'd rather not have to duplicate this logic (plus
    this fails to support the generic button using a named image that
    resides in the private framework)...

    I suppose I could also, at startup, go through all the images in the
    framework, load them, and then do a "setName:" to get them in the
    cache (but this seems like it could impact program launch times)

    Glenn Andreas                      <gandreas...>
      <http://www.gandreas.com/> wicked fun!
    quadrium2 | build, mutate, evolve, animate  | images, textures,
    fractals, art
  • I don't know about extending the search list, but you can use
    NSBundle's -pathForImageResource: to implement

    + (NSImage *) imageNamed:(NSString *)name fromBundle:(NSBundle *)bundle
      {
        NSString *path = [bundle pathForImageResource:name];
        return path != nil ? [[[NSImage alloc]
    initWithContentsOfFile:path] autorelease] : nil;
      }

    -dave

    On 11-Jan-08, at 1:10 PM, glenn andreas wrote:

    > NSImage's +imageNamed: is documented as searching the named images
    > cache, the apps main bundle, and then the AppKit framework bundle.
    > Unfortunately, I've got code in a private framework that wants to
    > get the image stored that framework (which isn't thus searched).
    >
    > Is there some way to add a framework to this search path?  (Which
    > would be best, because it will allow any object, such as a button,
    > that has an image name to automatically work correctly) Or at least
    > a way to explicitly pass a bundle to search (via a hypothetical
    > +imageNamed:fromBundle:).  The fall back, of course, is to get all
    > the possible file extensions from NSImage and manually try each and
    > every one of them, but I'd rather not have to duplicate this logic
    > (plus this fails to support the generic button using a named image
    > that resides in the private framework)...
    >
    > I suppose I could also, at startup, go through all the images in the
    > framework, load them, and then do a "setName:" to get them in the
    > cache (but this seems like it could impact program launch times)
    >
    > Glenn Andreas                      <gandreas...>
    > <http://www.gandreas.com/> wicked fun!
    > quadrium2 | build, mutate, evolve, animate  | images, textures,
    > fractals, art
  • On Jan 11, 2008, at 2:10 PM, glenn andreas wrote:

    > NSImage's +imageNamed: is documented as searching the named images
    > cache, the apps main bundle, and then the AppKit framework bundle.
    > Unfortunately, I've got code in a private framework that wants to
    > get the image stored that framework (which isn't thus searched).
    >
    > Is there some way to add a framework to this search path?  (Which
    > would be best, because it will allow any object, such as a button,
    > that has an image name to automatically work correctly) Or at least
    > a way to explicitly pass a bundle to search (via a hypothetical
    > +imageNamed:fromBundle:).  The fall back, of course, is to get all
    > the possible file extensions from NSImage and manually try each and
    > every one of them, but I'd rather not have to duplicate this logic
    > (plus this fails to support the generic button using a named image
    > that resides in the private framework)...

    As others have pointed out, use NSBundle's pathForImageResource.  I
    created an image factory that knows how to scan multiple areas looking
    for images.

    > I suppose I could also, at startup, go through all the images in the
    > framework, load them, and then do a "setName:" to get them in the
    > cache (but this seems like it could impact program launch times)

    Well, that may not be bad since load times are often very, very low.
    It's probably the case where image data is not decoded until you're
    actually drawing things.

    For example, all my images are PDF (to support res-ind).  While my
    factory loads them on-demand (and not all at once), I did measure the
    total loading time over the lifetime of the app.  This was the time
    taken to actually alloc/init NSImage images and then call setName:.

    When the images were then _drawn_, that's where the bulk of the time
    was taken.  Maybe this is specific to PDF; I don't know.  For PDF the
    raw data is loaded, but not "decoded" until drawn; also at the time of
    drawing, that's where you end up with cached reps (e.g. a cached
    bitmapimagerep) that will ultimately speed up drawing for the 2nd,
    etc. times the image is drawn.

    ___________________________________________________________
    Ricky A. Sharp        mailto:<rsharp...>
    Instant Interactive(tm)  http://www.instantinteractive.com
  • On Jan 11, 2008, at 3:34 PM, Ricky Sharp wrote:

    >
    > On Jan 11, 2008, at 2:10 PM, glenn andreas wrote:
    >
    >> NSImage's +imageNamed: is documented as searching the named images
    >> cache, the apps main bundle, and then the AppKit framework bundle.
    >> Unfortunately, I've got code in a private framework that wants to
    >> get the image stored that framework (which isn't thus searched).
    >>
    >> Is there some way to add a framework to this search path?  (Which
    >> would be best, because it will allow any object, such as a button,
    >> that has an image name to automatically work correctly) Or at least
    >> a way to explicitly pass a bundle to search (via a hypothetical
    >> +imageNamed:fromBundle:).  The fall back, of course, is to get all
    >> the possible file extensions from NSImage and manually try each and
    >> every one of them, but I'd rather not have to duplicate this logic
    >> (plus this fails to support the generic button using a named image
    >> that resides in the private framework)...
    >
    > As others have pointed out, use NSBundle's pathForImageResource.  I
    > created an image factory that knows how to scan multiple areas
    > looking for images.

    I've added code to explicitly call that, which seems to work (for a
    limited use where I know that I'm going to need that image), but the
    more I look at it, the more I want a global version that will update
    the cache so that plain old +imageNamed: works correctly (since it
    seems silly to subclass everything with an image to not only have to
    look for the image in a loaded framework, but to also have to then end
    up hard coding the image name, since pretty much nothing with an image
    lets you access the name of the image).

    >
    >
    >> I suppose I could also, at startup, go through all the images in
    >> the framework, load them, and then do a "setName:" to get them in
    >> the cache (but this seems like it could impact program launch times)
    >
    >
    > Well, that may not be bad since load times are often very, very
    > low.  It's probably the case where image data is not decoded until
    > you're actually drawing things.
    >
    > For example, all my images are PDF (to support res-ind).  While my
    > factory loads them on-demand (and not all at once), I did measure
    > the total loading time over the lifetime of the app.  This was the
    > time taken to actually alloc/init NSImage images and then call
    > setName:.
    >
    > When the images were then _drawn_, that's where the bulk of the time
    > was taken.  Maybe this is specific to PDF; I don't know.  For PDF
    > the raw data is loaded, but not "decoded" until drawn; also at the
    > time of drawing, that's where you end up with cached reps (e.g. a
    > cached bitmapimagerep) that will ultimately speed up drawing for the
    > 2nd, etc. times the image is drawn.

    Yeah, I probably shouldn't be doing the premature optimization -
    there's about 70 or so images currently, so I figured it would be
    better to just try to load them at start up (most of them are png or
    tiff files):

    @interface NSBundle(NameCacheImages)
    - (void) cacheNamedImages;
    @end
    @implementation NSBundle(NameCacheImages)
    - (void) cacheNamedImages;
    {
        NSArray *types = [NSImage imageFileTypes];
        NSEnumerator *e = [types objectEnumerator];
        NSString *type;
        while ((type = [e nextObject]) != nil) {
    NSArray *files = [self pathsForResourcesOfType: type inDirectory: nil];
    NSEnumerator *e2 = [files objectEnumerator];
    NSString *path;
    while ((path = [e2 nextObject]) != nil) {
           NSString *name = [[path lastPathComponent]
    stringByDeletingPathExtension];
           NSImage *image = [NSImage imageNamed:name];
           if (!image) {
      NSImage *image = [[NSImage alloc]  initByReferencingFile:path];
      if (image) {
               [image setName: name];
      }
           }
    }
        }
    }
    @end

    The result was that it cruised through the 74 images in 0.084809
    seconds, so I think I can live with that...

    Glenn Andreas                      <gandreas...>
      <http://www.gandreas.com/> wicked fun!
    quadrium2 | build, mutate, evolve, animate  | images, textures,
    fractals, art
previous month january 2008 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today