Currently I have an upper overlay image over a camera surface view.
I would like to do is only output the part of photo that is overlapped with upper layer. So Far I can merge the two image , that means , the overlap layer is on top of the camera view. But how can I get only the overlay part is in output? Thanks
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap resizedBottom;
Bitmap resizedTop;
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap photo=BitmapFactory.decodeByteArray(data, 0, data.length,options);
Matrix matrix = new Matrix();
matrix.postRotate(passDegree);
Bitmap rotatedBitmap = Bitmap.createBitmap(photo, 0, 0,photo.getWidth(), photo.getHeight(), matrix, true);
photo.recycle();
photo = null;
if (h >= w) {
h = w;
} else {
w = h;
}
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
resizedBottom = Bitmap.createScaledBitmap(rotatedBitmap,w,h,false);
resizedTop = Bitmap.createScaledBitmap(topLayer,w,h,false);
} else {
resizedBottom = Bitmap.createScaledBitmap(rotatedBitmap,h,w,false);
resizedTop = Bitmap.createScaledBitmap(topLayer,h,w,false);
}
Canvas c = new Canvas(resizedBottom);
Resources res = getResources();
Drawable drawable1 = new BitmapDrawable(res,resizedBottom);
Drawable drawable2 = new BitmapDrawable(res,resizedTop);
if (res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
drawable1.setBounds(0, 0, w, h);
drawable2.setBounds(0, 0, w, h);
} else {
drawable1.setBounds(0, 0, h, w);
drawable2.setBounds(0, 0, h, w);
}
drawable1.draw(c);
drawable2.draw(c);
File sdDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
// Write to SD Card
String fileName = String.format(sdDir+"/%d.jpg", System.currentTimeMillis());
OutputStream os = null;
try {
os = new FileOutputStream(fileName);
resizedBottom.compress(Bitmap.CompressFormat.PNG, 50, os);
} catch(IOException e) {
e.printStackTrace();
}
Log.i("test", "onPictureTaken - jpeg");
resetCam();
}
Spent an afternoon, at the end there is solution , it turn out easier than I thought:
Just
1.Create a temp bitmap to store render result
2.Set PorterDuff.Mode.DST_IN on top layer(In this mode only the overlap area is drawn)
Example code:
Bitmap result = Bitmap.createBitmap(topLayer.getWidth(), topLayer.getHeight(), Config.ARGB_8888);
Canvas mCanvas = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mCanvas.drawBitmap(resizedBottom, 0, 0, null);
mCanvas.drawBitmap(topLayer, 0, 0, paint);
paint.setXfermode(null);
Further reading about PorterDuff Mode:
http://www.ibm.com/developerworks/java/library/j-mer0918/
Related
I want to add a string on bitmap image.I have a metod drawTextToBitmap,this method working success place string on bitmap image.But my bitmap image is very small like pinmark image.This function set the string based on the bitmap height and width.I want to place the string exceed than the bitmap image.So Please help me to solve the problem.
Following method i am using to get bitmap :
public Bitmap drawTextToBitmap(Context gContext, int gResId, String gText) {
Resources resources = gContext.getResources();
float scale = resources.getDisplayMetrics().density;
Bitmap bitmap = BitmapFactory.decodeResource(resources, gResId);
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
// set default bitmap config if none
if (bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
// resource bitmaps are imutable,
// so we need to convert it to mutable one
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
// new antialised Paint
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// text color - #3D3D3D
paint.setColor(Color.BLACK);
// text size in pixels
paint.setTextSize((int) (70 * scale));
// text shadow
paint.setShadowLayer(1f, 0f, 1f, Color.BLACK);
// draw text to the Canvas center
Rect bounds = new Rect();
paint.getTextBounds(gText, 0, gText.length(), bounds);
int m = (bitmap.getWidth() - bounds.width()) / 2;
int l = (bitmap.getHeight() + bounds.height()) / 2;
canvas.drawText(gText, 1000, l, paint);
return bitmap;
}
Try this:
public static Bitmap drawStringonBitmap(Bitmap src, String string, Point location, int color, int alpha, int size, boolean underline,int width ,int height) {
Bitmap result = Bitmap.createBitmap(width, height, src.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
paint.setColor(color);
paint.setAlpha(alpha);
paint.setTextSize(size);
paint.setAntiAlias(true);
paint.setUnderlineText(underline);
canvas.drawText(string, location.x, location.y, paint);
return result;
}
My bitmap is rotated but is overlaped with original image.
Bitmap source
public void onImageAvailable(ImageReader reader) {
final Image image = reader.acquireNextImage();
// final Image image = reader.acquireLatestImage();
final ByteBuffer yuvBytes = imageToByteBuffer(image);
// Convert YUV to RGB
final RenderScript rs = RenderScript.create(MainActivity.this);
Bitmap bitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
final Allocation allocationRgb = Allocation.createFromBitmap(rs, bitmap);
final Allocation allocationYuv = Allocation.createSized(rs, Element.U8(rs), yuvBytes.array().length);
allocationYuv.copyFrom(yuvBytes.array());
ScriptIntrinsicYuvToRGB scriptYuvToRgb = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
scriptYuvToRgb.setInput(allocationYuv);
scriptYuvToRgb.forEach(allocationRgb);
allocationRgb.copyTo(bitmap);
int rotation = MainActivity.this.getWindowManager().getDefaultDisplay().getRotation();
int x = bitmap.getWidth();
int y = bitmap.getHeight();
Bitmap bitmap1 = Bitmap.createScaledBitmap(bitmap, y, x, true);
Bitmap rotatedBitmap = rotateBitmap(bitmap1, getOrientation(rotation));
RotatedBitmapFunction
public Bitmap rotateBitmap(Bitmap original, float degrees) {
int width = original.getWidth();
int height = original.getHeight();
Matrix matrix = new Matrix();
matrix.preRotate(degrees);
Bitmap rotatedBitmap = Bitmap.createBitmap(original, 0, 0, width, height, matrix, true);
Canvas canvas = new Canvas(rotatedBitmap);
canvas.drawBitmap(original, 5.0f, 0.0f, null);
return rotatedBitmap;
}
Output
The original bitmap is stacked on top of rotatedbitmap.
#Problem
Check these lines in your code
Canvas canvas = new Canvas(rotatedBitmap);
canvas.drawBitmap(original, 5.0f, 0.0f, null);
Why you are drawing the origin bitmap in the canvas just before returning the rotated Bitmap.
I guess this is the issue.
Solved It
public Bitmap rotateBitmap(Bitmap original, float degrees) {
int x = original.getWidth();
int y = original.getHeight();
Matrix matrix = new Matrix();
matrix.preRotate(degrees);
Bitmap rotatedBitmap = Bitmap.createBitmap(original , 0, 0, original .getWidth(), original .getHeight(), matrix, true);
return rotatedBitmap;
}
Hi everyone and beforehand thanks, I hope are well write because I am doing a simple application that should unite more than two bitmaps in only one, the problem is in which position bitmaps and size Side wrong, and the truth will not find the back for logic given to me that 's fine, in fact it is a Tengo Que code already in c # and PASE java obviously is different sin but have the same principle .
I wonder if you have the way to make the position and size of these images out as this saying in the code,
Sorry for my bad English
CODIGO JAVA
Paint mPaint;
Bitmap image1=BitmapUtils.decodeBase64(Lie.GeFondo().GetImagen());
Bitmap image2=BitmapUtils.decodeBase64(Utilidades.getImagenTomadabase64());
Bitmap image3=BitmapUtils.decodeBase64(Lie.GetBanner().GetImagen());
Bitmap result = Bitmap.createBitmap(image1.getWidth(), image1.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Rect srcRect = new Rect(0, 0, image1.getWidth(), image1.getHeight());
Rect dstRect = new Rect(srcRect);
Rect srcRect1 = new Rect( Foto.GetPosicionDeItems().Getx(),Foto.GetPosicionDeItems().Gety(),Foto.GetTamano().GetWidth(), Foto.GetTamano().GeHeight());
Rect srcRect3 = new Rect( Lie.GetBanner().GetPosicionDeItems().Getx(), Lie.GetBanner().GetPosicionDeItems().Gety() ,Lie.GetBanner().GetTamano().GetWidth(), Lie.GetBanner().GetTamano().GeHeight());
Rect srcRect2 = new Rect(0,0,image2.getWidth(), image2.getHeight());
Rect srcRect4 = new Rect(0,0,image3.getWidth(), image3.getHeight());
dstRect.offset(0, 0);
canvas.drawBitmap(image1, srcRect, dstRect, null);
dstRect.offset(image1.getWidth(), 0);
srcRect1.offset(0, 0);
canvas.drawBitmap(image2,srcRect2 ,srcRect1 , null);
srcRect1.offset(image2.getWidth(), 0);
srcRect3.offset(0, 0);
canvas.drawBitmap(image3,srcRect4 ,srcRect3 , null);
srcRect3.offset(image3.getWidth(), 0);
myImage = (ImageView) findViewById(R.id.imageView);
myImage.setImageBitmap(result);
in Java
see java picture http://i58.tinypic.com/1zywm5u.jpg
C# Code
Ignore the foreach.
System.Drawing.Bitmap Bac = (System.Drawing.Bitmap)Lienzo.Fondo.Imagen;
System.Drawing.Graphics r = System.Drawing.Graphics.FromImage(Bac);
if (Lienzo.Fotos != null)
{
if (Lienzo.Fotos.Count > 0)
{
int i = 0;
foreach (RADMLIB.Items item in Lienzo.Fotos)
{
System.Drawing.Bitmap img = (System.Drawing.Bitmap)Lista[i];
r.DrawImage(img, item.PosicionDeItems.X, item.PosicionDeItems.Y, item.Tamano.Width, item.Tamano.Height);
i++;
}
}
}
if (Lienzo.Banner != null)
{
r.DrawImage((System.Drawing.Bitmap)Lienzo.Banner.Imagen, Lienzo.Banner.PosicionDeItems.X, Lienzo.Banner.PosicionDeItems.Y, Lienzo.Banner.Tamano.Width, Lienzo.Banner.Tamano.Height);
}
return Bac;
see c# picture http://i61.tinypic.com/s61wlh.jpg
I found the solution
using Matrix for set location and scale x,y
Bitmap image1=BitmapUtils.decodeBase64(Lie.GeFondo().GetImagen());
Bitmap image2=BitmapUtils.getResizedBitmap(BitmapUtils.decodeBase64(Utilidades.getImagenTomadabase64()),Foto.GetTamano().GetWidth(),Foto.GetTamano().GeHeight());
Bitmap image3=BitmapUtils.getResizedBitmap(BitmapUtils.decodeBase64(Lie.GetBanner().GetImagen()),Lie.GetBanner().GetTamano().GetWidth(),Lie.GetBanner().GetTamano().GeHeight());
Bitmap result = Bitmap.createBitmap(image1.getWidth(), image1.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);//Create the canvas to your image
Rect srcRect = new Rect(0, 0, image1.getWidth(), image1.getHeight());
Rect dstRect = new Rect(srcRect);
Matrix matrix = new Matrix ();
Matrix matrix2 = new Matrix ();
matrix.postTranslate( Foto.GetPosicionDeItems().Getx(),Foto.GetPosicionDeItems().Gety());
matrix2.postTranslate( Lie.GetBanner().GetPosicionDeItems().Getx(),Lie.GetBanner().GetPosicionDeItems().Gety());
canvas.drawBitmap(image1, srcRect, dstRect, null);
dstRect.offset(image1.getWidth(), 0);
canvas.drawBitmap(image2,matrix , null);
canvas.drawBitmap(image3,matrix2 , null);
getResizedBitmap Method
public static Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
see the image
https://lh4.ggpht.com/LXW8kVc3U8qQUHnORI-3H4H-A2hjq92y_oEDsKIs-iBDkVBFTgjGP03xFReCeuyLlg=h900-rw
I have an electronic device (kind of scanner), that send bytes to android device via wifi.
In the android i am taking the bytes and create integer array(each number represent pixel).
Then i create png file with the bitmap class.
The image look as it should be.
I am processing the image in separate thread.
My goal is to create new image and replace the old image in the fastest way.
In fact i want to create illusion of movie.
The problem is that it took too much time to create images.
Here is the relevant code
Bitmap mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(mBitmap);
Paint paint = new Paint();
...
int count = mBufferIn.read(buffer);
while(count != -1)
{
for(int i=0;i<count;i=i+2)
{
k = ((buffer[i] << 8) & 0x0000ff00) | (buffer[i+1] & 0x000000ff);
Log.e("TCP Client", "k=" + Integer.toString(k) );
colors[pixelIndex]=k;
pixelIndex++;
}
count = mBufferIn.read(buffer);
if(count ==-1)
{
try {
pixelIndex=0;
c.drawBitmap(colors, 0, width, 0, 0, width, height, false, paint);
...
I have change the code to this:
try {
while((numberOfRead =mBufferIn.read(buffer)) != -1)
{
babff.append(buffer, 0, numberOfRead);
//offset = offset + numberOfRead;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte [] imageBytes = babff.toByteArray();
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.outHeight = height;
opt.outWidth = width;
Bitmap bitmap = BitmapFactory.decodeByteArray (imageBytes, 0, imageBytes.length,opt);
Paint paint1 = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(bitmap, 0, 0, paint1);
Now the problem is that the bitmap is NULL
Generating image setting pixel by pixel is very slow. Read everything inside a byte array and create the bitmap from the byte array
I am drawing a Bitmap with canvas.drawBitmap(bmp, 0, 0, null); to my canvas and the bitmap will just not show. Any ideas?
Thank you!
Bitmap bmp = BitmapFactory.decodeFile(myfile.getPath());
//Bitmap bmp = BitmapFactory.decodeStream(bis);
Log.i(TAG, "builded Bitmap");
Log.i(TAG, "scaling bitmap...");
//int scale;
//Matrix matrix = new Matrix();
//matrix.setScale(0.1F, 0.1F);
//if (bmp.getWidth() < bmp.getHeight()){
// scale = canvas.getWidth()/bmp.getWidth();
//}else{
// scale = canvas.getHeight()/bmp.getHeight();
//}
//matrix.postScale(scale, scale, bmp.getWidth(), bmp.getHeight());
//matrix.postScale(0.5F, canvas.getWidth()/bmp.getWidth());
//Bitmap bmp2 = Bitmap.createScaledBitmap(bmp, canvas.getWidth(), canvas.getHeight(), true);
//Paint p = new Paint();
//p.setFilterBitmap(true);
//try{
bmp = Bitmap.createScaledBitmap(bmp, canvas.getWidth(), canvas.getHeight(), true);
Log.i(TAG, "scaled");
Log.i(TAG, "showing bitmap...");
canvas.drawBitmap(bmp, 0, 0, null);
Log.i(TAG, "showed bitmap");
Can you draw a line?
Either call invalidate() or postInvalidate().
Read Drawing here:
http://developer.android.com/reference/android/view/View.html
And copy some examples like:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/TouchPaint.html
Just a guess:
Instead of "Bitmap bmp = BitmapFactory.decodeFile(myfile.getPath());
" try "Bitmap bmp = BitmapFactory.decodeStream(..);"