Exporting multiple bitmaps to one picture - android

I've got two ImageViews within a RelativeLayout. One ImageView is draggable and scalable upon the other ImageView. This all works fine except when I try to export those ImageViews to a bitmap and add it to a canvas.
I can't figure out how to calculate the scale and dragged position of view/bitmap B.
ImageView A functions as a background.
ImageView B is draggable and scalable on top of ImageView A.
Here is a code example
public static Bitmap MergeBitmaps(View v, View ViewA, Bitmap bitmapA, View viewB, Bitmap bitmapB) {
Bitmap b = Bitmap.createBitmap(
bitmapA.getWidth(), bitmapA.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
float scaleFactor = (float) ViewA.getHeight() / (float) bitmapA.getHeight();
float scaleFactorWidth = (float) ViewA.getWidth() / (float)bitmapA.getWidth();
int test2[] = new int[2];
viewB.getLocationOnScreen(test2);
//Rect rect1 = new Rect();
//selectedImg.getDrawingRect(rect1);
//Rect rect2 = new Rect();
//logo.getDrawingRect(rect2);
//int logoHeight = logo.getHeight();
//int logoWidth = logo.getWidth();
//int logoLeft = logo.getLeft();
//int selectedImgLeft = selectedImg.getLeft();
float scaleFactorMid = (scaleFactor + scaleFactorWidth)/2;
c.drawBitmap(bitmapA, 0, 0, null);
//c.drawBitmap(logoBitmap, test2[0]*scaleFactorWidth, test2[1]*scaleFactor, null);
bitmapB = getResizedBitmap(bitmapB, (int)(bitmapB.getHeight()*scaleFactorMid), (int)(bitmapB.getWidth()*scaleFactorMid));
c.drawBitmap(bitmapB, bitmapA.getWidth()/2, bitmapA.getHeight()/2, null);
//v.layout(0, 0, v.getWidth(), v.getHeight());
//selectedImg.draw(c);
return b;
}
I tried calculating the scale factor by dividing the view's width/height and the Bitmaps width/height.
I tried a lot more as you can see. Can anyone point me in the right direction?

For your reference below function are helpful,(In this i scaled bitmap statically, you can move the code).
public void mergeTwoBitmap() {
ImageView iv1 = (ImageView) findViewById(R.id.imageView1);
ImageView iv2 = (ImageView) findViewById(R.id.imageView2);
Bitmap bitmap1 = ((BitmapDrawable) iv1.getDrawable()).getBitmap();
Bitmap bitmap2 = ((BitmapDrawable) iv2.getDrawable()).getBitmap();
float img2X = iv2.getX(), img2Y = iv2.getY();
float img2Width = bitmap2.getWidth(), img2Height = bitmap2.getHeight(); // Original Width And Height
bitmap2 = Bitmap.createScaledBitmap(bitmap2, 300, 300, true);
float img2NewX, img2NewY;
img2NewX = img2X + (img2Width - bitmap2.getWidth()) * 0.5f; // here bitmap2.getWidth() after scale bitmap1
img2NewY = img2Y + (img2Height - bitmap2.getHeight()) * 0.5f; // here bitmap2.getHeight() after scale bitmap2
Bitmap b = mergeBitmap(iv1.getWidth(), iv1.getHeight(), bitmap1,
bitmap2, img2NewX, img2NewY);
}
private Bitmap mergeBitmap(float w, float h, Bitmap bmp1, Bitmap bmp2,
float x, float y) {
Bitmap cs = null;
int width = (int) w, height = (int) h;
cs = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas comboImage = new Canvas(cs);
comboImage.drawBitmap(
Bitmap.createScaledBitmap(bmp1, width, height, true), 0f, 0f,
null);
comboImage.drawBitmap(bmp2, x, y, null);
return cs;
}

Related

How to increase pixels size of a Bitmap

I want to know if it's possible to modify bitmap pixels by pixels. I'm not asking for changing bitmap size/scale. What I'm looking for is that I want to increase size of all or some specific pixels of a bitmap.
I tried this
Thread(Runnable {
val newBitmap = Bitmap.createScaledBitmap(bitmap, bitmap.width * 4,
bitmap.height * 4, true);
for (x in 0 until bitmap.getWidth()) {
for (y in 0 until bitmap.getHeight()) {
val pixel = bitmap.getPixel(x, y);
val redValue = Color.red(pixel)
val blueValue = Color.blue(pixel)
val greenValue = Color.green(pixel)
newBitmap.setPixel(x * 4, y * 4, Color.rgb(redValue, greenValue, blueValue))
}
}
runOnUiThread({ imageView.setImageBitmap(newBitmap) })
}).start()
But it has no effect on the bitmap. Any kind of help is highly appreciated.
If you want to pixelate just a part of your bitmap, then you could create a Bitmap of the part which you wish to edit, perform changes on the new bitmap and then overlay the changed bitmap on top of the original bitmap.
So for example, you could pixelate a portion of a Bitmap by doing something along the following lines,
#Override
protected void onCreate(Bundle savedInstanceState) {
...
Bitmap originalBitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.drawabledroid)).getBitmap();
// Pixelate just the top half
int x = 0, y = 0, width = originalBitmap.getWidth(), height = originalBitmap.getHeight()/2;
//Or pixelate a rectangle in the middle
//int x = originalBitmap.getWidth()/2 - 50, y = originalBitmap.getHeight()/2 - 50, width = 100, height = 100;
//Get bitmap with region you want to pixelate
Bitmap original = Bitmap.createBitmap(originalBitmap, x,y,width,height);
int normalWidth = original.getWidth(), normalHeight = original.getHeight();
int smallWidth = normalWidth/15, smallHeight = normalHeight/15;
Bitmap small = getResizedBitmap(original, smallWidth, smallHeight);
Bitmap pixelated = getResizedBitmap(small, normalWidth, normalHeight);
//Overlay the pixelated bitmap on top of the original
Bitmap overlayed = overlayBitmaps(originalBitmap, pixelated,x,y, width, height);
}
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
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);
return Bitmap.createBitmap(
bm, 0, 0, width, height, matrix, false);
}
public static Bitmap overlayBitmaps(Bitmap bmp1, Bitmap bmp2, int x, int y, int width, int height) {
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, new Matrix(), null);
//If you know the background in transparent or any specific color
//Then you can color the region before overlaying the pixelated bitmap
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.TRANSPARENT);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
mPaint.setAntiAlias(true);
canvas.drawRect(x,y, x+width,y+height, mPaint);
//Overlay the pixelated bitmap
canvas.drawBitmap(bmp2, x, y, null);
return bmOverlay;
}

