Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makalede, BitmapDecoder ve BitmapEncoder kullanarak görüntü dosyalarının nasıl yükleneceği ve kaydedileceği, ayrıca bit eşlemli görüntüleri temsil etmek için SoftwareBitmap nesnesinin nasıl kullanılacağı açıklanmaktadır.
SoftwareBitmap sınıfı, görüntü dosyaları, WriteableBitmap nesneleri, Direct3D yüzeyleri ve kod gibi birden çok kaynaktan oluşturulabilen çok yönlü bir API'dir. SoftwareBitmap , farklı piksel biçimleriyle alfa modları arasında kolayca dönüştürmenizi sağlar ve piksel verilerine düşük düzeyde erişim sağlar. Ayrıca, SoftwareBitmap Windows'nin birden çok özelliği tarafından kullanılan yaygın bir arabirimdir, örneğin:
CapturedFrame kamera tarafından SoftwareBitmap olarak yakalanan kareleri almanıza olanak tanır.
VideoFrameSoftwareBitmapVideoFrame gösterimini almanızı sağlar.
FaceDetectorSoftwareBitmap içindeki yüzleri algılamanızı sağlar.
Bu makaledeki örnek kod aşağıdaki ad alanlarına ait API'leri kullanır.
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using Windows.Graphics.Imaging;
using Microsoft.UI.Xaml.Media.Imaging;
using System.Runtime.InteropServices.WindowsRuntime;
BitmapDecoder ile bir görüntü dosyasından SoftwareBitmap oluşturma
Bir dosyadan SoftwareBitmap oluşturmak için görüntü verilerini içeren StorageFile örneğini alın. Bu örnekte kullanıcının bir görüntü dosyası seçmesine izin vermek için FileOpenPicker kullanılır.
private async Task<StorageFile?> PickInputFileAsync()
{
var picker = new FileOpenPicker();
// Initialize the picker with the window handle (required for WinUI 3).
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);
picker.ViewMode = PickerViewMode.Thumbnail;
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".png");
picker.FileTypeFilter.Add(".bmp");
return await picker.PickSingleFileAsync();
}
Görüntü verilerini içeren rastgele bir erişim akışı almak için StorageFile nesnesinin OpenAsync yöntemini çağırın. Belirtilen akış için BitmapDecoder sınıfının bir örneğini almak için BitmapDecoder.CreateAsync statik yöntemini çağırın. Görüntüyü içeren bir SoftwareBitmap nesnesi almak için GetSoftwareBitmapAsync çağrısı yapın.
private async Task<SoftwareBitmap> CreateSoftwareBitmapFromFileAsync(StorageFile file)
{
using IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);
// Create a decoder from the image file.
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
// Get the SoftwareBitmap representation of the file.
SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync();
return softwareBitmap;
}
BitmapEncoder ile SoftwareBitmap'i bir dosyaya kaydetme
SoftwareBitmap'i bir dosyaya kaydetmek için görüntünün kaydedileceği StorageFile örneğini alın. Bu örnekte, kullanıcının bir çıkış dosyası seçmesine izin vermek için FileSavePicker kullanılır.
private async Task<StorageFile?> PickOutputFileAsync()
{
var picker = new FileSavePicker();
// Initialize the picker with the window handle (required for WinUI 3).
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
picker.SuggestedFileName = "output";
picker.FileTypeChoices.Add("JPEG Image", new List<string> { ".jpg" });
picker.FileTypeChoices.Add("PNG Image", new List<string> { ".png" });
return await picker.PickSaveFileAsync();
}
Görüntünün yazılacağı rastgele bir erişim akışı almak için StorageFile nesnesinin OpenAsync yöntemini çağırın. Belirtilen akış için BitmapEncoder sınıfının bir örneğini almak için BitmapEncoder.CreateAsync statik yöntemini çağırın. CreateAsync'in ilk parametresi, görüntüyü kodlamak için kullanılması gereken codec bileşenini temsil eden bir GUID'dir. BitmapEncoder sınıfı, jpegEncoderId gibi kodlayıcı tarafından desteklenen her codec bileşeninin kimliğini içeren bir özelliği kullanıma sunar.
Kodlanacak görüntüyü ayarlamak için SetSoftwareBitmap yöntemini kullanın. BitmapTransform özelliğinin değerlerini, kodlanırken görüntüye temel dönüşümler uygulamak için ayarlayabilirsiniz. IsThumbnailGenerated özelliği, kodlayıcı tarafından küçük resim oluşturulup oluşturulmadığını belirler. Tüm dosya biçimlerinin küçük resimleri desteklemediğini unutmayın, bu nedenle bu özelliği kullanırsanız, küçük resimler desteklenmiyorsa oluşturulacak desteklenmeyen işlem hatasını yakalamanız gerekir.
Kodlayıcının görüntü verilerini belirtilen dosyaya yazmasına neden olmak için FlushAsync'i çağırın.
private async Task SaveSoftwareBitmapToFileAsync(SoftwareBitmap softwareBitmap, StorageFile outputFile)
{
using IRandomAccessStream stream = await outputFile.OpenAsync(FileAccessMode.ReadWrite);
// Create an encoder with the desired format.
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
// Set the software bitmap.
encoder.SetSoftwareBitmap(softwareBitmap);
// Set additional encoding parameters (optional).
encoder.BitmapTransform.ScaledWidth = (uint)softwareBitmap.PixelWidth;
encoder.BitmapTransform.ScaledHeight = (uint)softwareBitmap.PixelHeight;
encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant;
encoder.IsThumbnailGenerated = true;
try
{
await encoder.FlushAsync();
}
catch (Exception ex)
{
const int WINCODEC_ERR_UNSUPPORTEDOPERATION = unchecked((int)0x88982F81);
switch (ex.HResult)
{
case WINCODEC_ERR_UNSUPPORTEDOPERATION:
// If the encoder does not support thumbnail generation,
// disable it and try again.
encoder.IsThumbnailGenerated = false;
break;
default:
throw;
}
}
if (!encoder.IsThumbnailGenerated)
{
await encoder.FlushAsync();
}
}
BitmapEncoder öğesini oluştururken, yeni bir BitmapPropertySet nesnesi oluşturup bunu kodlayıcı ayarlarını temsil eden bir veya daha fazla BitmapTypedValue nesnesiyle doldurarak ek kodlama seçenekleri belirtebilirsiniz. Desteklenen kodlayıcı seçeneklerinin listesi için bkz. BitmapEncoder seçenekleri başvurusu.
private async Task SaveWithEncodingOptionsAsync(SoftwareBitmap softwareBitmap, StorageFile outputFile)
{
using IRandomAccessStream stream = await outputFile.OpenAsync(FileAccessMode.ReadWrite);
// Create encoding options with a specific image quality.
var propertySet = new BitmapPropertySet();
var qualityValue = new BitmapTypedValue(0.9, Windows.Foundation.PropertyType.Single);
propertySet.Add("ImageQuality", qualityValue);
// Create the encoder with the encoding options.
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(
BitmapEncoder.JpegEncoderId, stream, propertySet);
encoder.SetSoftwareBitmap(softwareBitmap);
await encoder.FlushAsync();
}
SoftwareBitmap'i XAML Görüntü denetimiyle kullanma
Görüntü denetimini kullanarak bir XAML sayfasında görüntü görüntülemek için önce XAML sayfanızda bir Görüntü denetimi tanımlayın.
<Image x:Name="imageControl"
Grid.Row="2"
Stretch="Uniform"/>
Şu anda Görüntü denetimi yalnızca BGRA8 kodlaması kullanan ve önceden çarpılmış veya alfa kanalı olmayan görüntüleri destekler. Bir görüntüyü görüntülemeye çalışmadan önce, doğru biçime sahip olduğundan emin olmak için test edin ve değilse, görüntüyü desteklenen biçime dönüştürmek için SoftwareBitmap statik Dönüştürme yöntemini kullanın.
Yeni bir SoftwareBitmapSource nesnesi oluşturun. SoftwareBitmap geçirerek SetBitmapAsync yöntemini çağırıp kaynak nesnenin içeriğini ayarlayın. Ardından Görüntü denetiminin Source özelliğini yeni oluşturulan SoftwareBitmapSource olarak ayarlayabilirsiniz.
private async Task DisplaySoftwareBitmapAsync(SoftwareBitmap softwareBitmap)
{
// SoftwareBitmap must be Bgra8 with premultiplied or no alpha
// to display in a XAML Image control.
if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 ||
softwareBitmap.BitmapAlphaMode == BitmapAlphaMode.Straight)
{
softwareBitmap = SoftwareBitmap.Convert(
softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
}
// In WinUI 3, SoftwareBitmapSource is in Microsoft.UI.Xaml.Media.Imaging.
var source = new SoftwareBitmapSource();
await source.SetBitmapAsync(softwareBitmap);
// Set the source of the Image control.
imageControl.Source = source;
}
Ayrıca, bir SoftwareBitmap'i bir ImageBrush için ImageSource olarak ayarlamak üzere SoftwareBitmapSource'u kullanabilirsiniz.
WriteableBitmap’ten SoftwareBitmap oluşturma
SoftwareBitmap.CreateCopyFromBuffer çağrısı yaparak ve piksel verilerini ayarlamak için WriteableBitmap'inPixelBuffer özelliğini sağlayarak mevcut bir WriteableBitmap'ten Bir SoftwareBitmap oluşturabilirsiniz. İkinci bağımsız değişken, yeni oluşturulan SoftwareBitmap için piksel biçimini belirtmenize olanak tanır. Yeni görüntünün boyutlarını belirtmek için WriteableBitmap'inPixelWidth ve PixelHeight özelliklerini kullanabilirsiniz.
private SoftwareBitmap ConvertWriteableBitmapToSoftwareBitmap(WriteableBitmap writeableBitmap)
{
// Create a SoftwareBitmap from the WriteableBitmap's pixel buffer.
SoftwareBitmap softwareBitmap = SoftwareBitmap.CreateCopyFromBuffer(
writeableBitmap.PixelBuffer,
BitmapPixelFormat.Bgra8,
writeableBitmap.PixelWidth,
writeableBitmap.PixelHeight);
return softwareBitmap;
}
Program aracılığıyla SoftwareBitmap oluşturma veya düzenleme
Bu konu şu ana kadar görüntü dosyalarıyla çalışmayı ele almıştır. Ayrıca kodda program aracılığıyla yeni bir SoftwareBitmap oluşturabilir ve SoftwareBitmap'in piksel verilerine erişmek ve bunları değiştirmek için aynı tekniği kullanabilirsiniz.
CopyFromBuffer yöntemini kullanarak bayt dizisinden Bir SoftwareBitmap'i doldurun ve CopyToBuffer'ı kullanarak piksel verilerini okumak veya değiştirmek üzere bayt dizisine kopyalayın. Bayt dizisini IBuffer olarak sarmak için AsBuffer uzantısı yöntemini kullanmak için System.Runtime.InteropServices.WindowsRuntime ad alanını ekleyin (bu, bu makalenin en üstündeki deyimleri kullanarak SnippetNamespaces dahildir).
İstediğiniz piksel biçimi ve boyutuyla yeni bir SoftwareBitmap oluşturun. Piksel verilerini barındıracak kadar büyük bir bayt dizisi ayırın, istenen değerlerle doldurun ve verileri bit eşlem içine yazmak için CopyFromBuffer öğesini çağırın.
private SoftwareBitmap CreateGradientBitmap(int width, int height)
{
// Create a new SoftwareBitmap programmatically.
var softwareBitmap = new SoftwareBitmap(
BitmapPixelFormat.Bgra8, width, height, BitmapAlphaMode.Premultiplied);
// Allocate a byte array for the pixel data.
int bytesPerPixel = 4; // BGRA8
byte[] pixelData = new byte[width * height * bytesPerPixel];
// Fill the bitmap with a gradient pattern.
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
int pixelIndex = (row * width + col) * bytesPerPixel;
// Blue channel: gradient left to right.
pixelData[pixelIndex + 0] = (byte)((double)col / width * 255);
// Green channel: gradient top to bottom.
pixelData[pixelIndex + 1] = (byte)((double)row / height * 255);
// Red channel: inverse diagonal gradient.
pixelData[pixelIndex + 2] = (byte)(255 - (((double)(col + row)
/ (width + height)) * 255));
// Alpha channel: fully opaque.
pixelData[pixelIndex + 3] = 255;
}
}
// Copy the pixel data into the SoftwareBitmap.
softwareBitmap.CopyFromBuffer(pixelData.AsBuffer());
return softwareBitmap;
}
Direct3D yüzeyinden SoftwareBitmap oluşturma
Bir Direct3D yüzeyinden SoftwareBitmap nesnesi oluşturmak için, projenize Windows.Graphics.DirectX.Direct3D11 ad alanını eklemeniz gerekir.
using Windows.Graphics.DirectX.Direct3D11;
Yüzeyden yeni bir SoftwareBitmap oluşturmak için CreateCopyFromSurfaceAsync'i çağırın. Adından da belirtildiği gibi, yeni SoftwareBitmap görüntü verilerinin ayrı bir kopyasına sahiptir. SoftwareBitmap'te yapılan değişikliklerin Direct3D yüzeyi üzerinde hiçbir etkisi olmayacaktır.
private async Task<SoftwareBitmap> CreateBitmapFromSurfaceAsync(IDirect3DSurface surface)
{
// Create a SoftwareBitmap from a Direct3D surface.
SoftwareBitmap softwareBitmap =
await SoftwareBitmap.CreateCopyFromSurfaceAsync(surface);
return softwareBitmap;
}
SoftwareBitmap'i farklı bir piksel biçimine dönüştürme
SoftwareBitmap sınıfı, mevcut bir SoftwareBitmap'ten belirttiğiniz piksel biçimini ve alfa modunu kullanan yeni bir SoftwareBitmap oluşturmanızı sağlayan Convert statik yöntemini sağlar. Yeni oluşturulan bit eşlem, görüntü verilerinin ayrı bir kopyasına sahiptir. Yeni bit eşlem üzerinde yapılan değişiklikler kaynak bit eşlemi etkilemez.
private SoftwareBitmap ConvertBitmapPixelFormat(SoftwareBitmap softwareBitmap)
{
// Convert the pixel format and alpha mode of the SoftwareBitmap.
SoftwareBitmap convertedBitmap = SoftwareBitmap.Convert(
softwareBitmap,
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Premultiplied);
return convertedBitmap;
}
Görüntü dosyasını dönüştürme
Görüntü dosyasını doğrudan BitmapDecoderBitmapEncoder olarak kodlayabilirsiniz. Kodlanacak dosyadan bir IRandomAccessStream oluşturun. Giriş akışından yeni bir BitmapDecoder oluşturun. Kodlayıcının yazacağı yeni bir InMemoryRandomAccessStream oluşturun ve bellek içi akış ile kod çözücü nesnesini parametre olarak geçirerek BitmapEncoder.CreateForTranscodingAsync yöntemini çağırın. Kod dönüştürme sırasında kodlama seçenekleri desteklenmez; bunun yerine CreateAsync kullanmalısınız. Kodlayıcıda özellikle ayarlamadığınız giriş görüntüsü dosyasındaki tüm özellikler değişmeden çıkış dosyasına yazılır. Kodlayıcının bellek içi akışa kodlamasına neden olmak için FlushAsync'i çağırın. Son olarak, dosya akışını ve bellek içi akışı en başa arayın ve bellek içi akışı dosya akışına yazmak için CopyAsync'i çağırın.
private async Task TranscodeImageFileAsync(StorageFile inputFile, StorageFile outputFile)
{
using IRandomAccessStream inputStream =
await inputFile.OpenAsync(FileAccessMode.Read);
using IRandomAccessStream outputStream =
await outputFile.OpenAsync(FileAccessMode.ReadWrite);
// Create a decoder for the input file.
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(inputStream);
// Create an encoder for transcoding to the output file.
BitmapEncoder encoder =
await BitmapEncoder.CreateForTranscodingAsync(outputStream, decoder);
// Optionally apply transforms during transcoding.
encoder.BitmapTransform.ScaledWidth = decoder.PixelWidth / 2;
encoder.BitmapTransform.ScaledHeight = decoder.PixelHeight / 2;
encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant;
await encoder.FlushAsync();
}
İlgili konular
Windows developer