Resize image and save as file - c#

My objective is to resize an image that I create and after resizing it with the same ratio and finally save it on my drive.
so just below the code is working I'm 100% sure that the code work
The problem is on the ResizeImage method.
Everything work well until the decoder, I don't know why but it always return me the code:
System.Exception: 'The component was not found. (Exception from HRESULT: 0x88982F50)'
private async Task<StorageFile> SaveSquaresPhotos(WriteableBitmap WB, FileFormat fileFormat, string username) {
string FileName = username + "-Carre.";
Guid BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;
switch (fileFormat)
{
case FileFormat.Jpeg:
FileName += "jpeg";
BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;
break;
case FileFormat.Png:
FileName += "png";
BitmapEncoderGuid = BitmapEncoder.PngEncoderId;
break;
case FileFormat.Bmp:
FileName += "bmp";
BitmapEncoderGuid = BitmapEncoder.BmpEncoderId;
break;
case FileFormat.Tiff:
FileName += "tiff";
BitmapEncoderGuid = BitmapEncoder.TiffEncoderId;
break;
case FileFormat.Gif:
FileName += "gif";
BitmapEncoderGuid = BitmapEncoder.GifEncoderId;
break;
}
if (config.getFolder() == null)
{
try
{
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
var folder = await StorageFolder.GetFolderFromPathAsync(resourceLoader.GetString("Folder"));
var file = await folder.CreateFileAsync(FileName, CreationCollisionOption.GenerateUniqueName);
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoderGuid, stream);
Stream pixelStream = WB.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
(uint)WB.PixelWidth,
(uint)WB.PixelHeight,
96.0,
96.0,
pixels);
await ResizeImage(pixels, 75, 75, pixelStream);
await encoder.FlushAsync();
}
return file;
}
catch {
var file = await _captureFolder.CreateFileAsync(FileName, CreationCollisionOption.GenerateUniqueName);
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoderGuid, stream);
Stream pixelStream = WB.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
(uint)WB.PixelWidth,
(uint)WB.PixelHeight,
96.0,
96.0,
pixels);
await ResizeImage(pixels, 75, 75, pixelStream);
await encoder.FlushAsync();
}
return file;
}
}
else
{
var file = await config.getFolder().CreateFileAsync(FileName, CreationCollisionOption.GenerateUniqueName);
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoderGuid, stream);
Stream pixelStream = WB.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
(uint)WB.PixelWidth,
(uint)WB.PixelHeight,
96.0,
96.0,
pixels);
await ResizeImage(pixels, 75, 75, pixelStream);
await encoder.FlushAsync();
}
return file;
}
}
public async Task<byte[]> ResizeImage(byte[] imageData, int reqWidth, int reqHeight, Stream stream)
{
var memStream = new MemoryStream();
stream.Position = 0;
await stream.CopyToAsync(memStream);
IRandomAccessStream imageStream = memStream.AsRandomAccessStream();
imageStream.Seek(0);
//The problem start just below
var decoder = await BitmapDecoder.CreateAsync(imageStream);
if (decoder.PixelHeight > reqHeight || decoder.PixelWidth > reqWidth)
{
using (imageStream)
{
var resizedStream = new InMemoryRandomAccessStream();
BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAsync(resizedStream, decoder);
double widthRatio = (double)reqWidth / decoder.PixelWidth;
double heightRatio = (double)reqHeight / decoder.PixelHeight;
double scaleRatio = Math.Min(widthRatio, heightRatio);
if (reqWidth == 0)
scaleRatio = heightRatio;
if (reqHeight == 0)
scaleRatio = widthRatio;
uint aspectHeight = (uint)Math.Floor(decoder.PixelHeight * scaleRatio);
uint aspectWidth = (uint)Math.Floor(decoder.PixelWidth * scaleRatio);
encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Linear;
encoder.BitmapTransform.ScaledHeight = aspectHeight;
encoder.BitmapTransform.ScaledWidth = aspectWidth;
await encoder.FlushAsync();
resizedStream.Seek(0);
var outBuffer = new byte[resizedStream.Size];
uint x = await resizedStream.WriteAsync(outBuffer.AsBuffer());
return outBuffer;
}
}
return imageData;
}
if someone can tell me where the problem is from, I'll be very grateful.
Edit:
I found the solution.
First my call for the second method was not on the correct line.
Finally I found an other method for resizing my file, that was more close to what I had.
private async Task<StorageFile> SaveThumbsPhotos(WriteableBitmap WB, FileFormat fileFormat, string username)
{
string FileName = username + "-Thumbs.";
Guid BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;
switch (fileFormat)
{
case FileFormat.Jpg:
FileName += "jpg";
BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;
break;
case FileFormat.Png:
FileName += "png";
BitmapEncoderGuid = BitmapEncoder.PngEncoderId;
break;
case FileFormat.Bmp:
FileName += "bmp";
BitmapEncoderGuid = BitmapEncoder.BmpEncoderId;
break;
case FileFormat.Tiff:
FileName += "tiff";
BitmapEncoderGuid = BitmapEncoder.TiffEncoderId;
break;
case FileFormat.Gif:
FileName += "gif";
BitmapEncoderGuid = BitmapEncoder.GifEncoderId;
break;
}
if (config.getFolder() == null)
{
try
{
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
var folder = await StorageFolder.GetFolderFromPathAsync(resourceLoader.GetString("Folder"));
var file = await folder.CreateFileAsync(FileName, CreationCollisionOption.GenerateUniqueName);
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoderGuid, stream);
Stream pixelStream = WB.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
(uint)WB.PixelWidth,
(uint)WB.PixelHeight,
96.0,
96.0,
pixels);
await encoder.FlushAsync();
}
await RescaleImage(file, 75, 75, username);
return file;
}
catch
{
var file = await _captureFolder.CreateFileAsync(FileName, CreationCollisionOption.GenerateUniqueName);
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoderGuid, stream);
Stream pixelStream = WB.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
(uint)WB.PixelWidth,
(uint)WB.PixelHeight,
96.0,
96.0,
pixels);
await encoder.FlushAsync();
}
await RescaleImage(file, 75, 75, username);
return file;
}
}
else
{
var file = await config.getFolder().CreateFileAsync(FileName, CreationCollisionOption.GenerateUniqueName);
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoderGuid, stream);
Stream pixelStream = WB.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
(uint)WB.PixelWidth,
(uint)WB.PixelHeight,
96.0,
96.0,
pixels);
await encoder.FlushAsync();
}
await RescaleImage(file, 75, 75, username);
return file;
}
}
private async Task<StorageFile> RescaleImage(StorageFile source, uint width, uint height, string username)
{
var imageStream = await source.OpenReadAsync();
var decoder = await BitmapDecoder.CreateAsync(imageStream);
using (var resizedStream = await source.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateForTranscodingAsync(resizedStream, decoder);
encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Linear;
encoder.BitmapTransform.ScaledWidth = width;
encoder.BitmapTransform.ScaledHeight = height;
await encoder.FlushAsync();
}
return source;
}

