I can't draw more than one circle on an image - java

I have a problem. I need to draw some circles on an image, but I don't know why, it only draws one circle. I put the code below to explain it better:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.previsualizacion);
myImage = (ImageView) findViewById(R.id.imageView1);
ctx = getApplicationContext();
//Obtenemos la información del layout anterior y la asignamos al tamaño del paso
data = getIntent();
myBundle = data.getExtras();
presasX = myBundle.getStringArrayList("arrayPixelX");
presasY = myBundle.getStringArrayList("arrayPixelY");
colores = myBundle.getStringArrayList("arrayColores");
Bitmap bitMap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
bitMap = bitMap.copy(bitMap.getConfig(), true);
Canvas canvas = new Canvas(bitMap);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Style.FILL_AND_STROKE);
//paint.setStrokeWidth(0.5f);
paint.setAntiAlias(true);
myImage.setImageBitmap(bitMap);
//changed set image resource to set image background resource
myImage.setBackgroundResource(R.drawable.pared);
for(int i = 0; i < presasX.size(); i++)
{
if(colores.get(i).equals("1"))
{
paint.setColor(Color.GREEN);
}
else if(colores.get(i).equals("2"))
{
paint.setColor(Color.RED);
}
else if(colores.get(i).equals("3"))
{
paint.setColor(Color.YELLOW);
}
canvas.drawCircle(Float.parseFloat(presasX.get(i)) * myImage.getWidth() / 100, Float.parseFloat(presasY.get(i)) * myImage.getHeight() / 100, 3, paint);
}
//invalidate to update bitmap in imageview
myImage.invalidate();
}
I have on some ArrayList the coords of the points I want to draw, also this coords are relative to an image, so I have to multiply that coords for the imagewidht and imageheight.
It only draws one green circle, but I need to draw (in that chase) five green points and four red points.
I put the arraylist info too:
presasX = [49.583333333333, 80.833333333333, 13.541666666667, 4.5833333333333, 77.708333333333, 49.583333333333, 4.5833333333333, 95.208333333333, 96.875]
presasY = [49.722222222222, 5, 22.5, 20.277777777778, 33.888888888889, 49.722222222222, 20.277777777778, 54.722222222222, 61.666666666667]
colores = [2, 2, 2, 2, 2, 1, 1, 1, 1]
Thanks a lot!

This is because layout has not inflated fully and therefore myImage.getWidth() and getHeight() are returning 0. So in effect the center of all your circles is the same (top left corner of the ImageView) and the next one is overwriting the previous one.
For actual width and height you can use ViewTreeObserver.addOnGlobalLayoutListener or programmatically create the ImageView with required dimensions or create a custom view extending the standard ImageView and implement its onDraw() etc.

Related

Bitmap is created with rough edges

