Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic Scaling of Multipage TIFF NSImage in a CALayer

Problem: I have a multipage TIFF image (generated with tiffutil) that contains the same image at multiple pixel dimension from 256x128 px all the way up to 4096x2048 px. I want to display this image in a CALayer so that the system automatically chooses the best representation of the image depending on the layer's size. At the moment, the layer always uses the 256x128 representation of the image, regardless of its size.

Here's what I do: I load the image with

NSImage *image = [NSImage imageNamed:@"map-multipage.tiff"];

Logging the image object confirms that it contains multiple representations with different pixel sizes, but all representations are the same size in points (256x128). AFAIK this is how Apple recommends multi-resolution images to be constructed.

NSLog(@"%@", image);

<NSImage 0x100623060 Name=map-multipage Size={256, 128} Reps=(
    "NSBitmapImageRep 0x10064d330 Size={256, 128} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=256x128 Alpha=NO Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x10014fdb0",
    "NSBitmapImageRep 0x10064e1b0 Size={256, 128} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=512x256 Alpha=NO Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x10014fdb0",
    ...
    "NSBitmapImageRep 0x100530bd0 Size={256, 128} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=4096x2048 Alpha=NO Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x10014fdb0"
)>

I then assign the NSImage instance directly to the layer's contents property:

self.layerView.layer.contents = image;

As mentioned, the result is that the layer uses the first representation (256x128 px) to display the image, regardless of the layer's size in points or pixels.

When I assign the same image to an NSImageView, it works as expected. The image view transparently selects the best image representation depending on its size. I would expect that CALayer would work the same way but apparently this is not the case. Can anybody confirm that CALayer does not support this automatic selection or am I doing something wrong?

(Note that this question is not directly related to HiDPI/Retina graphics. In fact, if I move the layer to a display in HiDPI mode, it does render a little sharper, indicating that it now uses the second bitmap representation (512x256 px) for rendering. This suggests that the automatism to select a higher resolution on a HiDPI display works while the fundamental selection of the best bitmap representation fails.)

like image 940
Ole Begemann Avatar asked Jun 25 '12 11:06

Ole Begemann


1 Answers

It seems like the AppKit method -[CALayer setContents:] chooses a bitmap representation of size matching -[contents size] if contents object is NSImage. Then the selected bitmap is used as is until -[CALayer setContents:] is called once again.

like image 161
Vadim Avatar answered Nov 05 '22 22:11

Vadim