我要实现一个从相册读取图片到bitmap的功能,其中一步需要把inputstream解析成bitmap,用到decodeStream.
decodeStream一次是没有问题的。
但是我不想直接解析,那样图片有可能太大了,我想先解析一下大小,然后在把bitmap解析出来,这是一个常规的思路,那么就需要decodeStream两次。
那么问题来了:
第二次解析的时候返回null。
为什么呢?因为inputstream再第一次的时候读完了,到达尾部了,再次使用当然就没有数据了。
怎么办?
可以回头再读一遍流,利用mark和reset。
mark是在需要重读的地方记录一下,reset是回到mark的这个地方,当然我这里就是在开头mark一下,第一次decode之后reset一下。
但是。。。
/**
* Sets a mark position in this InputStream. The parameter {@code readlimit}
* indicates how many bytes can be read before the mark is invalidated.
* Sending {@code reset()} will reposition the stream back to the marked
* position provided {@code readLimit} has not been surpassed.
* <p>
* This default implementation does nothing and concrete subclasses must
* provide their own implementation.
*
* @param readlimit
* the number of bytes that can be read from this stream before
* the mark is invalidated.
* @see #markSupported()
* @see #reset()
*/
public void mark(int readlimit) {
/* empty */
}
mark需要带一个参数readlimit,就是说如果从mark的地方你读取的时候超过了这个limit,mark就失效了,我去!!!这尼玛
猜测应该是mark之后,系统会再开一个buffer来记录。
先不管开销,但是问题是我去哪儿知道这个inputsteam多大呢?这可尼玛是图片呀!
这个问题暂时没解决,现在先用另一个方法把图片解出来,就是先把流转成字节数组,然后再解析,这总不可能把数据丢了吧
public static byte[] readStream(InputStream inStream) throws Exception {
byte[] buffer = new byte[1024];
int len = -1;
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
while ((len = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
byte[] data = outStream.toByteArray();
outStream.close();
inStream.close();
return data;
}
public static Bitmap decodeBitmapFromBytes(byte[] ib, int reqWidth,
int reqHeight) {
// 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(ib, 0, ib.length, options);
// 调用上面定义的方法计算inSampleSize值
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// 使用获取到的inSampleSize值再次解析图片
options.inJustDecodeBounds = false;
Bitmap bm = BitmapFactory.decodeByteArray(ib, 0, ib.length, options);
return bm;
}