Android Change Canvas Background Color Without Losing Any Drawings From It
Solution 1:
The answers already given to your question are all pointing in the right direction: you do need to separate your background color block and your foreground drawing in separate layers, then merge them before saving the whole of it in a .png file. This is how Adobe Photoshop workflow is designed as well... It does make sense, if we think about it: take for example a software like MsPaint: because it doesn't use layers, it has to rely on stuff like floodfill algorithms to accomplish (albeit in an incomplete way) something remotely similar to a background change...
One way to implement such a thing would be to instantiate 2 Canvas objects backed by 2 different bitmaps. The first Canvas-Bitmap pair would be used for your drawing at the foreground, and the second Canvas-Bitmap pair would be used for your merged-layers drawing (i.e. foreground drawing + background color block). Then the 2nd Bitmap is what will be saved to a .png file when you need it to be saved. This way, our first Canvas-Bitmap pair stores your foreground info, which is not destroyed if a background color change needs to be made. Everytime an operation is made, the layers can be merged into the 2nd Canvas-Bitmap pair so that there is always a Bitmap with the correct content that is ready to be saved at your whim.
Here is a custom View I made so as to clear this methodology up. It implements a simple view used to paint a blue line on the touch-screen using a finger, with a background color changing depending on the X-Y position of said finger so as to demonstrate a background color change without unnecessary code complexity inherent of a complete implementation with a color wheel/menus/inter alia:
package com.epichorns.basicpaint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Paint.Style;
import android.view.View;
publicclassPaintViewextendsView{
Bitmap mMergedLayersBitmap=null; //Note: this bitmap here contains the whole of the drawing (background+foreground) to be saved.
Canvas mMergedLayersCanvas=null;
BitmapmBitmap=null; //bitmap onto which we draw our stuffCanvasmCanvas=null; //Main canvas. Will be linked to a .bmp fileintmBackgroundColor=0xFF000000; //default background colorPaintmDefaultPaint=newPaint();
PaintmDrawPaint=newPaint(); //used for painting example foreground stuff... We draw line segments.PointmDrawCoor=newPoint(); //used to store last location on our PaintView that was finger-touched//Constructor: we instantiate 2 Canvas-Bitmap pairspublicPaintView(Context context, int width, int height) {
super(context);
mMergedLayersBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mMergedLayersCanvas = newCanvas(mMergedLayersBitmap);
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = newCanvas(mBitmap);
}
//Change background colorpublicvoidchangeColor(int newColor){
mBackgroundColor = newColor;
invalidate(); //refresh view: this will indirectly invoke onDraw soon afterwards
}
//Called by user of PaintView in order to start a painting "stroke" (finger touching touch-screen): stores the //location of the finger when it first touched the screenpublicvoidstartDraw(int x, int y, int radius, int color){
mDrawPaint.setColor(color);
mDrawPaint.setStyle(Style.STROKE);
mDrawPaint.setStrokeWidth(radius);
mDrawCoor.x = x;
mDrawCoor.y = y;
}
//Called by user of PaintView when finger touching touch-screen is moving (must be called after a startDraw, //as the latter initializes a couple of necessary things)publicvoidcontinueDraw(int x, int y){
mCanvas.drawLine(mDrawCoor.x, mDrawCoor.y, x, y, mDrawPaint);
mDrawCoor.x = x;
mDrawCoor.y = y;
invalidate(); //refresh view: this will indirectly invoke onDraw soon afterwards
}
//Merge the foreground Canvas-Bitmap with a solid background color, then stores this in the 2nd Canvas-Bitmap pair.privatevoidmergeLayers(){
mMergedLayersCanvas.drawColor(mBackgroundColor);
mMergedLayersCanvas.drawBitmap(mBitmap, 0, 0, mDefaultPaint);
}
@OverridepublicvoidonDraw(Canvas canvas){
mergeLayers();
canvas.drawBitmap(mMergedLayersBitmap, 0, 0, mDefaultPaint);
}
}
In order to test this view, here is a test Activity that uses the PaintView
class. Both of those files are self-sufficient in an Android project, so that you can test it on your real device without hassle:
package com.epichorns.basicpaint;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import com.epichorns.basicpaint.PaintView;
publicclassBasicPaintActivityextendsActivity {
PaintView mPaintView=null;
LinearLayoutmL=null;
boolean mIsDrawing=false;
intmBackgroundColor=0xFF000000;
/** Called when the activity is first created. */@OverridepublicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Displaydisplay= getWindowManager().getDefaultDisplay();
finalfloatdispWidth= (float)display.getWidth();
finalfloatdispHeight= (float)display.getHeight();
mPaintView = newPaintView(this, display.getWidth(), display.getHeight());
mPaintView.changeColor(mBackgroundColor);
mPaintView.setOnTouchListener(newView.OnTouchListener(){
publicbooleanonTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
mPaintView.startDraw((int)event.getX(), (int)event.getY(), 6, 0x806060FF);
mIsDrawing=true;
returntrue;
}
elseif(event.getAction()==MotionEvent.ACTION_UP){
mIsDrawing=false;
returntrue;
}
elseif(event.getAction()==MotionEvent.ACTION_MOVE){
if(mIsDrawing){
//To demonstrate background change, change background color depending on X-Y positionintr= (int)(255f*event.getX()/dispWidth);
intg= (int)(255f*event.getY()/dispHeight);
mBackgroundColor = Color.argb(0xFF, r,g, 0x00);
Log.d("DEBUG1", "Color channels: (r, g) = ("+String.valueOf(r)+", "+String.valueOf(g)+")");
mPaintView.changeColor(mBackgroundColor);
//now, draw stuff where finger was dragging...
mPaintView.continueDraw((int)event.getX(), (int)event.getY());
returntrue;
}
else{
returnfalse;
}
}
returnfalse;
}
});
setContentView(mPaintView);
}
}
Solution 2:
When you draw the color, it's drawn over your drawings. You need to draw the color, and then draw every thing else again.
Solution 3:
Look if you want to change in canvas then you have to call invalidate to apply these changes your screen.And if you call invalidate then your onDraw()
method will call.
If you want to change just background color of canvas from color picker then save color value in variable and call invalidate just after saving variable.Now your onDraw()
will call.Now change background of canvas by calling setBackgroundColor(color variable)
in onDraw()
and draw everything else you want
Solution 4:
use canvas.drawARGB(a,r,g,b) and it will work for definite
Solution 5:
As long as your background is and will be in another color, you can do:
for (x...)
for (y...)
if (bitmap.getPixel(x,y) == oldBackgroundColor)
bitmap.setPixel(x,y,newBackgroundColor)
Or, you can draw your content on an offscreen bitmap, and draw the background and then the offscreen to the actual bitmap. That way you can change the backgroundcolor that will be used when the next two-step-drawing will happen.
Post a Comment for "Android Change Canvas Background Color Without Losing Any Drawings From It"