1

I have a relative layout on which i add a view. this is the code in the activity:

paint = (RelativeLayout) findViewById(R.id.paint);
    new Handler().postDelayed(new Runnable() {

        @Override
        public void run() {
            myView = new CustomImage(getBaseContext());
            paint.addView(myView);
            String imagePath = (String) getIntent().getExtras().get("selectedImagePath");
            LogService.log("PaintActivity", "Imagepath: " + imagePath);
            //                Drawable background = BitmapDrawable.createFromPath(imagePath);
            //                bitmap = ((BitmapDrawable) background).getBitmap();
            try {
                fis = new FileInputStream(imagePath);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                mBitmap = loadBitmap(fis.getFD());
                bitmap = getResizedBitmap(mBitmap, 412*2, 1024*2);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                LogService.log("PaintActivity", "Bitmap = " + mBitmap);
                myView.setBitmap(bitmap);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            mPaint = new Paint();
            mPaint.setAntiAlias(true);
            mPaint.setDither(true);
            mPaint.setColor(0xFF000000);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeJoin(Paint.Join.ROUND);
            mPaint.setStrokeCap(Paint.Cap.ROUND);
            mPaint.setStrokeWidth(50);
            myView.setPaint(mPaint);

        }
    }, 50);

This is my View:

public class CustomImage extends View {

private boolean hasResized = false;

private Bitmap bitmap, bitmap2;

public Context context;

Paint paint;

private Canvas canvas;

public String text = null;

private Paint mBitmapPaint, paintText;

private Path mPath = new Path();

private float mX, mY, pX, pY, tX, tY;

private static final float TOUCH_TOLERANCE = 4;

private float screenDensity;

int height, width;

private Bitmap mBitmap;

private RandomAccessFile randomAccessFile;

private int bh;

private int bw;

public CustomImage(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
}

public CustomImage(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public CustomImage(Context context) {
    super(context);
    init(context);
}

private void init(Context context) {
    this.context = context;
    mBitmapPaint = new Paint(Paint.DITHER_FLAG);
  }

public void setImg(Context context, Canvas canvas, Bitmap bitmapw, int width, int height) {

    bw = bitmapw.getWidth();
    bh = bitmapw.getHeight();
    float scaleWidth = ((float) width)/ bw;
    float scaleHeight = ((float) height)/ bh;
    System.out.println("CustomImage.setImg()");
    bitmap = bitmapw;

}

public void setPaint(Paint paint) {
    this.paint = paint;
    LogService.log("in setPaint", "paint = " + paint);
}

public void setBitmap(Bitmap bitmap) throws Exception {
    File file = new File("/mnt/sdcard/sample/temp.txt");
    file.getParentFile().mkdirs();
    randomAccessFile = new RandomAccessFile(file, "rw");
    int bWidth = bitmap.getWidth();
    int bHeight = bitmap.getHeight();
    FileChannel channel = randomAccessFile.getChannel();
    MappedByteBuffer map = channel.map(MapMode.READ_WRITE, 0, bWidth*bHeight*4);
    bitmap.copyPixelsToBuffer(map);
    bitmap.recycle();
    this.bitmap = Bitmap.createBitmap(bWidth, bHeight, Config.ARGB_8888);
    map.position(0);
    this.bitmap.copyPixelsFromBuffer(map);
    channel.close();
    randomAccessFile.close();
    //        this.bitmap = bitmap;


    // canvas = new Canvas();
}

public void setBitmap2(Bitmap bitmap) {
    bitmap2 = bitmap;
    invalidate();
}

public void getText(String text) {
    this.text = text;
    paintText = new Paint();
    paintText.setColor(0xFFFFFFFF);
    paintText.setStrokeWidth(10);
    paintText.setTextSize(20);
    invalidate();
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawBitmap(bitmap, 0, 0, mBitmapPaint);
    if (PaintActivity.isPic == 1) {
        if (bitmap2 != null) {
            canvas.drawBitmap(bitmap2, mX, mY, mBitmapPaint);
            pX = mX;
            pY = mY;
        }
        if(text != null){
            canvas.drawText(text, tX, tY, paintText);
        }
    } else if (PaintActivity.isPic == 2) {
        if(text != null){
            canvas.drawText(text, mX, mY, paintText);
            tX = mX;
            tY = mY;
        }
        if (bitmap2 != null) {
            canvas.drawBitmap(bitmap2, pX, pY, mBitmapPaint);
        }
    }else{
        canvas.drawPath(mPath, paint);
        if (bitmap2 != null) {
            canvas.drawBitmap(bitmap2, pX, pY, mBitmapPaint);
        }
        if(text != null){
            canvas.drawText(text, tX, tY, paintText);
        }
    }
}

private void touch_start(float x, float y) {
    mPath.reset();
    mPath.moveTo(x, y);
    canvas.drawPoint(x, y, paint);
    mX = x;
    mY = y;

}
private void touch_move(float x, float y) {
    float dx = Math.abs(x - mX);
    float dy = Math.abs(y - mY);
    if ((dx >= TOUCH_TOLERANCE) || (dy >= TOUCH_TOLERANCE)) {
        mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
        mX = x;
        mY = y;
    }
}

private void touch_up() {
    mPath.lineTo(mX, mY);
    mPath.moveTo(mX, mY);
    canvas.drawPath(mPath, paint);
    mPath.reset();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        touch_start(x, y);

        invalidate();
        break;
    case MotionEvent.ACTION_MOVE:
        touch_move(x, y);
        invalidate();
        break;
    case MotionEvent.ACTION_UP:
        touch_up();
        invalidate();
        break;
    }
    return true;
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    System.out.println("CustomImage.onSizeChanged()");
    super.onSizeChanged(w, h, oldw, oldh);
    if ((w != 0) && (h != 0)) {
        if (!hasResized) {
            hasResized = true;
            renderImage();
        }
    }
}

public void renderImage() {
    System.out.println("======in renderimage=======w " + getMeasuredWidth() + "h " + getMeasuredHeight());
    width = getMeasuredWidth();
    height = getMeasuredHeight();
    canvas = new Canvas(bitmap);
    setImg(context, canvas, bitmap, width, height);
}
}

As you can see, I have a resizing function in the activity:

  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;

}

