Cor ampla no Xamarin.iOS
Este artigo aborda cores amplas e como ela pode ser usada em um aplicativo Xamarin.iOS ou Xamarin.Mac.
O iOS 10 e o macOS Sierra aprimoram o suporte para formatos de pixel de longo alcance e espaços de cores de gama ampla em todo o sistema, incluindo estruturas como Core Graphics, Core Image, Metal e AVFoundation. O suporte para dispositivos com telas de cores largas é ainda mais facilitado fornecendo esse comportamento em toda a pilha de gráficos.
Catálogos de ativos
Suporte a cores amplas com catálogos de ativos
No iOS 10 e no macOS Sierra, a Apple expandiu os Catálogos de Ativos usados para incluir e categorizar o conteúdo de imagem estática no pacote do aplicativo para dar suporte a cores amplas.
O uso de Catálogos de Ativos oferece os seguintes benefícios para um aplicativo:
- Eles fornecem a melhor opção de implantação para ativos de imagem estática.
- Eles dão suporte à correção automática de cores.
- Eles dão suporte à otimização automática de formato de pixel.
- Eles dão suporte à Divisão de Aplicativos e ao Afinamento de Aplicativos, o que garante que apenas o conteúdo relevante seja entregue ao dispositivo do usuário final.
A Apple fez os seguintes aprimoramentos nos Catálogos de Ativos para suporte a cores amplas:
- Eles dão suporte ao conteúdo de origem de 16 bits (por canal de cor).
- Eles dão suporte à catalogação de conteúdo por gama de exibição. O conteúdo pode ser marcado para as gamas sRGB ou Display P3.
O desenvolvedor tem três opções para dar suporte a conteúdo de cores amplas em seus aplicativos:
- Não fazer nada – como o conteúdo de cores largas só deve ser usado em situações em que o aplicativo precisa exibir cores vívidas (em que aprimorarão a experiência do usuário), o conteúdo fora desse requisito deve ser deixado como está. Ele continuará sendo renderizado corretamente em todas as situações de hardware.
- Atualizar conteúdo existente para Exibir P3 – isso exige que o desenvolvedor substitua o conteúdo de imagem existente em seu Catálogo de Ativos por um novo arquivo atualizado no formato P3 e marque-o como tal no Editor de Ativos. No momento da compilação, uma imagem derivada sRGB será gerada a partir desses ativos.
- Fornecer conteúdo de ativo otimizado – nessa situação, o desenvolvedor fornecerá um sRGB de 8 bits e uma visão P3 de exibição de 16 bits de cada imagem no Catálogo de Ativos (marcado corretamente no editor de ativos).
Implantação do Catálogo de Ativos
O seguinte ocorrerá quando o desenvolvedor enviar um aplicativo para o App Store com Catálogos de Ativos que incluem conteúdo de imagem de cores amplas:
- Quando o aplicativo for implantado no usuário final, o App Slicing garantirá que apenas a variante de conteúdo apropriada seja entregue ao dispositivo do usuário.
- No dispositivo que não dá suporte a cores largas, não há nenhum custo de carga para incluir conteúdo de cores largas, pois ele nunca é enviado para o dispositivo.
NSImage
no macOS Sierra (e posterior) selecionará automaticamente a melhor representação de conteúdo para a exibição do hardware.- O conteúdo exibido será atualizado automaticamente quando ou se as características de exibição de hardware dos dispositivos forem alteradas.
Armazenamento do Catálogo de Ativos
O armazenamento do Catálogo de Ativos tem as seguintes propriedades e implicações para um aplicativo:
- No momento da compilação, a Apple tenta otimizar o armazenamento do conteúdo da imagem por meio de conversões de imagem de alta qualidade.
- 16 bits são usados por canal de cores para conteúdo de cores largas.
- A compactação de imagem dependente de conteúdo é usada para reduzir os tamanhos de conteúdo que podem ser entregues. Novas compactações "com perda" foram adicionadas para otimizar ainda mais os tamanhos de conteúdo.
Renderizando imagens Off-Screen no aplicativo
Com base no tipo de aplicativo que está sendo criado, ele pode permitir que o usuário inclua o conteúdo da imagem coletado da Internet ou crie conteúdo de imagem diretamente dentro do aplicativo (como um aplicativo de desenho de vetor, por exemplo).
Em ambos os casos, o aplicativo pode renderizar as imagens necessárias fora da tela em cores amplas usando recursos aprimorados adicionados ao iOS e ao macOS.
Desenhando cores largas no iOS
Antes de discutir como desenhar corretamente uma imagem colorida ampla no iOS 10, dê uma olhada no seguinte código de desenho comum do iOS:
public UIImage DrawWideColorImage ()
{
var size = new CGSize (250, 250);
UIGraphics.BeginImageContext (size);
...
UIGraphics.EndImageContext ();
return image = UIGraphics.GetImageFromCurrentImageContext ();
}
Há problemas com o código padrão que precisarão ser resolvidos antes que ele possa ser usado para desenhar uma imagem colorida ampla. O UIGraphics.BeginImageContext (size)
método usado para iniciar o desenho de imagem do iOS tem as seguintes limitações:
- Ele não pode criar contextos de imagem com mais de 8 bits por canal de cor.
- Ele não pode representar cores no Espaço de Cor sRGB de Intervalo Estendido.
- Ele não tem a capacidade de fornecer uma interface para criar contextos em um espaço de cor não sRGB devido às rotinas C de baixo nível que estão sendo chamadas em segundo plano.
Para lidar com essas limitações e desenhar uma imagem colorida ampla no iOS 10, use o seguinte código:
public UIImage DrawWideColorImage ()
{
var size = new CGSize (250, 250);
var render = new UIGraphicsImageRenderer (size);
var image = render.CreateImage ((UIGraphicsImageRendererContext context) => {
var bounds = context.Format.Bounds;
CGRect slice;
CGRect remainder;
bounds.Divide (bounds.Width / 2, CGRectEdge.MinXEdge, out slice, out remainder);
var redP3 = UIColor.FromDisplayP3 (1.0F, 0.0F, 0.0F, 1.0F);
redP3.SetColor ();
context.FillRect (slice);
var redRGB = UIColor.Red;
redRGB.SetColor ();
context.FillRect (remainder);
});
// Return results
return image;
}
A nova UIGraphicsImageRenderer
classe cria um novo contexto de imagem que é capaz de lidar com o Espaço de Cor sRGB de Intervalo Estendido e tem os seguintes recursos:
- Ela é totalmente gerenciada por cor por padrão.
- Ele dá suporte ao Espaço de Cor sRGB de Intervalo Estendido por padrão.
- Ele decide de forma inteligente se deve renderizar no espaço de cores sRGB ou de intervalo estendido com base nos recursos do dispositivo iOS em que o aplicativo está sendo executado.
- Ele gerencia totalmente e automaticamente o tempo de vida do contexto de imagem (
CGContext
) para que o desenvolvedor não precise se preocupar em chamar comandos de contexto de início e fim. - Ele é compatível com o
UIGraphics.GetCurrentContext()
método .
O CreateImage
método da UIGraphicsImageRenderer
classe é chamado para criar uma imagem de cor ampla e passou um manipulador de conclusão com o contexto de imagem para desenhar. Todo o desenho é feito dentro desse manipulador de conclusão da seguinte maneira:
- O
UIColor.FromDisplayP3
método cria uma nova cor vermelha totalmente saturada no espaço de cor de exibição P3 de gama larga e é usado para desenhar a primeira metade do retângulo. - A segunda metade do retângulo é desenhada na cor vermelha SRGB totalmente saturada normal para comparação.
Desenhando cores largas no macOS
A NSImage
classe foi expandida no macOS Sierra para dar suporte ao desenho de imagens de Cores Largas. Por exemplo:
var size = CGSize(250,250);
var wideColorImage = new NSImage(size, false, (drawRect) =>{
var rects = drawRect.Divide(drawRect.Size.Width/2,CGRect.MinXEdge);
var color = new NSColor(1.0, 0.0, 0.0, 1.0).Set();
var path = new NSBezierPath(rects.Slice).Fill();
color = new NSColor(1.0, 0.0, 0.0, 1.0).Set();
path = new NSBezierPath(rects.Remainder).Fill();
// Return modified
return true;
});
Renderizando imagens na tela no aplicativo
Para renderizar imagens de cores largas na tela, o processo funciona de forma semelhante ao desenho de uma imagem de cores largas fora da tela para macOS e iOS apresentados acima.
Renderizando na tela no iOS
Quando o aplicativo precisar renderizar uma imagem em cores largas na tela no iOS, substitua o Draw
método do UIView
em questão como de costume. Por exemplo:
using System;
using UIKit;
using CoreGraphics;
namespace MonkeyTalk
{
public class MonkeyView : UIView
{
public MonkeyView ()
{
}
public override void Draw (CGRect rect)
{
base.Draw (rect);
// Draw the image to screen
...
}
}
}
Como o iOS 10 faz com a UIGraphicsImageRenderer
classe mostrada acima, ele decide de forma inteligente se deve renderizar no espaço de cores sRGB ou de intervalo estendido com base nos recursos do dispositivo iOS em que o aplicativo está sendo executado quando o Draw
método é chamado. Além disso, o UIImageView
foi gerenciado por cores desde o iOS 9.3 também.
Se o aplicativo precisar saber como a renderização está sendo feita em um UIView
ou UIViewController
, ele poderá marcar a nova DisplayGamut
propriedade da UITraitCollection
classe . Esse valor será uma UIDisplayGamut
enumeração do seguinte:
- P3
- Srgb
- Não Especificado
Se o aplicativo quiser controlar qual Espaço de Cor é usado para desenhar uma imagem, ele poderá usar uma nova ContentsFormat
propriedade do CALayer
para especificar o Espaço de Cor desejado. Esse valor pode ser uma CAContentsFormat
enumeração do seguinte:
- Gray8Uint
- Rgba16Float
- Rgba8Uint
Renderização na tela no macOS
Quando o aplicativo precisar renderizar uma imagem em cores largas na tela no macOS, substitua o DrawRect
método do NSView
em questão como de costume. Por exemplo:
using System;
using AppKit;
using CoreGraphics;
using CoreAnimation;
namespace MonkeyTalkMac
{
public class MonkeyView : NSView
{
public MonkeyView ()
{
}
public override void DrawRect (CGRect dirtyRect)
{
base.DrawRect (dirtyRect);
// Draw graphics into the view
...
}
}
}
Novamente, ele decide de forma inteligente se deve renderizar no espaço de cores sRGB ou de intervalo estendido com base nos recursos do hardware Mac em que o aplicativo está sendo executado quando o DrawRect
método é chamado.
Se o aplicativo quiser controlar qual Espaço de Cor é usado para desenhar uma imagem, ele poderá usar uma nova DepthLimit
propriedade da NSWindow
classe para especificar o Espaço de Cor desejado. Esse valor pode ser uma NSWindowDepth
enumeração do seguinte:
- OneHundredTwentyEightBitRgb
- SixtyfourBitRgb
- TwentyfourBitRgb