您的位置:首页 > 大数据 > 人工智能

缩略图Thumbnails

2015-12-13 15:06 513 查看
【Android】缩略图Thumbnails

在Android,多媒体文件(视频和图片)都是有缩略图的,在很多应用中,我们需要获取这些缩略图。比如最近在做一个类似相册的应用,需要扫描相册里面的图片,然后获取其缩略图,使用GridView去展示缩略图,当点击之后,我们需要获取其原始图,所以相关的需求如下:

1)获取缩略图(一个问题是:是否所有的图片以及视频都有缩略图?);

2)将缩略图和原始图关联起来;

关于1):

现在采用的方式是:

1 Options options=new Options();

2 options.inSampleSize=32;

3 Bitmap bitmap=BitmapFactory.decodeFile(url, options);

4 Drawable drawable=new BitmapDrawable(bitmap);

但是这种方法有问题:很难把握inSampleSize的大小(这里的32已经显得非常夸张了,但是从相册角度来说,图片数量是以百或者千为单位的,并且我遇到的问题是我的图片并不一样大小,我从网上下载了一些小图片到手机里面,原先的大图设置32没有问题,但是小图却明显太小了)。我很想知道Android系统是否能够聪明的帮我做到缩略到合适的尺寸(另一个原因是:跳过缩略图我就必须自己写一个函数遍历所有的文件夹寻找图片格式的文件,这大大降低了程序的性能)。下面研究直接提取缩略图。

提取图片和视频的缩略图可以直接访问:

1 android.provider.MediaStore.Images.Thumbnails

2 android.provider.MediaStore.Video.Thumbnails

这两个数据库,即可查询出来缩略图(这是contentprovider,具体的解释可见:【Android】ContentProvider)

之前我一直对Android在这方面的数据存储非常感兴趣,很想知道它是如何存储这些数据以及我可以从数据里面获得什么,今天将数据库导了出来,查看了一下存储,下面做出解释:

大家可以先查看一下/data/data/com.android.provider.media目录下面的databases:external-f042911.db 和 internal.db,如图:

选中后,点击右上角有个箭头向左的图案的图标即可将数据库导出到电脑文件夹中,然后下载一个SQLite数据库查看软件,我是在Mac下,下载的软件名叫MesaSQLite ,之后打开数据库,我们来查看一下:

首先是external-f042911.db数据库,这个数据库里面有很多表,如下:

这里很明显有两个thumbnails表,我查看的就是thumbnails表格,下面是表格内容:

总共11张缩略图,我们可以看到每张缩略图除了有一个_id之外,还有一个image_id(这个是关键?)。

然后要看的表格当然就是images,这个表格存储的是什么呢?截图如下,这个表表头很长,我截取两端:

这是第一张,可以看到什么??首先当然是同样的_id字段,这是和上面对应好的么??其次,我们可以找到图片的大小,类型,名称等属性,最重要的是其绝对物理路径!

这是第二张,是表格后面一段的属性,这张图上面最最重要的一个列就是”bucket_display_na
4000
me”,稍微对应一下我们就能发现这里面记录的是图片所在的文件夹(做相册的时候是很需要这个的!)

然后我再查看两个表:

第一个是albums表,这个表里面是什么呢?

这对我是个意外之喜,QIDUO是我创建的一个文件夹,我在里面存储了一些文件和一个amr录音文件,所以我就很好奇了,Android如何判定一个文件夹为album呢?

再看一个表:audio_meta,更是一个惊喜:

这个神奇的表格里面居然记录了我录制的amr音频,大家看到木有啊?有绝对路径,有尺寸,有时长!让人非常惊讶!

所以,到现在我有如下几个疑问:

1)是否所有的多媒体文件(我指的是视频和图片)都有缩略图?

2)缩略图和原始图是如何对应的?

3)album是如何定义的?

首先回答问题2):其实问题2)写一个程序即可验证,事实不是我们猜想的那样,两个_id字段是对应的,而是:

表thumbnails和images通过thumbnails.image_id与images._id关联的,通过images的_id,就可以找出来thumbnails表中的图片和images表中图片的映射关系了。原始图片的位置就是images表中的_data字段的值。

关于第1)个问题,我们貌似要了解一下,缩略图到底是如何实现的?这里有一个类:MediaScanner(详细要研究可见:http://blog.csdn.net/zqiang_55/article/details/7060171 )这个类是负责扫描所有的图片并将图片存储进入MediaStore(MediaScannerReceiver用来接收任务的,它收到广播后,会启动MediaService进行扫描工作。好复杂的样子。。。)我插一张图:

MediaScanner可以通过手动控制,在ANDROID系统中,已经定制了三种事件会触发MediaScanner去扫描磁盘文件:ACTION_BOOT_COMPLETED、ACTION_MEDIA_MOUNTED、 ACTION_MEDIA_SCANNER_SCAN_FILE。其中ACTION_BOOT_COMPLETED是系统启动完后发出这个消息,ACTION_MEDIA_MOUNTED是插卡事件触发的消息,ACTION_MEDIA_SCANNER_SCAN_FILE消息一般是在一些文件操作后,开发人员手动发出的一个重新扫描多媒体文件的消息。发送消息通过sendBroadcast函数完成,比如广播一个ACTION_MEDIA_MOUNTED消息:

1 sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse(“file://”+ Environment.getExternalStorageDirectory())));

由上可知是通过发送了一个广播(传递对应的扫描要求)来触发重新扫描磁盘事件,那么可以猜测系统肯定存在一个广播接收器(何时何地注册?),在收到这个广播消息后,通过对应参数启动MediaScannerService。MediaScannerService调用一个公用类MediaScanner去处理真正的工作。MediaScannerReceiver维持两种扫描目录:一种是内部卷(internal volume)指向(ANDROIDROOT)/media.另一种是外部卷(externalvolume)指向(EXTERNAL_STORAGE),扫描的位置可以修改(一般外部不用修改,默认为SDCARD,内部根据驱动命名的INAND路经名做对应的修改)。

所以对于问题1),如果你存储了图片但是没有启动磁盘扫描,就会造成缩略图不全。

关于第三点待续~

代码:

1)获取缩略图:

复制代码

1 cr = getContentResolver();

2 String[] projection = { Thumbnails._ID, Thumbnails.IMAGE_ID, Thumbnails.DATA };

3 Cursor cursor = cr.query(Thumbnails.EXTERNAL_CONTENT_URI, projection, null, null, null);

4 getColumnData(cursor);

5

6 private void getColumnData(Cursor cur) {

7 if (cur.moveToFirst()) {

8 int _id;

9 int image_id;

10 String image_path;

11 int _idColumn = cur.getColumnIndex(Thumbnails._ID);

12 int image_idColumn = cur.getColumnIndex(Thumbnails.IMAGE_ID);

13 int dataColumn = cur.getColumnIndex(Thumbnails.DATA);

14

15 do {

16 // Get the field values

17 _id = cur.getInt(_idColumn);

18 image_id = cur.getInt(image_idColumn);

19 image_path = cur.getString(dataColumn);

20

21 // Do something with the values.

22 Log.i(TAG, _id + ” image_id:” + image_id + ” path:”

23 + image_path + “—”);

24 HashMap
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: