How to do text block text font display smoothness and antialiasing in windows phone 8.1 c# - windows-phone-8.1

I am writing, write text on text block dynamically and save as image. Put image on text is not displayed properly smoothness.
I am use This Code :
xaml :<Grid x:Name="gridCanvasPanel" Grid.Row="1" Margin="0,12" Tap="CanvasPanel_Tap">
<Canvas x:Name="CanvasPanel" Height="400" VerticalAlignment="Top" Background="Green">
<RichTextBox Width="450" Canvas.Left="10" Canvas.Top="20">
<Paragraph>
<Run FontSize="25" Foreground="White">Now we're e-mailing and tweeting and texting so much, a phone call comes as a fresh surprise. I get text messages on my cell phone all day long, and it warbles to alert me that someone has sent me a message on Facebook or a reply or direct message on Twitter, but it rarely ever rings.</Run>
<LineBreak/>
<Run FontSize="20" Foreground="YellowGreen">Susan Orlean</Run>
</Paragraph>
</RichTextBox>
</Canvas>
</Grid>
C# Code :
var bmp = new RenderTargetBitmap();
await bmp.RenderAsync(this.CanvasPanel);
// Setting.
bitmap = bmp as RenderTargetBitmap;
StorageFile file = null;
file = obj;
using (var stream = await file.OpenStreamForWriteAsync())
{
// Initialization.
var pixelBuffer = await bitmap.GetPixelsAsync();
var logicalDpi = DisplayInformation.GetForCurrentView().LogicalDpi;
// convert stream to IRandomAccessStream
var randomAccessStream = stream.AsRandomAccessStream();
// encoding to PNG
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, randomAccessStream);
// Finish saving
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied, (uint)bitmap.PixelWidth,
(uint)bitmap.PixelHeight, logicalDpi, logicalDpi, pixelBuffer.ToArray());
// Flush encoder.
await encoder.FlushAsync();
}

Set Image BitmapProperty on bitmap Encoder.
IAsyncOperation<BitmapEncoder> CreateEncoderWithEncodingOptionsAsync(Windows.Storage.Streams.IRandomAccessStream stream)
{
var propertySet = new Windows.Graphics.Imaging.BitmapPropertySet();
var qualityValue = new Windows.Graphics.Imaging.BitmapTypedValue(
1.0, // Maximum quality
Windows.Foundation.PropertyType.Single
);
propertySet.Add("ImageQuality", qualityValue);
return Windows.Graphics.Imaging.BitmapEncoder.CreateAsync(
Windows.Graphics.Imaging.BitmapEncoder.JpegEncoderId,
stream,
propertySet
);
// Encoder is initialized with encoding options.
}

Related

BitmapDecoder .GetPixelDataAsync(params) changing the orientation of captured image

I am working with an UWP app and facing an issue while displaying a camera captured image(Portrait) in an image control.If I use parmaterized version
decoder.GetPixelDataAsync(
BitmapPixelFormat.Bgra8, // WriteableBitmap uses BGRA format
BitmapAlphaMode.Ignore,
transform,
ExifOrientationMode.IgnoreExifOrientation, // This sample ignores Exif orientation
ColorManagementMode.DoNotColorManage);
The outcome is image with change in orientation of 90 degree in anticlock direction. //Issue
Oriented Normal
However default decoder.GetPixelDataAsync();works fine.
Problem here is I cannot use default version of GetPixelDataSync() as I need to scale the image using BitmapTransformation.
Please help.
Complete Code:
public async Task PrepareCapturedImage(StorageFile originalFile)
{
try
{
BitmapImage capturedImage_ = new BitmapImage();
BitmapDecoder decoder = null;
// the image is sometimes not created and we are trying to access it
await Task.Delay(300);
using (IRandomAccessStream stream = await originalFile.OpenAsync(FileAccessMode.Read))
{
capturedImage_.SetSource(stream);
decoder = await BitmapDecoder.CreateAsync(stream);
}
BitmapTransform transform = new BitmapTransform();
uint newHeight = Convert.ToUInt32(capturedImage_.PixelHeight);
uint newWidth = Convert.ToUInt32(capturedImage_.PixelWidth);
transform.ScaledHeight = newHeight;
transform.ScaledWidth = newWidth;
PixelDataProvider pixelData = await decoder.GetPixelDataAsync(
BitmapPixelFormat.Bgra8, // WriteableBitmap uses BGRA format
BitmapAlphaMode.Ignore,
transform,
ExifOrientationMode.IgnoreExifOrientation, // This sample ignores Exif orientation
ColorManagementMode.DoNotColorManage);
// An array containing the decoded image data, which could be modified before being displayed
byte[] sourcePixels = pixelData.DetachPixelData();
using (InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream())
{
BitmapEncoder enc = null;
BitmapPropertySet propertySet = new BitmapPropertySet();
enc = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, ras, propertySet);
// write the pixel data to our stream
enc.SetPixelData(decoder.BitmapPixelFormat, decoder.BitmapAlphaMode, newWidth, newHeight, decoder.DpiX, decoder.DpiY, sourcePixels);
await enc.FlushAsync();
ras.Seek(0);
BitmapImage image = new BitmapImage();
image.SetSource(ras);
cameraOutputImage.Source = image;
}
}
catch (Exception ex)
{
}
}

