Reputation: 434
I'm capturing a photo using the WinRT
Mediacapture class, but when I take the picture it gets weird transparent stripes, it's kind of hard to explain so here's some pictures:
Before capturing picture (Previewing)
After taking picture
I have seen other people with kind of the same problem around here (like here, but the solutions to them didn't seem to work for me. (either no result, or the photo got messed up)
Code I use for setting the resolution:
System.Collections.Generic.IEnumerable<VideoEncodingProperties> available_resolutions = captureManager.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.Photo).Select(x => x as VideoEncodingProperties);
foreach (VideoEncodingProperties resolution in available_resolutions)
{
if (resolution != null && resolution.Width == 640 && resolution.Height == 480) //(resolution.Width==1920 && resolution.Height==1080) //resolution.Width==640 && resolution.Height==480)
{
await captureManager.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.Photo, resolution);
}
}
Code I'm using for taking the photo:
private async Task<BitmapImage> ByteArrayToBitmapImage(byte[] byteArray)
{
var bitmapImage = new BitmapImage();
using (var stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(byteArray.AsBuffer());
stream.Seek(0);
await bitmapImage.SetSourceAsync(stream);
await stream.FlushAsync();
}
return bitmapImage;
}
/// <summary>
/// Relayed Execute method for TakePictureCommand.
/// </summary>
async void ExecuteTakePicture()
{
System.Diagnostics.Debug.WriteLine("Started making picture");
DateTime starttime = DateTime.Now;
ImageEncodingProperties format = ImageEncodingProperties.CreateJpeg();
using (var imageStream = new InMemoryRandomAccessStream())
{
await captureManager.CapturePhotoToStreamAsync(format, imageStream);
//Compresses the image if it exceedes the maximum file size
imageStream.Seek(0);
//Resize the image if needed
uint maxImageWidth = 640;
uint maxImageHeight = 480;
if (AvatarPhoto)
{
maxImageHeight = 200;
maxImageWidth = 200;
//Create a BitmapDecoder from the stream
BitmapDecoder resizeDecoder = await BitmapDecoder.CreateAsync(imageStream);
if (resizeDecoder.PixelWidth > maxImageWidth || resizeDecoder.PixelHeight > maxImageHeight)
{
//Resize the image if it exceedes the maximum width or height
WriteableBitmap tempBitmap = new WriteableBitmap((int)resizeDecoder.PixelWidth, (int)resizeDecoder.PixelHeight);
imageStream.Seek(0);
await tempBitmap.SetSourceAsync(imageStream);
WriteableBitmap resizedImage = tempBitmap.Resize((int)maxImageWidth, (int)maxImageHeight, WriteableBitmapExtensions.Interpolation.Bilinear);
tempBitmap = null;
//Assign to imageStream the resized WriteableBitmap
await resizedImage.ToStream(imageStream, BitmapEncoder.JpegEncoderId);
resizedImage = null;
}
//Converts the final image into a Base64 String
imageStream.Seek(0);
}
//Converts the final image into a Base64 String
imageStream.Seek(0);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(imageStream);
PixelDataProvider pixels = await decoder.GetPixelDataAsync();
byte[] bytes = pixels.DetachPixelData();
//Encode image
InMemoryRandomAccessStream encoded = new InMemoryRandomAccessStream();
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, encoded);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, maxImageWidth, maxImageHeight, decoder.DpiX, decoder.DpiY, bytes);
//Rotate the image based on the orientation of the camera
if (currentOrientation == DisplayOrientations.Portrait)
{
encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees;
}
else if (currentOrientation == DisplayOrientations.LandscapeFlipped)
{
encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise180Degrees;
}
if (FrontCam)
{
if (currentOrientation == DisplayOrientations.Portrait)
{
encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise270Degrees;
}
else if (currentOrientation == DisplayOrientations.LandscapeFlipped)
{
encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise180Degrees;
}
}
await encoder.FlushAsync();
encoder = null;
//Read bytes
byte[] outBytes = new byte[encoded.Size];
await encoded.AsStream().ReadAsync(outBytes, 0, outBytes.Length);
encoded.Dispose();
encoded = null;
//Create Base64
image = await ByteArrayToBitmapImage(outBytes);
System.Diagnostics.Debug.WriteLine("Pixel width: " + image.PixelWidth + " height: " + image.PixelHeight);
base64 = Convert.ToBase64String(outBytes);
Array.Clear(outBytes, 0, outBytes.Length);
await imageStream.FlushAsync();
imageStream.Dispose();
}
DateTime endtime = DateTime.Now;
TimeSpan span = (endtime - starttime);
//Kind of a hacky way to prevent high RAM usage and even crashing, remove when overal RAM usage has been lowered
GC.Collect();
System.Diagnostics.Debug.WriteLine("Making the picture took: " + span.Seconds + " seconds");
if (image != null)
{
RaisePropertyChanged("CapturedImage");
//Tell both UsePictureCommand and ResetCommand that the situation has changed.
((RelayedCommand)UsePictureCommand).RaiseCanExecuteChanged();
((RelayedCommand)ResetCommand).RaiseCanExecuteChanged();
}
else
{
throw new InvalidOperationException("Imagestream is not valid");
}
}
If there is any more information needed feel free to comment, I will try to put it out as fast as possible, thanks for reading.
Upvotes: 1
Views: 237
Reputation: 2260
The aspect ratio of the preview has to match the aspect ratio of the captured photo, or you'll get artifacts like that one in your capture (although it actually depends on the driver implementation, so it may vary from device to device).
MediaCapture.VideoDeviceController.GetMediaStreamProperties()
method on the MediaStream.VideoPreview
.VideoEncodingProperties
, and use the Width and Height to figure out the aspect ratio.MediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties()
on the MediaStream.Photo
, and find out which ones have an aspect ratio that matches (I recommend using a tolerance value, something like 0.015f
might be good)MediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync()
on the MediaStream.Photo
and passing the encoding properties you want.More information in this thread. An SDK sample is available here.
Upvotes: 2