So I am using this library https://github.com/uptechteam/MotionViews-Android/ for creating bitmaps, which can be resized and dragged around just like snapchat/instagram stickers. But the problem is that the bitmaps that are generated are not smooth and have rough edges like this:
As you can see the text are somewhat distorted and the background has rough edges. Here is the code for generating the bitmap:
/**
* If reuseBmp is not null, and size of the new bitmap matches the size of the reuseBmp,
* new bitmap won't be created, reuseBmp it will be reused instead
*
* #param textLayer text to draw
* #param reuseBmp the bitmap that will be reused
* #return bitmap with the text
*/
#NonNull
private Bitmap createBitmap(#NonNull TextLayer textLayer, #Nullable Bitmap reuseBmp) {
int boundsWidth = canvasWidth;
int alignment = textLayer.getFont().getAlignment();
int style = textLayer.getFont().getStyle();
// init params - size, color, typeface
if (style == STYLE_UNDERLINE) {
textPaint.setFlags(Paint.UNDERLINE_TEXT_FLAG);
} else {
textPaint.setFlags(0);
}
textPaint.setAntiAlias(true);
textPaint.setDither(false);
textPaint.setElegantTextHeight(true);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(textLayer.getFont().getSize() * canvasWidth);
textPaint.setColor(textLayer.getFont().getColor());
textPaint.setTypeface(fontProvider.getTypeface(textLayer.getFont().getTypeface()));
textBackgroundColor = textLayer.getFont().getBackgroundColor();
// drawing text guide : http://ivankocijan.xyz/android-drawing-multiline-text-on-canvas/
// Static layout which will be drawn on canvas
Layout.Alignment layoutAlignment;
if (alignment == ALIGNMENT_LEFT) {
layoutAlignment = Layout.Alignment.ALIGN_NORMAL;
} else if (alignment == ALIGNMENT_RIGHT) {
layoutAlignment = Layout.Alignment.ALIGN_OPPOSITE;
} else {
layoutAlignment = Layout.Alignment.ALIGN_CENTER;
}
StaticLayout sl;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
sl = new StaticLayout(
textLayer.getText(), // - text which will be drawn
textPaint,
boundsWidth, // - width of the layout
layoutAlignment, // - layout alignment
1, // 1 - text spacing multiply
1, // 1 - text spacing add
true); // true - include padding
} else {
StaticLayout.Builder builder = StaticLayout.Builder.obtain(textLayer.getText(), 0, textLayer.getText().length(), textPaint, boundsWidth)
.setAlignment(layoutAlignment)
.setLineSpacing(1, 1)
.setIncludePad(true);
sl = builder.build();
}
// calculate height for the entity, min - Limits.MIN_BITMAP_HEIGHT
int boundsHeight = sl.getHeight();
// create bitmap not smaller than TextLayer.Limits.MIN_BITMAP_HEIGHT
int bmpHeight = (int) (canvasHeight * Math.max(TextLayer.Limits.MIN_BITMAP_HEIGHT,
1.0F * boundsHeight / canvasHeight));
// create bitmap where text will be drawn
Bitmap bmp;
if (reuseBmp != null && reuseBmp.getWidth() == boundsWidth
&& reuseBmp.getHeight() == bmpHeight) {
// if previous bitmap exists, and it's width/height is the same - reuse it
bmp = reuseBmp;
bmp.eraseColor(Color.TRANSPARENT); // erase color when reusing
} else {
bmp = Bitmap.createBitmap(boundsWidth, bmpHeight, Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(bmp);
final Rect rect = new Rect(0, 0, bmp.getWidth(), bmp.getHeight());
final RectF rectF = new RectF(rect);
final Paint textBackgroundPaint = new Paint();
textBackgroundPaint.setFlags(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
textBackgroundPaint.setDither(false);
textBackgroundPaint.setColor(textBackgroundColor);
textBackgroundPaint.setStyle(Paint.Style.FILL_AND_STROKE);
textBackgroundPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
canvas.drawRoundRect(rectF, textBackgroundRadius, textBackgroundRadius, textBackgroundPaint);
canvas.drawBitmap(bmp, rect, rect, textBackgroundPaint);
canvas.save();
// move text to center if bitmap is bigger that text
if (boundsHeight < bmpHeight) {
//calculate Y coordinate - In this case we want to draw the text in the
//center of the canvas so we move Y coordinate to center.
float textYCoordinate = (float) (bmpHeight - boundsHeight) / 2;
canvas.translate(0, textYCoordinate);
}
//draws static layout on canvas
sl.draw(canvas);
canvas.restore();
return bmp;
}
I tried using antialias, filterbitmap on the paint but it does nothing. Also tried setting the view's layer type to layer_type_software but the result is the same. How to fix this? Any help would be appreciated.
Please use below code for removing rough edges from bitmap
canvas.drawBitmap(bitmap, x, y, new Paint(Paint.ANTI_ALIAS_FLAG));
use the Paint.ANTI_ALIAS_FLAG flag, this flag is used for removing the jagged edges and smooth the edges

set bitmap in the center of screen in span

I am trying to put the bitmap in the center of my layout (Center-horizontal) but my bitmap always starts with the left and not centered. I assign the x value to setbound which center my image but shrink it rather the maintaining the ratio I selected.
private void setImageinText(Bitmap myBitmap){
myBitmap = Util.scaleBitmapToFitWidth(myBitmap, 1360, true);
Drawable d = new BitmapDrawable(getResources(), myBitmap);
Point outSize = new Point();
WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
display.getSize(outSize);
int[] widthAndHeight = new int[2];
widthAndHeight[0] = outSize.x;
int x = (widthAndHeight[0]- d.getIntrinsicWidth())/2;
SpannableString ssd = new SpannableString("\n \n");
d.setBounds(x, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
ssd.setSpan(span, 1 , 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
texto.setTransformationMethod(null);
texto.getText().insert(texto.getSelectionStart(), ssd);
}
take ImageView below TextView and set it Centerhorizontal with Visibility GONE, then when you capture image set it in that ImageView and VISIBLE it.

Android - set Dot on random position in imported image

thanks in advance!!!
Situation:
Me and a friend has to develop an app for the university. (I think this story is common?!) We had the idea for an App, where you take or import a picture and the App make one random dot/point on this picture.
So if you stand in front of a shelf in the store and dont know which of the beers/Liqours/crisps/... you should buy, take a picture and the random dot picks for you.
Problem:
We had an imageview, where to import the picture. Go to gallery or take a photo is working. But I dont know how to set a dot in this imageView/picture. At the moment i put a second imageview over it, where a random text including "•" appears. Its more like a workaround.
Code for the dot in Class MyCanvas:
int min = 5;
int max = 500;
Random r = new Random();
int i1 = r.nextInt(max - min + 1) + min;
int i2 = r.nextInt(max - min + 1) + min;
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint pBackground = new Paint();
pBackground.setColor(Color.TRANSPARENT);
canvas.drawRect(0, 0, 512, 512, pBackground);
Paint pText = new Paint();
pText.setColor(Color.RED);
pText.setTextSize(40);
canvas.drawText("•", i1 , i2, pText);
}
onClick method:
public void click_button_magic(View view) {
View v = new MyCanvas(getApplicationContext());
Bitmap bitmap =Bitmap.createBitmap(500/*width*/, 500/*height*/, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
v.draw(canvas);
ImageView iv2 = (ImageView) findViewById(R.id.imageView_point);
iv2.setImageBitmap(bitmap);
}
If i change this code to the imageview where the imported pictures get in, the picture get white after clicking on the "Magic" button.
What i want to change:
set dot (not text)
set dot in imported image
getting from image the max and min dimension within to set the dot (width, height)
I think for this tasks i made something fundamental wrong. But i dont know what... =(
So I hope you can help me (code or tips to get on the right way)
Thank you very much and i hope my english is good enough to understand my problem!
It's hard for me to understand how you did this, because I can't see all of your code. But if I would have done this project, I would use a FrameLayout, and add the Photo with:
android:layout_width="match_parent"
android:layout_height="match_parent"
And then make a small view with round background, and make the margin left margin right be random. That way you don't need to draw on the canvas and all that hassle.
meanwhile i get a solution for getting a point in the picture.
To set an image as imageview:
...
imageview.setImageBitmap(image);
bm = image;
iv = imageview;
...
bm is now the bitmap with the wanted image
iv is the imageview
Now the Clickfunction:
public void click_button_magic(View view) {
//bei jedem Klick wird das Bild neu geladen, damit bei erneutem Klicken ein neuer Punkt erscheint
iv.setImageBitmap(bm);
ImageView img = findViewById(R.id.imageView_photoImport);
img.setDrawingCacheEnabled(true);
Bitmap scaledBitmap = img.getDrawingCache();
//get Maße des IMG
int targetWidth = scaledBitmap.getWidth();
int targetHeight = scaledBitmap.getHeight();
Bitmap targetBitmap = loadBitmapFromView(iv, iv.getWidth(), iv.getHeight());//Bitmap.createBitmap(targetWidth,targetHeight,Bitmap.Config.ARGB_8888);
//get random coordinates
int min = 5;
int maxWidth = targetWidth;
int maxHeight = targetHeight;
Random r = new Random();
int randomWidth = r.nextInt(maxWidth - min + 1) + min;
int randomHeight = r.nextInt(maxHeight - min + 1) + min;
//Paint object
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
Canvas canvas = new Canvas(targetBitmap);
canvas.drawCircle(randomWidth, randomHeight,20, paint);
img.setImageBitmap(targetBitmap);
}
public static Bitmap loadBitmapFromView(View v, int width, int height) {
Bitmap b = Bitmap.createBitmap(width , height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(0, 0, width, height);
//Get the view’s background
Drawable bgDrawable =v.getBackground();
if (bgDrawable!=null)
//has background drawable, then draw it on the canvas
bgDrawable.draw(c);
else
//does not have background drawable, then draw white background on the canvas
c.drawColor(Color.WHITE);
v.draw(c);
return b;
}
I hope it will help someone in the future...maybe not, maybe it will

How to set an onclick listener to a canvas?

I have some rectangles drawn on Canvas. And now I need for each rectangle an onclickListener.
But because I'm very new to android and specially Canvas, I need some help.
Anyway is it possible to add a listener?
It looks like this:
And this is my code for it:
RelativeLayout ll = (RelativeLayout) findViewById(R.id.rect);
Paint paint = new Paint();
Paint paintForSize = new Paint();
paintForSize.setColor(Color.parseColor("#FFFFFF"));
paintForSize.setTextSize(45);
Bitmap bg = Bitmap.createBitmap(480, 800, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bg);
int left = 0; // initial start position of rectangles (50 pixels from left)
int leftText =70;
int topText = 93;
int top = 50; // 50 pixels from the top
int width = 60;
int height = 60;
for(int x = 0; x < 4; x++) { // draw 4 rectangles
if(x == 0){
paint.setColor(Color.parseColor("#FF7979"));
canvas.drawText("Rec 1", leftText, topText, paintForSize);
}
if(x == 1){
paint.setColor(Color.parseColor("#FFD060"));
canvas.drawText("Rec 2", leftText, topText, paintForSize);
}
if(x == 2){
paint.setColor(Color.parseColor("#B6DB49"));
canvas.drawText("Rec 3", leftText, topText, paintForSize);
}
if(x == 3){
paint.setColor(Color.parseColor("#CB97E5"));
canvas.drawText("Rec 4", leftText, topText, paintForSize);
}
canvas.drawRect(left, top, left+width, top+height, paint);
top = (top + height + 10); // set new left co-ordinate + 10 pixel gap
topText = (topText + height + 10);
}
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
ImageView iV = new ImageView(this);
iV.setImageBitmap(bg);
ll.addView(iV,params);
Can anybody guide me through this, how should I do it?
Canvas is not a View. You cannot add listeners to them. You could create a custom View implementation. Whatever you do with the Canvas, implement that in onDraw(), which receives a Canvas as a parameter. Then add your view to a layout and give it whatever listeners you want. You may as well look into SurfaceView for drawing, which is a View.
This might help you.
Might I suggest rethinking how this is going to work. If these rectangles are going to be buttons of some sort, perhaps your better off drawing buttons in your user interface, or using images instead of the rectangles. (Sorry didnt realise this is what you were going to do in your previous question)
Have a look at: Difference between a clickable ImageView and ImageButton
You can set an eventlistener on your imageview, as mentioned in another answer. See here: Image in Canvas with touch events

Trying to mirror a picture with java android canvas.drawImage

I'm having problems while trying to rotate a picture with java android canvas.drawImage. I'm doing a little game, and I'm painting different pictures on the screen using my drawImage function. However now I want to rotate some little images, I have created a function called drawMirroredImage for this. However now this little images don't appear on the same place.
Here is my code:
public void drawImage(Image Image, int x, int y) {
canvas.drawBitmap(((AndroidImage) Image).bitmap, x, y, null);
}
public void drawMirroredImage(Image Image, int x, int y) {
canvas.save();
canvas.scale(-1.0f, 1.0f);
canvas.drawBitmap(((AndroidImage) Image).bitmap, x - canvas.getWidth(), y, null);
canvas.restore();
}
Anyone knows what I'm doing wrong?
Lot of thanks for helping
Following will work for you.
I found it somewhere on SO itself but don't remember where.
public static Bitmap getReflectionedBitmap(Context context,int resourceId,Bitmap originalImage,int reflectionGap) {
if(originalImage==null)
originalImage = BitmapFactory.decodeResource(context.getResources(),resourceId);
int width = originalImage.getWidth();
int height = originalImage.getHeight();
// This will not scale but will flip on the Y axis
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
// Create a Bitmap with the flip matix applied to it.
// We only want the bottom half of the image
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
height / 2, width, height / 2, matrix, false);
// Create a new bitmap with same width but taller to fit reflection
Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
(height + height / 2), Config.ARGB_8888);
// Create a new Canvas with the bitmap that's big enough for
// the image plus gap plus reflection
Canvas canvas = new Canvas(bitmapWithReflection);
// Draw in the original image
canvas.drawBitmap(originalImage, 0, 0, null);
// Draw in the gap
Paint deafaultPaint = new Paint();
deafaultPaint.setColor(0xffffffff);
canvas.drawRect(0, height, width, height + reflectionGap , deafaultPaint);
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0,
originalImage.getHeight(), 0, bitmapWithReflection.getHeight()
+ reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
// Set the paint to use this shader (linear gradient)
paint.setShader(shader);
// Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
+ reflectionGap, paint);
return bitmapWithReflection;
}
I tweaked the snippet a little bit to use it with resource images as well.
Pass in null as parameter in place of Bitmap if you want to create reflection for images in resource.

Categories

Resources