Android应用程序 - 如何将画布上的位图绘制保存为图像?检查代码?

时间:2013-09-07 18:03:37

标签: java android bitmap android-canvas

我尝试使用以下代码

  1. 在画布上绘画
  2. 将画布保存在图像
  3. 问题 - 当我尝试保存图像时,它显示空指针错误,并且没有保存任何内容。

    请帮助我找到代码的问题或建议我一个替代方案,这是非常相似的。提前谢谢。

    在画布上绘制的代码:

    package com.example.draw2;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    
    public class MyDrawView extends View {
        private Bitmap  mBitmap;
        private Canvas  mCanvas;
        private Path    mPath;
        private Paint   mBitmapPaint;
        private Paint   mPaint;
    
        public MyDrawView(Context c, AttributeSet attrs) {
            super(c, attrs);
    
            mPath = new Path();
            mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    
            mPaint = new Paint();
            mPaint.setAntiAlias(true);
            mPaint.setDither(true);
            mPaint.setColor(0xFF000000);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeJoin(Paint.Join.ROUND);
            mPaint.setStrokeCap(Paint.Cap.ROUND);
            mPaint.setStrokeWidth(9);
        }
    
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            mCanvas = new Canvas(mBitmap);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
    
            canvas.drawPath(mPath, mPaint);
    
    
        }
    
        private float mX, mY;
        private static final float TOUCH_TOLERANCE = 4;
    
        private void touch_start(float x, float y) {
            mPath.reset();
            mPath.moveTo(x, y);
            mX = x;
            mY = y;
        }
        private void touch_move(float x, float y) {
            float dx = Math.abs(x - mX);
            float dy = Math.abs(y - mY);
            if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
                mX = x;
                mY = y;
            }
        }
        private void touch_up() {
            mPath.lineTo(mX, mY);
            // commit the path to our offscreen
            mCanvas.drawPath(mPath, mPaint);
            // kill this so we don't double draw
            mPath.reset();
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();
    
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    touch_start(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_MOVE:
                    touch_move(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_UP:
                    touch_up();
                    invalidate();
                    break;
            }
            return true;
        }
    
        public Bitmap getBitmap()
        {
        return mBitmap;
        }
    
    
    
        public void clear(){
            mBitmap.eraseColor(Color.GREEN);
            invalidate();
            System.gc();
    
        }
    
    }
    

    将画布保存为图像的第二个代码位于主要活动中。

    我尝试了一些事情,并对部分代码进行了评论。

    由于我是初学者,我感谢任何建议

    第二个代码MainActivity:

    package com.example.draw2;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    import android.app.Activity;
    import android.graphics.Bitmap;
    import android.os.Bundle;
    import android.os.Environment;
    import android.view.Menu;
    import android.view.View;
    import android.widget.Button;
    import android.widget.Toast;
    
    
    public class MainActivity extends Activity 
    {
        MyDrawView myDrawView;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) 
        {
    
            super.onCreate(savedInstanceState);
            myDrawView = new MyDrawView(this, null);
            setContentView(R.layout.activity_main);
    
            Button button1 = (Button)findViewById(R.id.button1);    
            button1.setOnClickListener(new View.OnClickListener() 
            {
                public void onClick(View v)
                {       
                    //View content = myDrawView;
    
                    //System.out.println(content);
    
    
                    //Bitmap bitmap = content.getDrawingCache();
    
                    File folder = new File(Environment.getExternalStorageDirectory().toString());
                     boolean success = false;
                     if (!folder.exists()) 
                     {
                         success = folder.mkdirs();
                     }
    
                     System.out.println(success+"folder");
    
                     File file = new File(Environment.getExternalStorageDirectory().toString() + "/sample.JPEG");
    
                 if ( !file.exists() )
                 {
                       try {
                        success = file.createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                 }
    
                 System.out.println(success+"file");
    
    
    
                 FileOutputStream ostream = null;
                    try
                    {
                    ostream = new FileOutputStream(file);
    
                    System.out.println(ostream);
    
                    Bitmap save = myDrawView.getBitmap();
                    if(save == null) {
                        System.out.println("NULL bitmap save\n");
                    }
                    save.compress(Bitmap.CompressFormat.PNG, 100, ostream);
                    //bitmap.compress(Bitmap.CompressFormat.PNG, 100, ostream);
                       ostream.flush();
                        ostream.close();
                    }catch (NullPointerException e) 
                    {
                        e.printStackTrace();
                        Toast.makeText(getApplicationContext(), "Null error", Toast.LENGTH_SHORT).show();
                    }
    
                    catch (FileNotFoundException e) 
                    {
                        e.printStackTrace();
                        Toast.makeText(getApplicationContext(), "File error", Toast.LENGTH_SHORT).show();
                    }
    
                    catch (IOException e) 
                    {
                        e.printStackTrace();
                        Toast.makeText(getApplicationContext(), "IO error", Toast.LENGTH_SHORT).show();
                    }
    
                }
            });
    
        }
    
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    }
    

2 个答案:

答案 0 :(得分:20)

MyDrawView

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.LruCache;
import android.view.MotionEvent;
import android.view.View;

public class MyDrawView extends View {
    public Bitmap  mBitmap;
    public Canvas  mCanvas;
    private Path    mPath;
    private Paint   mBitmapPaint;
    private Paint   mPaint;


    public MyDrawView(Context c, AttributeSet attrs) {
        super(c, attrs);

        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(0xFF000000);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(9);

    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

        canvas.drawPath(mPath, mPaint);


    }

    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;

