1

I am designing a drawing app where user can import image from gallery and then scale up or down to fit the screen width or height. so that user can draw onto the imported picture, using the below code.

I am extending View, named DrawView. The DrawView is same as screenwidth, but its height is less than screenheight because there are some buttons above it, placing the DrawView to the bottom of the Screen under the functioning buttons, and so I declared DrawViewHeight.

See below for examples for dimension and results of variables.

Question:

The bitmap can be properly loaded and scaled to fit to the DrawView.

However, it is located at the top of the DrawView. I would like to place it in the middle of the screen, so i added the following code but still FAILS.

bitmapCanvas.drawBitmap(bitmap, x_adjustment, y_adjustment, null);

How could it be further modified such that the imported image (decoded and copied as bitmap while importing) is placed center of DrawView, with blank space (eg. white) above and below and left and right of the loaded scaled bitmap image?

Note: Those surrounding space around the image are not to be drawn onto by user.

Codes:

Declarations:

private Bitmap bitmap; // drawing area for display or saving
private Canvas bitmapCanvas; // used to draw on bitmap

OnSizeChanged:

   public void onSizeChanged(int w, int h, int oldW, int oldH)
   {
      super.onSizeChanged(w, h, oldW, oldH);
      DrawViewWidth = w;       
      DrawViewHeight = h;

      bitmap = Bitmap.createBitmap(getWidth(), DrawViewHeight, Bitmap.Config.ARGB_8888);
      bitmapCanvas = new Canvas(bitmap);
      bitmap.eraseColor(Color.WHITE); // erase the BitMap with white            
   } 

OnDraw:

   @Override
   protected void onDraw(Canvas canvas)  // called each time this View is drawn 
   {
      canvas.drawBitmap(bitmap, 0, 0, paintScreen);       
   } 

Load Pictures:

   public void load_pic(final String picturePath) 
   {   

// get screen dimension first
WindowManager wm = (WindowManager) context_new.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
final int screenWidth = display.getWidth();
final int screenHeight = display.getHeight(); 

//get importing bitmap dimension
Options op = new Options();
op.inJustDecodeBounds = true;
Bitmap pic_to_be_imported = BitmapFactory.decodeFile(picturePath, op);
final int x_pic = op.outWidth;
final int y_pic = op.outHeight;

// scaling     
final int IMAGE_MAX_SIZE= (int) Math.max(DrawViewWidth, DrawViewHeight);

int scale = 1;
if (op.outHeight > IMAGE_MAX_SIZE || op.outWidth > IMAGE_MAX_SIZE) {
scale = (int)Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE /  (double) Math.max(op.outHeight, op.outWidth)) / Math.log(0.5)));  }

final BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;



// Start loading image to the DrawView