Now if i comment this function out of the code, the image looks normal, but not scaled. If i leave it there, then i get an ugly image, but it is resized. Example: normal not resized: http://imgur.com/BD5Pp,YWDTi altered but resized pic: http://imgur.com/BD5Pp,YWDTi#1

Loktar
  • 34,764
  • 7
  • 90
  • 104
rosu alin
  • 5,674
  • 11
  • 69
  • 150
  • because while re-sizing image quality gets reduced and the size also get reduced. for uploading to server purpose we will reduce the weight-age at the mean time we are reducing the size also. first we need to look how to set the fixed size of image... then your image file wont get looks strange... – itsrajesh4uguys Nov 01 '12 at 13:53
  • so what could i do then so that it wont look so strange? – rosu alin Nov 01 '12 at 14:08
  • Looks like this may be a duplicate. http://stackoverflow.com/questions/12243185/resize-images-in-canvas?rq=1 – jeremy Nov 01 '12 at 14:55
  • 1
    It looks a bit like messed up bitmap configuration (as they call it, it's essentially a pixel format). What does `getConfig()` return called on original and scaled bitmap? – Code Painters Nov 01 '12 at 18:19
  • @ rosu alin just try to fix the size .. then resize . – itsrajesh4uguys Nov 02 '12 at 07:03
  • @CodePainters the scaled one returns: RGB_565 and the original returns: ARGB_8888. – rosu alin Nov 02 '12 at 08:17
  • @Rajesh, i can't really fix the file, because, the program chooses a file from the gallery. It's not the same file – rosu alin Nov 02 '12 at 08:19
  • yeah ... normally it wont be a same file . need to fix the out put bitmap size. i mean width and height – itsrajesh4uguys Nov 03 '12 at 06:44

1 Answers1

1

As OP stated answering my question, the bitmap is converted to RGB_565, which is a known bug in createBitmap() - #16211, fixed in Android 3.0. It affects createScaledBitmap() as well. The bitmap wouldn't look distorted if it remained ARGB_8888.

As a workaround you have to create target bitmap manually (which gives you full control of the pixel format), then create canvas attached to this bitmap and paint a scaled version of the original bitmap on it. Here's a sample from my project:

public class BitmapUtils {

    private static Matrix matrix = new Matrix();
    private static Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);

    public static final Bitmap resizeBitmap(Bitmap bitmap, float scale, Bitmap.Config targetConfig) {
            int srcWidth = bitmap.getWidth();
            int srcHeight = bitmap.getHeight();

            int newWidth = (int) (srcWidth * scale);
            int newHeight = (int) (srcHeight * scale);

            float sx = newWidth / (float) srcWidth;
            float sy = newHeight / (float) srcHeight;
            matrix.setScale(sx, sy);

            Bitmap target = Bitmap.createBitmap(newWidth, newHeight, targetConfig);
            Canvas c = new Canvas(target);
            c.drawBitmap(bitmap, matrix, paint);
            return target;
    }
}

Note: this code is not reentrant, due to global matrix instance. Also, it takes scale as parameter, but adapting it to your needs (new width/height as parameters) is trivial.

Code Painters
  • 7,175
  • 2
  • 31
  • 47