I was trying to create a PNG file from a canvas. The canvas has a image and also three textblocks. The purpose was to allow the user to move these textblocks around the canvas, and then, save the screenshot to an image.
The captured image looks ok. I used RenderTargetBitmap to capture the canvas. But once I tried to encode the RenderTargetBitmap to the PNG or JPEG, the text becomes very blurry.
Here is the original pictures:
Here is the code I used:
var pixels = await ArrangePicturePage.ArrangedImage.GetPixelsAsync();
byte[] bytes = pixels.ToArray();
IRandomAccessStream stream = new InMemoryRandomAccessStream();
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
encoder.SetPixelData(BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
(uint) ArrangePicturePage.ArrangedImage.PixelHeight,
(uint) ArrangePicturePage.ArrangedImage.PixelWidth
, 96.0, 96.0, bytes);
await encoder.FlushAsync();
byte[] resultingBuffer = new byte[stream.Size];
await stream.ReadAsync(resultingBuffer.AsBuffer(), (uint)resultingBuffer.Length, InputStreamOptions.None);
The resultingBuffer is the blob that I assume is the PNG or JPEG. Here is how it looks:
Is there something wrong with my conversion code that blurred the text?
You can control the compression by seting the InterpolationMode on the BitmapTransform you pass to the BitmapEncoder.
The default setting optimizes for performance over quality. If your need is for quality at the expense of performance then you can bump it up to BitmapInterpolationMode.Fant.
Related
I created a model using CINEMA 4D which has some colors like green, gray, red..., and exported as obj format. Then I converted the obj file to gltf format file using obj2gltf tool, and load gltf file on Cesium like this:
var position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, height);
var heading = Cesium.Math.toRadians(10000);
var pitch = 0;
var roll = 0;
var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);
entity = viewer.entities.add({
name : url,
position : position,
orientation : orientation,
model : {
uri : url,
minimumPixelSize : 128,
maximumScale : 20000,
}
});
viewer.trackedEntity = entity;
But on the Chrome browser, the model's color is completely black.
When I disabled the chrome GPU acceleration option,it is normal.
Then I checked my graphics card is NVIDIA Geforce GTX,but on another notebook compute with AMD graphics card, it works normally.
I tried some other obj file which size less than the obj(about 44M),and they worked normally.
I tried other browser IE and Firefox, the result is the same as the chrome browser.
Did any body have the same problem?
Please help me to issue it.
Thanks very much and forgive my poor chinese english!
Just copying Sean's answer from the Cesium forum, so this question can be marked resolved:
Since you are using obj2gltf, pass in --materialsCommon and the materials should show up correctly.
Trying to read an image that is stored in the pictures library via an URI the image is never displayed (in an Image control). Reading the same image via a stream works (assuming the app hat the Picture Library capability declared of course). Reading images from the application's data folder via an URI works.
Does someone know what could be wrong?
Here is how I (unsucessfully) try to read an image via an URI:
var imageFile = (await KnownFolders.PicturesLibrary.GetFilesAsync()).FirstOrDefault();
string imagePath = imageFile.Path;
Uri uriSource = new Uri(imagePath);
var bitmap = new BitmapImage(uriSource);
this.Image.Source = bitmap;
Here is how I sucessfully read the same image via a stream:
var imageFile = (await KnownFolders.PicturesLibrary.GetFilesAsync()).FirstOrDefault();
BitmapImage bitmap;
using (var stream = await imageFile.OpenReadAsync())
{
bitmap = new BitmapImage();
await bitmap.SetSourceAsync(stream);
}
this.Image.Source = bitmap;
I need to read the image via URI because this is the fastest way to read images and is async by nature, working perfectly with data binding.
There is no URI for the pictures library. You'll need to get the StorageFile and stream it in.
The file URI you use doesn't work because the app doesn't have direct access to the PicturesLibrary and so cannot reference items there by path. The StorageFile object provides brokered access to locations that the app doesn't natively have permissions to.
I am trying to save an image selected with FileOpenPicker. I am lunching this event when an image is selected
async void photoChooserTask_Completed(object sender, PhotoResult e)
{
// get the file stream and file name
Stream photoStream = e.ChosenPhoto;
string fileName = Path.GetFileName(e.OriginalFileName);
// persist data into isolated storage
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (Stream current = await file.OpenStreamForWriteAsync())
{
await photoStream.CopyToAsync(current);
}
}
But this code which will give me the lenght of the saved file return 0
var properties = await file.GetBasicPropertiesAsync();
i = properties.Size;
Have I done something wrong in saving the image?
You may need to flush the stream.
If that does not work, add a breakpoint and check the two streams' lengths after the copy. Are they equal? They should be. Anything suspicious on those two stream objects?
Edit
On the image you posted, I can see that you use the SetSource method of a BitmapImage with the same Stream that you copy. Once you do that, the Stream's Position will be at the end, as it was just read by that call.
CopyToAsync copies everything after the current Position of the Stream you call it on. Since the position is at the end, because it was just read, the CopyToAsync does not copy anthing.
All you need to do to fix your problem is set the stream's Position to 0.
Can I use phantomjs to create an image of the contents of <div><iframe ..></div> (The div contains an iframe)
how do I make this image (binary data) as part of a json ? , as ({img: binary data}) ?
Is it possible to load the iframe by itself? If you can achieve that then there's no reason why you can't call var base64string = page.renderBase64(); to get a base-64 encoded string. See the API for renderBase64().
You can re-create the image later by evaluating img.src = "data:image/png;base64," + base64string;.
I want to load local html file which in the local folder to the webview, but WebView doesn't support 'ms-aspx:///' protocal, I found a solution to read the html file to stream, and then convert it to string, using NavigateToString method to load the html, it works well. But, If there's an image in the html file, the image couldn't display, anyone can help?
I have solved.
Solution:
Convert the image file to base64 string
StorageFolder appFolder = ApplicationData.Current.LocalFolder;
StorageFile file = await appFolder.GetFileAsync("SplashScreen.png");
using (var stream = await file.OpenAsync(FileAccessMode.Read))
{
var reader = new DataReader(stream.GetInputStreamAt(0));
var bytes = new byte[stream.Size];
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(bytes);
base64 = Convert.ToBase64String(bytes);
}
Use StringBuilder to create the html string
sb.Append("<html><head><title>Image test</title></head><body><p>This is a test app!</p><img src=\"data:image/png;base64,");
sb.Append(base64);
sb.Append("\" /></body></html>");
TestWebView.NavigateToString(sb.ToString());
Try using the ms-appx-web:// scheme instead of ms-aspx:// to load html from a WebView. If that doesn't work, you may need to use the ms-appdata:// scheme to access the image if it's in your application data folder.
Some further resources that might help:
How to load a local HTML-File into Webview
URI schemes
How to reference content