- Getting Started with Android Canvas Drawing 🖼
- Learn the basics of drawing with the Android Canvas Class
- What is a Canvas?
- Canvas Coordinate System
- How do I use a Canvas?
- Get access to a Canvas instance
- What can I draw on a Canvas? ✏️
- Paint 🎨
- Next up…
- A Computer Engineer
- Just another geek.
- How to draw Canvas on ImageView and save Canvas as Bitmap and store in sdcard in Android
- Share this:
- Like this:
- Related
- 9 thoughts on “ How to draw Canvas on ImageView and save Canvas as Bitmap and store in sdcard in Android ”
- Creating and Drawing to an Image
- Drawing an Image
- Filtering Images
Getting Started with Android Canvas Drawing 🖼
Learn the basics of drawing with the Android Canvas Class
Diving into using the Android Canvas class can unlock magical super powers you never knew you had 🤯. Imagine being able to draw anything* your heart desires just with some basic shapes, paths and bitmaps? Well, the Android Canvas gives you just that ability.
What is a Canvas?
Canvas is a class in Android that performs 2D drawing of different objects onto the screen. The saying “a blank canvas” is very similar to what a Canvas object is on Android. It is basically, an empty space to draw onto.
The Canvas class is not a new concept, this class is actually wrapping a SKCanvas under the hood. The SKCanvas comes from SKIA, which is a 2D Graphics Library that is used on many different platforms. SKIA is used on platforms such as Google Chrome, Firefox OS, Flutter, Fuschia etc. Once you understand how the Canvas works on Android, the same drawing concepts apply to many other different platforms.
Tip: Check out the SKIA source code for a deeper understanding of the Canvas implementation.
It is useful to know that SKIA is used in the underlying code for Android, so when you get stuck trying to understand how a certain API works, you can look at the source for SKIA to gain a deeper understanding.
Canvas Coordinate System
The coordinate system of the Android canvas starts in the top left corner, where [0,0] represents that point. The y axis is positive downwards, and x axis positive towards the right.
All elements drawn on a canvas are placed relative to the [0,0] point.
When working with the Canvas, you are working with px and not dp, so any methods such as translating, or resizing will be done in pixel sizes. This means you need to translate any dp values into px before calling any canvas operations. This will ensure that your drawing looks consistent across devices with different pixel densities.
Canvas draw commands will draw over previously drawn items. The last draw command will be the topmost item drawn onto your canvas. It is up to you to ensure that your items are laid out correctly (Alternatively, you might want to use some of the built-in layout mechanisms for this — such as LinearLayout ).
How do I use a Canvas?
To draw onto a canvas in Android, you will need four things:
- A bitmap or a view — to hold the pixels where the canvas will be drawn.
- Canvas — to run the drawing commands on.
- Drawing commands — to indicate to the canvas what to draw.
- Paint — to describe how to draw the commands.
Get access to a Canvas instance
In order to get access to a Canvas instance, you will need to create a class that extends from View . This will then allow you to override the onDraw method, which has a Canvas as a parameter.
You can then include this view inside your layout XML and this will then automatically invoke the onDraw method of the Custom View.
You can also get access to a Canvas object by programatically creating one in code, like this:
It’s worth noting at this point that any Canvas created programmatically without using a View , will be software rendered and not hardware rendered. This can affect the appearance of some of the drawing commands. For instance, some commands are just not supported with hardware rendering, or only supported from a certain API level. For more information about the differences between hardware rendering and software rendering, read this post.
What can I draw on a Canvas? ✏️
There are many different things you can draw onto a Canvas . One of the most common drawing operations is to draw a bitmap (image) onto the canvas. The method for doing this is just called drawBitmap and it takes in the bitmap object that is loaded up either with Android’s built-in mechanisms, or with Glide.
The second parameter here allows us to pass in the portion of the bitmap that you want to render, when passing in null the whole bitmap will be rendered. The third parameter is a RectF object which represents the scale and translation of the bitmap that you want to draw on screen.
Tip: Make sure your RectF object that you pass into the drawBitmap function is scaled with the correct aspect ratio otherwise your output may be stretched
You need to be careful with this, since it can quite easily stretch the bitmap, as the Canvas calls don’t take into account the aspect ratio of the provided image. You need to ensure the rect that is passed in is properly scaled. The fourth parameter is the paint object, we will cover the purpose of this parameter soon.
There are many other Canvas drawing methods that can give you some great looking views. We won’t be covering them all here, but here are two other examples of drawing methods on the Canvas class:
To draw a circle onto the view, give it a center point x,y , its size and a paint object:
Another one is the drawRect() method. This draws a rectangle on screen:
This is not the full list of drawing methods but just a small highlight of some of them to get you more comfortable with the concepts, feel free to browse the Canvas documentation for a comprehensive list of all of them.
Paint 🎨
In my opinion, the Paint class is possibly the most interesting graphics class and it is also my favourite, for that very reason. There is so much that a Paint object can do that can really make your drawing operations shine. ✨
The Paint class typically holds colour and style information. The Paint object is then used for drawing objects (i.e. bitmap, text, paths etc) onto a Canvas .
To create a Paint object:
This object should be created before using it in Canvas#onDraw() . It is not recommended to create it in onDraw() since you shouldn’t be doing object allocations in that method.
Tip: Use the isAntiAlias flag to ensure your drawing has smooth edges.
The isAntiAlias flag is quite an important one. If you are drawing objects to your canvas and you notice that the edges of your objects have jagged edges, it is likely that you haven’t set this flag to true. This flag indicates to the paint to smooth out the edges of the object you are drawing to the canvas.
The Paint class has more than just those three properties, there are many more things you can do with it. For instance, you can also set properties related to text rendering, such as the typeface , letterSpacing (kerning) and textSize .
Tip: Check that the Canvas/Paint APIs you are using work across different API versions. See this site for more information.
It is worth noting that the Paint#setShadowlayer() method doesn’t work consistently across API levels and drawing commands. It works when drawing text on a Canvas, but applying the shadow to other commands such as drawBitmap doesn’t yield the same results across API levels.
The reason for the inconsistency between API levels is because the Canvas APIs are bundled with the Android Platform and therefore are not updated until the OS is updated. See the list on this page for more information about which APIs work on which Android versions.
Once you’ve created the Paint object, pass that object into your Canvas#draw*() calls and the drawing will then take on the properties you’ve specified in the paint.
Next up…
In the next few articles, we will be diving into other parts of working with Canvas and drawing on Android. Be sure to subscribe to updates and follow me on Twitter for more tips.
If you prefer watching this content — be sure to check out my talk from Mobile Matters London for a summary of this content.
Источник
A Computer Engineer
Just another geek.
How to draw Canvas on ImageView and save Canvas as Bitmap and store in sdcard in Android
In some of the application we draw image, text and line on Canvas object in Android. Canvas is the basic component in android for drawing objects on it.
#1 Create Canvas and display it in ImageView.
Now we create a Canvas and display its content in ImageView.
Now set this canvas to your ImageView using following code.
You can see “Sample Text” in ImageView.
#2 Save canvas bitmap to sdcard.
We will save this bitmap to sdcard so all your drawing on canvas will be stored as image.
If you find any problem or doubt, please mention in comments. Do not forget to share!
Share this:
Like this:
Related
9 thoughts on “ How to draw Canvas on ImageView and save Canvas as Bitmap and store in sdcard in Android ”
Hi sir,
i am new one for android development, i need reference for draw on image by touch, how to implement,. when i m trying canvas image are load separately.
when i m zoom the image canvas only gets run .please give me solution to rectify this.
Let me know if you need any further help.
But using the above code ,I could save the image.But on opening,is is not having any content.
please check the #2 code in your project, there must be a problem which cause the result image blank.
If you can see your content within the app, then the image should also display it if it saved properly.
Let me know if you need any further help.
hey, is there any permssion for write sd card at manifest?
Yes there is 2 permission for the storage. One if for write: And second is for read:
Источник
Creating and Drawing to an Image
We already know how to load an existing image, which was created and stored in your system or in any network location. But, you probably would like also to create an new image as a pixel data buffer.
In this case, you can create a BufferedImage object manually, using three constructors of this class:
- new BufferedImage(width, height, type) — constructs a BufferedImage of one of the predefined image types.
- new BufferedImage(width, height, type, colorModel) — constructs a BufferedImage of one of the predefined image types: TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED .
- new BufferedImage(colorModel, raster, premultiplied, properties) — constructs a new BufferedImage with a specified ColorModel and Raster .
On the other hand, we can use methods of the Component class. These methods can analyze the display resolution for the given Component or GraphicsConfiguration and create an image of an appropriate type.
- Component.createImage(width, height)
- GraphicsConfiguration.createCompatibleImage(width, height)
- GraphicsConfiguration.createCompatibleImage(width, height, transparency)
GraphicsConfiguration returns an object of BufferedImage type, but the Component returns an object of Image type , if you need a BufferedImage object instead then you can perform an instanceof and cast to a BufferedImage in your code.
As was already mentioned in the previous lessons, we can render images not only on screen. An images itself can be considered as a drawing surface. You can use a createGraphics() method of the BufferedImage class for this purpose:
Another interesting use of off-screen images is an automatic double buffering. This feature allows to avoid flicker in animated images by drawing an image to a back buffer and then copying that buffer onto the screen instead of drawing directly to the screen.
Java 2D also allows access to hardware acceleration for off-screen images, which can provide the better performance of rendering to and copying from these images. You can get the benefit of this functionality by using the following methods of the Image class:
- The getCapabilities method allows you to determine whether the image is currently accelerated.
- The setAccelerationPriority method lets you set a hint about how important acceleration is for the image.
- The getAccelerationPriority method gets a hint about the acceleration importance.
Источник
Drawing an Image
As you have already learned, the Graphics.drawImage method draws an image at a specific location:
The x,y location specifies the position for the top-left of the image. The observer parameter notifies the application of updates to an image that is loaded asynchronously. The observer parameter is not frequently used directly and is not needed for the BufferedImage class, so it usually is null.
The described method addresses only the case where the entire image is to be drawn, mapping image pixels to user space coordinates 1:1. Sometimes applications require to draw a part of the image (a sub-image), or scale the image to cover a particular area of the drawing surface, or transform or filter the image before drawing.
The overloads of the drawImage() method perform these operations. For example, the following overload of the drawImage() method enables you to draw as much of a specified area of the specified image as is currently available, scaling it to fit inside the specified area of the destination drawable surface:
The src parameters represent the area of the image to copy and draw. The dst parameters display the area of the destination to cover by the source area. The dstx1, dsty1 coordinates define the location to draw the image. The width and height dimensions on the destination area are calculated by the following expressions: (dstx2-dstx1), (dsty2-dsty1) . If the dimensions of the source and destinations areas are different, the Java 2D API will scale up or scale down, as needed.
The following code example divides an image into four quadrants and randomly draws each quadrant of the source image into a different quadrant of the destination.
The complete code for this applet is in JumbledImageApplet.java .
This example uses the following code to paint the jumbled duke_skateboard.jpg image. It iterates over the four sub-images of the source, drawing each in turn into a randomly selected destination quadrant.
Filtering Images
In addition to copying and scaling images, the Java 2D API also filter an image. Filtering is drawing or producing a new image by applying an algorithm to the pixels of the source image. Image filters can be applied by using the following method:
The BufferedImageOp parameter implements the filter. The following applet represents an image drawn on top of text. Drag the slider to show more or less of the text through the image and make the image more or less transparent.
The following code shows how the filter action is done by operating on a BufferedImage object with an alpha channel and rescales that alpha channel by using the RescaleOp object. The alpha channel determines the translucency of each pixel. It also specifies the degree to which this image overwrites.
The complete example represented in SeeThroughImageApplet.java includes the code that uses the slider to adjust the transparency from the initial 50%. This example also requires the duke_skateboard.jpg image.
The RescaleOp object is just one of many filters that can be created. The Java 2D API has several built in filters including the following:
- ConvolveOp . Each output pixel is computed from surrounding pixels in the source image. It may be used to blur or sharpen images.
- AffineTransformOp . This filter maps pixels in the source to a different position in the destination by applying a transformation on the pixel location.
- LookupOp . This filter uses an application supplied lookup table to remap pixel colors.
- RescaleOp . This filter multiplies the colors by some factor. Can be used to lighten or darken the image, to increase or reduce its opacity, etc.
The following example uses each of the described filters as well as scaling:
The complete code for this applet is in ImageDrawingApplet.java and this applet requires the bld.jpg image.
Use the drop-down menu to select an image scaling or filtering operation.
Источник