How to encode IImageProvider as a PNG image?

Assuming I have a LumiaImagingSDK rendering chain setup, with a final IImageProvider object that I want to render, how do I encode that into a PNG image?
Lumia Imaging SDK supports PNG images as input, however there isn't a "PNG Renderer" avaliable in the SDK.
Luckily if you are developing for Windows 8.1 (StoreApplication / universal application / Windows phone 8.1 project) there is a Windows encoder (Windows.Graphics.Imaging.BitmapEncoder) you can use.
Assuming the IImageProvider you want to render is called "source" this is a code snippet you can use to encode the resulting image as PNG:
using Lumia.Imaging;
using Windows.Graphics.Imaging;
using System.IO;
...
using (var renderer = new BitmapRenderer(source, ColorMode.Bgra8888))
{
var bitmap = await renderer.RenderAsync();
byte[] pixelBuffer = bitmap.Buffers[0].Buffer.ToArray();
using (var stream = new InMemoryRandomAccessStream())
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream).AsTask().ConfigureAwait(false);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)bitmap.Dimensions.Width, (uint)bitmap.Dimensions.Height, 96, 96, pixelBuffer);
await encoder.FlushAsync().AsTask().ConfigureAwait(false);
//If InMemoryRandomAccessStream (IRandomAccessStream) works for you, end here.
//If you need an IBuffer, here is how you get one:
using (var memoryStream = new MemoryStream())
{
memoryStream.Capacity = (int)stream.Size;
var ibuffer = memoryStream.GetWindowsRuntimeBuffer();
await stream.ReadAsync(ibuffer, (uint)stream.Size, InputStreamOptions.None).AsTask().ConfigureAwait(false);
}
}
}
This will give you bytes in memory as either InMemoryRandomAccessStream (IRandomAccessStream) or an IBuffer depending on what you need. You can then save the buffer to disk or pass it to other parts of your application.

How to set a background image by code on windows phone?

My question is very simple but I don't find a solution that works.
I code a Windows Phone app and I have to change the background. The change depends of the user profile on the application. If the user is a male, the app display a blue background, if she is a female, a pink one.
I've tried to bind the background but I still have a blink effect (black to the background image).
It is very visible when the app navigates between two pages but invisible when the change is made on the same page.
I tried these solutions too but the background stay black:
string uri = String.Format("/Assets/Background{0}.png", App.Context.SelectedUser.IsMan ? "Boy" : "Girl");
var imageBrush = new System.Windows.Media.ImageBrush
{
ImageSource = new BitmapImage(new Uri(uri, UriKind.Relative))
};
this.Background = imageBrush;
string uri = String.Format("/Assets/Background{0}.png", App.Context.SelectedUser.IsMan ? "Boy" : "Girl");
var imageBrush = new System.Windows.Media.ImageBrush
{
ImageSource = new BitmapImage(new Uri(uri, UriKind.Relative))
};
App.RootFrame.Background = imageBrush;
I tried with .jpg and .png image file but none works.
Is my code wrong?
Anyone has a suggestion?
Thanks a lot :-)
This code works in a blank silverlight app in Windows Phone 8.
In Xaml:
<Grid x:Name="LayoutRoot" >
<Grid.Background>
<ImageBrush ImageSource="/Assets/boy.png" Stretch="UniformToFill" />
</Grid.Background>
<Button Content="Change" Click="Button_Click" />
</Grid>
and in the code behind:
private void Button_Click(object sender, RoutedEventArgs e)
{
System.Windows.Media.Imaging.BitmapImage bmp = new System.Windows.Media.Imaging.BitmapImage();
bmp.UriSource = new Uri("/Assets/girl.png", UriKind.Relative);
var imageBrush = new System.Windows.Media.ImageBrush
{
ImageSource = bmp
};
LayoutRoot.Background = imageBrush;
}