Related

BitmapEncoder FlushAsync throws Argument Exception - c#

When I'm using below code for image processing it throws exception at FlushAsync(). Strangely this issue happens for some video files only. Can you help why this happen ?
private async Task<String> PreProcessVideoToGetTextAsync(StorageFile file, int i)
{ /*--------To get frame from video----------*/
var thumbnail = await GetThumbnailAsync(file, i);
BitmapImage bitmapImage = new BitmapImage();
StringBuilder ocr = null;
InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
await RandomAccessStream.CopyAsync(thumbnail, randomAccessStream);
randomAccessStream.Seek(0);
SoftwareBitmap inputBitmap;
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(randomAccessStream);
// create a new stream and encoder for the new image
InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
BitmapEncoder enc = await BitmapEncoder.CreateForTranscodingAsync(ras, decoder);
BitmapBounds bounds = new BitmapBounds();
bounds.Height = 270;//screnheight/4 =270
bounds.Width = 960;//screenwidth/2 =960
bounds.X = 960;//screenwidth/2 =960
bounds.Y = 810;
enc.BitmapTransform.Bounds = bounds;
// write out to the stream
try
{
await enc.FlushAsync();
}
catch (Exception ex)
{
string exx = ex.ToString();
var dialog = new MessageDialog(exx);
await dialog.ShowAsync();
}
//Remain portion of code
}
I've already used the following code snippet to save video thumbnails in my uwp app, hopefully you can apply a little bit of changes as you want to use it.
private async Task PreProcessVideoToGetTextAsync(string videopath)
{
try
{
SoftwareBitmap softwareBitmap = null;
StorageFile videofile = await StorageFile.GetFileFromPathAsync(videopath);
var thumbnail = await GetThumbnailAsync(videofile);
Windows.Storage.Streams.InMemoryRandomAccessStream randomAccessStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
await Windows.Storage.Streams.RandomAccessStream.CopyAsync(thumbnail, randomAccessStream);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(randomAccessStream);
softwareBitmap = await decoder.GetSoftwareBitmapAsync();
StorageFile outputFile = await ApplicationData.Current.LocalCacheFolder.CreateFileAsync(Path.GetFileNameWithoutExtension(videopath) + ".jpg");//save path for video thumbnail image in app cache folder
using (Windows.Storage.Streams.IRandomAccessStream stream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
encoder.SetSoftwareBitmap(softwareBitmap);
encoder.BitmapTransform.ScaledWidth = 128;//thumbnail width
encoder.BitmapTransform.ScaledHeight = 128;//thumbnail height
encoder.IsThumbnailGenerated = true;
try
{
await encoder.FlushAsync();
if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 || softwareBitmap.BitmapAlphaMode == BitmapAlphaMode.Straight)
{
softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
}
var source = new Windows.UI.Xaml.Media.Imaging.SoftwareBitmapSource();
await source.SetBitmapAsync(softwareBitmap);
return;
}
catch (Exception err)
{
switch (err.HResult)
{
case unchecked((int)0x88982F81): //WINCODEC_ERR_UNSUPPORTEDOPERATION
// If the encoder does not support writing a thumbnail, then try again
// but disable thumbnail generation.
encoder.IsThumbnailGenerated = false;
break;
default:
throw err;
}
}
if (encoder.IsThumbnailGenerated == false)
{
await encoder.FlushAsync();
}
}
return;
}
catch (Exception)
{
return;
}
finally
{
GC.Collect();
}
}
private async Task<Windows.Storage.Streams.IInputStream> GetThumbnailAsync(StorageFile file)
{
var mediaClip = await Windows.Media.Editing.MediaClip.CreateFromFileAsync(file);
var mediaComposition = new Windows.Media.Editing.MediaComposition();
mediaComposition.Clips.Add(mediaClip);
return await mediaComposition.GetThumbnailAsync(
TimeSpan.Zero, 0, 0, Windows.Media.Editing.VideoFramePrecision.NearestFrame);
}
}

