Is it possible to access underlying Xamarin UI elements using SkiaSharp? - c#

In a cross platform Xamarin.Forms application, I would like to add a SKCanvas on top of other UI elements to allow the user to draw e.g. on images. I know it is possible to load an image directly into an SKCanvas, but images are not the only application I need.
A perfect solution would be able to load the underlying content of the page, including all of its UI elements into the Canvas/Surface, so that the user can then draw on it and save the drawing + underlying content into an image (probably using the snapshot method?).
Is this possible?

I didn't find a way to do this exactly as planned originally, but ended up doing a workaround that satisfied the requirements at the time.
I added a transparent canvas on top of my content, such that the underlying content would be shown through the canvas, but anything on the canvas would always be drawn on top. The drawings were saved and transmitted separately from the content and re-drawn when needed. On demand, when the user would need to export both together for a snapshot/share/export function, I then loaded the underlying content as image into the canvas and exported it together with the drawings from the canvas into a new image.

Related

Exporting all content of ListView as Png

I'm building an app that contains a kanban board which I would like to export as a PNG image. The board consists of a ListView of the card status' (To-do, doing, etc ) and each one of those is ListView containing the cards of the same status.
I'm already able to export the board as an image using a RenderTargetBitmap, however, the output will have the content that's in view. Instead, I want to have an image containing all the cards.
I honestly don't think it's that simple since only the visible cards are rendered on the page in the first place but I want to know if there's a different approach to this problem.
This is how an exported board would look at the moment
Exporting all content of ListView as Png
Currently, UWP has no such api to get long screenshot. I'm afraid you can't approach with RenderTargetBitmap class.
And we can imagine, if we could scale current view, and make all content show in the current window, then we could get the complete screenshot. So we could try to place above all in ScrollViewer and set it ZoomMode as enable. Just call ChangeView method to give it a appropriate ZoomFactor value to display all the content in visible place .
<ScrollViewer ZoomMode="Enabled" >
<Grid>
<ListView>
Please note this way will disable the listview's ui virtualization. and if we scaled scrollviewer, the effective pixels of the current windows will be lower.
And you do want this feature, please feel free post your requirement with windows feedback hub.

Using a canvas on top of an image to show visuals relating to image properties read of a list box

We have images created off a a high resolution scanner for showing defects on glass products. Our C# application is used by clients to manage defects. Many customers are having difficulties translating the image properties like actual length provided. I am working with a base image with a canvas on top. I also have a grid with a list of properties which when selected, I want to show a visual on how to translate the selection by say, drawing a line on the canvas in a manner that depicts the translation.
It turns out that the requirement was misconstrued and what was needed was creating simulations on separate images that I had to create and load. Next time I will try to think outside the box.

Adding UIEliments at runtime, without overlapping

I am adding an unknown amount of images to a canvas at runtime via code behind but I suspect they are laying on top of each other so only 1 image is visible.
I am converting multiple page PDF's into jpg images with ghostscript and wish to add them to a canvas in a vertical sequential row inside a scroll viewer.
Currently I am just rolling through a for loop generating each jpg and adding it to the canvas with canvas.children.add()
Is there a common way to ensure elements added to a canvas do not overlap? Or a common method people use to make sure children.add places the element in the right position?
I am thinking inside my for loop I will need to see what else exists on the canvas and add the heights together and palace my new image at the correct position but I am not sure how this is done. Is anyone able to steer me in the right direction?
You could use a StackPanel instead of the Canvas and add the images in there. The StackPanel will then place the images next to each other (or one under another, depending on its Orientation).

Implementing a clickable map for an arbitrary image

I have a C# WPF application where I have several possible images, some having irregular shapes within the image. I would like to generate different events when clicking on the different shapes within the image.
For example: If the image was of the front of the house, I would genereate different events when clicking on the doorknob, the door, the windows, the roof, etc.
The image has to be resizable.
I can do it manually with a grid and shapes, but it seems like there should be a more elegant way.
I thought I saw a technique where you could make a "shadow" image that was like the original, but with each clickable region filled in a different color. (A "color map" of the clickable regions.) Then the click handler could access the color of the shadow image and raise the appropriate event. However, I couldn't figure out how to hide the shadow image "under" the display image and still have the click event handler pick up the color.
I'm sure there's a good way to handle this, I just don't normally work with images so I'm completely ignorant of it.
Thanks.
How about having the nice image higher in the Z-order than the "shadow image" and setting topImage.IsHitTestVisible = false;
This would cause clicks to bypass the top, visible image and go straight to the underlying shadow image click handler.
Another technique I have used in production code is to derive a new class from Image and override HitTestCore and test the pixel value myself and if it's a certain color or opacity, I return a different object. This way I control all the action.

How to display images on top of each other using C# (Forms or WPF)?

I need to display images on top of each other. This can either be a composite\layered image or separate images. This will typically be a larger image with smaller images on top. With the composite\layered approach the smaller images would each need to be a separate (and accessible) layer. With the separate images approach the smaller images are on top with a transparent background. With either approach the smaller images must be accessible i.e. can be moved (dragged) or deleted. The app needs to display these images together (as if it was one image) and keep track of the coordinates (position) of the smaller images.
The current (proof-of-concept) solution has a PictureBox control that displays the large image and a treeview. Nodes are dragged from the treeview to the picture box and rendered using the graphics DrawString or DrawImage methods – these draw the smaller images. The problem is that once the smaller image is drawn I cannot get back to it as a separate graphics object. The picture box “sees” it as part of the current image.
I need to do this in C# (WinForms or WPF). And the image type must be a common and open format i.e. not proprietary. Preferably no 3rd party controls.
Any suggestions\guidance?
WPF would be the technology of my choice for this project.
Drag & Drop way nicer, without flickering, better concept
Rendering directly on HW, way smoother for image manipulation
General idea of the implementation:
MVVM pattern
ViewModel holding your layer information
ItemsControl bound to the collection of Small overlay Images holding a DataTemplate which visualizes the images thour custom UserControl based on a Thumb (for drag & drop functionality) displayes the small images on top.
Easy to add functionality to drag, edit, hide each small image seperately.
The problem is that once the smaller image is drawn I cannot get back
to it as a separate graphics object. The picture box “sees” it as part
of the current image.
That behaviour is perfectly normal. GDI drawing does not work with objects. To do what you are asking, you need to track any event that can cause a change in the final image and when such an event occur, you need to draw the whole image from the begining, including the first image (assigning the background image, I guess).
May be create picture box per image. The transparent background will give the effect of single image.

Categories