Save an Image from .NET MAUI Community Toolkit DrawingView

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
How to save something from the .NET MAUI Community Toolkit DrawingView into an image. That is what we're going to see in this video. Earlier on this channel, I've made a video on how to get started with .NET MAUI DrawingView which is a control in the .NET MAUI Community Toolkit which allows you to basically draw anything on a canvas. So think of maybe, I don't know, some app there where you can have to do pictionary. That's the game, right? Where you have to kind of guess what the drawing is going to be. Or maybe much more practical having a signature pad where your customer has to sign something in the app. But I've got a couple of questions under my videos, which I always welcome. So if you have something in this video or another question, let me know down in the comments about how to actually save an image from that drawing view. So in this video, we're going to see how to get all the data from that DrawingView inside of an image as a PNG and save that to your device or file and then you can process it further. So let's hop into Visual Studio. Here in Visual Studio, I've loaded the sample code for the .NET MAUI DrawingView video. You can find the link down below that will also contain the code that I'm going to write right now because all my videos have a GitHub sample attached. So go check that out. In the video description here, you can see it running on Windows. And this little gray box is the area, the canvas that I can actually draw. So on Windows I can use my mouse cursor. And I already implemented whenever you have drawn a line that it will show the image in an image control in .NET MAUI. So that's how to do that. And from there it's actually a little step to also save it to a file. So we're going to implement that here on the on click button that we can see here I'm going to show you for Windows, Android and iOS. So all the platforms that are here. So let me close this for a little bit and we can inspect the code that's already here. We have this little image that I've implemented in the previous video. I highly recommend that you check out that one first so that you know all about the drawing view and what it could do for you. But here we have this image and there we load the image that is resulting from the DrawingView that you can see right here, which is a control in the .NET MAUI Community Toolkit. I'm giving it a background, a width request, a height request on Windows. It's a little bit small, but it's fine for now. Multiline mode enabled. We don't allow multiple lines. The line color is green, the line width, you can have all these configuration options on how your drawing thing is going to look like. Or you can let the user influence that by setting the color and let them make a little drawing thing. So that's really cool. We don't really need this label. So actually let me just remove this one and this button. Let's name this not click me but save image. And we already have this clicked event handler wired up here. So OnCounterClicked, I'm just going to leave the name there. It doesn't really matter, it's all sample code. Sample code. So let's go to our MainPage.xaml.cs and you can here see that whenever a line is completed, which is an event from the DrawingView, we're going to get the stream, which is kind of important. We're going to get the stream and we're going to load that into an image source from stream, use that stream and it's going to be shown in an image. But we can also use that stream to do all kinds of other stuff. You can send it to a back end if that's what you want. You can save it to a file and that's exactly what we're going to do right now. So this OnCounterClicked, let's remove all the code that's here. Let's remove this redundant count field because we are not using it. And in here we are going to implement the code to actually save this to a file. Now file system, we have a FileSystem helper in .NET MAUI directly, which has a couple of things but it doesn't have the thing that I actually want to do here. This only gives you some information about the app data directory, the cache directory, which is very useful, but not for what we're trying to do. So accessing the file system and saving a file is kind of file specific, sorry, not file specific, platform specific stuff. So I'm going to do a couple of compiler directives here. So I'm going to say #if Windows, Windows is the easiest one, then I'm going to say else if which is #elif Android and then lastly, whoops... Android and then lastly #elif iOS. And you can probably add Mac Catalyst here as well. So that we have them all and then we do #endif. So this is an easy way, this is enabled by the .NET MAUI single project approach to write platform specific code right inside of your code here. You can definitely do it other ways. Neater ways if this is not what you like to do, litter your code with these compiler directives. But this is an easy way to make some sidesteps for different platforms here and there. So that's really cool. So for Windows, like I already said, it's pretty easy. We're just going to basically say file, you have System.IO.File and you can save all the bytes, right? But the first thing we need to do, and this is in our shared code. So if you don't put it in these compiler directives we can do some shared code. So I can just do var stream. You've already seen that down below for the drawing view is await draw view. So that draw view is my name for the drawing view here, right? If we go back to the example you can see here that I have this x name of draw view so that's just my reference to this element right here drawingview getimage stream and you can specify a width and a height. So this is just 200 by 200. Let's make it a little bit more impressive by making it 1020 4024 and we have our stream, right? It will get the image stream with all the drawings on top of it and we will have that another way that you can do this we also have net Maui drawingview drawing view dot and we don't have the right using here so use community toolkit Maui views. If we add that we can do drawing views and we can also do get image stream. So this is the static instance, the static method but now you have to suddenly provide the lines so you can also provide a custom set of lines right for this drawing or you can just get the draw view lines. There we go. So we get this lines collection. So if you want to maybe use it in a more data binding way you will just bind those lines of the draw view lines and you can call this static instance of drawing view and you can use it in a more MVVM kind of way, right? So we have these lines you still need to do a size. So new size is 1020 4024, right? So that's the same as what we see in the line above and then we can say the background, right? So you can set a background color. Well actually we have to do colors, I don't know, red something like that, right? So we can set a custom background color because we don't have the background color from the draw view, right? If you're just calling this get image stream on the draw view instance. So this control right here in the example is going to get the background color that we set here which is in this case light gray. So that's how that all works together. You can use this get image stream like this as well. But I'm just going to use that actual instance that we have here. Then what you want to do is get a using you probably want to do this stream as a using as well because streams are always you have to clean them up and if you don't do that then they will keep resources and you will create a memory leak. So do a using here and we also do a using var memoryStream because if we really want to get the bytes then a memory stream is the easiest thing, = new MemoryStream(). So we create a new one and then we're going to say memory stream. Well no, actually stream copy two. We're going to copy everything from our stream to the memory stream. So that we also have it in our memory stream like this. Then we probably want to set the stream position because if you're going to read through a stream, it's going to read to the end and then the position is going to be the end one. We want to reset the position here also for the memory stream. So that if we're going to do this again, if we're going to save these, then the position has to be 0 because it's going to go through that stream again. The methods that we're going to call here to actually save all the bytes. So we want to set the positions to zero just to be sure. Now for Windows it's quite easy. Make sure that you have this box right here set to Windows so that we are living in Windows land here. And we're going to say System.IO. I'm using the full namespaces here because else I would have to repeat all these compiler flags here. So in the using here at the top as well. If Windows, then using System.IO, et cetera, et cetera. So again, that's choices that you want to make. But I'm just going to do it this way. That file and then I'm going to say WriteAllBytes. You probably want to do it async actually WriteAllBytesAsync. Let's just do that because this is async already. So WriteAllBytesAsync. And then I have to specify the file path. So let's just do C:\users\ my username\desktop\ DrawingView and I know it's going to be a PNG. So let's just make this Test.png. There we have it and it's not going to know these slashes. So you can either duplicate the slashes or you can add an @ sign here so that it will pick up automatically as well. And then I have to specify the bytes that I actually want to write here. So I want to specify the memory stream to Array because that will get me the bytes. And I need to await this of course. So I need to do await to actually do this. Make this awatable. So now I have everything to write. It on windows. Windows is kind of easy, right? Windows lets you write to the file system. So if I'm going to do this, I'm going to run this on Windows. I can do my little drawing and then when I click the save file, then it's going to write all the bytes to this little test PNG here. So my application is coming up. I'm going to make the best drawing that you've ever seen. This actually says subscribe to my channel. So this is your signal. If you haven't subscribed to my channel just yet. Find the subscribe button down below and do it now. And then when I click Save image, it's going to save the image. I didn't really give any feedback. So this is not really great user experience, but oh well. Here in the folder though, we can now see this test PNG. And whenever I double click it, it's going to open this viewer. And we have the little image now here as a file. So that's pretty cool, right? We have this on Windows, so that's working. Now we need some code for Android and as is usually the case, Android needs a lot of code. Android has some weird things here. So I'm going to copy and paste some code on here. Don't be alarmed, it's a lot. And we have boom our code for Android here as well. You can see it's grayed out. If we switch again here to the different target platform here for Android in the top left, then you can see that Windows gets grayed out. And now we have all of our code for Android. This is going to get our current Activity. Activity is just your screen, your thing. On Android we're going to use a content resolver. Now note this API that you see here is kind of newish. There is a deprecated API that you need to use for older Android versions. I will include that in the final code that you'll find on the GitHub repository. But this is the most up to date code and you can see that we use this content resolver. We are adding some metadata. So we are setting the display name, which is test PNG, the Mime type, the relative path where we are going to save it and do some other things right here. And then we're actually going to get that bitmap from our stream. So here we can use the regular stream. I could have taken in this memory stream code into the Windows one. Maybe I need it for iOS as well. Then we're going to do bitmap compress. We're going to save it as PNG 100% quality. We're going to flush and close to clean up all the resources. And now it also works on Android. Now I'm not going to deploy it on Android. I already have it here on the Emulator. So it's running here. You can see that same square. It actually hasn't deployed with the save me here. So this has click me, but this is the exact same code otherwise. And whenever I do this little drawing right here, again, this has subscribed to my channel. Really weird, but that's what it is in Dutch. So click this button and now it's saved in the background to a file and it's going to be picked up kind of like with the media features of your Android device. So if I switch to the folders, the files and folders Explorer here on Android that I have installed on this emulator. It takes a little while before this refreshes. Maybe I can do it manually. And here you can see it pop up the test PNG with the drawing that I've just saved. So we can also do this on Android. Cool, cool. Now for iOS again, it's pretty easy to actually do this to just save something to the gallery. So I'm just going to paste this code in here again and switch to iOS land. And here we can just create a new image UIKit.UIImage with an NSData.FromArray. I'm going to use that memory stream again. See, there it is again. And I'm going to say image.SaveToPhotosAlbum. You probably want to do something with this error whenever something comes up that you detect the error, but otherwise it should just save it to the Photos album. You probably do need the permissions for this to actually do something like this. So again, I will double check that, make sure that it's in the GitHub repository code. But this is all there is to it to actually save a file to well, no, save a drawing to a file. Well, that wasn't too bad, was it? It just is one of those things that you kind of need to know how to do it. But once you know it, then there is a lot of power in here. Because now you can save these files or you can upload them to some kind of API. You probably want to do that through the stream directly and not maybe save the file first and send that. Because then you have to save that file to a stream again and then stream that to, well, anyway, you get the idea, right? So you can save this to API, you can save this on the local device. You can maybe, I don't know, put this on a PDF automatically if that's what you want. So there is lots of options that you can do with this we're, which is really amazing. So like I said at the beginning of this video, if there is something still unclear, if you have other questions, please let me know down in the comments or just let me know how nice this video was. And if you actually thought this video was nice, then please click the like button to actually enforce that and let the YouTube algorithm know to other people. This is the video to watch. Subscribe to my channel. if you haven't done so already. And I'll be seeing you for my next video. But not before I tell you that this playlist has a couple of more .NET MAUI videos. So be sure to check that out. And this video is recommended especially for you. See you for the next video.
Info
Channel: Gerald Versluis
Views: 5,066
Rating: undefined out of 5
Keywords: .net maui, dotnet maui, .net maui tutorial, .net maui community toolkit, community toolkit, dotnet maui getting started, .net maui app, dotnet maui tutorial, drawingview, maui drawingview, dotnet maui drawingview, .net maui drawingview, signaturepad, maui signaturepad, save file from drawing, drawingview save file, drawingview save image, dotnet maui ui, community toolkit maui
Id: OB65n17bR98
Channel Id: undefined
Length: 14min 27sec (867 seconds)
Published: Mon Jan 09 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.