Convert Image to Base64 string

I am trying to convert an Image file to Base64 string in UWP with StorageFile
Here's the method I have:
public async Task<string> ToBase64String(StorageFile file)
{
var stream = await file.OpenAsync(FileAccessMode.Read);
var decoder = await BitmapDecoder.CreateAsync(stream);
var pixels = await decoder.GetPixelDataAsync();
var bytes = pixels.DetachPixelData();
return await ToBase64(bytes, (uint)decoder.PixelWidth, (uint)decoder.PixelHeight, decoder.DpiX, decoder.DpiY);
}
and ToBase64 goes like this:
private async Task<string> ToBase64(byte[] image, uint pixelWidth, uint pixelHeight, double dpiX, double dpiY)
{
//encode
var encoded = new InMemoryRandomAccessStream();
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, encoded);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, pixelWidth, pixelHeight, dpiX, dpiY, image);
await encoder.FlushAsync();
encoded.Seek(0);
//read bytes
var bytes = new byte[encoded.Size];
await encoded.AsStream().ReadAsync(bytes, 0, bytes.Length);
return System.Convert.ToBase64String(bytes);
}
and calling it from my MainPage.xaml.cs
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
string square_b64 = converter.ToBase64String(await storageFolder.GetFileAsync("Image.png")).Result;
However, This is not working. Any Heads up?
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFile file1 = await storageFolder.GetFileAsync("Image.png");
string _b64 = Convert.ToBase64String(File.ReadAllBytes(file1.Path));
This worked for me.

Get a new Image by cropping