"Index was outside the bounds of the array" in ZXing.Net Decode method

I'm new in Windows Phone 8.1 development.
I'm doing a simple app to scan barcode using ZXing.Net and Windows Phone 8.1 SDK.
When I call the Decode method I got an exception with text of "Index was outside the bounds of the array"
Here is a portion of code:
InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();
await Camera.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream);
stream.Seek(0);
var properties = Camera.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview);
var videoEncodingProperties = properties as VideoEncodingProperties;
WriteableBitmap writableImg = new WriteableBitmap((int)videoEncodingProperties.Width, (int)videoEncodingProperties.Height);
await writableImg.SetSourceAsync(stream);
result = barcode.Decode(writableImg); // The exception is here
if (result != null)
{
debug.Text = result.Text;
}
else
{
debug.Text = "No results";
}
I think the problem is with the size of the WritableImage, because when I run the app on the emulator (and definitely there is no barcode in it), the decoder decodes and returns no value (and that's ok), but when I run it on my WP8.1 device, I got an exception with a text of:
"Index was outside the bounds of the array"
I tried to resize the writable image with no results! but maybe I'm resizing a bad way or values.
Any help with that? Thanks.
You will need to emulate this action:
var stream = await file.OpenReadAsync();
// initialize with 1,1 to get the current size of the image
var writeableBmp = new WriteableBitmap(1, 1);
writeableBmp.SetSource(stream);
// and create it again because otherwise the WB isn't fully initialized and decoding
// results in a IndexOutOfRange
writeableBmp = new WriteableBitmap(writeableBmp.PixelWidth, writeableBmp.PixelHeight);
stream.Seek(0);
writeableBmp.SetSource(stream);
first pull the image out of the stream then do it again with the PixelWidth found on the actual image.

How to update a custom image Live Tile every minute in Windows Phone 8.1?

There are quite a few Windows Phone 8.1 apps (e.g. Clock hub, Analog Clock Tile, etc.) which allow you to pin an analog clock on the main screen.
I am trying to do the same by following this sample which shows me how to update an XML document every minute.
But if I am going to create an analog clock tile then it needs to be an image.
I have tried to use XamlRenderingBackgroundTask with RenderTargetBitmap to generate the image, this bit works. What I am not sure is how can I update this image every minute.
Any help wold be greatly appreciated!
I took the sample you provided and modified it to generate a custom image live tile every minute.
I've tested it on my phone and it seems to be working OK. You might need to do more testing such as memory usage testing to make sure it doesn't go over the cap (maybe can reduce planTill to 30 minutes to generate less tiles in the loop?).
The UserControl xml file SquareFrontTile1.xml
<Border Height="360" Width="360" Background="#00b2f0" xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:mc='http://schemas.openxmlformats.org/markup-compatibility/2006'>
<TextBlock Text="{0}" HorizontalAlignment="Left" VerticalAlignment="Top" Foreground="White" FontSize="50.667" />
</Border>
The code
public static async void UpdateAsync(BackgroundTaskDeferral deferral)
{
TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
IReadOnlyList<ScheduledTileNotification> plannedUpdated = tileUpdater.GetScheduledTileNotifications();
string language = GlobalizationPreferences.Languages.First();
CultureInfo cultureInfo = new CultureInfo(language);
DateTime now = DateTime.Now;
DateTime planTill = now.AddHours(1);
DateTime updateTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0).AddMinutes(1);
if (plannedUpdated.Count > 0)
updateTime = plannedUpdated.Select(x => x.DeliveryTime.DateTime).Union(new[] { updateTime }).Max();
StorageFolder folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Assets");
StorageFile file = await folder.GetFileAsync("SquareFrontTile1.xml");
string xml = await Windows.Storage.FileIO.ReadTextAsync(file);
string startXml = string.Format(xml, now.ToString(cultureInfo.DateTimeFormat.ShortTimePattern));
XmlDocument tileDocumentNow = await GetTileXmlDocument(startXml);
TileNotification notification = new TileNotification(tileDocumentNow) { ExpirationTime = now.AddMinutes(1) };
tileUpdater.Update(notification);
for (var startPlanning = updateTime; startPlanning < planTill; startPlanning = startPlanning.AddMinutes(1))
{
Debug.WriteLine(startPlanning);
Debug.WriteLine(planTill);
try
{
string updateXml = string.Format(xml, startPlanning.ToString(cultureInfo.DateTimeFormat.ShortTimePattern));
XmlDocument updatedTileDocument = await GetTileXmlDocument(updateXml);
ScheduledTileNotification scheduledNotification = new ScheduledTileNotification(updatedTileDocument, new DateTimeOffset(startPlanning)) { ExpirationTime = startPlanning.AddMinutes(1) };
tileUpdater.AddToSchedule(scheduledNotification);
Debug.WriteLine("schedule for: " + startPlanning);
}
catch (Exception e)
{
Debug.WriteLine("exception: " + e.Message);
}
}
deferral.Complete();
}
private static async Task<XmlDocument> GetTileXmlDocument(string xml)
{
Border tileUIElement = XamlReader.Load(xml) as Border;
string liveTileImageName = string.Format("UpdatedLiveTile_{0}.png", DateTime.Now.Ticks.ToString());
if (tileUIElement != null)
{
RenderTargetBitmap rtb = new RenderTargetBitmap();
await rtb.RenderAsync(tileUIElement, 150, 150);
IBuffer pixels = await rtb.GetPixelsAsync();
DataReader dReader = Windows.Storage.Streams.DataReader.FromBuffer(pixels);
byte[] data = new byte[pixels.Length];
dReader.ReadBytes(data);
var outputFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.CreateFileAsync(liveTileImageName, Windows.Storage.CreationCollisionOption.ReplaceExisting);
var outputStream = await outputFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
BitmapEncoder enc = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, outputStream);
enc.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied, 150, 150, 96, 96, data);
await enc.FlushAsync();
}
var tileDocument = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Image);
var tileImageAttributes = tileDocument.GetElementsByTagName("image");
XmlElement tmp = tileImageAttributes[0] as XmlElement;
tmp.SetAttribute("src", liveTileImageName);
return tileDocument;
}
I am not going to fully answer the question since I am myself trying to get this working at present. However I will set you in right direction. I have done this in past with windows 8.
What you need to do is create Tile Updater and schedule tiles updates every so often.. in this case one every minute. The tile schema chosen can have be image or text or a combination of both.
you can find the TileSchema catalogue here
http://msdn.microsoft.com/en-us/library/windows/apps/hh761491.aspx
and details of Tile Schema here
http://msdn.microsoft.com/en-us/library/windows/apps/br212859.aspx
Here is a Windows 8 sample
http://code.msdn.microsoft.com/windowsapps/scheduled-notifications-da477093
Here is a snippet from my code which isn't working correctly so far.. tile is blank
TileUpdater updater = TileUpdateManager.CreateTileUpdaterForApplication();
XmlDocument document = new XmlDocument();
document.LoadXml(str2);
ScheduledTileNotification notification2 = new ScheduledTileNotification(document, new DateTimeOffset(time4));
notification2.ExpirationTime = (new DateTimeOffset?((DateTimeOffset)time4.AddMinutes(1.0)));
ScheduledTileNotification notification = notification2;
updater.AddToSchedule(notification);
Once I finish this, I will write up a blog post and add a link here
I have created a repro project that tries to do this from within sample app (not background task).
http://1drv.ms/1nai8nn
The sample work for me, I add to Windows Phone Silverlight 8.1. You must change Notification Services from MPN to WNS in WMAppManifest.xml and add Background task, tick System event, Timer in Package.appxmanifest (Declarations tab).
#Justin XL: your code not work for me, error in line
Border tileUIElement = XamlReader.Load(xml) as Border;
Error: The application called an interface that was marshalled for a different thread.