How to properly display small, high resolution images?

  • Hey all - I'm trying to display a bunch of very small high resolution images, and I'm confused.  They render perfectly well (full screen) in Preview or iPhoto, and yet when I do the standard

      NSImage* tempImage = [[NSImage alloc] initWithContentsOfFile:filename];
      NSSize newSize;

    //snip - just sets the dimensions of newSize properly
      NSImage *scaleImage = [[NSImage alloc] initWithSize:newSize];
      [scaleImage lockFocus];
      [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
      [tempImage drawInRect:NSMakeRect(0, 0, newSize.width, newSize.height) fromRect:NSZeroRect operation:NSCompositeSourceOver  fraction:1.0];
      [scaleImage unlockFocus];
      [scaleImage drawInRect:NSMakeRect(screenSize.width/2-newSize.width/2, screenSize.height/2-newSize.height/2, newSize.width, newSize.height) fromRect:NSZeroRect operation:NSCompositeSourceOver  fraction:1.0];

    , everything ends up horrendously pixellated.  The "actual" size of these images is tiny (like 150x150) and yet, as I said, they render in full screen perfectly well.

    I also tried "NSImageInterpolationNone" on a lark - no luck.  Can anyone give me a hint?

          ____________________________________________________________________________________
    Looking for last minute shopping deals?
    Find them fast with Yahoo! Search.  http://tools.search.yahoo.com/newsearch/category.php?category=shopping
  • On Dec 15, 2007, at 1:33 PM, that guy wrote:

    > Hey all - I'm trying to display a bunch of very small high
    > resolution images, and I'm confused.  They render perfectly well
    > (full screen) in Preview or iPhoto, and yet when I do the standard
    >
    > NSImage* tempImage = [[NSImage alloc]
    > initWithContentsOfFile:filename];
    > NSSize newSize;
    >
    > //snip - just sets the dimensions of newSize properly
    > NSImage *scaleImage = [[NSImage alloc] initWithSize:newSize];
    > [scaleImage lockFocus];
    > [[NSGraphicsContext currentContext]
    > setImageInterpolation:NSImageInterpolationHigh];
    > [tempImage drawInRect:NSMakeRect(0, 0, newSize.width,
    > newSize.height) fromRect:NSZeroRect operation:NSCompositeSourceOver
    > fraction:1.0];
    > [scaleImage unlockFocus];
    > [scaleImage drawInRect:NSMakeRect(screenSize.width/2-newSize.width/
    > 2, screenSize.height/2-newSize.height/2, newSize.width,
    > newSize.height) fromRect:NSZeroRect operation:NSCompositeSourceOver
    > fraction:1.0];
    >
    > , everything ends up horrendously pixellated.  The "actual" size of
    > these images is tiny (like 150x150) and yet, as I said, they render
    > in full screen perfectly well.
    >
    > I also tried "NSImageInterpolationNone" on a lark - no luck.  Can
    > anyone give me a hint?
    >

    The problem is that with high resolution images, NSImage's size will
    return the size in points (72/inch), which is where I'm guessing you
    get "newSize" from.  Since you draw the image in that lower resolution
    value, and then draw that expanded, you get pixelization.

    So, for example (to make the numbers easy), if it is 720dpi 1" x 1"
    image (i.e. 720px x 720px), [tempImage size] will return (72,72) - you
    make a new image at that size, draw the 720px image into that 72px
    size, and then scale the 72px size up.

    Instead of making a new image, you could start by just using the
    "tempImage" and draw that (and if you need to make changes to it,
    you'll need to iterate through the NSImageRep's inside NSImage to find
    the highest resolution one and base your tempImage's size based on that)

    Glenn Andreas                      <gandreas...>
      <http://www.gandreas.com/> wicked fun!
    quadrium | prime : build, mutate, evolve, animate : the next
    generation of fractal art
  • Perhaps try using core graphics:

    CGRect drawingRect;
    NSImage *yourImage;

    // Get the CGImageRef from the image....
    NSBitmapImageRep *rep = (NSBitmapImageRep *)[yourImage
    bestRepresentationForDevice: nil]; // is there a better way to get the
    nsbitmapimagerep out of an nsimage?
    CGImageRef cgImage = [rep CGImage];

    // Draw the image
    CGContextDrawImage ([[NSGraphicsContext currentContext] graphicsPort],
    drawingRect, cgImage);

    CoreGraphics automatically scales the image to the specified size
    (smoothly).

    Cheers
    Nik

    On 16/12/2007, at 6:33 AM, that guy wrote:

    > Hey all - I'm trying to display a bunch of very small high
    > resolution images, and I'm confused.  They render perfectly well
    > (full screen) in Preview or iPhoto, and yet when I do the standard
    >
    > NSImage* tempImage = [[NSImage alloc]
    > initWithContentsOfFile:filename];
    > NSSize newSize;
    >
    > //snip - just sets the dimensions of newSize properly
    > NSImage *scaleImage = [[NSImage alloc] initWithSize:newSize];
    > [scaleImage lockFocus];
    > [[NSGraphicsContext currentContext]
    > setImageInterpolation:NSImageInterpolationHigh];
    > [tempImage drawInRect:NSMakeRect(0, 0, newSize.width,
    > newSize.height) fromRect:NSZeroRect operation:NSCompositeSourceOver
    > fraction:1.0];
    > [scaleImage unlockFocus];
    > [scaleImage drawInRect:NSMakeRect(screenSize.width/2-newSize.width/
    > 2, screenSize.height/2-newSize.height/2, newSize.width,
    > newSize.height) fromRect:NSZeroRect operation:NSCompositeSourceOver
    > fraction:1.0];
    >
    > , everything ends up horrendously pixellated.  The "actual" size of
    > these images is tiny (like 150x150) and yet, as I said, they render
    > in full screen perfectly well.
    >
    > I also tried "NSImageInterpolationNone" on a lark - no luck.  Can
    > anyone give me a hint?
  • I'm not sure what the purpose of the code with the comment 'just sets
    the dimensions of newSize properly' is.

    The 'tempImage' had all the data from the original file.  When you
    called lockFocus and drew into the new image, that data was thrown
    away - all that was left was a bitmap at screen resolution with size
    newSize.  -lockFocus should be considered a somewhat expensive thing
    to do.  It's making a new bitmap memory buffer, drawing, and setting
    up a context for you to draw into.  Sometimes this is genuinely what
    you need, but if not, it's churn.  It also trashes CG-level caches.

    As Glenn suggested, it looks like you probably wanted to draw directly
    with the 'templmage' here.  The draw methods take a destination rect,
    and the image will be scaled to fill it with whatever quality is
    available.  A caveat: if your image is drawn at _multiple_ resolutions
    to the screen, you need to advise NSImage not to optimize itself to
    the first context it's drawn into and throw away extra data.  This is
    done by calling [image setDataRetained:YES].  Then the image may still
    create an optimized cache when it is drawn, but all the original data
    will be around if it's drawn to a context that doesn't match the
    original destination. If the image is infrequently drawn, for example
    if it's _only_ redrawn once per different resolution at which it's
    rendered, you may want to ask it not to create the cache as well,
    which is done with [image setCacheMode:NSImageCacheNever].

    -Ken

    On Dec 15, 2007 11:33 AM, that guy <drrelyea...> wrote:
    > Hey all - I'm trying to display a bunch of very small high resolution images, and I'm confused.  They render perfectly well (full screen) in Preview or iPhoto, and yet when I do the standard
    >
    > NSImage* tempImage = [[NSImage alloc] initWithContentsOfFile:filename];
    > NSSize newSize;
    >
    > //snip - just sets the dimensions of newSize properly
    > NSImage *scaleImage = [[NSImage alloc] initWithSize:newSize];
    > [scaleImage lockFocus];
    > [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
    > [tempImage drawInRect:NSMakeRect(0, 0, newSize.width, newSize.height) fromRect:NSZeroRect operation:NSCompositeSourceOver  fraction:1.0];
    > [scaleImage unlockFocus];
    > [scaleImage drawInRect:NSMakeRect(screenSize.width/2-newSize.width/2, screenSize.height/2-newSize.height/2, newSize.width, newSize.height) fromRect:NSZeroRect operation:NSCompositeSourceOver  fraction:1.0];
    >
    > , everything ends up horrendously pixellated.  The "actual" size of these images is tiny (like 150x150) and yet, as I said, they render in full screen perfectly well.
    >
    > I also tried "NSImageInterpolationNone" on a lark - no luck.  Can anyone give me a hint?
    >
previous month december 2007 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