I have been facing a weird problem in the last 2-3 days. The thing I would like to do looks easy but my solutions do not respond in somehow I would like. Let me inform you about what I certainly want.
I have a picture(.png). I have split it in 5 parts and saved them as .png also. My expectation is to have a view objects displaying those 5 pictures as a picture. So I have decided to use canvas.drawBitmap() method to draw that 5 pics in onDraw() method. It works fine. However, when I wanted to resize it I have used createScaledBitmap(bitmap, width, height, boolean). I have applied this way to every 5 differen bitmap object to resize and draw in onDraw() method. Unfortunately, I have got a full picture but between every picture there was a line vercitally. I have changed the boolean value as true in the method createScaledBitmap(bitmap, width, height, boolean) then it was working well with a bad quality of the picture.
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < 5; i++) {
Bitmap image = BitmapFactory.decodeResource(getResources(),
getResources().getIdentifier(
"f" + i, "drawable", getContext().getPackageName()));
image = Bitmap.createScaledBitmap(image, getWidth(), getHeight(), true);
canvas.drawBitmap(image, new Matrix(), null);
}
}
http://imageshack.us/photo/my-images/717/96553428.png
http://imageshack.us/photo/my-images/809/33612864.png
http://imageshack.us/photo/my-images/255/53597408.png
Note : Drawing speed matters. It means it should take less than 500 ms to draw.
Related
I have a list of items where I am displaying a bitmap next to the item's name. This bitmap is to be created from 2 images, I have a background image with a smaller foreground image to add on top of the background.
I am seeing that the background image appears to not be present on some of my rows in my list. It is not consistent when and which row has the combined bitmap without the background. It is not always the same row where the combined bitmap does not have the background and it is not always the first or not always the last row where the bitmap does not have the background. And sometimes the whole list has every row with the correct image.
The image below is a mockup showing my issue.
My code for creating the combined bitmap is as follows.
Bitmap combinedBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas combinedCanvas = new Canvas(combinedBitmap);
// Add the first bitmap to the canvas (this is my background and this is what appears to be
// missing on some rows in my list on some occasions)
combinedCanvas.drawBitmap(backgroundBitmap, 0, 0, null);
// my second smaller image, on top of the first image but 1 pixel in
// from the left and 20 pixels down from the top
combinedCanvas.drawBitmap(foregroundBitmap, 1, 20, null);
return combinedBitmap;
Note: My backgroundBitmap is generated from a Drawable using the following code
Bitmap backgroundBitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getMinimumHeight(),
Bitmap.Config.ARGB_8888);
backgroundBitmap.setDensity(resources.getDisplayMetrics().densityDpi);
Canvas canvas = new Canvas(backgroundBitmap);
drawable.draw(canvas);
Any suggestions of what I have wrong or even where to look to try and resolve this would be greatly appreciated.
EDIT: I have tested adding a colour to the background of my combinedCanvas to try and see where the image generation is going wrong by adding the following code
// TEMP: fill the canvas in red for now so I can see which combinedBitmaps are missing
// the background image
combinedCanvas.drawColor(Color.RED);
Now the rows which do not have the background are coloured in red. This indicates that the code above to create the combined canvas is somehow not adding the backgroundBitmap. I have checked and my background image is not null for every row in my list.
This method works fine for me. It's in C# (Xamarin), you'll have to translate it to Java I'm afraid.
public static Bitmap CombineImages(Bitmap background, Bitmap foreground)
{
int width = background.Width, height = background.Height;
Bitmap cs = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888);
Canvas comboImage = new Canvas(cs);
background = Bitmap.CreateScaledBitmap(background, width, height, true);
comboImage.DrawBitmap(background, 0, 0, null);
int top = (int)(0.05 * height);
int left = (int)(width - (foreground.Width + (width * 0.05)));
comboImage.DrawBitmap(foreground, left, top, null);
return cs;
}
The left and top are hardcoded for my requirements, it would be better to pass them in as arguments.
Two images are given blow i call first image as frame image and second image as frame image.Here fst is my Linear Layout and i set the frame-image as background image of it. Now i want to fill the pattern image in my frame image's white area. Outer area of the frame image is transparent and inner area is white.
How can i fill pattern image in my frame-Image. I tryied this code.
private void patternFill(Bitmap tempBitmapColor) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.pattern_a);
BitmapDrawable bitmapDrawable = new BitmapDrawable(bmp);
bitmapDrawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
fst.setBackgroundDrawable(bitmapDrawable);
}
but this is giving a square bitmap Image.
and my Imageview is like this in which i want to fill pattern.
pattern image is like this-
I want to fill pattern image in the white area of this image only. I am able to fill the color inside this image frame but not done in case of pattern Images.
can any one help me please ...
UPDATE :-
I read that if we want to set more then one color so we should use shader I updated the current code
public void setPattern(String newPattern){
postInvalidate();
//get pattern
int patternID = getResources().getIdentifier(newPattern, "drawable", "com.akanksha.partternfillexperiment");
//decode
Bitmap patternBMP = BitmapFactory.decodeResource(getResources(), patternID);
//create shader
BitmapShader patternBMPshader = new BitmapShader(patternBMP,
Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
//color and shader
// drawPaint.setColor(0xFFFFFFFF);
drawPaint.setShader(patternBMPshader);
patternset=true;
}
So, Here I am able to set the shader successfully .
After this method OnDraw method will call
#Override
protected void onDraw(Canvas canvas) {
if(patternset){
for (int x = 0; x < canvasBitmap.getWidth(); x++) {
drawPath.moveTo(x, 0);
for (int y = 0; y < canvasBitmap.getHeight(); y++) {
drawPath.lineTo(x, y);
}
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
invalidate();
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
What is setXfermode
I tried some mode in my setpattern method
like: DST_OVER,DST_IN
drawPaint.setColorFilter(new PorterDuffColorFilter(Color.YELLOW,Mode.MULTIPLY));
drawPaint.setXfermode(new PorterDuffXfermode(Mode.DST_OVER));
but not getting result according to need.
Is any mode can solve my purpose currently I am getting this output
I think I am very close to the result. I can draw the pattern what ever i need now the remaning problem is to set patten only in Inner non transparent area of frame.
I also tried this
if(canvasBitmap.getPixel(x, y) == Color.TRANSPARENT)
to identify transparent area so that i can fill pattern in another nontransparent are but this also not working.
Here I am uploading the Image for more clarification In the blow Image I fill the color in frame-image Now I want to fill pattern in place of Pink color.
Can anyone have any good point to try please share ...
You can have look on the following tutorial for your help
Drawing with Pattern Fills by Sue Smith
Using the above tutorial you can get following output
I need to "compute" the resulting bitmap obtained from overlapping two different bitmaps that have an alpha value somewhere between 0 and 255. I need to do this in java code, not xml, because bitmaps are being loaded dinamically and not from resources.
Here is my first try (which always yields a black bitmap...):
private Drawable composeBitmaps(int alpha1, BitmapDrawable bm1,
int alpha2, BitmapDrawable bm2)
{
Canvas c = new Canvas();
Bitmap b1 = bm1.getBitmap();
BitmapDrawable draw1 = new BitmapDrawable(b1.copy(b1.getConfig(), true));
draw1.setAlpha(alpha1);
c.setBitmap(draw1.getBitmap());
Paint p = new Paint();
p.setAlpha(alpha2);
c.drawBitmap(bm2.getBitmap(), 0, 0, p);
return draw1;
}
...
View v = // whatever
v.setBackgroundDrawable(composeBitmaps(100, bdrawable1, 150, bdrawable2));
And the view goes black background. What am I doing wrong?
My code above is absolutely correct. The bug that made the bitmap go black was elsewhere. Found it, fixed it, now it works.
The only thing to note is that my code is slow as hell and it cannot be used to crossfade two fullscreen bitmaps at a reasonable fps rate.
I have an application which requires me to draw paths to a canvas. As the number of paths builds up, the cumulative drawing action takes longer, so I thought I would improve speed by using the drawing cache.
To do this I have an onDraw method looking a bit like this:
#Override
protected void onDraw(Canvas canvas) {
Path path;
Paint paint;
synchronized(mPaths) {
buildDrawingCache();
Bitmap bmp = getDrawingCache();
if(bmp!=null) canvas.drawBitmap(bmp,
new Rect(0, 0, bmp.getWidth(), bmp.getHeight()),
new Rect(getLeft(), getTop(), getRight(), getBottom()),
null);
for(int i=mLastCount; i<mPaths.size(); ++i) {
path = mPaths.get(i);
paint = mPaints.get(i);
canvas.drawPath(path, paint);
}
mLastCount = 0;
mDrawn = true;
destroyDrawingCache();
}
}
mPaths and mPaints are lists of Path and Paint objects and I have a method set up to work out how many are new so it only redraws the last one. I originally called setDrawingCacheEnabled(true) instead of buildDrawingCache() and destroyDrawingCache() but this didn't work (that may be significant).
Anyway, this code works—it produces a bitmap which I can write to the canvas, then I only draw the last path and everything is fine except that as I draw more and more paths, it still slows down, as though it were still redrawing all the paths during buildDrawingCache().
Is that what's happening? Ideally I would like the draw method to be blitting a bitmap, then placing a single path over it. If it's generating the bitmap from all the paths, every time, I might as well not bother (in fact I will probably write my own bitmap generation code if this is the case, but it seems a pain).
If it isn't what's happening, is there something else that could be causing the code to slow down?
I have a bitmap with the size of 400 x 70 pixels. I would like to scroll this bitmap up by one row and fill up row 70 with new pixels.
I have tried to scroll the bitmap by copying it to an IntBuffer , copy it to another IntBuffer (starting at the second row) and the then write it back to the bitmap.
This works but it takes a lot of CPU power and it is kind of slow.
Is there any faster way to do this?
private Bitmap shift(Bitmap bitmap)
{
buffer.rewind();
buffer1.rewind();
bitmap.copyPixelsToBuffer(buffer);
buffer.position(bitmap.getWidth());
buffer1.put(buffer.array(), bitmap.getWidth()*2, bitmap.getWidth() * bitmap.getHeight());
buffer1.rewind();
bitmap.copyPixelsFromBuffer(buffer1);
return bitmap;
}
This is one way to do it using canvas:
canvas.drawBitmap(bgr, bgrPosition, 0, null);
canvas.drawBitmap(bgr, 0 - bgrW + bgrPosition, 0, null);
//next value for the background's position
if ( (bgrPosition += bgrDx) > bgrW){
bgrPosition = 0;
}
bgrDx is the speed of scrolling try bgrDx = 1, while bgrW is the width of the bgr bitmap.
This method repeats the image and produces an infinite scroll, however you would need to use a looped image (the same on both ends) to make the scroll look seamless. Perhaps you should experiment with this and see if it performs any better for you.