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
Related
I'm trying to draw a bunch of bitmaps vertically one below the other like this :
Original Bitmap :
Result expected :
Code :
int repeater = 4;
Bitmap bitmapTextSticker = ImageUtils.drawable2Bitmap(ResourceUtils.getDrawable(R.drawable.icon));
Bitmap background = Bitmap.createBitmap(bitmapTextSticker.getWidth(), bitmapTextSticker.getHeight() * repeater, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(background);
int top = 0;
for (int i = 0; i < repeater; i++) {
top = (i == 0 ? 0 : top + bitmapTextSticker.getHeight());
canvas.drawBitmap(bitmapTextSticker, 0f, top, null);
}
The above code is working, but the output is cropped.
I'm not sure if I'm missing something in your question, but all you have to do is change the top coordinate for each bitmap when calling drawBitmap(). In your specific code, just add:
top += height;
inside the for loop
Edit: from your updated question, it sounds like a Bitmap scaling issue, not a problem with position. Even your 1st bitmap is cropped. So, you should probably use a different canvas.drawbitmap() method:
public void drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint)
You can specify the dimensions of the destination Rect, which should let it scale properly. So, your code should be:
for(...){
...
RectF dest = new RectF(new Rect(0, top, bitmapTextSticker.getWidth(), bitmapTextSticker.getHeight()));
canvas.drawBitmap(bitmapTextSticker, null, dest, null);
}
The issue was I didn't set the density for the bitmap and the canvas :
ArrayList<Bitmap> bitmaps = new ArrayList<>();
for (int i = 0; i < repeater; i++) bitmaps.add(bmp);
int height = 0;
for (Bitmap map : bitmaps) height += map.getHeight();
Bitmap bitmap = Bitmap.createBitmap(bmp.getWidth(), height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.setDensity(DisplayMetrics.DENSITY_MEDIUM);
bitmap.setDensity(DisplayMetrics.DENSITY_MEDIUM);
int drawHeight = 0;
for (Bitmap map : bitmaps) {
if (map != null) {
canvas.drawBitmap(map, 0, drawHeight, null);
drawHeight += map.getHeight();
}
}
return bitmap;
I know it's a common problem for working with bitmaps but I don't know how to go on this with example. Especially because the size of the image view is not big that you would say it should cause a memory error. I think it's because I create the bitmaps to often instead of creating it once ant display it every five seconds but don't know how to do it. First of all the code for creating the bitmaps.
java class trapViews:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int x = 20;
Random r = new Random();
int i1 = r.nextInt(900 - 200) + 200;
rnd = new Random();
//Linke Seite
System.gc();
Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.stachelnstart);
Bitmap resizedBitmap = Bitmap.createScaledBitmap(image, i1, 300, true);
float left = (float) 0;
float top = (float) (getHeight() - resizedBitmap.getHeight());
canvas.drawBitmap(resizedBitmap, left, top, paint);
//rechte Seite
Bitmap images = BitmapFactory.decodeResource(getResources(), R.drawable.stachelnstart1);
Bitmap resizedBitmaps = Bitmap.createScaledBitmap(images, getWidth()-resizedBitmap.getWidth()-OwlHole, 300, true);
float left1 = (float) (getWidth() - resizedBitmaps.getWidth());
float top1 = (float) (getHeight() - resizedBitmaps.getHeight());
canvas.drawBitmap(resizedBitmaps, left1, top1, paint);
}
}
Creates a drawable on the right and left side of the screen with an random length.
Now I call this every 5 sec in the MainActivity with a Handler:
final Handler h = new Handler();
Runnable r = new Runnable() {
public void run() {
System.gc();
traps();
h.postDelayed(this,5000); // Handler neustarten
}
}
private void traps() {
container = (ViewGroup) findViewById(R.id.container);
trapViews tv = new trapViews(this);
container.addView(tv,
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
//tV.setImageCount(8);
h.postDelayed(r, 5000);
}
first of all, it's working like I want it to work. But every time a new drawable appears my game is lagging and after 5-6 times creating one its crashing down
The System.gc() and bitmap.recycle functions aren't working really well. Does anybody have a solution?
You're creating the bitmaps every 5 seconds which is not a good idea as they are always the same. You should create them once instead
trapViews extends View{
Bitmap image;
Bitmap resizedBitmap;
//rechte Seite
Bitmap images ;
Bitmap resizedBitmaps;
trapViews(Context c){
image = BitmapFactory.decodeResource(getResources(), R.drawable.stachelnstart);
images = BitmapFactory.decodeResource(getResources(), R.drawable.stachelnstart1);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int x = 20;
Random r = new Random();
int i1 = r.nextInt(900 - 200) + 200;
rnd = new Random();
//Linke Seite
//I have left this bitmap in the here as it is affected by the random int
resizedBitmap = Bitmap.createScaledBitmap(image, i1, 300, true);
float left = (float) 0;
float top = (float) (getHeight() - resizedBitmap.getHeight());
canvas.drawBitmap(resizedBitmap, left, top, paint);
//create this bitmap here as getWidth() will return 0 if created in the view's constructor
if(resizedBitmaps == null)
resizedBitmaps = Bitmap.createScaledBitmap(images, getWidth()-resizedBitmap.getWidth()-OwlHole, 300, true);
float left1 = (float) (getWidth() - resizedBitmaps.getWidth());
float top1 = (float) (getHeight() - resizedBitmaps.getHeight());
canvas.drawBitmap(resizedBitmaps, left1, top1, paint);
}
}
Remember to call Bitmap.recycle() after you replace a bitmap or when it's not visible anymore.
Creating mutiple bitmaps is not the problem but left unused objects without making use of recycle to free up memory.
I'm trying to cut a circle into semicircles using android canvas. The circle is loaded using Bitmap class.
Here's the example:
I've been looking for any solution, especially the ones which enable you to crop a bitmap using coordinates, but to no avail.
Any help is appreciated, thanks before..
I had the same challenge before and I solved it in a simple way, The main idea is simple! Use a Bitmap mask, Fill the pixel you want to save (in this case a pie) with the highest integer value (0xFFFFFFFF), So you can use a bitwiseAND to gain the result color, Other pixels of the mask Bitmap will be a transparent black color (0x00000000), When you're done with the mask, Create the result Bitmap and fill the pixels as the method below does:
public Bitmap applyPieMask(Bitmap src, float startAngle, float sweepAngle) {
int width = src.getWidth();
int height = src.getHeight();
//create bitmap mask with the same dimension of the src bitmap
Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mask);
canvas.drawColor(0x00000000);//fill mask bitmap with transparent black!
//init mask paint
Paint maskPaint = new Paint();
maskPaint.setColor(0xFFFFFFFF);//pick highest value for bitwise AND operation
maskPaint.setAntiAlias(true);
//choose entire bitmap as a rect
RectF rect = new RectF(0, 0, width, height);
canvas.drawArc(rect, startAngle, sweepAngle, true, maskPaint);//mask the pie
Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
//combine src color and mask to gain the result color
int color = mask.getPixel(i, j) & src.getPixel(i, j);
result.setPixel(i, j, color);
}
}
return result;
}
And here we go ...
public void doIt(View view) {
ImageView imageView = (ImageView) findViewById(R.id.iv);
Bitmap src = Bitmap.createBitmap(500, 500, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(src);
canvas.drawColor(Color.BLUE);//fill src bitmap with blue color
imageView.setImageBitmap(applyPieMask(src, -90, 60));
}
Hope you find it helpful
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.
Is there anyway i could scale an image to become 1.25x bigger everytime a button is pushed?
Basically, could someone give me some tips on how to do this? An explanation, a link, a tutorial, anything would be helpful :) thanks in advance
You should follow this.
http://www.anddev.org/resize_and_rotate_image_-_example-t621.html
Here is code from this page. It creates a Matrix to perform operations(resize and rotate) and applies that matrix to create new BitMap.
You can add the code(with some modifications) on OnClickListener event of yout Button.
public class bitmaptest extends Activity {
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout linLayout = new LinearLayout(this);
// load the origial BitMap (500 x 500 px)
Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),
R.drawable.android);
int width = bitmapOrg.width();
int height = bitmapOrg.height();
int newWidth = 200;
int newHeight = 200;
// calculate the scale - in this case = 0.4f
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// createa matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// rotate the Bitmap
matrix.postRotate(45);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
width, height, matrix, true);
// make a Drawable from Bitmap to allow to set the BitMap
// to the ImageView, ImageButton or what ever
BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
ImageView imageView = new ImageView(this);
// set the Drawable on the ImageView
imageView.setImageDrawable(bmd);
// center the Image
imageView.setScaleType(ScaleType.CENTER);
// add ImageView to the Layout
linLayout.addView(imageView,
new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT
)
);
// set LinearLayout as ContentView
setContentView(linLayout);
}
}
You can use Bitmap.createScaledBitmap() to resize image.
Refer to my articles on Image Processing to get some idea :): https://xjaphx.wordpress.com/learning/tutorials/