2012-06-25 13 views
7

Problema: ho un'immagine TIFF multipagina (generata con tiffutil) che contiene la stessa immagine a più dimensioni di pixel da 256x128 px fino a 4096x2048 px. Voglio visualizzare questa immagine in un CALayer in modo che il sistema scelga automaticamente la migliore rappresentazione dell'immagine a seconda delle dimensioni del livello. Al momento, il layer utilizza sempre la rappresentazione 256x128 dell'immagine, indipendentemente dalle sue dimensioni.Scaling automatico di TIFF multipagina NSImage in un CALayer

Ecco quello che faccio: ho caricare l'immagine con

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

Logging l'oggetto image conferma che contiene rappresentazioni multiple con diverse dimensioni dei pixel, ma tutte le rappresentazioni sono le stesse dimensioni in punti (256x128). AFAIK è così che Apple consiglia di costruire immagini multi-risoluzione.

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" 
)> 

poi assegniamo l'istanza NSImage direttamente alla proprietà del livello contents:

self.layerView.layer.contents = image; 

Come accennato, il risultato è che lo strato utilizza la prima rappresentazione (256x128 px) per visualizzare l'immagine, indipendentemente della dimensione del livello in punti o pixel.

Quando assegno la stessa immagine a NSImageView, funziona come previsto. La vista dell'immagine seleziona in modo trasparente la migliore rappresentazione dell'immagine in base alla sua dimensione. Mi aspetto che lo CALayer funzioni allo stesso modo, ma a quanto pare non è così. Qualcuno può confermare che CALayer non supporta questa selezione automatica o sto facendo qualcosa di sbagliato?

(Si noti che questa domanda non è direttamente correlata alla grafica HiDPI/Retina. Infatti, se si sposta il livello su un display in modalità HiDPI, rende un po 'più nitido, indicando che ora utilizza la seconda rappresentazione bitmap (512x256 px) per il rendering Questo suggerisce che l'automatismo per selezionare una risoluzione più alta su un display HiDPI funziona mentre la selezione fondamentale della migliore rappresentazione bitmap fallisce.)

+0

Solo un'idea, prova a rimuovere '.tiff' in' @ "map-multipagina.tiff" '. Inoltre, assicurati che 'layerContentsRedrawPolicy' non sia' Never'. O forse il 'contentsGravity' di layer influenza il modo in cui il suo contenuto viene aggiornato? – Stream

+1

@ Stream: grazie mille per i suggerimenti. No, rimuovere l'estensione del file non ha alcun effetto, né giocare con 'layerContentsRedrawPolicy' o' contentsGravity'. Avendo visto la sessione 245 del WWDC 2012 di ieri sera, sospetto che la risposta alla mia domanda sia che non funziona in questo modo. Sembra che i 'contenuti' di' CALayer' non "sappiano" nulla sulla dimensione effettiva del livello in punti/pixel e quindi non possono selezionare una rappresentazione bitmap basata su questa informazione. –

+0

Ha senso! '- [Contenuto CALayer]' è solo un bitmap, troppo "stupido" per sapere qualcosa sulla sua fonte. È 'CALayer' che si basa sulla rappresentazione tramite' drawRect: inContext: '. Quindi, quando si imposta 'contents' direttamente, la sua dimensione deve essere basata su' - [NSImage size] '. – Stream

risposta

2

Sembra che il metodo AppKit -[CALayer setContents:] scelga una rappresentazione bitmap di corrispondenza di dimensioni -[contents size] se l'oggetto contents è NSImage. Quindi la bitmap selezionata viene utilizzata fino a quando non viene richiamato -[CALayer setContents:].