为什么调整大小会让我的图像看起来很奇怪?

时间:2012-11-01 13:39:25

标签: android graphics bitmap android-canvas rescale

我有一个相对布局,我在其上添加一个视图。这是活动中的代码:

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);

这是我的观点:

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);
}
}

如您所见,我在活动中有一个调整大小功能:

  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;

}

现在,如果我从代码中评论此功能,图像看起来正常,但没有缩放。如果我把它留在那里,那么我会得到一个丑陋的图像,但它会被调整大小。例: 普通未调整大小:http://imgur.com/BD5Pp,YWDTi 已更改但已调整大小的图片:http://imgur.com/BD5Pp,YWDTi#1

1 个答案:

答案 0 :(得分:1)

正如OP所述回答我的问题,位图转换为RGB_565,这是createBitmap() - #16211中的一个已知错误,已在Android 3.0中修复。它也会影响createScaledBitmap()。如果位图保持ARGB_8888,则位图看起来不会失真。

作为一种解决方法,您必须手动创建目标位图(这使您可以完全控制像素格式),然后创建附加到此位图的画布并在其上绘制原始位图的缩放版本。这是我项目的样本:

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;
    }
}

注意:由于全局matrix实例,此代码不可重入。此外,它需要将比例作为参数,但根据您的需要进行调整(新的宽度/高度作为参数)是微不足道的。