    private void touch_start(float x, float y) {
        mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }
    private void touch_move(float x, float y) {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
            mX = x;
            mY = y;
        }
    }
    private void touch_up() {
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        mPath.reset();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touch_start(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                touch_move(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                touch_up();
                invalidate();
                break;
        }
        return true;
    }

    public Bitmap getBitmap()
    {
        //this.measure(100, 100);
        //this.layout(0, 0, 100, 100);
        this.setDrawingCacheEnabled(true);  
        this.buildDrawingCache();
       Bitmap bmp = Bitmap.createBitmap(this.getDrawingCache());   
        this.setDrawingCacheEnabled(false);


    return bmp;
    }



    public void clear(){
        mBitmap.eraseColor(Color.GREEN);
        invalidate();
        System.gc();

    }

}

MainActivity

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Environment;
import android.view.Menu;
import android.view.View;
import android.view.View.MeasureSpec;
import android.widget.Button;
import android.widget.Toast;


public class MainActivity extends Activity 
{
    MyDrawView myDrawView;


    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {

        super.onCreate(savedInstanceState);
       // myDrawView = new MyDrawView(this, null);
        setContentView(R.layout.activity_main);
        myDrawView = (MyDrawView)findViewById(R.id.draw);
        Button button1 = (Button)findViewById(R.id.button1);    
        button1.setOnClickListener(new View.OnClickListener() 
        {
            public void onClick(View v)
            {       


                File folder = new File(Environment.getExternalStorageDirectory().toString());
                 boolean success = false;
                 if (!folder.exists()) 
                 {
                     success = folder.mkdirs();
                 }

                 System.out.println(success+"folder");

                 File file = new File(Environment.getExternalStorageDirectory().toString() + "/sample.png");

             if ( !file.exists() )
             {
                   try {
                    success = file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
             }

             System.out.println(success+"file");



             FileOutputStream ostream = null;
                try
                {
                ostream = new FileOutputStream(file);

                System.out.println(ostream);
                View targetView = myDrawView;

               // myDrawView.setDrawingCacheEnabled(true);
               //   Bitmap save = Bitmap.createBitmap(myDrawView.getDrawingCache());
               //   myDrawView.setDrawingCacheEnabled(false);
                // copy this bitmap otherwise distroying the cache will destroy
                // the bitmap for the referencing drawable and you'll not
                // get the captured view
               //   Bitmap save = b1.copy(Bitmap.Config.ARGB_8888, false);
                //BitmapDrawable d = new BitmapDrawable(b);
                //canvasView.setBackgroundDrawable(d);
               //   myDrawView.destroyDrawingCache();
               // Bitmap save = myDrawView.getBitmapFromMemCache("0");
               // myDrawView.setDrawingCacheEnabled(true);
               //Bitmap save = myDrawView.getDrawingCache(false);
                Bitmap well = myDrawView.getBitmap();
                Bitmap save = Bitmap.createBitmap(320, 480, Config.ARGB_8888);
                Paint paint = new Paint();
                paint.setColor(Color.WHITE);
                Canvas now = new Canvas(save);
                now.drawRect(new Rect(0,0,320,480), paint);
                now.drawBitmap(well, new Rect(0,0,well.getWidth(),well.getHeight()), new Rect(0,0,320,480), null);

              // Canvas now = new Canvas(save);
               //myDrawView.layout(0, 0, 100, 100);
               //myDrawView.draw(now);
                if(save == null) {
                    System.out.println("NULL bitmap save\n");
                }
                save.compress(Bitmap.CompressFormat.PNG, 100, ostream);
                //bitmap.compress(Bitmap.CompressFormat.PNG, 100, ostream);
                   //ostream.flush();
                    //ostream.close();
                }catch (NullPointerException e) 
                {
                    e.printStackTrace();
                    Toast.makeText(getApplicationContext(), "Null error", Toast.LENGTH_SHORT).show();
                }

                catch (FileNotFoundException e) 
                {
                    e.printStackTrace();
                    Toast.makeText(getApplicationContext(), "File error", Toast.LENGTH_SHORT).show();
                }

                catch (IOException e) 
                {
                    e.printStackTrace();
                    Toast.makeText(getApplicationContext(), "IO error", Toast.LENGTH_SHORT).show();
                }

            }
        });

    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

activity_main.xml中

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >
<com.example.draw2.MyDrawView 
    android:id ="@+id/draw"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"></com.example.draw2.MyDrawView>"
   <Button 
       android:id ="@+id/button1"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="save"
       android:layout_alignParentBottom="true"
       ></Button>"

</RelativeLayout>

并在您的AndroidManifest.xml中确保您有

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.draw2"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.draw2.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

答案 1 :(得分:0)

上面的代码中有一点添加。上面的代码将pic保存在存储器中。但图像没有在画廊中显示。要在图库中显示图片,只需为我们保存的位图设置MediaScannerConnection

示例函数

public void scanPhoto(final String imageFileName) {
    MediaScannerConnection msConn = new MediaScannerConnection(PaintPic.this,
            new MediaScannerConnectionClient() {
                public void onMediaScannerConnected() {
                    msConn.scanFile(imageFileName, null);
                    Log.i("msClient obj  in Photo Utility",
                            "connection established");
                }

                public void onScanCompleted(String path, Uri uri) {
                    msConn.disconnect();
                    Log.i("msClient obj in Photo Utility", "scan completed");
                }
            });
    msConn.connect();
}

在此行之后调用此函数

save.compress(Bitmap.CompressFormat.PNG, 100, ostream);

现在,Gallery

中也可以看到保存的位图