I have a drawing class i have created that has some performance issues. I imagine it has to do with the way i am handling the drawing actions and undo/redo functions. Can anyone offer some advice as to how to improve the performance?
public class KNDrawingSurfaceView extends View {
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
public Bitmap mBitmap;
public Canvas mCanvas;
public Path mPath;
public Paint mBitmapPaint;
float myWidth;
float myHeight;
public Paint mPaint;
public MaskFilter mEmboss;
public MaskFilter mBlur;
public ArrayList<Path> paths = new ArrayList<Path>();
public ArrayList<Paint>paints = new ArrayList<Paint>();
public ArrayList<Path> undonePaths = new ArrayList<Path>();
public ArrayList<Paint>undonePaints = new ArrayList<Paint>();
private KNSketchBookActivity _parent;
public KNDrawingSurfaceView(Context c, float width,float height, KNSketchBookActivity parent) {
super(c);
myWidth = width;
myHeight = height;
_parent =parent;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
mBitmap = Bitmap.createBitmap((int)myWidth, (int)myHeight, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
Log.v("onDraw:", "curent paths size:"+paths.size());
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
Paint tile = new Paint();
Bitmap tileImage = BitmapFactory.decodeResource(getResources(),R.drawable.checkerpattern);
BitmapShader shader = new BitmapShader(tileImage, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
tile.setShader(shader);
canvas.drawRect(0, 0, myWidth, myHeight, tile);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for (Path p : paths){
canvas.drawPath(p, mPaint);
}
canvas.drawPath(mPath,mPaint);
}
public void onClickUndo () {
if (paths.size()>0)
{
undonePaths.add(paths.remove(paths.size()-1));
undonePaints.add(paints.remove(paints.size()-1));
invalidate();
}
else
{
}
_parent.checkButtonStates();
}
public void onClickRedo (){
if (undonePaths.size()>0)
{
paths.add(undonePaths.remove(undonePaths.size()-1));
paints.add(undonePaints.remove(undonePaints.size()-1));
invalidate();
}
else
{
}
_parent.checkButtonStates();
}
public void onClickClear (){
paths.clear();
undonePaths.clear();
invalidate();
_parent.checkButtonStates();
}
public void saveDrawing(){
FileOutputStream outStream = null;
String fileName = "tempTag";
try {
outStream = new FileOutputStream("/sdcard/" + fileName + ".png");
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
undonePaths.clear();
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);
mCanvas.drawPath(mPath, mPaint);
paths.add(mPath);
paints.add(mPaint);
_parent.checkButtonStates();
mPath = new Path();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
if(x>myWidth){
x=myWidth;
}
if(y>myHeight){
y=myHeight;
}
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;
}
}
please share with me any experience or links you may have dealing with drawing/canvas optimization
Use the below for reference and modify the below according to your requirements.
You have the below in onDraw()
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
// will clear the draw
Everytime you can invalidate() will call onDraw(canvas). Your draw will be refreshed.
I don't know what you are trying to do but i removed the above
Moved the inside onSizeChanged
mBitmap = Bitmap.createBitmap((int)myWidth, (int)myHeight, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
Your code works fine. Tested it on emulator.
public class MainActivity extends Activity {
DrawingView dv ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dv = new DrawingView(this);
setContentView(dv);
}
public class DrawingView extends View {
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
public Bitmap mBitmap,tileImage;
public Canvas mCanvas;
public Path mPath;
public Paint mBitmapPaint;
float myWidth;
float myHeight;
Paint tile ;
public Paint mPaint;
public MaskFilter mEmboss;
public MaskFilter mBlur;
public ArrayList<Path> paths = new ArrayList<Path>();
public ArrayList<Paint>paints = new ArrayList<Paint>();
public ArrayList<Path> undonePaths = new ArrayList<Path>();
public ArrayList<Paint>undonePaints = new ArrayList<Paint>();
BitmapShader shader;
public DrawingView(Context c) {
super(c);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.RED);
tile = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
tileImage = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
shader = new BitmapShader(tileImage, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
tile.setShader(shader);
}
#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);
myWidth =w;
myHeight = h;
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
Log.v("onDraw:", "curent paths size:"+paths.size());
for (Path p : paths){
canvas.drawPath(p, mPaint);
}
canvas.drawPath(mPath,mPaint);
}
public void onClickUndo () {
if (paths.size()>0)
{
undonePaths.add(paths.remove(paths.size()-1));
undonePaints.add(paints.remove(paints.size()-1));
invalidate();
}
else
{
}
}
public void onClickRedo (){
if (undonePaths.size()>0)
{
paths.add(undonePaths.remove(undonePaths.size()-1));
paints.add(undonePaints.remove(undonePaints.size()-1));
invalidate();
}
else
{
}
}
public void onClickClear (){
paths.clear();
undonePaths.clear();
invalidate();
}
public void saveDrawing(){
FileOutputStream outStream = null;
String fileName = "tempTag";
try {
outStream = new FileOutputStream("/sdcard/" + fileName + ".png");
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
undonePaths.clear();
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);
mCanvas.drawPath(mPath, mPaint);
paths.add(mPath);
paints.add(mPaint);
mPath = new Path();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
if(x>myWidth){
x=myWidth;
}
if(y>myHeight){
y=myHeight;
}
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;
}
}
You are recreating 2 bitmaps, paint and BitmapShader in onDraw() method. This is causing your performance issues.
try this:
- move object creations to constructor.
- i think that you can remove this part completely:
mBitmap = Bitmap.createBitmap((int)myWidth, (int)myHeight, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
(if you need to get bitmap from your canvas, create separate method for that and call it when needed)
Do not create or instantiate any variable on your "loop", do that before and outside onDraw and reuse the same variables. This will surely increase performance!
As you all suggested i pulled all my var initiations out of onDraw and put them in the constructor.
This particular piece is needed to clear the canvas when the user undoes or redoes something they have drawn:
mBitmap = Bitmap.createBitmap((int) myWidth, (int) myHeight, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
so i created a new method that i just call on undo/redo:
public void clearCanvasCache() {
mBitmap = Bitmap.createBitmap((int) myWidth, (int) myHeight, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
Works great now..
The Whole class:
public class KNDrawingSurfaceView extends View {
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
public Bitmap mBitmap;
public Canvas mCanvas;
public Path mPath;
public Paint mBitmapPaint;
float myWidth;
float myHeight;
public Paint mPaint;
public MaskFilter mEmboss;
public MaskFilter mBlur;
public ArrayList<Path> paths = new ArrayList<Path>();
public ArrayList<Paint> paints = new ArrayList<Paint>();
public ArrayList<Path> undonePaths = new ArrayList<Path>();
public ArrayList<Paint> undonePaints = new ArrayList<Paint>();
private KNSketchBookActivity _parent;
Paint tile;
Bitmap tileImage;
BitmapShader shader;
public KNDrawingSurfaceView(Context c, float width, float height, KNSketchBookActivity parent) {
super(c);
myWidth = width;
myHeight = height;
mBitmap = Bitmap.createBitmap((int) myWidth, (int) myHeight, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
_parent = parent;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
tile = new Paint();
tileImage = BitmapFactory.decodeResource(getResources(), R.drawable.checkerpattern);
shader = new BitmapShader(tileImage, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
tile.setShader(shader);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
Log.v("onDraw:", "curent paths size:" + paths.size());
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.drawRect(0, 0, myWidth, myHeight, tile);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for (Path p : paths) {
canvas.drawPath(p, mPaint);
}
canvas.drawPath(mPath, mPaint);
}
public void onClickUndo() {
if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
undonePaints.add(paints.remove(paints.size() - 1));
clearCanvasCache();
invalidate();
} else {
}
_parent.checkButtonStates();
}
public void onClickRedo() {
if (undonePaths.size() > 0) {
paths.add(undonePaths.remove(undonePaths.size() - 1));
paints.add(undonePaints.remove(undonePaints.size() - 1));
clearCanvasCache();
invalidate();
} else {
}
_parent.checkButtonStates();
}
public void onClickClear() {
paths.clear();
undonePaths.clear();
clearCanvasCache();
invalidate();
_parent.checkButtonStates();
}
public void saveDrawing() {
FileOutputStream outStream = null;
String fileName = "tempTag";
try {
outStream = new FileOutputStream("/sdcard/" + fileName + ".png");
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
undonePaths.clear();
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);
mCanvas.drawPath(mPath, mPaint);
paths.add(mPath);
paints.add(mPaint);
_parent.checkButtonStates();
mPath = new Path();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!_parent.isDrawerOpen()) {
float x = event.getX();
float y = event.getY();
if (x > myWidth) {
x = myWidth;
}
if (y > myHeight) {
y = myHeight;
}
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;
} else {
return false;
}
}
public void clearCanvasCache() {
mBitmap = Bitmap.createBitmap((int) myWidth, (int) myHeight, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
}
Related
I am trying to create a canvas that you can draw over a bitmap with. I have loaded the bitmap and there's no problem with it. But when I use drawBitmap I only get a blank screen, while the painting and drawPath still works. I have tried passing the bitmap directly into the constructor as well. Pls help
public class DrawView extends View implements OnTouchListener {
private static final String TAG = "DrawView" ;
private Canvas mCanvas;
private Path mPath;
private Paint mPaint;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
final int defaultBrushSize = 10;
private Bitmap im;
public DrawView(Context context, Intent intent,String fileroot)
{
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(Color.parseColor("#000000"));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.BEVEL);
mPaint.setStrokeCap(Paint.Cap.SQUARE);
mPaint.setAlpha(150);
mPaint.setStrokeWidth(defaultBrushSize);
FileInputStream in = null;
try {
in = new FileInputStream(fileroot+"/"+intent.getStringExtra("image")+".jpg");
BufferedInputStream buf = new BufferedInputStream(in);
byte[] bMapArray= new byte[buf.available()];
Log.d(TAG, "onCreate: bMap array: " + bMapArray.toString());
buf.read(bMapArray);
im = BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length).copy(Bitmap.Config.ARGB_8888, true);
Log.d(TAG, "onCreate: bmap " + im);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
mPath = new Path();
mCanvas = new Canvas();
mCanvas.drawBitmap(im,null,new Rect(0,0,im.getWidth(),im.getHeight()),null);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
for (Path p : paths){
canvas.drawPath(p, mPaint);
}
canvas.drawPath(mPath, mPaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
undonePaths.clear();
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
paths.add(mPath);
mPath = new Path();
}
public void onClickUndo () {
if (paths.size()>0)
{
undonePaths.add(paths.remove(paths.size()-1));
invalidate();
}
else
{
}
//toast the user
}
public void onClickRedo (){
if (undonePaths.size()>0)
{
paths.add(undonePaths.remove(undonePaths.size()-1));
invalidate();
}
else
{
}
//toast the user
}
public void setSize(int s){
mPaint.setStrokeWidth(s);
invalidate();
}
#Override
public boolean onTouch(View arg0, 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;
}
You aren't backing the Canvas anywhere. Just calling new Canvas, without backing it somewhere, sends the draw commands into a black hole. Generally you back them to an in memory Bitmap object you have to create first. So here you'd want to use canvas = new Canvas(bitmap);
Also note that to get anything to appear on screen, you must draw it to the Canvas passed into onDraw during the onDraw function. So just drawing to a random Canvas, backed or not, will not draw it to the screen.
I was using this class to draw like pen tool with multi color it is working good but when i change color ,it does not change color in between choosing color. i checked and try many solution they don't have any solution.
public class DrawingView extends View {
private static final float TOUCH_TOLERANCE = 4;
Paint mPaint;
//MaskFilter mEmboss;
//MaskFilter mBlur;
Bitmap mBitmap;
Canvas mCanvas;
Path mPath;
Paint mBitmapPaint;
ProgressDialog pd;
String color;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Paint> paints = new ArrayList<Paint>();
private ArrayList<Integer> colorlist = new ArrayList<Integer>();
private float mX, mY;
public DrawingView(Context context, String color) {
super(context);
// TODO Auto-generated constructor stub
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(10);
pd = new ProgressDialog(context);
mPath = new Path();
paths.add(mPath);
mBitmapPaint = new Paint();
paints.add(mPaint);
colorlist.add(Color.parseColor(color));
mBitmapPaint.setColor(Color.parseColor(color));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (w > 0 && h > 0) {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
} else {
mBitmap = Bitmap.createBitmap(300, 250, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
}
#Override
public void draw(Canvas canvas) {
// TODO Auto-generated method stub
super.draw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
// canvas.drawPath(mPath, mPaint);
int count = paints.size();
for (int i = 0; i < count; i++) {
mPaint.setColor(colorlist.get(i));
canvas.drawPath(paths.get(i), mPaint);
}
}
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);
//mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
// kill this so we don't double draw
mPath.reset();
// mPath= new Path();
}
#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 SMILEY;
}
}
i'm using this class to draw painting, i'm using this class in activity like this.
mDrawingView = new DrawingView(getApplicationContext(), color);
mDrawingPad.addView(mDrawingView);
mDrawingPad is a linear layout in which i'm creating view.
I got the solution of this problem from here
I made some changes according to this solution in my code and finally i found it.
public class DrawingView extends View {
private static final float TOUCH_TOLERANCE = 4;
Paint mPaint;
//MaskFilter mEmboss;
//MaskFilter mBlur;
Bitmap mBitmap;
Canvas mCanvas;
Path mPath;
Paint mBitmapPaint;
ProgressDialog pd;
String color;
ArrayList<Pair<Path, Paint>> p = new ArrayList<Pair<Path, Paint>>();
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Paint> paints = new ArrayList<Paint>();
private float mX, mY;
public DrawingView(Context context, String color) {
super(context);
// TODO Auto-generated constructor stub
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
// mPaint.setColor(Color.parseColor(color));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(10);
pd = new ProgressDialog(context);
mPath = new Path();
paths.add(mPath);
mBitmapPaint = new Paint();
paints.add(mPaint);
p.add(new Pair<Path, Paint>(mPath, mPaint));
//colorlist.put(mPath,color);
mBitmapPaint.setColor(Color.parseColor(color));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (w > 0 && h > 0) {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
} else {
mBitmap = Bitmap.createBitmap(300, 250, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
}
#Override
public void draw(Canvas canvas) {
// TODO Auto-generated method stub
super.draw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
// canvas.drawPath(mPath, mPaint);
for (Pair<Path, Paint> pp : p) {
canvas.drawPath(pp.first, pp.second);
}
}
private void touch_start(float x, float y) {
mPaint.setColor(ImageEditOptionActivity.pencolor);
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);
//mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
// kill this so we don't double draw
p.add(new Pair<Path, Paint>(mPath, mPaint));
mPath.reset();
mPath = new Path();
//colorlist.put(mPath,color);
mPaint = new Paint(mPaint);
p.add(new Pair<Path, Paint>(mPath, mPaint));
}
#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 SMILEY;
}
}
I've create an Activity for draw a sign, save it into internal storage, reaload it and continue to draw starting from Bitmap saved.
At first launch the file is not loaded because it doesn't exists. So I draw and when I click back to previos Activity I save the Bitmap in file. From second launch the file exists and it is correctly loaded (I view image from debug in android studio). The problem is that the canvas appear blank. I have not Exception. Any ideas?
public class PhysicalSignatureActivity extends AppCompatActivity {
DrawingView dv ;
private Paint mPaint;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setTitle("Physical sign");
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(3);
if (!(getIntent().getStringExtra("filename") == null)){
try {
InputStream inputStream = getApplicationContext().openFileInput(getIntent().getStringExtra("filename"));
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
Bitmap bitmap_mutable = bitmap.copy(Bitmap.Config.ARGB_8888, true);
dv = new DrawingView(this,bitmap_mutable);
} catch (FileNotFoundException ex) {
}
} else {
dv = new DrawingView(this);
}
setContentView(dv);
}
#Override
public void onBackPressed() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(false);
builder.setMessage("Save sign?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String filename = UUID.randomUUID().toString()+".png";
FileOutputStream outputStream = null;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
dv.buildDrawingCache();
Bitmap bitmap = dv.getDrawingCache();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();
} catch (FileNotFoundException ex) {
} catch (IOException e) {
e.printStackTrace();
} finally {
Intent i = new Intent(PhysicalSignatureActivity.this, PerformanceActivity.class);
i.putExtra("performance_id",getIntent().getStringExtra("performance_id"));
i.putExtra("authentication_token",getIntent().getStringExtra("authentication_token"));
i.putExtra("filename",filename);
startActivity(i);
finish();
}
}
});
builder.setNegativeButton("No",new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
AlertDialog alert=builder.create();
alert.show();
}
public class DrawingView extends View {
public int width;
public int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
Context context;
private Paint circlePaint;
private Path circlePath;
public DrawingView(Context c) {
super(c);
context=c;
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
circlePaint = new Paint();
circlePath = new Path();
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
}
public DrawingView(Context c, Bitmap b) {
super(c);
context=c;
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
circlePaint = new Paint();
circlePath = new Path();
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
mBitmap = b;
mCanvas = new Canvas();
mCanvas.drawBitmap(mBitmap,0,0,mBitmapPaint);
}
#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) {
super.onDraw(canvas);
canvas.drawBitmap( mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath( mPath, mPaint);
canvas.drawPath( circlePath, circlePaint);
}
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;
circlePath.reset();
circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
circlePath.reset();
// 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;
}
}
}
this has been driving me a little crazy today. I've implimented this class which enables me to draw lines over an image file. however I want to be able to to add a template mask at creation time. Whatever I try i.e. within the class or from the calling class it causes a Null pointer exception, if however I put the call into a button in the calling class then I can get it to work?
here is the class I'm using. You can see the commented out section, if I call "coverScreen()" from here it causes the NPE. Also from the main Activity where I create the maskBoard if I call "coverScreen()" it causes NPE. But as mentioned if I add a button, and put the "coverScreen()" into this button onclick then it works?
public class MaskBoard extends View {
private String TAG = "Test APP - maskboard";
private int mx = -1;
private int my = -1;
private Bitmap mainImage = null;
private Bitmap bm = null;
private Paint mPaint = null;
public final int CLOSER = 50;
public final int CLOSE = 100;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
public MaskBoard(Context c, AttributeSet s) {
super(c, s);
String fileToMask = "/__temppic.png";
File imagePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES + "/temp/");
File imgFile = new File(imagePath+fileToMask);
if (imgFile.exists()) {
bm = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
Log.i(TAG, "found image");
}
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mPaint = new Paint();
mPaint.setAntiAlias(false);
mPaint.setDither(true);
mPaint.setColor(0xFFFE0000); // FFFF0000
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(50);
/* coverScreen() */
setEraser();
}
public void coverScreen() {
Bitmap maskImage = BitmapFactory.decodeResource(getResources(), R.drawable.mask); //get mask image
maskImage = Bitmap.createScaledBitmap(maskImage, bm.getWidth(), bm.getHeight(), true);
mPaint.setXfermode(null);
mCanvas.drawBitmap(maskImage,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
public void setEraser() {
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
public void setPaint() {
mPaint.setXfermode(null);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Log.i(TAG, "onsizechanged");
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
Log.i(TAG, "onDraw");
canvas.drawRect(0,0, getWidth(), getHeight(), mPaint);
canvas.drawColor(0xFFAAAAAA);
canvas.drawBitmap(bm, mx, my, null);
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;
Log.i(TAG, " touchdown: X(" + x + "), Y(" + 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;
Log.i(TAG, " touchmove: X(" + x + "), Y(" + 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);
// coverScreen() ;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}
Am not performing Undo/Redo operation canvas in this code. When am use the array list for removing the postion then it not work and during changing the color of paint from color picker the previous drawing color has been also change.
I am not understanding that how to perform UNDO/REDO for this.
So plz help
//This is main class
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView (mView = new MyView(this));
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(4);
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 },
0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
}
//And MyView class is
public class MyView extends View {
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
ArrayList<Path> paths = new ArrayList<Path>();
ArrayList<Path> undonePaths = new ArrayList<Path>();
public MyView(Context c)
{
super(c);
mBitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
// mCanvas.setBackgroundResource(0xFFFFFFFF);
mCanvas.drawColor (0xFFFFFFFF);
paths.add(mPath);
}
public MyView (Context c, int color)
{
super(c);
mBitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mCanvas.drawColor (color);
paths.add(mPath);
}
#Override protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
}
#Override protected void onDraw(Canvas canvas)
{
canvas.drawColor(0xFF000000);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for(Path p: paths)
{
canvas.drawPath(p, 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);
mCanvas.drawPath(mPath, mPaint);
paths.add(mPath);
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 void clear ()
{
Paint p = new Paint();
p.setAntiAlias(true);
p.setDither(true);
p.setColor(0xFFFFFFFF);
mCanvas.drawPaint (p);
}
public void drawImage (int resourceId)
{
Bitmap _scratch = BitmapFactory.decodeResource(getResources(), resourceId);
mCanvas.drawBitmap(_scratch, 0, 0, null);
}
public void undo() {
// TODO Auto-generated method stub
mCanvas.drawCircle(posX, posY, 100, mPaint);
Toast.makeText(getApplicationContext(), "Hello", 1000).show();
if (paths.size()>0)
{
undonePaths.add(paths.remove(paths.size()-1));
mView.invalidate();
Toast.makeText(getApplicationContext(), "Undo", 1000).show();
}
else
{
Toast.makeText(getApplicationContext(), "Not", 1000).show();
}
}
public void redo() {
// TODO Auto-generated method stub
if (undonePaths.size()>0)
{
paths.add(undonePaths.remove(undonePaths.size()-1));
invalidate();
}
else
{
}
}
public void saveAsJpg (File f)
{
String fname = f.getAbsolutePath ();
FileOutputStream fos = null;
try {
fos = new FileOutputStream (f);
mBitmap.compress (CompressFormat.JPEG, 95, fos);
} catch (Throwable ex) {
ex.printStackTrace ();
}
} // end saveAsJpg
} // end MyView
} // end class FingerPaint
this working code .I test it on my own app and it is working very good.
May be it help u.Please comment on it.
public class Main extends Activity implements OnColorChangedListener {
//public static int selectedColor = Color.BLACK;
public static ArrayList<Path> mMaindialog;
// private ArrayList<Path> undonePaths;
// public int selectedcolor;
private static final String COLOR_PREFERENCE_KEY = "color";
private FrameLayout relativelayout;
static String sdpath,location;
Boolean i;
// Instance variables
private Bitmap mBitmap=null;
Bitmap bitmap;
private Paint mPaint, mBitmapPaint, mPaint1;
private MyView mView;
ImageView idd;
// private Path mPath;
int slll = Color.BLACK;
Bitmap map=ListView5.bMap;
private Button ClearPaint, Colorpaint;
Ghostdatabase gost;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
idd=(ImageView)findViewById(R.id.imageView1);
relativelayout = (FrameLayout) findViewById(R.id.frameLayout);
DisplayMetrics metrics = getBaseContext().getResources()
.getDisplayMetrics();
int w = metrics.widthPixels;
int h = metrics.heightPixels;
System.out.println(" width " + w);
System.out.println(" height " + h);
mView = new MyView(this, w, h);
mView.setDrawingCacheEnabled(true);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(4);
ClearPaint = (Button) findViewById(R.id.ne);
ClearPaint.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// mBitmap.eraseColor(Color.TRANSPARENT);
// mPath.reset();
// mView.invalidate();
mView.onClickUndo();
}
});
Button save22 = (Button) findViewById(R.id.save);
save22.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
File cacheDir;
Toast.makeText(Main.this, "Photo", 500).show();
Bitmap icon;
relativelayout.setDrawingCacheEnabled(true);
icon = Bitmap.createBitmap(relativelayout.getDrawingCache());
Bitmap bitmap = icon;
relativelayout.setDrawingCacheEnabled(false);
// File mFile1 = Environment.getExternalStorageDirectory();
Date d = new Date();
String fileName = d.getTime() + "mg1.jpg";
File storagePath = (Environment.getExternalStorageDirectory());
File dest = new File(storagePath + "/CityAppImages");
if (!dest.exists()) {
dest.mkdirs();
}
File mFile2 = new File(dest, fileName);
sdpath = mFile2.getAbsolutePath();
Log.d("qqqqqqqqqqqqqqqqqqqqqqq", "zzzzzzzz" + sdpath);
try {
FileOutputStream outStream;
outStream = new FileOutputStream(mFile2);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
Toast.makeText(Main.this, "Photo Saved Sucessfully", 500)
.show();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(Main.this, "Photo Not Saved Sucessfully",
500).show();
}
gost = new Ghostdatabase(Main.this);
gost.open();
gost.insertTitle(sdpath);
}
});
Button view = (Button) findViewById(R.id.listtt);
view.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent ii = new Intent(Main.this, ListView5.class);
startActivity(ii);
}
});
Button Colorpaint = (Button) findViewById(R.id.Color);
Colorpaint.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
int color = PreferenceManager.getDefaultSharedPreferences(
Main.this).getInt(COLOR_PREFERENCE_KEY, Color.WHITE);
// int _color = R.color.red;
new ColorPickerDialog(v.getContext(),
new OnColorChangedListener() {
public void colorChanged(int color) {
mPaint.setColor(color);
slll = color;
Log.i("TAG", "mpaint one" + mPaint);
}
}, mPaint.getColor()).show();
Log.i("TAG", "mpaint two" + mPaint);
}
});
relativelayout.addView(mView);
}
// //////////******************* Pinting view
// *******************///////////////////
public class MyView extends View implements OnTouchListener {
private Map<Path, Integer> colorsMap = new HashMap<Path, Integer>();
private ArrayList<Path> mMaindialog = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
int colorPicked = slll;
// Paint mPaint1;
private Canvas mCanvas;
private Path mPath;
public MyView(Context c, int w, int h) {
super(c);
if(GlobalVariable.impath==1)
{
Log.d("","111111"+GlobalVariable.impath);
System.out.println(GlobalVariable.impath);
Intent ii = getIntent();
location = ii.getStringExtra("IMAGE");
// bitmap.recycle();
Log.d("","location"+location);
bitmap = BitmapFactory.decodeFile(location);
mBitmap = Bitmap.createScaledBitmap(bitmap,300, 300,false);
Log.d("hhhhhhhhhhhhhhhssssssss","mBitmap"+mBitmap);
//mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
// idd.setImageBitmap(mBitmap);
Log.d("hhhhhhhhhhhhhhhssssssss","GlobalVariable.impath"+GlobalVariable.impath);
}
else if(GlobalVariable.impath==2){
//bitmap.recycle();
Log.d("","22222222222222222222222"+GlobalVariable.impath);
bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.base);
mBitmap = Bitmap.createScaledBitmap(bitmap,100, 100, false);
//mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Log.d("hhhhhhhhhhhhhhhssssssss1111111","mBitmap"+mBitmap);
}
//
mCanvas = new Canvas(mBitmap);
mPath = new Path();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for (Path p : mMaindialog) {
mPaint.setColor(colorsMap.get(p));
canvas.drawPath(p, mPaint);
}
mPaint.setColor(slll);
canvas.drawPath(mPath, mPaint);
}
// //////************touching evants for painting**************///////
private float mX, mY;
private static final float TOUCH_TOLERANCE = 0;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
undonePaths.clear();
}
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 = new Path();
mPath.reset();
mMaindialog.add(mPath);
}
#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();
undonePaths.clear();
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
// touch_move(x, y);
// invalidate();
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;
}
invalidate();
break;
case MotionEvent.ACTION_UP:
// touch_up();
// invalidate();
mPath.lineTo(mX, mY);
mMaindialog.add(mPath);
colorsMap.put(mPath, slll);
mPath = new Path();
mPath.reset();
invalidate();
break;
}
return true;
} // end of touch events for image
private Paint createPen(int colorPicked) {
// TODO Auto-generated method stub
mPaint1 = new Paint();
mPaint1.setColor(colorPicked);
mPaint1.setAntiAlias(true);
mPaint1.setDither(true);
mPaint1.setStyle(Paint.Style.STROKE);
mPaint1.setStrokeJoin(Paint.Join.ROUND);
mPaint1.setStrokeCap(Paint.Cap.ROUND);
// mPaint1.setStrokeWidth(3);
return mPaint1;
}
public void onClickRedo() {
if (undonePaths.size() > 0) {
mMaindialog.add(undonePaths.remove(undonePaths.size() - 1));
mView.invalidate();
} else {
}
// toast the user
}
public void onClickUndo() {
if (mMaindialog.size() > 0) {
undonePaths.add(mView.mMaindialog.remove(mView.mMaindialog
.size() - 1));
mView.invalidate();
}
else {
}
}
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
return false;
}
}// end MyView
#Override
public void colorChanged(int color) {
// TODO Auto-generated method stub
PreferenceManager.getDefaultSharedPreferences(this).edit()
.putInt(COLOR_PREFERENCE_KEY, color).commit();
slll = color;
}
}