For a school project I need to make a module to shrink a bitmap. So I made a matrix for this but when I draw directly the bitmap with the matrix like this :
canvas.drawBitmap(Bmp, ShrinkMatrice, p);
This work very fine, but I need to assign this matrix into the Bmp so I used a second canvas like this :
Canvas SuperCanvas = new Canvas(Bmp);
SuperCanvas.drawBitmap(Bmp, ShrinkMatrice, p);
but when I look the result with this :
canvas.drawBitmap(Bmp, 0,0, p);
the result look like this ( see the picture on the link ), the rest of the page is not draw correctly ...
if someone can explain me this problem :/...
Thank you in advance...
(Sorry if I made some error it's my first time on stackoverflow )
Related
I am working on an android application which has 2 features:-
is to remove(erase) a part of the image for a given path, just like the eraser
in photoshop.
is to restore the image for a given path.
I've implemented the erasing part
mEraserPaint = new Paint(1);
mEraserPaint.setDither(true);
mEraserPaint.setAntiAlias(true);
mEraserPaint.setFilterBitmap(true);
mEraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mEraserPaint.setStyle(Paint.Style.STROKE);
mEraserPaint.setStrokeJoin(Paint.Join.ROUND);
mEraserPaint.setStrokeCap(Paint.Cap.ROUND);
mEraserPaint.setStrokeWidth(this.strokeWidth);
mEditingCanvas.drawPath(mPath, mEraserPaint);
And, the repair feature like,
mRepairPaint = new Paint(1);
mRepairPaint.setDither(true);
mRepairPaint.setAntiAlias(true);
mRepairPaint.setFilterBitmap(true);
mRepairPaint.setStyle(Paint.Style.STROKE);
mRepairPaint.setStrokeJoin(Paint.Join.ROUND);
mRepairPaint.setStrokeCap(Paint.Cap.ROUND);
mRepairPaint.setStrokeWidth(this.strokeWidth);
mRepairPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
Bitmap overlay = Bitmap.createBitmap(mOriginalBitmap.getWidth(),
mOriginalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(overlay);
canvas.drawPath(mPath, mRepairPaint);
mRepairPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(mOriginalBitmap, 0, 0, mRepairPaint);
mRepairPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
mEditingCanvas.drawBitmap(overlay, 0, 0, mRepairPaint);
The problem is that, in the repair feature alpha of the image is not preserved and the image is drawn with full opacity. I need to preserve the alpha of image.
So, I need to know how to repair an image after erasing a part of it, while preserving its alpha.
I have a rather big number of small bitmaps (100+, size about 40x40) each one have some opaque and some transparent parts and i need to paint them respecting these areas.
Bitmaps are in ARGB format, 888(rgb) plus a 256bit alpha channel, standard like in PNG format.
The only (working) way i found to draw them is the following approach:
create a bitmap (ARGB_8888)
fill the bitmap with the raw data
extract the alpha layer from the bitmap
create a BitmapShader (RGB_565) based on the original bitmap
Create a paint for the bitmap which uses the created shader
Then paint the alpha mask using the paint with the special BitmapShader.
The initialization code is run only once, of course:
void initializeTile( int t ){
// Allocate the bitmap:
Bitmap original_data = Bitmap.createBitmap( tile_w, tile_h, Bitmap.Config.ARGB_8888);
// Fill with raw data (this is actually native C++ code):
populateBitmap( original_data );
// Get the alpha mask:
tile_mask[ t ] = original_data.extractAlpha();
// Create the bitmap shader:
tile_data = original_data.copy( Bitmap.Config.RGB_565, false);
// Create the shader:
BitmapShader shader = new BitmapShader(tile_data, CLAMP, CLAMP);
// Create the paint:
tile_paint[ t ] = new Paint();
tile_paint[ t ].setDither(true);
tile_paint[ t ].setAntiAlias(true);
tile_paint[ t ].setFilterBitmap(true);
tile_paint[ t ].setShader( shader );
}
And the paint code is the most simple possible, and it's in the main draw loop:
void paintTile(t){
canvas.drawBitmap( tile_mask[ t ], tile_x[ t], tile_y[ t], tile_paint[ t] );
}
Now, on phones like the Ideos (Android 2.2) it run smooth and fine, but on other phones like the top-end Samsung Galaxy SII (Android 2.3) it's crappy and slow. This does not make much sense to me...
So, what do you think of this approach? Are there better, faster, ways to achieve the same result?
And, why do you think it's so slow on modern, fast hardware? Is there any ways to improve it?
Ok, after some work i found out a better solution. I cannot answer my own questions, so please do if you know more than me.
But, in case more people needs this, i am posting my new solution, which is much faster albeit a bit more complicated. The key idea is to use the shader approach ONLY during initialization and not for painting.
To do this, i create a new bitmap which will contain the "clipped" bitmap (with all the transparent areas cleared) using the shader approach, then paint that clipped bitmap without any shader in the draw code.
void initializeTile( int t ){
// Allocate the bitmap:
Bitmap original_data = Bitmap.createBitmap( tile_w, tile_h, Bitmap.Config.ARGB_8888);
// Fill with raw data (this is actually native C++ code):
populateBitmap( original_data );
// Now make a new bitmap to be clipped:
Bitmap clipped_data = Bitmap.createBitmap( tile_w, tile_h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(clipped_data);
Paint clip_paint = new Paint();
clip_paint.setDither(true);
clip_paint.setAntiAlias(true);
clip_paint.setFilterBitmap(true);
clip_paint.setShader( new BitmapShader(original_data, CLAMP, CLAMP));
// Paint the clipped bitmap:
canvas.drawBitmap( tile_mask[ t ], 0, 0, clip_paint );
//Use the clipped bitmap as original bitmap:
tile_data[ t ] = clipped_data;
}
And also drawing code:
void paintTile(t){
canvas.drawBitmap( tile_data[ t ], tile_x[ t], tile_y[ t], null );
}
Overall, this is much faster.
Still it's unclear to me WHY Android would not paint my alpha-channelled bitmaps properly without all this mess!
Which is the difference between these two code snippets?
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.image)
Matrix m = new Matrix();
m.postRotate(angle, bmp.getWidth()/2, bmp.getHeight()/2);
m.postTranslate(x,y);
canvas.drawBitmap(bmp,m,null);
Or:
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.image)
canvas.save();
canvas.rotate(angle, bmp.getWidth()/2, bmp.getHeight()/2);
canvas.drawBitmap(bmp, x, y, null);
canvas.restore();
Is there a performance difference? Is it worth caching the Matrix in option 1 if I am trying to achieve a high framerate?
I am not sure why you are calling canvas.save() and canvas.restore() in only one of the examples, but I have done performance tests and show:
Using Matrix seems consistently faster (usually by 30-50%), for loading the same image.
However, some tests shows Canvas eventually was faster: after 300,000
tests - by 4-15%.
So if you need to load it a few times, use Matrix.
If you need to load it hundreds of thousands of times - you may be better off using only Canvas (or at least reusing the same Matrix instance).
I have to scan a Data Matrix written on something like this.
The code is white/light gray but the background reflects different colors, depending on the position of the camera(angle), light.
Where would be the right place to edit the image captured in Android Zxing?
Is there any possible adjustment to make the image black on white before processing?
Any idea would be great.
Bitmap bm = Bitmap.createBitmap(500, 500, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bm);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
int xo = (w-500)/2;
int yo = (h-500)/2;
c.drawBitmap(bmp, -xo, -yo, paint);
bmp.recycle();
Also have a look at this class:
http://zxing.org/w/docs/javadoc/com/google/zxing/common/HybridBinarizer.html
Maybe you are using by default the GlobalHistogramBinarizer, which is faster but doesn't work so good with gradients.
It seems that you need some image processing before recognition. Previous answer suggest histogram bianrizer, which is sensitive to background intensity changes. Sauvola filter is known to have good tolerance to background changes ( and gradients), but has higher processing time.
( Implemented in our OCR Project: http://sourceforge.net/projects/javaocr/ , and you can see it in action
in this application: https://market.android.com/details?id=de.pribluda.android.ocrcall&feature=search_result )
Hello I am trying to place acouple bitmaps on the screen and rotate them. I can get this to work by doing
canvas.drawBitmap(pic2, rotatePic, null);
rotatePic is matrix with
postRotate(5, pic2.getHieght()/2, pic2.getWidth()/2)
this rotates the pic and puts it at 0, 0 so to place it i tried
Bitmap topPic = Bitmap.createBitmap(pic2, 0, 0, pic2.getWidth(),
pic2.getHeight(), rotatePic, false);
than place with
canvas.drawBitmap(topPic, 200, 100, null);
it places it correctley but it no longer rotates correctley it looks like it is bouncing and spinning I've tried everthing
You can alternatively try rotating the canvas itself, using
canvas.rotate(degress, px, py);
Here's a link to the Android reference page for this:
Canvas.rotate();
Hope this helps!!