Aplicación de Android – ¿Cómo guardar un dibujo de mapa de bits en lienzo como imagen? ¿Código de verificación?

Traté de usar los siguientes códigos para

  1. Dibujar sobre lienzo
  2. Guardar el lienzo en la imagen

Problema – Cuando intento guardar la imagen, muestra un error de puntero nulo y no se guarda nada.

Por favor, ayúdame a encontrar el problema con el código o sugerirme una alternativa, que hace excatly lo mismo. Gracias por adelantado.

Código para dibujar sobre lienzo:

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(); } } 

El segundo código para guardar el lienzo como imagen está en la actividad principal.

He probado algunas cosas y se ha comentado parte del código.

Ya que soy un principiante, aprecio cualquier consejo

Segundo código 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 Solutions collect form web for “Aplicación de Android – ¿Cómo guardar un dibujo de mapa de bits en lienzo como imagen? ¿Código de verificación?”

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(); } } 

Actividad principal

 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> 

Y en tu AndroidManifest.xml asegúrate de tener

  <?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> 

Hay un poco de añadir en el código anterior. El código anterior está guardando la imagen en el almacenamiento. Pero la imagen no se muestra en la galería. Para mostrar la imagen en la galería sólo tiene que configurar un MediaScannerConnection para el mapa de bits que estamos guardando

Función de muestra

 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(); } 

Y llamar a esta función justo después de esta línea

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

Ahora el mapa de bits guardado también es visible en la Gallery

  • Fuga de memoria de ViewPager de Android
  • Visualización de lienzo / mapa de bits al instante durante la depuración en eclipse
  • Escritura Bitmap al almacenamiento externo (sdcard)
  • Canvas Cambia dinámicamente el índice z de un mapa de bits
  • Cargando imágenes con Picasso desde el almacenamiento interno
  • Bitmapshader y canvas.scaling android
  • Deslizar para eliminar con rotación
  • Ventaja dibujable sobre mapa de bits para la memoria en android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.