Notions de base de bitmap dans SkiaSharp
Chargez des bitmaps à partir de différentes sources et affichez-les.
La prise en charge des bitmaps dans SkiaSharp est très étendue. Cet article couvre uniquement les concepts de base : comment charger des bitmaps et comment les afficher :
Vous trouverez une exploration beaucoup plus approfondie des bitmaps dans la section SkiaSharp Bitmaps.
Une bitmap SkiaSharp est un objet de type SKBitmap
. Il existe de nombreuses façons de créer une bitmap, mais cet article se limite à la SKBitmap.Decode
méthode, qui charge la bitmap à partir d’un objet .NET Stream
.
La page Bitmaps de base du programme SkiaSharpFormsDemos montre comment charger des bitmaps à partir de trois sources différentes :
- À partir d’Internet
- À partir d’une ressource incorporée dans l’exécutable
- À partir de la bibliothèque de photos de l’utilisateur
Trois SKBitmap
objets pour ces trois sources sont définis en tant que champs dans la BasicBitmapsPage
classe :
public class BasicBitmapsPage : ContentPage
{
SKCanvasView canvasView;
SKBitmap webBitmap;
SKBitmap resourceBitmap;
SKBitmap libraryBitmap;
public BasicBitmapsPage()
{
Title = "Basic Bitmaps";
canvasView = new SKCanvasView();
canvasView.PaintSurface += OnCanvasViewPaintSurface;
Content = canvasView;
...
}
...
}
Chargement d’une bitmap à partir du web
Pour charger une bitmap basée sur une URL, vous pouvez utiliser la HttpClient
classe. Vous ne devez instancier qu’une seule instance et HttpClient
la réutiliser. Stockez-la en tant que champ :
HttpClient httpClient = new HttpClient();
Lorsque vous utilisez HttpClient
des applications iOS et Android, vous devez définir les propriétés du projet comme décrit dans les documents sur TLS (Transport Layer Security) 1.2.
Étant donné qu’il est plus pratique d’utiliser l’opérateur await
avec HttpClient
, le code ne peut pas être exécuté dans le BasicBitmapsPage
constructeur. Au lieu de cela, il fait partie du OnAppearing
remplacement. L’URL ici pointe vers une zone sur le site web Xamarin avec des exemples de bitmaps. Un package sur le site web permet d’ajouter une spécification pour redimensionner la bitmap à une largeur particulière :
protected override async void OnAppearing()
{
base.OnAppearing();
// Load web bitmap.
string url = "https://developer.xamarin.com/demo/IMG_3256.JPG?width=480";
try
{
using (Stream stream = await httpClient.GetStreamAsync(url))
using (MemoryStream memStream = new MemoryStream())
{
await stream.CopyToAsync(memStream);
memStream.Seek(0, SeekOrigin.Begin);
webBitmap = SKBitmap.Decode(memStream);
canvasView.InvalidateSurface();
};
}
catch
{
}
}
Le système d’exploitation Android génère une exception lors de l’utilisation du Stream
retour de GetStreamAsync
la SKBitmap.Decode
méthode, car il effectue une longue opération sur un thread principal. Pour cette raison, le contenu du fichier bitmap est copié dans un MemoryStream
objet à l’aide CopyToAsync
de .
La méthode statique SKBitmap.Decode
est responsable du décodage des fichiers bitmap. Il fonctionne avec les formats bitmap JPEG, PNG et GIF, et stocke les résultats dans un format SkiaSharp interne. À ce stade, il SKCanvasView
doit être invalidé pour permettre PaintSurface
au gestionnaire de mettre à jour l’affichage.
Chargement d’une ressource bitmap
En termes de code, l’approche la plus simple pour charger des bitmaps consiste à inclure une ressource bitmap directement dans votre application. Le programme SkiaSharpFormsDemos inclut un dossier nommé Media contenant plusieurs fichiers bitmap, dont un nommé monkey.png. Pour les bitmaps stockées en tant que ressources de programme, vous devez utiliser la boîte de dialogue Propriétés pour donner au fichier une action de génération de ressource incorporée !
Chaque ressource incorporée a un ID de ressource qui se compose du nom du projet, du dossier et du nom de fichier, tous connectés par points : SkiaSharpFormsDemos.Media.monkey.png. Vous pouvez accéder à cette ressource en spécifiant cet ID de ressource comme argument de la GetManifestResourceStream
méthode de la Assembly
classe :
string resourceID = "SkiaSharpFormsDemos.Media.monkey.png";
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream(resourceID))
{
resourceBitmap = SKBitmap.Decode(stream);
}
Cet Stream
objet peut être transmis directement à la SKBitmap.Decode
méthode.
Chargement d’une bitmap à partir de la bibliothèque de photos
Il est également possible pour l’utilisateur de charger une photo à partir de la bibliothèque d’images de l’appareil. Cette installation n’est pas fournie par Xamarin.Forms elle-même. Le travail nécessite un service de dépendance, tel que celui décrit dans l’article Sélection d’une photo à partir de la bibliothèque d’images.
Le fichier IPhotoLibrary.cs dans le projet SkiaSharpFormsDemos et les trois fichiers PhotoLibrary.cs dans les projets de plateforme ont été adaptés à partir de cet article. En outre, le fichier android MainActivity.cs a été modifié comme décrit dans l’article, et le projet iOS a été autorisé à accéder à la bibliothèque de photos avec deux lignes vers le bas du fichier info.plist .
Le BasicBitmapsPage
constructeur ajoute un TapGestureRecognizer
à la SKCanvasView
notification des appuis. À la réception d’un appui, le Tapped
gestionnaire obtient l’accès au service de dépendance du sélecteur d’images et aux appels PickPhotoAsync
. Si un Stream
objet est retourné, il est passé à la SKBitmap.Decode
méthode :
// Add tap gesture recognizer
TapGestureRecognizer tapRecognizer = new TapGestureRecognizer();
tapRecognizer.Tapped += async (sender, args) =>
{
// Load bitmap from photo library
IPhotoLibrary photoLibrary = DependencyService.Get<IPhotoLibrary>();
using (Stream stream = await photoLibrary.PickPhotoAsync())
{
if (stream != null)
{
libraryBitmap = SKBitmap.Decode(stream);
canvasView.InvalidateSurface();
}
}
};
canvasView.GestureRecognizers.Add(tapRecognizer);
Notez que le Tapped
gestionnaire appelle également la InvalidateSurface
méthode de l’objet SKCanvasView
. Cela génère un nouvel appel au PaintSurface
gestionnaire.
Affichage des bitmaps
Le PaintSurface
gestionnaire doit afficher trois bitmaps. Le gestionnaire suppose que le téléphone est en mode portrait et divise verticalement le canevas en trois parties égales.
La première bitmap s’affiche avec la méthode la plus simple DrawBitmap
. Il vous suffit de spécifier les coordonnées X et Y dans lesquelles le coin supérieur gauche de la bitmap doit être positionné :
public void DrawBitmap (SKBitmap bitmap, Single x, Single y, SKPaint paint = null)
Bien qu’un SKPaint
paramètre soit défini, il a une valeur par défaut et null
vous pouvez l’ignorer. Les pixels de la bitmap sont simplement transférés aux pixels de l’aire d’affichage avec un mappage un-à-un. Vous verrez une application pour cet SKPaint
argument dans la section suivante sur SkiaSharp Transparency.
Un programme peut obtenir les dimensions de pixels d’une bitmap avec les propriétés et Height
les Width
propriétés. Ces propriétés permettent au programme de calculer les coordonnées pour positionner la bitmap au centre du tiers supérieur du canevas :
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
if (webBitmap != null)
{
float x = (info.Width - webBitmap.Width) / 2;
float y = (info.Height / 3 - webBitmap.Height) / 2;
canvas.DrawBitmap(webBitmap, x, y);
}
...
}
Les deux autres bitmaps sont affichées avec une version d’un DrawBitmap
SKRect
paramètre :
public void DrawBitmap (SKBitmap bitmap, SKRect dest, SKPaint paint = null)
Une troisième version comporte DrawBitmap
deux SKRect
arguments pour spécifier un sous-ensemble rectangulaire de l’image bitmap à afficher, mais cette version n’est pas utilisée dans cet article.
Voici le code permettant d’afficher la bitmap chargée à partir d’une bitmap de ressource incorporée :
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
...
if (resourceBitmap != null)
{
canvas.DrawBitmap(resourceBitmap,
new SKRect(0, info.Height / 3, info.Width, 2 * info.Height / 3));
}
...
}
La bitmap est étirée aux dimensions du rectangle, c’est pourquoi le singe est étiré horizontalement dans ces captures d’écran :
La troisième image , que vous pouvez voir uniquement si vous exécutez le programme et charger une photo à partir de votre propre bibliothèque d’images, est également affichée dans un rectangle, mais la position et la taille du rectangle sont ajustées pour maintenir le rapport d’aspect de la bitmap. Ce calcul est un peu plus impliqué, car il nécessite le calcul d’un facteur de mise à l’échelle en fonction de la taille de la bitmap et du rectangle de destination, et le centre du rectangle dans cette zone :
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
...
if (libraryBitmap != null)
{
float scale = Math.Min((float)info.Width / libraryBitmap.Width,
info.Height / 3f / libraryBitmap.Height);
float left = (info.Width - scale * libraryBitmap.Width) / 2;
float top = (info.Height / 3 - scale * libraryBitmap.Height) / 2;
float right = left + scale * libraryBitmap.Width;
float bottom = top + scale * libraryBitmap.Height;
SKRect rect = new SKRect(left, top, right, bottom);
rect.Offset(0, 2 * info.Height / 3);
canvas.DrawBitmap(libraryBitmap, rect);
}
else
{
using (SKPaint paint = new SKPaint())
{
paint.Color = SKColors.Blue;
paint.TextAlign = SKTextAlign.Center;
paint.TextSize = 48;
canvas.DrawText("Tap to load bitmap",
info.Width / 2, 5 * info.Height / 6, paint);
}
}
}
Si aucune bitmap n’a encore été chargée à partir de la bibliothèque d’images, le else
bloc affiche du texte pour inviter l’utilisateur à appuyer sur l’écran.
Vous pouvez afficher des bitmaps avec différents degrés de transparence, et l’article suivant sur SkiaSharp Transparency décrit comment procéder.