SkiaSharp drawing with OpenGL/Vulkan backend from console application - c#

I want to draw something with GPU acceleration (using OpenGL or Vulkan) using SkiaSharp and save the image later. There is no need to display the image anywhere in the application, because it's a console application targeting Windows and Linux.
I already tried the following code, with various variations, but nothing worked (raises an exception at var surface = SKSurface.Create(context, false, info); because glInterface and context are null.
Can somebody give me a hint?
var glInterface = GRGlInterface.Create();
var context = GRContext.CreateGl(glInterface);
var info = new SKImageInfo(256, 256);
var surface = SKSurface.Create(context, false, info);
var canvas = surface.Canvas;
In the end it would be nice to have the ability to call SKBitmap.SetPixels(IntPrt) or something similar to set the resulting bitmap buffer to a specific place.

The solution is you need to manually create an OpenGL context first.
Have a look at https://github.com/mono/SkiaSharp/blob/master/tests/Tests/GRContextTest.cs for implementation details.
For copying the rendered pixel buffer you can use SKSurface.ReadPixels.

Related

Lumia Imaging SDK JpegRenderer.RenderAsync InvalidOperationException

I'm using Lumia Imaging SDK ver 2.0 to crop images in Windows Phone 8.1 RT application. The code works fine, but JpegRenderer.RenderAsync() sometimes throws InvalidOperationException, Operation is not valid due to the current state of the object.
The issue reproduces every time with a some images, and crashes the application. I use the following code for cropping:
using (StorageFileImageSource inputImageSource = new StorageFileImageSource(inputImageFile))
{
using (FilterEffect filterEffect = new FilterEffect(inputImageSource))
{
// Create cropping filter.
List<IFilter> filters = new List<IFilter>();
CropFilter cropFilter = new CropFilter(croppedImageSize);
filters.Add(cropFilter);
// Add filters to effects.
filterEffect.Filters = filters;
// Create renderer with above filters and render new image.
using (JpegRenderer renderer = new JpegRenderer(filterEffect))
{
IBuffer croppedImage = await renderer.RenderAsync();
return croppedImage.ToArray();
}
}
}
I referred to this resource and it says the JpegRenderer.RenderAsync() throws InvalidOperationException when the filter property value changes while the rendering is in progress. I don't change the value of the property once it's set, then why is the exception being thrown?
I figured out the problem, and as David said, I was passing wrong dimensions which were larger than the size of the image. I was using BitmapDecoder.PixelHeight and BitmapDecoder.PixelWidth to calculate dimensions.
However, in some images having orientation data in EXIF data, BitmapDecoder.PixelHeight gave the width of the image and vice-versa. For this, I had to use BitmapDecoder.OrientedPixelHeight and BitmapDecoder.OrientedPixelWidth to get the actual height and width of the image, accommodating the orientation of the image.

How to find barcodes of a PDF document

I started searching how to create a Windows Phone 8 app to recognize barcodes inside a PDF document.
My best guest is to following the process below:
Find a lib to split PDF documents into image streams (one per page).
Find a lib to recognize if there is a barcode in the image stream:
2.1. Try to recognize barcode in each portion of the image, i. e.:
try #1 (from y = 0, x = 0 to y = 100, x = 100);
try #2 (from y = 100, x = 0 to y = 200, x = 100);
try #3 (from y = 200, x = 0 to y = 300, x = 100);
and so on.
I'm wondering if this is the best approach to accomplish barcode recognition in a PDF document using WP8.
Another concern is about whether this process when executed by a not so good device will present an acceptable performance.
Someone already did that? Any advice?
UPDATE
I want to scan ITF barcodes, i. e., I need to scan the barcode in this image:
I'm trying to start achieving the scanning barcodes from a Image, but I'm not getting success. Below is my first try:
//get the assets folder for the app
StorageFolder folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Assets");
BitmapSource bitmapSource = await GetBitmapImage(folder, "Barcode.png");
WriteableBitmap writeableBitmap = new WriteableBitmap(bitmapSource);
var rgb = new RGBLuminanceSource(writeableBitmap.ToByteArray(), writeableBitmap.PixelWidth, writeableBitmap.PixelHeight);
var hybrid = new HybridBinarizer(rgb);
BinaryBitmap binBitmap = new BinaryBitmap(hybrid);
Reader reader = new ITFReader();
try
{
Result result = reader.decode(binBitmap);
if (result != null)
{
this.textBlock.Text = result.Text;
}
}
catch (Exception ex)
{
this.textBlock.Text = ex.Message;
}
Unfortunately, my text box is being filled up with this Exception:
Exception of type 'com.google.zxing.ReaderException' was thrown.
I'm using this "lib": https://silverlightzxing.codeplex.com/
Yes, this concept actually works.
Read the PDF as Image
after that use any external Library to detect Barcodes from image. (There are many libraries available to do so)
And for another concern that you mentioned regarding performance of Low-End devices, it depends on many things.
First of all it depends on the library that you use to convert PDF to Image
then library that you use to detect Barcode from Image.
though there is no certainity for Time Complexity in this Task, what i think is it will not take much time then required..! It's a general process, so you can go with the scenario above.
Hope that helps...
I'd like to help you to implement the part 1 of the solution, render PDF to image:
this blog post shows how to do it on windows phone and this lib can be used to convert PDFs to images in universal windows store apps as well as xamarin apps. I personally use it in my projects and because it offers same API for all platforms it fits incredibly well.

Unity3d - 2 issues with Facebook Sharing in Window Phone

Everybody,I must say that I have post this question 3 times in Unity Community (include answer hub and its forum) but no one can solve it.
I use TakeScreenShot() function (it's in the InteractiveConsole example in FB SDK for Unity) to take a screenshot and post it to FB. But there are 2 problems appeared:
First: the screenshot that's captured is a gray blank like this: http://i7.minus.com/iXiHlCcSWaVfC.jpg
Second: No one can see my post except me although I set the photo to public.
How can I fix these problems?
Here is the code of TakeScreenShot() function:
private IEnumerator TakeScreenshot() {
yield return new WaitForEndOfFrame();
var width = Screen.width;
var height = Screen.height;
var tex = new Texture2D(width, height, TextureFormat.RGB24, false);
// Read screen contents into the texture
tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
tex.Apply();
byte[] screenshot = tex.EncodeToPNG();
var wwwForm = new WWWForm();
wwwForm.AddBinaryData("image", screenshot, "InteractiveConsole.png");
wwwForm.AddField("message", "herp derp. I did a thing! Did I do this right?");
FB.API("me/photos", Facebook.HttpMethod.POST, Callback, wwwForm);
Debug.Log("done");
}
I hope you solved your issues but I will answer anyways to your questions:
•First: the screenshot that's captured is a gray blank.
I think this works for Windows Phone only since very recently on Unity 4.5, update and try again.
Unity 4.5 Windows Phone Fixes
Grey Textures happen if you forget to call the Apply method. You will end up with a grey texture if forget to call. I see you are calling tex.Apply() but my guess is that you added it later and you may be seeing an old grey texture. Your code should work as it is. If you still get the grey Texture after updating to version 4.5 or later, try to wait a little time between the Apply and calling the EncodeToPNG(), maybe yield between those calls. Bear in mind that both are expensive operations.
•Second: No one can see my post except me although I set the photo to public.
That is because you have not go live (public) with you facebook app, during development only you will see you and your development team will see the messages. By the way fecebook will not approve hardcoded messages so even though this may work, and I know you based your code on facebook own smaples, you will need to allow the user to edit the message before posting.

SharpDX render in WPF

I want to draw lines as fast as possible. For that reason I implemented a method using InteropBitmap. This works quite good. Next step was to compare with ShardDX. Basically what I want to do is:
Running the following code in a BackgroundWorker. This does inform the WPF about an update of WIC. I found out that this code (creating all needed for ShapeDX and draw line) takes about 10ms longer than doing the same using InteropBitmap.
My question now is simply, how to speed this up? Can I change the code somehow that I only have to call BeginDraw, create lines and EndDraw, not always doing all of this Image Encoding/Decoding stuff? Or is there a better approach?
var wicFactory = new ImagingFactory();
var d2dFactory = new SharpDX.Direct2D1.Factory();
const int width = 800;
const int height = 200;
var wicBitmap = new Bitmap(wicFactory, width, height, SharpDX.WIC.PixelFormat.Format32bppBGR, BitmapCreateCacheOption.CacheOnLoad);
var renderTargetProperties = new RenderTargetProperties(RenderTargetType.Default, new PixelFormat(Format.Unknown, AlphaMode.Unknown), 0, 0, RenderTargetUsage.None, FeatureLevel.Level_DEFAULT);
var d2dRenderTarget = new WicRenderTarget(d2dFactory, wicBitmap, renderTargetProperties);
var solidColorBrush = new SharpDX.Direct2D1.SolidColorBrush(d2dRenderTarget, SharpDX.Color.White);
d2dRenderTarget.BeginDraw();
//draw whatever you want
d2dRenderTarget.EndDraw();
// Memorystream.
MemoryStream ms = new MemoryStream();
var stream = new WICStream(wicFactory, ms);
// JPEG encoder
var encoder = new SharpDX.WIC.JpegBitmapEncoder(wicFactory);
encoder.Initialize(stream);
// Frame encoder
var bitmapFrameEncode = new BitmapFrameEncode(encoder);
bitmapFrameEncode.Initialize();
bitmapFrameEncode.SetSize(width, height);
var pixelFormatGuid = SharpDX.WIC.PixelFormat.FormatDontCare;
bitmapFrameEncode.SetPixelFormat(ref pixelFormatGuid);
bitmapFrameEncode.WriteSource(wicBitmap);
bitmapFrameEncode.Commit();
encoder.Commit();
ms.Seek(0, SeekOrigin.Begin);
// JPEG decoder
var decoder = new System.Windows.Media.Imaging.JpegBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
// Write to wpf image
_WIC = decoder.Frames[0];
// Tell WPF to update
RaisePropertyChanged("WIC");
bitmapFrameEncode.Dispose();
encoder.Dispose();
stream.Dispose();
With:
System.Windows.Media.Imaging.BitmapFrame _WIC;
public System.Windows.Media.Imaging.BitmapSource WIC
{
get
{
return (System.Windows.Media.Imaging.BitmapSource)_WIC.GetAsFrozen();
}
}
And:
<StackPanel>
<Image Name="huhu1" Source="{Binding WIC}" />
</StackPanel>
SharpDX Toolkit has support for WPF via a Direct3D11-to-Direct3D9 shared texture. It is implemented in the SharpDXElement class.
You may not be able to reuse this as is because Direct2D (which you are using to draw) can interop either with Direct3D11.1 or Direct3D10 and SharpDX uses Direct3D11 for WPF support, so you will need to tweak the solution a little bit.
Basically you need to do the following:
Initialize Direct3D (10 or 11.1).
Initialize Direct2D.
Create the D3D render target with Direct2D support and the Shared flag (here is how it is done in SharpDX).
Initialize Direct3D9.
Create the shared texture.
Bind the texture to an D3DImage.
Do not forget to call D3DImage.AddDirtyRect when the contents of the render target are updated.
From the code you provided it is not clear if you are doing all initializations only once or not, so try to call any initialization code only once and reuse the render target - just clear it at the beginning of every frame. This is mandatory to get a decent performance.
Update: SharpDX.Toolkit has been deprecated and it is not maintained anymore. It is moved to a separate repository.
If you want to share a directx surface with WPF, the best option is using a WPF D3DImage. It promises to work without copying if you use the right color format.
I have only used it with Directx9, but it is possible that its compatible with Direct2D too, but if it isn't D3d9 can draw lines too.
There's a great codeproject article with examples. From managed code using slimdx or sharpdx the only nonobvious caveat is that D3DImage retains a reference count to your DirectX surface, so you need to null the backbuffer expicitly when you want to reset your d3d device.
You can use Smartrak/WpfSharpDxControl: Provides WPF control to host SharpDx content.
It uses sharpDx in WPF and the wpf can add Win32HwndControl to HwndHost.

Can't use Android.Graphics.BitmapRegionDecoder with Xamarin

I'm using Xamarin to build an Android app in c#.
The problem I'm having is that I need to load a part of an image without loading the whole image first. I have a rectangle of the region I want from the image.
I found this solution for normal Android : BitmapRegionDecoder
However when I try to invoke this class in my Xamarin project it's not there and I can't import it either.
I looked in the API and it says that it should be there.Android.Graphics.BitmapRegionDecoder documentation
Does anyone know if it's possible to use this class or if there is another way to achieve this?
Note that it says it is present in API level 10, hence you have to set your minimum target to 10 in the Application properties.
Then you can use it like so:
using (var inStream = ContentResolver.OpenInputStream(Android.Net.Uri.Parse("YourBitmapUri")))
{
using (var decoder = BitmapRegionDecoder.NewInstance(inStream, false))
{
var bitmap = decoder.DecodeRegion(YourRect, new BitmapFactory.Options());
// use your bitmap i.e. for an ImageView
bitmap.Dispose();
}
}

Categories

Resources