Search code examples
androidcanvasandroid-imageviewandroid-canvasandroid-bitmap

how to put text on image bitmap at bottom?


What I Want: I want to add text at bottom of a image which I have chose from either gallery or camera.

Original Image

Original Image

I added blue color strip to image at bottom

I added little strip to image at bottom

In that strip, I want to add some text exactly in middle.

What's the Problem:

  1. I'm unable to position text exactly in middle of blue color strip.
  2. For different images, text size changes. Some time it is very small, some time it is very big.

What I Tried: My code is like below.

MainActivity.java

    public class MainActivity extends AppCompatActivity {

    private ImageView mImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mImageView = findViewById(R.id.imageView);
    }

    public void openGallery(View view) {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select Picture"), 100);
    }

    public void openCamera(View view) {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(intent, 101);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (data != null && resultCode == Activity.RESULT_OK) {

            if (requestCode == 100) {

                Bitmap bitmap = null;
                try {
                    bitmap = MediaStore.Images.Media
                            .getBitmap(getApplicationContext().getContentResolver(), data.getData());
                } catch (IOException e) {
                    e.printStackTrace();
                }

                addStampToImage(bitmap);

            } else if (requestCode == 101) {

                Bitmap bitmap = (Bitmap) data.getExtras().get("data");
                ByteArrayOutputStream bytes = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
                File destination = new File(Environment.getExternalStorageDirectory(),
                        System.currentTimeMillis() + ".jpg");
                FileOutputStream fo;
                try {
                    destination.createNewFile();
                    fo = new FileOutputStream(destination);
                    fo.write(bytes.toByteArray());
                    fo.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                addStampToImage(bitmap);
            }
        }
    }

    private void addStampToImage(Bitmap originalBitmap) {

        int extraHeight = (int) (originalBitmap.getHeight() * 0.15);

        Bitmap newBitmap = Bitmap.createBitmap(originalBitmap.getWidth(),
                originalBitmap.getHeight() + extraHeight, Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(newBitmap);
        canvas.drawColor(Color.BLUE);
        canvas.drawBitmap(originalBitmap, 0, 0, null);

        Resources resources = getResources();
        float scale = resources.getDisplayMetrics().density;

        Paint pText = new Paint();
        pText.setColor(Color.WHITE);
        pText.setTextSize((int) (20 * scale));

        String text = "Maulik";

        /*Rect r = new Rect();
        canvas.getClipBounds(r);
        int cHeight = r.height();
        int cWidth = r.width();
        pText.setTextAlign(Paint.Align.LEFT);
        pText.getTextBounds(text, 0, text.length(), r);
        float x = -r.left;
        float y = cHeight / 2f + r.height() / 2f - r.bottom;

        int minusSpace = (int) (canvas.getClipBounds().bottom * 0.07);

        canvas.drawText(text, 0, canvas.getClipBounds().bottom - minusSpace, pText);*/

        Rect bounds = new Rect();
        pText.getTextBounds(text, 0, text.length(), bounds);
        int x = (newBitmap.getWidth() - bounds.width())/6;
        int y = (newBitmap.getHeight() + bounds.height())/5;

        canvas.drawText(text, x * scale, y * scale, pText);

        mImageView.setImageBitmap(newBitmap);
    }
}

Any help will be appreciated!

Updated: 1st Aug 2018

Changes in addStampToImage method.

int extraHeight = (int) (originalBitmap.getHeight() * 0.15);

Rect textHeightWidth = new Rect();
pText.getTextBounds(fromWhichMode, 0, fromWhichMode.length(), textHeightWidth);

canvas.drawText(textToStamp, (canvas.getWidth() / 2) - (textHeightWidth.width() / 2),
                originalBitmap.getHeight() + (extraHeight / 2) + (textHeightWidth.height() / 2),
                pText);

Above changes giving me text in middle of blue strip. But core ISSUE remains same. i.e Text size changes with respect to different image sizes.


Solution

  • Check the below code:-

    private void addStampToImage(Bitmap originalBitmap) {
    
        int extraHeight = (int) (originalBitmap.getHeight() * 0.15);
    
        Bitmap newBitmap = Bitmap.createBitmap(originalBitmap.getWidth(),
                originalBitmap.getHeight() + extraHeight, Bitmap.Config.ARGB_8888);
    
        Canvas canvas = new Canvas(newBitmap);
        canvas.drawColor(Color.BLUE);
        canvas.drawBitmap(originalBitmap, 0, 0, null);
    
        Resources resources = getResources();
        float scale = resources.getDisplayMetrics().density;
    
        String text = "Maulik";
        Paint pText = new Paint();
        pText.setColor(Color.WHITE);
    
        setTextSizeForWidth(pText,(int) (originalBitmap.getHeight() * 0.10),text);
    
    
    
    
        Rect bounds = new Rect();
        pText.getTextBounds(text, 0, text.length(), bounds);
    
        int x=  ((newBitmap.getWidth()-(int)pText.measureText(text))/2);
        int h=(extraHeight+bounds.height())/2;
        int y=(originalBitmap.getHeight()+h);
    
        canvas.drawText(text, x, y, pText);
    
        imageView.setImageBitmap(newBitmap);
    }
    
    
    private void setTextSizeForWidth(Paint paint, float desiredHeight,
                                            String text) {
    
        // Pick a reasonably large value for the test. Larger values produce
        // more accurate results, but may cause problems with hardware
        // acceleration. But there are workarounds for that, too; refer to
        // http://stackoverflow.com/questions/6253528/font-size-too-large-to-fit-in-cache
        final float testTextSize = 48f;
    
        // Get the bounds of the text, using our testTextSize.
        paint.setTextSize(testTextSize);
        Rect bounds = new Rect();
        paint.getTextBounds(text, 0, text.length(), bounds);
    
        // Calculate the desired size as a proportion of our testTextSize.
        float desiredTextSize = testTextSize * desiredHeight / bounds.height();
    
        // Set the paint for that size.
        paint.setTextSize(desiredTextSize);
    }
    

    Edit:- Instead of above addStampToImage method you can also use your updated addStampToImage method like below:-

    private void addStampToImage(Bitmap originalBitmap) {
    
        int extraHeight = (int) (originalBitmap.getHeight() * 0.15);
    
        Bitmap newBitmap = Bitmap.createBitmap(originalBitmap.getWidth(),
                originalBitmap.getHeight() + extraHeight, Bitmap.Config.ARGB_8888);
    
        Canvas canvas = new Canvas(newBitmap);
        canvas.drawColor(Color.BLUE);
        canvas.drawBitmap(originalBitmap, 0, 0, null);
    
        Resources resources = getResources();
        float scale = resources.getDisplayMetrics().density;
    
        String text = "Maulik";
        Paint pText = new Paint();
        pText.setColor(Color.WHITE);
    
        setTextSizeForWidth(pText,(int) (originalBitmap.getHeight() * 0.10),text);
    
    
        Rect bounds = new Rect();
        pText.getTextBounds(text, 0, text.length(), bounds);
    
        Rect textHeightWidth = new Rect();
        pText.getTextBounds(text, 0, text.length(), textHeightWidth);
    
        canvas.drawText(text, (canvas.getWidth() / 2) - (textHeightWidth.width() / 2),
                originalBitmap.getHeight() + (extraHeight / 2) + (textHeightWidth.height() / 2),
                pText);
    
        imageView.setImageBitmap(newBitmap);
    }