I'm trying to convert my cropped image (and/or Grid) to new Normal Image , but it returns as it cropped , in same position, how to fix it, there is how works my program after cropping
private async void Save(object sender, RoutedEventArgs e)
{
RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(GGrid, 4096 , 2448);
// IBuffer pixels = await renderTargetBitmap.GetPixelsAsync();
IBuffer pixelBuffer = await renderTargetBitmap.GetPixelsAsync();
FileSavePicker fileSavePicker = new FileSavePicker();
fileSavePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
fileSavePicker.FileTypeChoices.Add("JPEG files", new List<string>() { ".png"});
fileSavePicker.SuggestedFileName = "image";
var outputFile = await fileSavePicker.PickSaveFileAsync();
if (outputFile == null)
{
// The user cancelled the picking operation
return;
}
using (IRandomAccessStream stream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Straight,
(uint)renderTargetBitmap.PixelWidth,
(uint)renderTargetBitmap.PixelHeight,
DisplayInformation.GetForCurrentView().LogicalDpi,
DisplayInformation.GetForCurrentView().LogicalDpi,
pixelBuffer.ToArray());
try
{
await encoder.FlushAsync();
}
catch (Exception err)
{
switch (err.HResult)
{
case unchecked((int)0x88982F81): //WINCODEC_ERR_UNSUPPORTEDOPERATION
// If the encoder does not support writing a thumbnail, then try again
// but disable thumbnail generation.
encoder.IsThumbnailGenerated = false;
break;
default:
throw err;
}
}
//if (encoder.IsThumbnailGenerated == false)
//{
// await encoder.FlushAsync();
//}
}
}
You need to translate and crop the bitmap.
double x,y,w,h;
GGrid.RenderTransform = new TranslateTransform
{
X = -x, // translate back to origin (0,0)
Y = -y
};
RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(GGrid, w, h); // use crop size

Create a BitmapImage from a Byte array and display it on an Image object UWP Raspberry Pi 3

I'm using this code to write a Byte Array inside a file BMP:
private async void ScriviBMP()
{
using (Stream stream = immagineBitmap.PixelBuffer.AsStream())
{
await stream.WriteAsync(arrayImmagine, 0, arrayImmagine.Length);
}
StorageFolder folder = KnownFolders.PicturesLibrary;
if (folder != null)
{
StorageFile file = await folder.CreateFileAsync("area2_128x128" + ".bmp", CreationCollisionOption.ReplaceExisting);
using (var storageStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, storageStream);
var pixelStream = immagineBitmap.PixelBuffer.AsStream();
var pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)immagineBitmap.PixelWidth, (uint)immagineBitmap.PixelHeight, 48, 48, pixels);
await encoder.FlushAsync();
}
}
}
Then i'm using this code to display the BMP image in a Image object
private async void VisBMP()
{
var file = await KnownFolders.PicturesLibrary.GetFileAsync("area2_128x128.bmp");
using (var fileStream = (await file.OpenAsync(Windows.Storage.FileAccessMode.Read)))
{
var bitImg = new BitmapImage();
//bitImg.UriSource = new Uri(file.Path);
bitImg.SetSource(fileStream);
image.Source = bitImg;
}
}
these functions take about 400 milliseconds to complete the process, that's a lot of time.
Is there a way to avoid the usage of a BMP file and use only a stream to display the image on the image object?
It can be that debugging the program can slow the processes? I'm using Visual Studio 2015.
You can transfer the data buffer(arrayImmagine) to image in InMemoryRandomAccessStream.These codes take about 200ms.I tested with following pieces of code. In addition, you can reference this article to get more information.
BitmapImage biSource = new BitmapImage();
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(bytes.AsBuffer());
stream.Seek(0);
await biSource.SetSourceAsync(stream);
}
image.Source = biSource;

BitmapEncoder flush throws Argument Exception