How to pass many textview on random position over image view?

now I am getting only one Text over the image I am using Canvas and Bitmap :
here is my code :
public Bitmap drawTextArrayToBitmap(Context mContext, int resourceId,String mText) {
try {
Resources resources = mContext.getResources();
float scale = resources.getDisplayMetrics().density;
Bitmap bitmap = BitmapFactory.decodeResource(resources, resourceId);
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
if(bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.rgb(110,110, 110));
paint.setTextSize((int) (12 * scale));
paint.setShadowLayer(1f, 0f, 1f, Color.DKGRAY);
Rect bounds = new Rect();
paint.getTextBounds(mText, 0, mText.length(), bounds);
/* int x = (bitmap.getWidth() - bounds.width())/6;
int y = (bitmap.getHeight() + bounds.height())/5;*/
int x = 100, y = 100;
for(int i=0;i<20;i++)
{
canvas.drawText(mText, x * scale, y * scale, paint);
}
return bitmap;
} catch (Exception e) {
// TODO: handle exception
return null;
}
}
inside oncreate ;
ImageView mImageView = (ImageView)findViewById(R.id.imageView1);
// Bitmap bmp =drawTextToBitmap(this,R.drawable.man,"Hello Android");
Bitmap bmp =drawTextArrayToBitmap(this,R.drawable.man,"Smile");
mImageView.setImageBitmap(bmp);
In this above code, I want to add multiple texts on random position over Image and different style I have tried much time I could not get succeed yet. I have tried inside loop also.
Thank you in Advance I would appreciate your effort

