android - how to save bitmap with painted canvas - android

Im trying to draw canvas on the image and save it with changes. When app starts I can see my canvas drawing, but it saves without canvas drawing. Here is my code:
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawView(this));
}
class DrawView extends View {
Paint p;
Path path;
public DrawView(Context context) {
super(context);
p = new Paint();
p.setStrokeWidth(30);
p.setStyle(Paint.Style.STROKE);
path = new Path();
}
#Override
protected void onDraw(Canvas can) {
Bitmap bm = BitmapFactory.decodeFile("/sdcard/MANUAL/img1394916221.png");
can.drawBitmap(bm, 0, 0, p);
path.reset();
path.moveTo(250, 100);
path.lineTo(300, 200);
path.lineTo(200, 200);
path.close();
p.setColor(Color.RED);
can.drawPath(path, p);
FileOutputStream out;
try {
out = new FileOutputStream("/sdcard/MANUAL/img.png");
bm.compress(Bitmap.CompressFormat.PNG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
Where is my mistake?

Check this sample . How to export a View as Bitmap
http://gmariotti.blogspot.it/2013/10/how-to-export-view-as-bitmap.html?m=1

Related

Android: How to use a Canvas to mask a Bitmap?

I am fetching a Bitmap with Parse on my Android application.
final WeakReference<ImageView> weakImageView = new WeakReference<>(imageViewToMask);
fetchFromParse(getContext(), new Success() {
#Override
public void success(Bitmap image) {
if (weakImageView.get() != null) {
// Here how to make this image a MaskDrawable to mask it?
// MaskedDrawable d = new MaskedDrawable(bitmap, context, [canvas here]?)
// weakImageView.get().setImageDrawable(d);
weakImageView.get().setImageDrawable(image);
}
}
});
Now I want to mask this bitmap with another image, I found this answer in this thread:
public class MaskedDrawable extends Drawable {
public void draw(Bitmap original, Context context, Canvas canvas) {
Bitmap mask = BitmapFactory.decodeResource(context.getResources(), R.drawable.mask_image);
Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Config.ARGB_8888);
Canvas tempCanvas = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
tempCanvas.drawBitmap(original, 0, 0, null);
tempCanvas.drawBitmap(mask, 0, 0, paint);
paint.setXfermode(null);
// How do I create this canvas user here?
canvas.drawBitmap(result, 0, 0, new Paint());
}
}
I already have the original bitmap and the context object, but I don't know how to use canvas. What to do?
Thanks for your help!

Capture Screenshot of SurfaceView with bitmap content on it

I want to capture image of surface view with content draw on surface view.
I n my app i have surface view on which user can draw some bitmap by drag and drop some objects on it.
After that on a button click i want to store image of that surfaceview with its bitmap content in sd card.
For these i have a canvas object and all bitmap are draw on it.
below is my code -
mHolder = mSurfaceView.getHolder();
mHolder.lockCanvas();
canvas.drawColor(0,Mode.CLEAR);
//border's properties
paint = new Paint();
FontMetrics fm = new FontMetrics();
Paint paint2 = new Paint();
paint2.setColor(Color.WHITE);
paint2.setTextSize(30);
paint2.setTextAlign(Paint.Align.CENTER);
paint2.getFontMetrics(fm);
canvas.drawText("Building", RectLeft+60, RectTop+60, paint2);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(color);
paint.setStrokeWidth(3);
canvas.drawRect(RectLeft, RectTop, RectRight, RectBottom, paint);
mHolder.unlockCanvasAndPost(canvas);
How to do that.
Thanks in advance.
EDITED
Below is my code that captures only view that i have created in xml and not draw what i have draw on surface.
public static Bitmap getBitmapFromView(View view) {
//Define a bitmap with the same size as the view
Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888);
//Bind a canvas to it
Canvas canvas = new Canvas(returnedBitmap);
//Get the view's background
Drawable bgDrawable =view.getBackground();
if (bgDrawable!=null)
//has background drawable, then draw it on the canvas
bgDrawable.draw(canvas);
else
//does not have background drawable, then draw white background on the canvas
canvas.drawColor(Color.WHITE);
// draw the view on the canvas
view.draw(canvas);
//return the bitmap
return returnedBitmap;
}
EDITED my hole fragment for drawing is below-
public class DrawingLayoutFragment extends Fragment implements SurfaceHolder.Callback{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
....
....
mSurfaceView = (SurfaceView) view.findViewById(R.id.surfaceview);
init();
return view;
}
public void init(){
mSurfaceView.getHolder().addCallback(this);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
RectLeft = width/2 - 60;
RectTop = height/2 - 60 ;
RectRight = width/2 + 60;
RectBottom = height/2 + 60;
DrawFocusRect(RectLeft, RectTop, RectRight, RectBottom, getResources().getColor(com.nep.R.color.white_color));
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mHolder = mSurfaceView.getHolder();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
try{
if(mHolder!=null){
mHolder.lockCanvas();
canvas = null;
mHolder.addCallback(null);
mHolder = null;
}
}catch(Exception e){
e.printStackTrace();
}
}
private void DrawFocusRect(float RectLeft, float RectTop, float RectRight, float RectBottom, int color){
try {
if(canvas!=null){
mHolder.lockCanvas();
}
else{
canvas = mHolder.lockCanvas();
}
canvas.drawColor(0,Mode.CLEAR);
paint = new Paint();
FontMetrics fm = new FontMetrics();
Paint paint2 = new Paint();
paint2.setColor(Color.WHITE);
paint2.setTextSize(30);
paint2.setTextAlign(Paint.Align.CENTER);
paint2.getFontMetrics(fm);
canvas.drawText("Building", RectLeft+60, RectTop+60, paint2);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(color);
paint.setStrokeWidth(3);
canvas.drawRect(RectLeft, RectTop, RectRight, RectBottom, paint);
mHolder.unlockCanvasAndPost(canvas);
} catch (Exception e) {
e.printStackTrace();
}
}
public void createFIle(){
try {
DrawFocusRect(RectLeft, RectTop, RectRight, RectBottom, getResources().getColor(com.nep.R.color.white_color));
Bitmap b = Bitmap.createBitmap(mSurfaceView.getWidth(), mSurfaceView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
mSurfaceView.draw(c);
// Bitmap bmp = getBitmapFromView(frame);
String mFile = mPath+"_layout011.png";
File directory = new File (mFile);
directory.createNewFile();
OutputStream fo = new FileOutputStream(directory);
ByteArrayOutputStream os = new ByteArrayOutputStream();
b.compress(CompressFormat.JPEG, 100, os);
os.writeTo(fo);
fo.close();
os.close();
// mSurfaceView.destroyDrawingCache();
BasicMethods.showToast("Saved at - "+mFile, mContext);
} catch (Exception e) {
e.printStackTrace();
}
}
}
i have user this code and it is not working,so i put my surface view inside other view and try to capture bitmap from that i was previously posted.i have try both way but not geting any solution.
Create a Bitmap, create a Canvas for the bitmap, execute all of your drawing commands on that Canvas, save the bitmap.
You can't capture the SurfaceView's surface, so re-drawing onto a Bitmap is the easiest way. This comes up fairly often; see e.g. this.

setwallpaper from class which extends view

I am trying to setwallpaper from my class which extends view superclass , i am trying to convert view into the bitmap but i am getting an error (NullPointerException).
case R.id.wallpaper: // This is an event of my button
View view = new CustomWallpaper(this);
b = convertToBitmap(view);
WallpaperManager myWallpaperManager
= WallpaperManager.getInstance(getApplicationContext());
try {
myWallpaperManager.setBitmap(b);
new CustomToast(context, "Wallpaper has been set").show();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
and this is my method
private Bitmap convertToBitmap(View view) {
// TODO Auto-generated method stub
Bitmap viewCapture = null;
view.setDrawingCacheEnabled(true);
viewCapture = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
return viewCapture;
}
And this is my class which extends view
public class CustomWallpaper extends View {
public CustomWallpaper(Context context) {
super(context);
// TODO Auto-generated constructor stub
setBackgroundColor(Color.BLACK);
LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT);
setLayoutParams(params);
}
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawCircle(50, 50, 30, paint);
}
}
Thank You
Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
Drawable bgDrawable = view.getBackground();
if (bgDrawable != null) {
bgDrawable.draw(canvas);
} else {
canvas.drawColor(Color.WHITE);
}
view.draw(canvas);
and your bitmap is returnedBitmap
then no need to create CustomView. try this. it may help you...
public void onClick(View view) {
switch (view.getId()) {
case R.id.wallpaper:
Bitmap bitmap = getWallPaperBitmap();
.......
wallPaperManager.setBitmap(bitmap);
break;
default:
break;
}
}
public static Bitmap getWallPaperBitmap() {
Bitmap bitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawARGB(0, 0, 0, 0);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
// this style will fill the circle
paint.setStyle(Paint.Style.FILL);
// this style will draw Circle path.
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(bitmap.getWidth()/2, bitmap.getHeight()/2, 40, paint);
return bitmap;
}

How to draw outside canvas and make bitmap of it?

I am drawing some rows of text. After a couple of rows, it goes offscreen. What i want to do is capture all the rows(also the rows outside the canvas) in a bitmap.
I have the code below which only works for within the canvas(screen).
private class DeciderView extends View {
private Paint paint;
String text = "";
String[] options = { "een", "twee", "drie", "vier", "vijf", "zes", "zeven", "acht",
"negen", "tien", "elf", "twaalf", "dertien", "vertien", "vijftien" };
public DeciderView(Context context) {
super(context);
// Keep screen on
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// Remove title bar
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Remove notification bar
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.setBackgroundColor(Color.WHITE);
paint = new Paint();
paint.setTextSize(75);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(10);
paint.setAntiAlias(true);
setDrawingCacheEnabled(true);
setDrawingCacheQuality(DRAWING_CACHE_QUALITY_HIGH);
}
private void drawInput(Canvas canvas) {
Paint p = new Paint();
p.setTextAlign(Align.CENTER);
p.setTextSize(canvas.getWidth() / 10f);
p.setColor(Color.BLACK);
float xText = canvas.getWidth() / 2f;
float yText = (canvas.getHeight() / 4f);
for (int i = 0; i < options.length; i++) {
text += options[i] + "\n";
}
for (String line : text.split("\n")) {
canvas.drawText(line, xText, yText, p);
yText -= (p.ascent() + p.descent()) * 2.5f;
}
}
#Override
public void onDraw(Canvas canvas) {
drawInput(canvas);
this.setDrawingCacheEnabled(true);
Bitmap b = Bitmap.createBitmap(this.getDrawingCache());
b = Bitmap.createScaledBitmap(b, canvas.getWidth(), canvas.getHeight(), false);
try {
b.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(
new File(Environment.getExternalStorageDirectory().getPath()
+ "/Pictures/aaaaa.jpg")));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (b != null) {
b.recycle();
b = null;
}
}
}
So basically i want to make a bitmap from all the rows, even if the rows are drawn outside the canvas.
Why not just draw directly to the bitmap? You can create a new Canvas that has a bitmap backing it. You use the normal canvas draw commands, and the output will be written to the bitmap rather than the screen. If you also want to draw it to the screen, just draw the new bitmap to the screen at the end. To do this all you need is
Canvas myCanvas = new Canvas(myBitmap);

How to Implement the erase on image with this example and save it?

I am using this demo to imnplement the paint in my application. This Demo.
Now i want Image as a Background of the paint. after that the paint done on that image should be erased as like the it has functionality right now for paint. And while i save that image then it should be save with that Image.
So What should i have to do for that ??
Updated:
Save code:
case PHOTO_SAVE:
final Activity currentActivity = this;
Handler saveHandler = new Handler(){
#Override
public void handleMessage(Message msg) {
final AlertDialog alertDialog = new AlertDialog.Builder(currentActivity).create();
alertDialog.setTitle("Drawing App");
alertDialog.setMessage("Your drawing is saved. :)");
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
return;
}
});
alertDialog.show();
}
} ;
System.out.println("1");
new ExportBitmapToFile(this,saveHandler, mBitmap).execute();
System.out.println("2");
return true;
And the ExportBitmapToFile class is:
private class ExportBitmapToFile extends AsyncTask<Intent,Void,Boolean> {
private Context mContext;
private Handler mHandler;
private Bitmap nBitmap;
private ProgressDialog m_progressDialog = null;
#Override
protected void onPreExecute(){
m_progressDialog = new ProgressDialog(mContext);
m_progressDialog.setTitle("Drawing App");
m_progressDialog.setMessage("Please wait...");
m_progressDialog.setCancelable(false);
m_progressDialog.show();
System.out.println("3");
}
public ExportBitmapToFile(Context context,Handler handler,Bitmap bitmap) {
mContext = context;
nBitmap = bitmap;
mHandler = handler;
}
#Override
protected Boolean doInBackground(Intent... arg0) {
try {
if (!APP_FILE_PATH.exists()) {
APP_FILE_PATH.mkdirs();
}
System.out.println("4");
final FileOutputStream out = new FileOutputStream(new File(APP_FILE_PATH + "/"+filename+".jpg"));
nBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
System.out.println("5");
out.flush();
out.close();
return true;
}catch (Exception e) {
e.printStackTrace();
}
//mHandler.post(completeRunnable);
return false;
}
#Override
protected void onPostExecute(Boolean bool) {
super.onPostExecute(bool);
if ( bool ){
mHandler.sendEmptyMessage(1);
}
if (m_progressDialog.isShowing()) {
m_progressDialog.dismiss();
}
}
}
A Small Change.
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createScaledBitmap(mBackground, w, h, true);
mCanvas = new Canvas(mBitmap);
}
where mBackground is a Bitmap you initialize in the Constructor of MyView.
I'm pretty sure, that should do, if you have any problems do report back.
Update : See Comments
In That Case, forget the above changes, and modify the onDraw Method like this.
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFAAAAAA);
canvas.drawBitmap(mBackground, 0, 0, mBitmapPaint); //Make sure mBackground is the same size as the view.
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
While saving, You'll have to overlay both Bitmaps onto a new Bitmap Object and then finally write it to disk.
To Overlap both Bitmaps,
private Bitmap overlay(Bitmap bmp1, Bitmap bmp2) { //code borrowed from stackoverflow question 1540272
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, new Matrix(), null); // or use the other overloaded functions
canvas.drawBitmap(bmp2, new Matrix(), null);
return bmOverlay;
}

Categories

Resources