I am drawing some rows of text. After a couple of rows, it goes offscreen. What i want to do is capture all the rows(also the rows outside the canvas) in a bitmap.
I have the code below which only works for within the canvas(screen).
private class DeciderView extends View {
private Paint paint;
String text = "";
String[] options = { "een", "twee", "drie", "vier", "vijf", "zes", "zeven", "acht",
"negen", "tien", "elf", "twaalf", "dertien", "vertien", "vijftien" };
public DeciderView(Context context) {
super(context);
// Keep screen on
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// Remove title bar
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Remove notification bar
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.setBackgroundColor(Color.WHITE);
paint = new Paint();
paint.setTextSize(75);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(10);
paint.setAntiAlias(true);
setDrawingCacheEnabled(true);
setDrawingCacheQuality(DRAWING_CACHE_QUALITY_HIGH);
}
private void drawInput(Canvas canvas) {
Paint p = new Paint();
p.setTextAlign(Align.CENTER);
p.setTextSize(canvas.getWidth() / 10f);
p.setColor(Color.BLACK);
float xText = canvas.getWidth() / 2f;
float yText = (canvas.getHeight() / 4f);
for (int i = 0; i < options.length; i++) {
text += options[i] + "\n";
}
for (String line : text.split("\n")) {
canvas.drawText(line, xText, yText, p);
yText -= (p.ascent() + p.descent()) * 2.5f;
}
}
#Override
public void onDraw(Canvas canvas) {
drawInput(canvas);
this.setDrawingCacheEnabled(true);
Bitmap b = Bitmap.createBitmap(this.getDrawingCache());
b = Bitmap.createScaledBitmap(b, canvas.getWidth(), canvas.getHeight(), false);
try {
b.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(
new File(Environment.getExternalStorageDirectory().getPath()
+ "/Pictures/aaaaa.jpg")));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (b != null) {
b.recycle();
b = null;
}
}
}
So basically i want to make a bitmap from all the rows, even if the rows are drawn outside the canvas.
Why not just draw directly to the bitmap? You can create a new Canvas that has a bitmap backing it. You use the normal canvas draw commands, and the output will be written to the bitmap rather than the screen. If you also want to draw it to the screen, just draw the new bitmap to the screen at the end. To do this all you need is
Canvas myCanvas = new Canvas(myBitmap);
Related
I already post two question related this (plz refer this
custom piechart 1 and this custom pie chart 2) but not getting answer ,finally i develop my own but getting stuck at some point .
I need to create lines between drawn area as you can see in image .for inner circle i used canvas.drawArc() .for outer circle i used canvas.drawCircle() and for middle lines i used canvas.drawBitmap() method with differ angle .here inner and outer circle drawn properly but for middle arc ,only first two bitmap/arcs are drawn properly but remaining two are not in their exact position .
I used same code for drawing all bitmap/arcs but not getting exact output .I am getting stuck what is the exact problem.need help ,thanks in advance .
you can see my output
here..
Hear is my onCreate() , in which i generate and set view .
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv1 = (LinearLayout) findViewById(R.id.linear);
matrix = new Matrix();
MyView myview = new MyView(this);
lv1.addView(myview);
}
this is my customview class that i want to generate.
public class MyView extends View {
private Paint p ,paint,paint_text;
private int startX;
private int startY;
private int radius;
private ArrayList<Integer> colors;
private ArrayList<Float> values;
Bitmap bitmap;
Context mContext;
RectF rectF , rectF2 ;
public MyView(Context context) {
super(context);
mContext = context;
p = new Paint();
p.setAntiAlias(true);
colors = new ArrayList<Integer>();
values = new ArrayList<Float>();
Display display = getWindowManager().getDefaultDisplay();
width1 = display.getWidth();
height1 = display.getHeight();
startX = 0 ;
startY = 0;
radius = (int) (width1/2);
colors.add(Color.RED);
colors.add(Color.BLUE);
colors.add(Color.YELLOW);
colors.add(Color.GREEN);
values.add(8f);
values.add(2f);
values.add(4f);
values.add(2f);
}
This is my onDraw() method .
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float _angle1 = 0 ,_angle2 = 0 ,_angle3 = 0 , _angle4 =0;
Bitmap myBitmap1 = BitmapFactory.decodeResource(getResources(),R.drawable.saperate_line);
bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
float offset = 0;
float angle = (float) 5.60 ;
matrix.reset();
canvas.translate(0,canvas.getHeight()); //reset where 0,0 is located
canvas.scale(1,-1); // for scaling
rectF = new RectF();
rectF.set(-(getStartX() + getRadius()), -(getStartY() + getRadius()), getStartX() + getRadius(),getStartY() + getRadius());
//for creating outer circle using canvas.drawCircle-----------
paint = new Paint();
paint.setColor(Color.GREEN);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(0, 0, (float) (width1/(1.4)), paint);
//for creating inner circle using canvas.drawArc-----------
for (int i = 0; i < values.size(); i++) {
p.setColor(colors.get(i));
if (i == 0) {
canvas.drawArc(rectF, offset, values.get(i) * angle, true, p);
_angle1 = ((offset+(values.get(i) * angle)))/2;
matrix.postRotate(_angle1);
canvas.drawBitmap(myBitmap1, matrix, null);
}
if(i == 1){
canvas.drawArc(rectF, offset, values.get(i) * angle, true, p);
_angle2 = ((offset + (values.get(i) * angle)))/2;
matrix.postRotate(_angle2);
canvas.drawBitmap(myBitmap1, matrix, null);
}
if(i == 2){
canvas.drawArc(rectF, offset, values.get(i) * angle, true, p);
_angle3 = ((offset + (values.get(i) * angle)))/2;
// _angle3 = (offset + angle);
matrix.postRotate(_angle3);
canvas.drawBitmap(myBitmap1, matrix, null);
}
if (i == 3){
canvas.drawArc(rectF, offset, values.get(i) * angle, true, p);
_angle4 = ((offset + (values.get(i) * angle)))/2;
matrix.postRotate(_angle4);
canvas.drawBitmap(myBitmap1, matrix, null);
}
offset += (values.get(i) * angle);
Log.e("new offset :: ","****************************"+offset);
}
canvas.save();
}
Thanks to every one.
finally i did it using replacing this stuff Rotating Image on A canvas
matrix.postRotate(_angle1);
canvas.drawBitmap(myBitmap1, matrix, null);
with this
Matrix matrix1 = new Matrix();
matrix1.setRotate(_angle1, 0, 0);
canvas.drawBitmap(myBitmap1, matrix1, null);
here ,first you should change the value like this ,
float myAngle = 0;
myAngle = ((90 * values.get(i)) / 16);
I want to capture image of surface view with content draw on surface view.
I n my app i have surface view on which user can draw some bitmap by drag and drop some objects on it.
After that on a button click i want to store image of that surfaceview with its bitmap content in sd card.
For these i have a canvas object and all bitmap are draw on it.
below is my code -
mHolder = mSurfaceView.getHolder();
mHolder.lockCanvas();
canvas.drawColor(0,Mode.CLEAR);
//border's properties
paint = new Paint();
FontMetrics fm = new FontMetrics();
Paint paint2 = new Paint();
paint2.setColor(Color.WHITE);
paint2.setTextSize(30);
paint2.setTextAlign(Paint.Align.CENTER);
paint2.getFontMetrics(fm);
canvas.drawText("Building", RectLeft+60, RectTop+60, paint2);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(color);
paint.setStrokeWidth(3);
canvas.drawRect(RectLeft, RectTop, RectRight, RectBottom, paint);
mHolder.unlockCanvasAndPost(canvas);
How to do that.
Thanks in advance.
EDITED
Below is my code that captures only view that i have created in xml and not draw what i have draw on surface.
public static Bitmap getBitmapFromView(View view) {
//Define a bitmap with the same size as the view
Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888);
//Bind a canvas to it
Canvas canvas = new Canvas(returnedBitmap);
//Get the view's background
Drawable bgDrawable =view.getBackground();
if (bgDrawable!=null)
//has background drawable, then draw it on the canvas
bgDrawable.draw(canvas);
else
//does not have background drawable, then draw white background on the canvas
canvas.drawColor(Color.WHITE);
// draw the view on the canvas
view.draw(canvas);
//return the bitmap
return returnedBitmap;
}
EDITED my hole fragment for drawing is below-
public class DrawingLayoutFragment extends Fragment implements SurfaceHolder.Callback{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
....
....
mSurfaceView = (SurfaceView) view.findViewById(R.id.surfaceview);
init();
return view;
}
public void init(){
mSurfaceView.getHolder().addCallback(this);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
RectLeft = width/2 - 60;
RectTop = height/2 - 60 ;
RectRight = width/2 + 60;
RectBottom = height/2 + 60;
DrawFocusRect(RectLeft, RectTop, RectRight, RectBottom, getResources().getColor(com.nep.R.color.white_color));
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mHolder = mSurfaceView.getHolder();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
try{
if(mHolder!=null){
mHolder.lockCanvas();
canvas = null;
mHolder.addCallback(null);
mHolder = null;
}
}catch(Exception e){
e.printStackTrace();
}
}
private void DrawFocusRect(float RectLeft, float RectTop, float RectRight, float RectBottom, int color){
try {
if(canvas!=null){
mHolder.lockCanvas();
}
else{
canvas = mHolder.lockCanvas();
}
canvas.drawColor(0,Mode.CLEAR);
paint = new Paint();
FontMetrics fm = new FontMetrics();
Paint paint2 = new Paint();
paint2.setColor(Color.WHITE);
paint2.setTextSize(30);
paint2.setTextAlign(Paint.Align.CENTER);
paint2.getFontMetrics(fm);
canvas.drawText("Building", RectLeft+60, RectTop+60, paint2);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(color);
paint.setStrokeWidth(3);
canvas.drawRect(RectLeft, RectTop, RectRight, RectBottom, paint);
mHolder.unlockCanvasAndPost(canvas);
} catch (Exception e) {
e.printStackTrace();
}
}
public void createFIle(){
try {
DrawFocusRect(RectLeft, RectTop, RectRight, RectBottom, getResources().getColor(com.nep.R.color.white_color));
Bitmap b = Bitmap.createBitmap(mSurfaceView.getWidth(), mSurfaceView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
mSurfaceView.draw(c);
// Bitmap bmp = getBitmapFromView(frame);
String mFile = mPath+"_layout011.png";
File directory = new File (mFile);
directory.createNewFile();
OutputStream fo = new FileOutputStream(directory);
ByteArrayOutputStream os = new ByteArrayOutputStream();
b.compress(CompressFormat.JPEG, 100, os);
os.writeTo(fo);
fo.close();
os.close();
// mSurfaceView.destroyDrawingCache();
BasicMethods.showToast("Saved at - "+mFile, mContext);
} catch (Exception e) {
e.printStackTrace();
}
}
}
i have user this code and it is not working,so i put my surface view inside other view and try to capture bitmap from that i was previously posted.i have try both way but not geting any solution.
Create a Bitmap, create a Canvas for the bitmap, execute all of your drawing commands on that Canvas, save the bitmap.
You can't capture the SurfaceView's surface, so re-drawing onto a Bitmap is the easiest way. This comes up fairly often; see e.g. this.
I'm trying to draw two circles like this:
This is how I'm trying to do it:
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
Canvas c = new Canvas(bmp);
RectF rect = new RectF(0,0,width,width);
Paint paint = new Paint();
drawCircles(paint, c, width, height, width);
ImageView img = (ImageView) findViewById(R.id.imageView1);
img.setImageBitmap(bmp);
img.setScaleType(ScaleType.FIT_CENTER);
And here is my drawCircles() method:
private void drawCircles(Paint paint, Canvas c, int width, int height, int radius) {
paint.setARGB(255, 255 , 10, 21);
paint.setStrokeWidth(10);
paint.setAntiAlias(true);
paint.setStrokeCap(Paint.Cap.BUTT);
paint.setStyle(Paint.Style.STROKE);
if(width < height && radius == 0){
radius = width/2;
height = width;
} else if (radius == 0){
radius = height/2;
width = height;
}
Paint paint2 = new Paint();
paint2.setARGB(255, 255 , 10, 21);
paint2.setStrokeWidth(10);
paint2.setAntiAlias(true);
paint2.setStrokeCap(Paint.Cap.BUTT);
paint2.setStyle(Paint.Style.STROKE);
c.drawCircle(width/2, height/2, radius-10, paint);
c.drawCircle(width/2, height/2, 50, paint2);
}
I don't know why but I get only one circle, the small one (the one drawn with paint2).
What can be the reason?
Try this code.Hope it may helps :)
public class SimpleCircleActivity extends Activity
{
private CircleDemoView circledemoView ;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
circledemoView =new CircleDemoView(this);
setContentView(circledemoView);
}
private class CircleDemoView extends View
{
public CircleDemoView(Context context)
{
super(context);
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint p = new Paint();
p.setColor(Color.RED);
DashPathEffect dashPath = new DashPathEffect(new float[]{5,5}, (float)1.0);
p.setPathEffect(dashPath);
p.setStyle(Style.STROKE);
for (int i = 0; i < 2; i ++) {
canvas.drawCircle(200, 200, 50+(i*40), p);
}
invalidate();
}
}
}
i have two bitmap in my project what i need is that i need to combine those two bit map and combine those bit map to a single image i will show my code
public class FotosurpriseActivity extends Activity {
/** Called when the activity is first created. */
Bitmap overlay;
Paint pTouch;
int X = -100;
int Y = -100;
Canvas c2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.android);
Bitmap mBitmapover = BitmapFactory.decodeResource(getResources(), R.drawable.ss);
overlay = BitmapFactory.decodeResource(getResources(),R.drawable.ss).copy(Config.ARGB_8888, true);
c2 = new Canvas(overlay);
pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);
// pTouch.setXfermode(new PorterDuffXfermode(Mode.TARGET);
pTouch.setColor(Color.TRANSPARENT);
pTouch.setMaskFilter(new BlurMaskFilter(15, Blur.NORMAL));
setContentView(new BitMapView(this, mBitmap,mBitmapover));
}
class BitMapView extends View {
Bitmap mBitmap = null;
Bitmap mBitmapover = null;
public BitMapView(Context context, Bitmap bm, Bitmap bmover) {
super(context);
mBitmap = bm;
mBitmapover = bmover;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();
break;
}
case MotionEvent.ACTION_MOVE: {
X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();
break;
}
case MotionEvent.ACTION_UP:
break;
}
return true;
}
#Override
protected void onDraw(Canvas canvas) {
// called when view is drawn
Paint paint = new Paint();
paint.setFilterBitmap(true);
// The image will be scaled so it will fill the width, and the
// height will preserve the image’s aspect ration
/* double aspectRatio = ((double) mBitmap.getWidth()) / mBitmap.getHeight();
Rect dest = new Rect(0, 0, this.getWidth(),(int) (this.getHeight() / aspectRatio));
double aspectRatio2 = ((double) mBitmapover.getWidth()) / mBitmapover.getHeight();
Rect dest2 = new Rect(0, 0, this.getWidth(),(int) (this.getHeight() / aspectRatio2));
canvas.drawBitmap(mBitmap, null, dest, paint);
canvas.drawBitmap(mBitmapover, null, dest2, paint); */
//draw background
canvas.drawBitmap(mBitmap, 0, 0, null);
//copy the default overlay into temporary overlay and punch a hole in it
c2.drawBitmap(mBitmapover, 0, 0, null); //exclude this line to show all as you draw
c2.drawCircle(X, Y, 80, pTouch);
//draw the overlay over the background
canvas.drawBitmap(overlay, 0, 0, null);
}
}
}
how can i make this happen?
The onDraw function draws to the view. You don't actually need to do that at all. You can do this all in memory where the bitmaps reside. You draw the other bitmap on C2 as well. You don't have to draw anything to canvas in the onDraw() all that does is draw that to the screen.
I have some code where I'm drawing my text on bitmap (canvas)
canvas.drawTextOnPath(Text, textPath[count], gipa, -10, text);
Please tell me, it's possible to draw this text in path(textPath) with background color?
it's full function for drawing only text
public void drawText(float x,float y ,String Text,Canvas canvas,Paint paint1 ,int count )
{
float xren =text.measureText(Text.trim());
canvas.drawTextOnPath(Text, textPath[count], gipa, -10, text);
}
Using this function I'm drawing text on my canvas. so how to modify this function for drawing this text with background?
Most likely two steps are needed here. you would draw a line along path first with color for background and then draw the text as indicated. Set the thickness of the line with a paint object. Also, changing the style of the paint can help with the effect. try FILL, STROKE or FILL_AND_STROKE for different effects.
mpaint.setStyle(Paint.Style.STROKE);
mpaint.setStrokeWidth(strokeWidth);
Added sample to draw a path(rectangle) with red color:
Paint mPaint = new Paint();
mPaint.setColor(Color.RED);
Path mPath = new Path();
RectF mRectF = new RectF(20, 20, 240, 240);
mPath.addRect(mRectF, Path.Direction.CCW);
mPaint.setStrokeWidth(20);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawPath(mPath, mPaint);
Then draw text along same path (blue color):
mPaint.setColor(Color.BLUE);
mPaint.setStrokeWidth(0);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize(20);
canvas.drawTextOnPath("Draw the text, with origin at (x,y), using the specified paint, along the specified path.", mPath, 0, 5, mPaint);
If you want to make like this then implement below code snippet:
/**
* PUT THIS METHOD FOR IMPLEMENT WATER-MARK IN COMMON FILE
*/
public static Bitmap waterMark(Bitmap src, String watermark) {
//get source image width and height
int w = src.getWidth();
int h = src.getHeight();
Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
Paint.FontMetrics fm = new Paint.FontMetrics();
paint.setColor(Color.WHITE);
paint.getFontMetrics(fm);
int margin = 5;
canvas.drawRect(50 - margin, 50 + fm.top - margin,
50 + paint.measureText(watermark) + margin, 50 + fm.bottom
+ margin, paint);
paint.setColor(Color.RED);
canvas.drawText(watermark, 50, 50, paint);
return result;
}
// To Get Bitmap from URI:
private Bitmap getBitmapFromUri(String photoPath) {
Bitmap image = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(photoPath, options);
return bitmap;
}
// Save Image :
private String SaveImage(Bitmap finalBitmap) {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/shareImage");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image" + n + ".jpg";
File file = new File(myDir, fname);
if (file.exists()) file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 20, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
return file.getAbsolutePath();
}
// Call like this :
Bitmap bitmap = getBitmapFromUri(attachment.get(i).getPath()); // Enter here your Image path
Bitmap bitmapp = waterMark(bitmap, "ENTER YOUR TEXT FOR WATERMARK LABEL");
String path = SaveImage(bitmapp);
Uri uri = Uri.fromFile(new File(path));
Here at last from uri you can get a new implemented watermark image.
Hope this helps you.
I believe this solution is better and more flexible than drawPath.
Use this to calculate the size of the text background:
private #NonNull Rect getTextBackgroundSize(float x, float y, #NonNull String text, #NonNull TextPaint paint) {
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float halfTextLength = paint.measureText(text) / 2 + 5;
return new Rect((int) (x - halfTextLength), (int) (y + fontMetrics.top), (int) (x + halfTextLength), (int) (y + fontMetrics.bottom));
}
Then draw the background as a Rect:
Rect background = getTextBackgroundSize(x, y, text, textPaint);
canvas.drawRect(background, bkgPaint);
canvas.drawText(text, x, t, textPaint);
this method i created , it will give you better idea how easily you can do this
public static Drawable getTextToDrawable(final String sText, final float textSize, final int textColor, final int bgColor, final int imageSize) {
Shape shape = new Shape() {
#Override
public void draw(Canvas canvas, Paint paint) {
paint.setTextSize(spToPixel(textSize));
int ivImageSize = SUtils.dpToPx(imageSize);
paint.setTextAlign(Paint.Align.LEFT);
float baseline = -paint.ascent(); // ascent() is negative
int width = (int) (paint.measureText(sText)); // round
int height = (int) (baseline + paint.descent());
Bitmap image = Bitmap.createBitmap(ivImageSize, (int) (ivImageSize), Bitmap.Config.ARGB_8888);
canvas.drawBitmap(image, ivImageSize, ivImageSize, paint);
paint.setColor(bgColor);
if (sText != null) {
if (sText.length() < 3) {
canvas.drawCircle(ivImageSize / 2, ivImageSize / 2, ivImageSize / 2, paint);
paint.setColor(textColor);
canvas.drawText(sText, (ivImageSize - width) / 2, (height+baseline)/2, paint);
} else {
canvas.drawRect(0, 0, ivImageSize, height, paint);
paint.setColor(textColor);
canvas.drawText(sText, (ivImageSize - width) / 2, baseline, paint);
}
}
}
};
return new ShapeDrawable(shape);
}