Resize and reposition watermark bitmap in Android

I'm using the following method to add a watermark logo on top of an existing bitmap:
private Bitmap addWaterMark(Bitmap src) {
int w = src.getWidth();
int h = src.getHeight();
Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
Bitmap waterMark = BitmapFactory.decodeResource(getActivity().getResources(), R.drawable.menu_logo);
canvas.drawBitmap(waterMark, 0, 0, null);
return result;
}
How can I modify the above code to position the watermark in the bottom right of the bitmap, and to also make its width 33% of the bitmap, while maintaining its aspect ratio?
Ended up getting it to work how I wanted like this:
private Bitmap addWaterMark(Bitmap src) {
int w = src.getWidth();
int h = src.getHeight();
Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
int watermarkPadding = 50;
Bitmap waterMark = BitmapFactory.decodeResource(getActivity().getResources(), R.drawable.menu_logo);
int newWatermarkWidth = w / 3;
int newWatermarkHeight = (waterMark.getHeight() * newWatermarkWidth) / waterMark.getWidth();
Bitmap newWatermark = Bitmap.createScaledBitmap(waterMark, newWatermarkWidth, newWatermarkHeight, true);
canvas.drawBitmap(newWatermark, w - newWatermarkWidth - watermarkPadding, h - newWatermarkHeight - watermarkPadding, null);
return result;
}
Hope this helps.
private Bitmap addWaterMark(Bitmap src) {
int w = src.getWidth();
int h = src.getHeight();
Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
float scale = 0.33f;
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
matrix.postTranslate(w - w * scale, h - h * scale);
Bitmap waterMark = BitmapFactory.decodeResource(getActivity().getResources(), R.drawable.menu_logo);
canvas.drawBitmap(waterMark, matrix, null);
return result;
}
You can use this library, you can draw you watermark in XML (view) and convert to Bitmap and add on your original.
private Bitmap generateWaterMark(Bitmap src) {
//src is your original image
WaterMark waterMark = new WaterMark(mContext);
//return the your original image with watermark added
return waterMark.getImageWaterMarkFromView(src, R.layout.watermark_all);
}

I want to scale my image to the bottom after center crop