if ((x_pic > DrawViewWidth) || (y_pic > DrawViewHeight))
{

AlertDialog.Builder onBackBuilder = new AlertDialog.Builder(context_new);

onBackBuilder.setPositiveButton(R.string.buttontext_create_load_pic_stretch, new DialogInterface.OnClickListener() 
    {
        //skipped
    }


onBackBuilder.setNegativeButton(R.string.buttontext_create_load_pic_keep_scale, new DialogInterface.OnClickListener() 
{
    public void onClick(DialogInterface dialog, int id) 
    {                       

    float xratio = (float) x_pic / (float) screenWidth;
    float yratio = (float) y_pic / (float) DrawViewHeight;
    int adjusted_x = 0;
    int adjusted_y = 0;

    if (xratio >= yratio) {adjusted_x = screenWidth; adjusted_y = (int) (y_pic / xratio);}
    if (xratio < yratio) {adjusted_y = DrawViewHeight; adjusted_x = (int) (x_pic / yratio);}                      

    bitmap = (BitmapFactory.decodeFile(picturePath, o2));
    bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
    bitmap = Bitmap.createScaledBitmap(bitmap, adjusted_x, adjusted_y, true);                     

    int x_adjustment = (screenWidth - adjusted_x) /2;
    int y_adjustment = (DrawViewHeight -adjusted_y) /2;

    bitmapCanvas.drawBitmap(bitmap, x_adjustment, y_adjustment, null);

    // How to modify to put to center of DrawView????                 

    invalidate();
    }             
});

AlertDialog alert = onBackBuilder.create();
alert.show();          
}

Examples of dimension and results of variables:

Screen         : 480W * 800H
DrawView       : 480W * 590H
Original image : 3264W * 2448H
Scaled image   : adjusted_x=480 (meet screenwidth), adjusted_y=360
x_adjustment   : 0
y-adjustment   : 115

Layout.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

<com.pearmak.drawing.DrawView
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/drawView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:layout_gravity="center_vertical|center_horizontal|center"
            android:background="@drawable/drawview_border" />

</RelativeLayout> 
pearmak
  • 4,979
  • 15
  • 64
  • 122
  • What is the problem exactly? That you can't get the DrawView to center on the screen or that you can't get the bitmap you are drawing on the DrawView to center on the canvas of DrawView? – Michael A. Feb 15 '13 at 13:28
  • Judging by your code, you render the bitmap yourself to the view, the layout params are for the view and not the rendered bitmap - i believe you need to render that bitmap in the center yourself... might be mistaken thou, thus only commenting. – Sagi Antebi Feb 16 '13 at 11:26
  • @Michael A: I cannot get the bitmap that is drawing to the center on the canvas of DrawView. The DrawView itself is to be placed at bottom of the Screen. And now importing images always showing at top of the DrawView. I would like this importing images placing at center of the DrawView. – pearmak Feb 16 '13 at 12:18
  • @Sagi Antebi: I am thinking whether when it is importing images, then bitmap which is designed at dimension of DrawView is overriden by the importing dimensions, such that the bitmap is then finalized as the scaled image's dimension? I really dont know. I have added respective codes for the setting of bitmap. – pearmak Feb 16 '13 at 12:36
  • looking at the new code, have you tried saving the x,y values you used in the onClick event ? you might be drawing on top of bitmap in onDraw ? – Sagi Antebi Feb 16 '13 at 12:40
  • saving the x, y values? i have retrieved the x_adjustment, y_adjustment values using toast and show correctly. those toast output are like those in the above dimensions and results of variables. But I dont know whether drawing on top of bitmap...i tried and can draw on the imported scaled image but cannot draw on the blank space outside the scaled image. (the part that i skipped above is to stretch the image to full screen and is sucessful to draw on the whole screen) – pearmak Feb 16 '13 at 14:51
  • I am thinking when the app initiated, bitmap is created at dimension of full DrawView @ bitmap = Bitmap.createBitmap(getWidth(), DrawViewHeight, Bitmap.Config.ARGB_8888); Now importing image would it be a problem to code as bitmap = Bitmap.createScaledBitmap(bitmap, adjusted_x, adjusted_y, true); and then bitmapCanvas.drawBitmap(bitmap, x_adjustment, y_adjustment, null); making the bitmapCanvas to be set as same dimension of bitmap, and hence both bitmapCanvas and bitmap are of same size and thereby cannot be placed center? – pearmak Feb 16 '13 at 14:54

4 Answers4

4
    // You can try this :         

            int width = containerBitmap.getWidth();
            int height = containerBitmap.getHeight();
            float centerX = (width  - centeredBitmap.getWidth()) * 0.5f;
            float centerY = (height- centeredBitmap.getHeight()) * 0.5f;
            mCanvas.drawBitmap(centeredBitmap, centerX, centerY, paint);

You can use it to draw a bitmap at the center of another bitmap.

azamani
  • 121
  • 1
  • 3
1

In your onDraw() you specify (0,0) as the bitmap (x,y) which will draw it at the top left corner of your DrawView so your x_adjustment, y_adjustment effect is lost once onDraw is called.

You should do your bitmap location adjustment code inside onDraw not inside onClick

@Override
protected void onDraw(Canvas canvas)  // called each time this View is drawn 
{
  canvas.drawBitmap(bitmap, x_adjustment, y_adjustment, null);       
} 
iTech
  • 18,192
  • 4
  • 57
  • 80
  • Thanks!! it works! but it arises another problem because though when the user is drawing the line can be shown correctly, when the user removes the finger then finalized line would be shifted by x_adjustment or y_adjustment. Yet this is another question and I should accept your answer for this question because it really can now place the imported image to center of DrawView. Thanks for your help! =) – pearmak Feb 17 '13 at 15:04
  • see if you mind also help me with the question arised at http://stackoverflow.com/questions/14922297/android-path-shifted-once-finger-is-removed as you know what is going on lol – pearmak Feb 17 '13 at 16:08
0

The LayoutParameters of your imageview or the imageview's parent view need to specify centering within the screen

also, post your XML layout if there is one, as well as where you make the bitmap part of an imageview in your code

CQM
  • 42,592
  • 75
  • 224
  • 366
  • i dont know if it is relevant, i am now making a drawing app of which the user can select picture from the gallery and further draw on it, and hence do not have any imageview. All is canvas. The layout is also posted. i am a really beginner and if i have misunderstood your advice, please correct me, many thanks =) – pearmak Feb 03 '13 at 17:30
  • add android:layout_centerInParent="true" to the `DrawView` in the xml, try that – CQM Feb 03 '13 at 17:47
  • it still fails...would there be any problem for the code: bitmapCanvas.drawBitmap(bitmap, sxhalf - bxhalf, syhalf - byhalf, null); ? – pearmak Feb 03 '13 at 17:53
  • instead of using variables, @pearmak , try putting random numeric values in your drawBitmap function, start with 0, 0 and see where it ends up on screen. – CQM Feb 04 '13 at 16:26
  • i have tired and forced a Toast to write out the variables, the sxhalf - bxhalf and syhalf - byhalf giving positive values, say 10 and 115. If then it should start draw down 115 and right 10, counting from the left top corner? It seems bitmapCanvas.drawBitmap(bitmap, sxhalf - bxhalf, syhalf - byhalf, null) has some problem? actually what the "null" represents? – pearmak Feb 11 '13 at 16:49
  • and i have just tried using different values in drawBitmap and it still starts at 0,0...do you have any insights? – pearmak Feb 11 '13 at 16:58
  • @pearmak I don't, you can try putting a bounty on this question – CQM Feb 11 '13 at 19:21
  • yup I have reconstructed and updated the question to the most updated codes and started putting a bounty~ all in all, thanks for your support all the way! – pearmak Feb 13 '13 at 05:35
0

As iTech has noted, to get your Bitmap drawn in the center of the DrawView, you need to draw it in the correct location inside your onDraw method.

Create two additional fields:

int x_adjust, y_adjust;

In your onClick (when loading the bitmap), calculate the correct center, and set x_adjust and y_adjust to the relevant values. Then make sure you use these values in the onDraw method (rather than 0,0).

@Override
protected void onDraw(Canvas canvas)
{
    canvas.drawBitmap(bitmap, x_adjust, y_adjust, null);       
}

Note: Make sure to recalculate x_adjust and y_adjust in the onSizeChanged method also. Otherwise the bitmap will no longer be centered after you rotate the device.

Michael A.
  • 4,163
  • 3
  • 28
  • 47