I'm trying to resize images in my UWP application. Most of the time the appended code works, but sometimes await encoder.FlushAsync(); throws an ArgumentException.
I've headed over to MSDN (https://msdn.microsoft.com/en-us/library/windows/apps/windows.graphics.imaging.bitmapencoder.bitmaptransform.aspx) and they tell me (at "Remarks"):
If you try scale an image stored in an indexed pixel format using the BitmapTransform member, FlushAsync fails with HRESULT WINCODEC_ERR_INVALIDPARAMETER . Instead, you must use GetPixelDataAsync to obtain the scaled pixel data and then use SetPixelData to set it on the encoder.
I've tried to do that, see the two commented lines (which look somehow wrong to me due to the repetition). On the second line (where I try to SetPixelData) the Encoder rewards me with an buffer allocated not sufficient Exception.
var decoder = await BitmapDecoder.CreateAsync(streamToReadFrom.AsStream().AsRandomAccessStream());
if (decoder.OrientedPixelHeight > height ||
decoder.OrientedPixelWidth > width)
{
var resizedStream = new InMemoryRandomAccessStream();
BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAsync(resizedStream, decoder);
encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant;
encoder.BitmapTransform.ScaledHeight = newHeight;
encoder.BitmapTransform.ScaledWidth = newWidth;
//"buffer allocated not sufficient"
// var pd = await decoder.GetPixelDataAsync(BitmapPixelFormat.Rgba16, BitmapAlphaMode.Ignore,
// encoder.BitmapTransform, ExifOrientationMode.IgnoreExifOrientation, ColorManagementMode.DoNotColorManage);
// encoder.SetPixelData(BitmapPixelFormat.Rgba16, BitmapAlphaMode.Ignore,
// decoder.OrientedPixelWidth, decoder.OrientedPixelHeight, decoder.DpiX, decoder.DpiY, pd.DetachPixelData());
// write out to the stream
// might fail cause https://msdn.microsoft.com/en-us/library/windows/apps/windows.graphics.imaging.bitmapencoder.bitmaptransform.aspx
await encoder.FlushAsync();
// Read out resizedStream and return
}
Example image which causes this issue: http://www.spiegel.de/images/image-1028227-hppano-lqbn.jpg. Unit Test here: https://github.com/famoser/OfflineMedia/blob/master/Famoser.OfflineMedia.UnitTests/Presentation/ImageResizeTest.cs
How can I avoid the ArgumentException? How do I know an image is in an "indexed pixel format", and how can I resize this format too?
On the second line (where I try to SetPixelData) the Encoder rewards me with an buffer allocated not sufficient Exception.
This is because when you SetPixelData, the pixel data doesn't match it from GetPixelDataAsync. You can for example code like this:
if (file != null)
{
BitmapImage bmp = new BitmapImage();
using(var imageStream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
{
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(imageStream);
InMemoryRandomAccessStream pixelras = new InMemoryRandomAccessStream();
BitmapEncoder pixelencoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, pixelras);
BitmapTransform transform = new BitmapTransform();
transform.InterpolationMode = BitmapInterpolationMode.Fant;
transform.ScaledHeight = 400;
transform.ScaledWidth = 400;
var provider = await decoder.GetPixelDataAsync(BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
transform,
ExifOrientationMode.RespectExifOrientation,
ColorManagementMode.DoNotColorManage);
var pixels = provider.DetachPixelData();
pixelencoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, 400,
400, decoder.DpiX, decoder.DpiY, pixels);
try
{
await pixelencoder.FlushAsync();
}
catch(Exception ex)
{
}
bmp.SetSource(pixelras);
img.Source = bmp;
}
}
How do I know an image is in an "indexed pixel format", and how can I resize this format too?
I couldn't find any effective way to detect an indexed pixel format image, but since it is said
If you try scale an image stored in an indexed pixel format using the BitmapTransform member, FlushAsync fails with HRESULT WINCODEC_ERR_INVALIDPARAMETER . Instead, you must use GetPixelDataAsync to obtain the scaled pixel data and then use SetPixelData to set it on the encoder.
It is a method to use catch the exception and use SetPixelData again, for example:
if (file != null)
{
BitmapImage bmp = new BitmapImage();
using(var imageStream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
{
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(imageStream);
InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAsync(ras, decoder);
encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant;
encoder.BitmapTransform.ScaledHeight = 400;
encoder.BitmapTransform.ScaledWidth = 400;
try
{
await encoder.FlushAsync();
bmp.SetSource(ras);
}
catch (Exception ex)
{
if (ex.HResult.ToString() == "WINCODEC_ERR_INVALIDPARAMETER")
{
InMemoryRandomAccessStream pixelras = new InMemoryRandomAccessStream();
BitmapEncoder pixelencoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, pixelras)
BitmapTransform transform = new BitmapTransform();
transform.InterpolationMode = BitmapInterpolationMode.Fant;
transform.ScaledHeight = 400;
transform.ScaledWidth = 400;
var provider = await decoder.GetPixelDataAsync(BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
transform,
ExifOrientationMode.RespectExifOrientation,
ColorManagementMode.DoNotColorManage);
var pixels = provider.DetachPixelData();
pixelencoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, 400,
400, decoder.DpiX, decoder.DpiY, pixels);
try
{
await pixelencoder.FlushAsync();
bmp.SetSource(pixelras);
}
catch
{
}
}
}
img.Source = bmp;
}
}

Categories

Resources