I use image view to display picture of customer and I use this command to scale my images in the image view
iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
but after this command the heads of the customers have been cut partially so I want to scale the images to buttons after center crop command so the bottom of image will be cut
There's no out of the box solution for your requirements.
You need to do the scaling yourself. Here's how you do it:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// we need to wait till the layout has been inflated to get the size of the ImageView
final ImageView iv = (ImageView) findViewById(R.id.image);
iv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
scaleBitmap(iv);
}
}
);
}
private void scaleBitmap(ImageView iv) {
// get ImageView and determine width & height
int imageWidth = iv.getWidth();
int imageHeight = iv.getHeight();
Rect imageRect = new Rect(0, 0, imageWidth, imageHeight);
// determine destination rectangle
BitmapDrawable drawable = (BitmapDrawable)iv.getDrawable();
Bitmap sourceBitmap = drawable.getBitmap();
Rect bitmapRect = new Rect(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
// determine source rectangle
Rect sourceRect = computeSourceRect(imageRect, bitmapRect);
// here's where we do the magic
Bitmap scaledBitmap = Bitmap.createBitmap(imageRect.width(), imageRect.height(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(scaledBitmap);
canvas.drawBitmap(sourceBitmap, sourceRect, imageRect, new Paint());
iv.setImageBitmap(scaledBitmap);
}
private Rect computeSourceRect(Rect imageRect, Rect bitmapRect) {
float imageWidth = (float) imageRect.width();
float imageHeight = (float) imageRect.height();
float bitmapWidth = (float) bitmapRect.width();
float bitmapHeight = (float) bitmapRect.height();
float aspectRatioImage = imageWidth / imageHeight;
float aspectRatioBitmap = bitmapWidth / bitmapHeight;
if (aspectRatioImage<aspectRatioBitmap) {
float newWidth = bitmapHeight * aspectRatioImage;
float widthOffset = (bitmapWidth - newWidth) / 2f;
return new Rect((int) widthOffset, 0, (int) (widthOffset + newWidth), (int) bitmapHeight);
}
else {
float newHeight = bitmapWidth / aspectRatioImage;
float heightOffset = (bitmapHeight - newHeight) / 2f;
// return this for center_crop
//return new Rect(0, (int) heightOffset, (int) bitmapWidth, (int) (heightOffset + newHeight));
// return this for bottom align
return new Rect(0, 0, (int) bitmapWidth, (int) newHeight);
}
}
This basically scales a Bitmap to an ImageView according to your requirements (can easily be modified to work with a Button). You can do any scaling possible that way.

Problems drawing a bitmap on a layout

I create the Layout programatically in onCreate:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
myView = new MyView(SketchActivity.this, layout.getWidth(), layout.getHeight());
layout2.addView(myView);
layout2.bringToFront();
}
}, 50);
The View where i create the (mutable?) bitmap:
public MyView(Context c, int width, int height) {
super(c);
WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int w = display.getWidth(); // deprecated
int h = display.getHeight();
setFocusable(true);
setBackgroundResource(R.drawable.download);
// setting paint
mPaint = new Paint();
mPaint.setAlpha(0);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setAntiAlias(true);
// getting image from resources
Resources r = this.getContext().getResources();
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.smoke);
// converting image bitmap into mutable bitmap
bitmap = bm.createBitmap(w, h, Config.ARGB_8888);
mCanvas = new Canvas();
mCanvas.setBitmap(bitmap); // drawXY will result on that Bitmap
mCanvas.drawBitmap(bm, 0, 0, null);
}
My onDraw function:
#Override
protected void onDraw(Canvas canvas) {
mCanvas.drawCircle(x, y, r, mPaint);
canvas.drawBitmap(bitmap, 0, 0, null);
super.onDraw(canvas);
}
OnTouchEvent:
#Override
public boolean onTouchEvent(MotionEvent event) {
x = (int) event.getX();
y = (int) event.getY();
r = 20;
// Atlast invalidate canvas
invalidate();
return true;
}
No LogCat Errors
The problem is in myView. when i create the bitmap bitmap = bm.createBitmap(w, h, Config.ARGB_8888); If i put instead of w,h(width and height of screen) a small number Example: bitmap = bm.createBitmap(20, 20, Config.ARGB_8888); it creates a tiny picture. But if I put w and h, then instead of drawing on all the layout, it only draws on a small part. (even if i try: bitmap = bm.createBitmap(800, 1080, Config.ARGB_8888); it still draws on a small part, instead of all the screen. What should i do?
This solved it:
public 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;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// RECREATE THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
public MyView(Context c, int width, int height) {
super(c);
WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int w = display.getWidth(); // deprecated
int h = display.getHeight();
setFocusable(true);
setBackgroundResource(R.drawable.download);
// setting paint
mPaint = new Paint();
mPaint.setAlpha(0);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setAntiAlias(true);
mPaint.setMaskFilter(new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL));
// getting image from resources
Resources r = this.getContext().getResources();
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.smoke);
Bitmap bm2 = getResizedBitmap(bm, h, w);
// converting image bitmap into mutable bitmap
bitmap = bm2.createBitmap(w, h, Config.ARGB_8888);
mCanvas = new Canvas();
mCanvas.setBitmap(bitmap); // drawXY will result on that Bitmap
mCanvas.drawBitmap(bm2, 0, 0, null);
}
Looks like you're recycling your Bitmap somwhere in the code. There is a problem.
Yes, you should recycle it, but it's always a bit risky.
EDIT
Looks like you're drawing onto Bitmap. If it's not what you're trying to do, then you shouldn't call onDraw manually. Instead call invalidate() when you want to redraw your view.
You need to add an Options data like this:
Options options = new Options();
options.isMutable = true; // works from api 11
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.smoke, options);

Categories

Resources