Android 图片处理

1. Bitmap 性能相关

使用 inSampleSize 来缩放

使用方式:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 设为 true 不会分配内存,用来获取图片宽高
BitmapFactory.decodeResource(getResources(), R.mipmap.test, options);
int width = options.outWidth;
int height = options.outHeight;
// 根据图片宽高和实际需要宽高计算 inSampleSize, 需要是 2 的次方,inSampleSize 是 2 则图片宽高压缩为原来的 1/2, inSampleSize 小于 1 则置为 1
// options.inSampleSize = ;
options.inJustDecodeBounds = false;
// 按照 inSampleSize 来解析 bitmap
Bitmap resource = BitmapFactory.decodeResource(getResources(), R.mipmap.test, options);
使用合适的 Config

在把资源解析为 Bitmap 过程中通过设置 options.inPreferredConfig, 或者在创建 Bitmap (Bitmap.createBitmap) 时指定 Config, Config 的值有以下几种:

ALPHA_8:无颜色,只有透明度
RGB_565:只有颜色,无透明度
ARGB_4444:一个像素占8个字节
ARGB_8888:一个像素占4个字节,相比 ARGB_4444, ARGB_8888 更推荐使用

根据自己需要选择使用

2. 大图加载

大图加载使用的是 BitmapRegionDecoder, 代码如下:

// 自定义大图加载 View
public class LongImageView extends View {

    private static BitmapFactory.Options options = new BitmapFactory.Options();
    private static BitmapRegionDecoder decoder;
    private Rect rect = new Rect();

    // View 宽高
    private int mHeight;
    private int mWidth;

    // 图片宽高
    private int mImgHeight;
    private int mImgWidth;

    static {
        options.inPreferredConfig = Bitmap.Config.RGB_565;
    }

    public LongImageView(Context context) {
        super(context);
    }

    public LongImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public LongImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private int lastX;
    private int lastY;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (lastX == 0) {
                    lastX = (int) event.getX();
                }
                if (lastY == 0) {
                    lastY = (int) event.getY();
                }
                break;
            case MotionEvent.ACTION_MOVE: // 这里只是简单地处理了手势,待优化
                int disY = (lastY - (int)event.getY());
                int disX = (lastX - (int)event.getX());
                if (mImgWidth > mWidth) {
                    rect.offset(disX, 0);
                    checkWidth();
                    invalidate();
                }
                if (mImgHeight > mHeight) {
                    rect.offset(0, disY);
                    checkHeight();
                    invalidate();
                }
                lastX = (int) event.getX();
                lastY = (int) event.getY();
                break;
            case MotionEvent.ACTION_UP:
                lastX = 0;
                lastY = 0;
                break;
        }
        return true;
    }

    private void checkHeight() {
        if (rect.top < 0) {
            rect.top = 0;
            rect.bottom = mHeight;
        }
        if (rect.bottom > mImgHeight) {
            rect.bottom = mImgHeight;
            rect.top = mImgHeight - mHeight;
        }
    }

    private void checkWidth() {
        if (rect.left < 0) {
            rect.left = 0;
            rect.right = mWidth;
        }
        if (rect.right > mImgWidth) {
            rect.right = mImgWidth;
            rect.left = mImgWidth - mWidth;
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
        rect.left = 0;
        rect.top = 0;
        rect.right = mWidth;
        rect.bottom = mHeight;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Bitmap bitmap = decoder.decodeRegion(rect, options);
        canvas.drawBitmap(bitmap, 0, 0, null);
    }

    public void setInputStream(InputStream is) {
        try {

            decoder = BitmapRegionDecoder.newInstance(is, true);
            // 直接使用了 decoder 获取宽高,就不能再用 BitmapFactory 来解析 is 获取图片宽高了
            mImgHeight = decoder.getHeight();
            mImgWidth = decoder.getWidth();

            requestLayout();
            invalidate();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

// 使用
LongImageView liv = (LongImageView) findViewById(R.id.liv);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.test);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
InputStream isBm = new ByteArrayInputStream(baos.toByteArray());
liv.setInputStream(isBm);

猜你喜欢

转载自blog.csdn.net/hexiaosa91/article/details/82632784