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.
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).
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.
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.
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.
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.
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;
});
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.
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
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