I have created a class that extends View. I am drawing on it. It works as expected. Now I wanna select an image from Gallery and set it to draw above it.
I am setting the image to the bitmap of the canvas once it is selected.
Bitmap bitmap= BitmapFactory.decodeStream(inputStream);
mdb.mExtraBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
mdb is the object of the that custom View.
Here is the onSizeChanged method of the View.
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mExtraBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mExtraCanvas = new Canvas(mExtraBitmap);
mExtraCanvas.drawColor(WHITE);
}
And here is the code inside onDraw method
super.onDraw(canvas);
canvas.drawBitmap(mExtraBitmap, 0, 0, null);
In the onTouchEvent method drawing paths on the mExtraCanvas.
The problem are.
1. The image is set but cannot draw on it.
2. Scale the image to cover.
Thanks!
You just need to draw the selected image on mExtraCanvas
mdb.mExtraCanvas.drawBitmap(image, 0, 0, null)
And for the scaled part create a scaled bitmap like.
Bitmap.createScaledBitmap(image,
mdb.mExtraBitmap.getWidth(),
mdb.mExtraBitmap.getHeight(), false);
Not Tested. But should be work.
Actually What happen, After set mdb.mExtraBitmap , onSizeChanged called. And new bitmap created by Bitmap.createBitmap.
change onSizeChanged() method by below.
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mExtraBitmap = Bitmap.createScaledBitmap(mExtraBitmap,w, h,false);
mExtraCanvas = new Canvas(mExtraBitmap);
}
And no need to draw bitmap again since you are making canvas from Bitmap.
Use mExtraCanvas for every drawing instead of other canvas.
Related
During the past weeks I was looking for appropriate solution for zooming and scrolling functionality on a custom view.In my custom view I am drawing bitmaps on my canvas in onDraw() and creating new bitmap and canvas in onSizeChanged().
my code snippet here :
onDraw() method.In this method I am calling drawBitmap() this method takes image times from pagesProvider class that is my custom class.
Bitmap backBitmap = pagesProvider.getPageBitmap(tile);
src = new Rect();
dst = new Rect();
#Override
public void onDraw(Canvas canvas) {
drawBitmap(canvas, b, src, dst);
}
Here it is drawBitmap() this method drawBitmap on canvas based on Color mode. This color takes from my custom Options Class.And again I am drawing bitmap on canvas with mBitmap this mBitmap created on onSizeChanged() and drawing path on canvas.
private void drawBitmap(Canvas canvas, Bitmap backBitmap, Rect src, Rect dst) {
if (colorMode != Options.COLOR_MODE_NORMAL) {
paint.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(
Options.getColorModeMatrix(this.colorMode))));
canvas.drawBitmap(backBitmap, src, dst, paint);
} else {
canvas.drawBitmap(b, src, dst, null);
}
canvas.drawBitmap(mTopBitmap, 0, 0, mPaint); // mTopBitmap canvas is creating new bitmap on backBitmap bitmap canvas.
canvas.drawPath(mPath, mPaint);
}
onSizeChanged() :
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.width = w;
this.height = h;
mTopBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mTopBitmap);
}
If I remove canvas.drawPath(mPath, mPaint); line from drawBitmap() canvas is not drawing paths on mTopBitmap canvas.And if I remove canvas.drawBitmap(mTopBitmap, 0, 0, mPaint); paths are drawn on backBitmap but those paths resetting when touch up.
In onTouch UP I am calling mCanvas.drawPath(mPath, mPaint); for drawing new path on mTopBitmap.
And My problem was I want to scroll the mTopBitmap canvas content whatever I draw on mCanvas and zoom the mTopBitmap canvas content of mCanvas.
I written zooming functionality and I added scroller according to backBitmap size.It's working fine.But I have confuse with mTopBitmap canvas how I can put scroll and zoom into mTop Canvas.
I'm developing an painting app at the moment for the first time. I can draw and such things.
But everytime the orientation changes, everything is lost. How can i fix this? I have been searching on the internet for solution but dont seem to find one. I know it has to to with the onSizeChanged event from the view class. I have overriden that event and changed a lot to make it work with the orientation change but i cant get it to work.
Here is the code from the onSizeChanged event:
private Canvas drawCanvas;
private Bitmap canvasBitmap;
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//View given size
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
I have already tryed android:configChanges. But it doesnt seem to work.
I have found an solution for this problem. Everytime the screen orientation changed the event was being called. So the bitmap was recreated everytime. I have fixed this by scaling the bitmap before recreation and then setting it as new bitmap. This way it is automatticly scaled and nothing is lost.
This is the full code now:
private Canvas drawCanvas;
private Bitmap canvasBitmap;
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//View given size
super.onSizeChanged(w, h, oldw, oldh);
if(canvasBitmap == null){
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}else{
Bitmap temporary = Bitmap.createScaledBitmap(canvasBitmap, w, h, true);
canvasBitmap = temporary;
}
drawCanvas = new Canvas(canvasBitmap);
}
I got a picture of a sun, 860x860 pixels.
I want to rotate the sun with the anchor-point being center of the screen.
This is what I got so far:
class GraphicalMenu extends View{
int screenH;
int screenW;
int angle;
Bitmap sun, monster;
public GraphicalMenu(Context context){
super(context);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
sun = BitmapFactory.decodeResource(getResources(),R.drawable.sun,options);
monster = BitmapFactory.decodeResource(getResources(),R.drawable.monster,options);
}
#Override
public void onSizeChanged (int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
screenH = h;
screenW = w;
sun = Bitmap.createScaledBitmap(sun, w, h, true);
monster = Bitmap.createScaledBitmap(monster, w, h, true);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
//Increase rotating angle.
if (angle++ >360)
angle =0;
Matrix matrix = new Matrix();
matrix.setRotate(angle , getWidth()/2, getHeight()/2);
canvas.drawBitmap(sun, matrix, new Paint());
//Call the next frame.
canvas.drawBitmap(monster,0 , 0, null);
invalidate();
}
}
I've tried to change this line:
sun = Bitmap.createScaledBitmap(sun, w, h, true);
to:
sun = Bitmap.createScaledBitmap(sun, h, h, true);
but then the sun leaves the center of the screen and rotates far out to the right.
How can I fit the sun to the screen?
And how can I make it keep its ratio?
edit
Screenshot from running it on my N5 and the picture of the sun.
If I understand correctly, you have several problems with your code:
If you're making multiple calls to onSizeChanged() then you'll want to keep the original bitmap (pre-scaled) otherwise when you upscale the bitmaps again, they will look pixelated because every time you downscale them, you're losing information.
When you provide a matrix through which to transform your bitmap for drawing onto the canvas, that matrix will apply to the bitmap itself, not the screen as a whole. So when you make the drawBitmap() call, what you are actually requesting is for the bitmap to be rotated around the local point (getWidth()/2, getHeight()/2), not the screen point.
You're not actually rotating around the screen centre, you're rotating around the View's centre. Unless the View takes up the entire screen, you won't get the intended effect.
I can't pinpoint exactly what your problem is, but uploading some images would likely clarify what you're trying to achieve and what your current situation is.
I need a little help with the application that I'm working. I'm trying to create an application for painting and there is one problem which I noticed a few days ago and now I decide to make some research to solve it. When I use PorterDuff.Mode.CLEAR to use my brush as eraser it's working as it should be while my background is white. But if I set my background in other color ( for example Black like : mCanvas.drawColor(Color.BLACK); ) and after I use the eraser, the places where I use the eraser are painted with white color.
Here is how I'm setting the variables for my eraser :
erase.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stamp=false;
MODE = ERASER_MODE;
mPaint.setColorFilter(null);
mPaint.setShader(null);
mPaint.setMaskFilter(null);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
});
So any ideas why it's happening and how can I fix that problem?
Thanks in advance!
Actually I find where were my problem. In my Custom View that I was using for drawing and etc I was doing this
#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);
mCanvas.drawColor(parentColor); //parentColor = currentBackgroundColor
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
and I had to change only on my
I want to set an image from gallery as a background to the canvas in fingerpaint (api demo sample). I can retrieve the image from gallery but not able to set that as a background. One guess is I can open the image as a input stream, convert that as a array and pass it for bitmap - but I am not sure whether it will work or not and i don't have any clue for how the code will be. Can somebody help me?
You can modify the onSizeChanged() function to,
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
BitmapFactory.Options decode_options = new BitmapFactory.Options();
decode_options.inMutable = true;
mBitmap = BitmapFactory.decodeFile(<file_path>,decode_options);
mCanvas = new Canvas(mBitmap);
mBitmapPaint.setXfermode(new PorterDuffXfermode (SRC_IN));
}