In my application I extended the ImageView and overriden its onDraw() method. I am using a color filter to manipulate the bitmap for adding some effects like invert, grayscale etcc. After drawing the bitmap I am trying to save it but I am only able to save the original bitmap with no added effects. Here is the code for onDraw() and save method:
protected void onDraw(Canvas canvas)
{
Paint paint = mPaint;
//cmf is the color matrix filter
paint.setColorFilter(cmf);
if(mBitmap != null)
{
canvas.drawBitmap(mBitmap, offsetW, offsetH, paint);
}
}
code for saving the bitmap:
try
{
FileOutputStream fout = new FileOutputStream(path);
mBitmap.compress(CompressFormat.JPEG, 100, fout);
} catch (FileNotFoundException e)
{
e.printStackTrace();
}
Am I doing something wrong? Any help will be appretiated.
You are painting on the canvas that is displayed, original bitmap is not changed. You should create a new bitmap and paint on it. When color matrix filter changes do this:
Bitmap tmp = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), mBitmap.getConfig())
Canvas canvas = new Canvas(tmp)
cnvas.drawBitmap(tmp, 0, 0, paint);
Then, you can use this tmp bitmap to draw it and save it.
Instead of using customized ImageView use a normal one and set its image to this new bitmap:
imageView.setImageBitmap(tmp)
Related
I have a Picture object, loaded from an SVG file, and I have set hardwareAccelerated=false to make it works on all devices.
Since there is a bug on android 4.0.4, I have to convert the Picture to Bitmap and I do that, in this way:
...
...
public void draw(Canvas canvas) {
...
...
//myPicture size is 9000x5000 but I want to display only this portion
clipRect.set(50, 50, 370, 530);
Bitmap bmp = getBitmapFromPicture(myPicture, clipRect);
canvas.drawBitmap(bmp, 0, 0, null);
bmp.recycle();
...
...
}
public static Bitmap getBitmapFromPicture(Picture picture, RectF clipRect) {
Bitmap bitmap = Bitmap.createBitmap(Math.round(clipRect.width()), Math.round(clipRect.height()), Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
canvas.drawPicture(picture);
}
Now I want to clip the Picture because I want to display only the visible screen part of it.
But the canvas.drawPicture does not accept srcRect parameter.
How is it possible to achieve this?
EDIT:
By translate the canvas: canvas.translate(-50, -50) it seems that translate the bitmap, too.
You need to set a transform on the Canvas.
To move the portion of the picture at 50,50 down so it is on the bitmap (ie. at 0,0), just do:
canvas.translate(-50, -50);
So your method becomes:
public static Bitmap getBitmapFromPicture(Picture picture, RectF clipRect)
{
Bitmap bitmap = Bitmap.createBitmap(Math.round(clipRect.width()),
Math.round(clipRect.height()),
Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
canvas.translate(-clipRect.left, -clipRect.top);
canvas.drawPicture(picture);
}
I am programmatically drawing to a canvas using data entered by the user. Once all of the data is entered, the user can flip through the images and they will be drawn to the canvas. The user has the option to save all of the images(could be several hundred). I use a runnable that runs on the UI thread that will draw and save each image(since you can't draw to a canvas from an AsyncTask). This works, but the problem I am having is if while the saving is going on, the user turns off the screen or minimizes the app. This causes the jpegs to just be black. I would like the saving to be something that could run in the background and still work.
Code used to draw to canvas and save image:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Bitmap bitmap;
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
canvas.setBitmap(bitmap);
// draw everything here
OutputStream stream = new FileOutputStream(imageName + ".jpg");
bitmap.compress(CompressFormat.JPEG, 100, stream);
stream.close();
}
So, is there a way for images to be drawn and saved to a file in the background while the canvas is not visible? Any help would be appreciated!
I think you can use this:
signLayout.setDrawingCacheEnabled(true); //signLayout is layout that contains image you want to save
// Save image from layout
String path = "sdcard0/test/test.jpg"; //file path you want to save
gestureSign.save(signLayout, path);
SAVE METHOD
//Save to path
public void save(View v, String SavePath)
{
if(mBitmap == null)
{
mBitmap = Bitmap.createBitmap (layoutSign.getWidth(), layoutSign.getHeight(), Bitmap.Config.RGB_565);;
}
Canvas canvas = new Canvas(mBitmap);
try
{
FileOutputStream mFileOutStream = new FileOutputStream(SavePath);
v.draw(canvas); //Lay toan bo layout
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, mFileOutStream);
mFileOutStream.flush();
mFileOutStream.close();
}
catch(Exception e)
{
Log.v("log_tag", e.toString());
}
}
I am drawing rotated text on canvas and then saving it to SD card as JPEG.
The problem I am facing is the canvas preview looks fine, but the rotated text in the saved image is not coming properly. When I use the default Android fonts, the final JPEG is the same as the canvas preview, but this code doesn't work for a custom typeface.
I have uploaded both the final saved image and screenshot of canvas preview
I am using a custom view class for canvas drawing, here is my code
public class MyBringBack extends View {
Bitmap bitmap;
Typeface type;
public MyBringBack(Context context) {
super(context);
// TODO Auto-generated constructor stub
type = Typeface.createFromAsset(context.getAssets(),"fonts/rockwell-bold.ttf");
setDrawingCacheEnabled(true);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.BLUE);
// paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
paint.setTextSize(23);
Paint paint1 = new Paint();
paint1.setTextSize(40);
paint1.setColor(Color.RED);
canvas.rotate(90,434,110);
canvas.drawText("Demo Text Demo Text Demo Text ", 434, 110, paint);
canvas.restore();
canvas.save();
paint1.setTypeface(type);
canvas.rotate(90,130,185);
canvas.drawText("Text using Typeface ", 130, 185, paint1);
canvas.restore();
canvas.save();
canvas.rotate(90,180,185);
canvas.drawText("Text using Typeface ",180, 185, paint1);
canvas.restore();
canvas.save();
canvas.rotate(90,230,185);
canvas.drawText("Text using Typeface ", 230, 185, paint1);
canvas.restore();
canvas.save();
this.setDrawingCacheEnabled(true);
Bitmap c= Bitmap.createScaledBitmap(this.getDrawingCache(), canvas.getWidth(),canvas.getHeight(), false);
/* Saving File To SD Card */
OutputStream outStream = null;
File bgv = new File("/sdcard/");
/* To build directory if needed */
bgv.mkdirs();
File file = new File(bgv, "final22.jpg");
try {
outStream = new FileOutputStream(file);
c.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Is there is any problem with my code?
Please help...
thanks in advance :)
Finally after lots of research on image processing i got my answer.
For Saving the jpg exactly same as what is drawn on canvas we have to add just two line of code.
First is :
setDrawingCacheQuality(DRAWING_CACHE_QUALITY_HIGH);
and second in onDraw we have to set AntiAlias to true,refering to my code
paint1.setAntiAlias(true);
But after this also the saved image is not of same quality that of what is drawn on canvas.
to get the same crisp quality of image this two code will do the trick
paint1.setDither(true);
paint1.setFilterBitmap(true);
Dither mainly provide smooth corners,AntiAlias,Dither and FilterBitmap can also be used while drawing Bitmap on canvas.
To get more information about Dither and AntiAlias here is the link
AntiAlias
Dither
It looks as though the canvas's drawing cache may not be returning what you expect. You can blit directly to a bitmap using something like this:
Bitmap myBitmap = new Bitmap(width, height, Config.ARGB_8888);
canvas.setBitmap(myBitmap);
... draw your text, etc ...
Then save myBitmap to disk. Everything that you draw on the canvas should be drawn into the bitmap.
I am new to canvas. I want to use the My already saved Image and want some paint on that image. after that i want to save it.
I know that with using Canvas it is possible. I can able to do painting on the Image but while i am going to store that image it only saved the painting. Not the Image with painting.
So can anybudy tell me code of how to paint on image and save that image ?
Thanks.
Here is my Code that use to do paint on the SurfaceView.
Source Code:
#Override
public void run() {
//Canvas canvas = null;
while (_run){
try{
canvas = mSurfaceHolder.lockCanvas(null);
if(mBitmap == null){
mBitmap = Bitmap.createBitmap (1, 1, Bitmap.Config.ARGB_8888);
}
final Canvas c = new Canvas (mBitmap);
//canvas.drawColor(0, PorterDuff.Mode.CLEAR);
c.drawColor(0, PorterDuff.Mode.CLEAR);
canvas.drawColor(Color.WHITE);
// Bitmap kangoo = BitmapFactory.decodeResource(getResources(),R.drawable.icon);
// if(!(DrawingActivity.imagePath==null)){
// canvas.drawBitmap(DrawingActivity.mBitmap, 0, 0, null);
// }
commandManager.executeAll(c);
canvas.drawBitmap (mBitmap, 0, 0,null);
} finally {
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
I am using mBitmap to save the Bitmap to the SDCard.
Your problem is your drawing over and over on your entire canvas:
final Canvas c = new Canvas (mBitmap); // creates a new canvas with your image is painted background
c.drawColor(0, PorterDuff.Mode.CLEAR); // this makes your whole Canvas transparent
canvas.drawColor(Color.WHITE); // this makes it all white on another canvas
canvas.drawBitmap (mBitmap, 0, 0,null); // this draws your bitmap on another canvas
Use logic roughly like this:
#Override
public void run() {
Canvas c = new Canvas(mBitmap);
/* Paint your things here, example: c.drawLine()... Beware c.drawColor will fill your canvas, so your bitmap will be cleared!!!*/
...
/* Now mBitmap will have both the original image & your painting */
String path = Environment.getExternalStorageDirectory().toString(); // this is the sd card
OutputStream fOut = null;
File file = new File(path, "MyImage.jpg");
fOut = new FileOutputStream(file);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
fOut.flush();
fOut.close();
}
Also don't forget to add necessary permission to save your file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
outside <application></application> in your manifest file.
I am using canvas to draw the Different colour.
I want to set the Image that should be appear as the background of the canvas. And while i am drawing on that image it should be drawn on the Image not behind the image.
Right now with below code it is drawing behind the Image.
#Override
public void run() {
Canvas canvas = null;
while (_run){
try{
canvas = mSurfaceHolder.lockCanvas(null);
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
commandManager.executeAll(canvas);
} finally {
Bitmap kangoo = BitmapFactory.decodeResource(getResources(),R.drawable.icon);
canvas.drawBitmap(kangoo, 130, 100, null);
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
So what should i have to do to make drawing on the image ???
As you redrawing the canvas in While(1) loop you can put the statement canvas.drawBitmap(kangoo, 130, 100, null) at the top inside the loop so that its drawn again and again then do you painting over top of it.
If you want to save the drawn part to you do something like converting the Canvas to bitmap like:
Bitmap bitmapToBeDrawnFromNextTime = Bitmap.createBitmap( canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
Canvas imageCanvas = new Canvas(bitmapToBeDrawnFromNextTime);
imageCanvas.draw(canvas);
No one have giving me answer.
But i got solution, I have to set the image after clearing canvas.
code:
#Override
public void run() {
//Canvas canvas = null;
while (_run){
try{
canvas = mSurfaceHolder.lockCanvas(null);
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
Bitmap kangoo = BitmapFactory.decodeResource(getResources(),R.drawable.icon);
canvas.drawBitmap(kangoo, 130, 100, null);
commandManager.executeAll(canvas);
} finally {
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}