http://www.it165.net/pro/html/201305/5795.html

# 文件与Bitmap间的方法

1. 从文件载入Bitmap

01./**
02.* @brief 从文件载入Bitmap
03.* @param path 图片路径
04.* @param opts 选项
05.* @return Bitmap
06.*/
07.public Bitmap loadFromFile(String path, Options opts) {
08.try {
09.File f = new File(path);
10.if (!f.exists() || f.isDirectory()) {
11.return null;
12.}
13.Bitmap bm = BitmapFactory.decodeFile(path, opts);
14.return bm;
15.catch (Exception e) {
16.return null;
17.}
18.}
19./**
20.* @brief 从文件载入Bitmap
21.* @param path 图片路径
22.* @return Bitmap
23.*/
24.public Bitmap loadFromFile(String path) {
25.return loadFromFile(path, null);
26.}

2. 载入取样的Bitmap

原宽度和高度的各1/sampleSize大小。

显示图片文件时一般都是取样图,否则很容易outofmemory。

01./**
02.* @brief 从文件载入采样后的Bitmap
03.* @see android.graphics.BitmapFactory.Options#inSampleSize
04.*/
05.public Bitmap loadSampleSize(String path, int sampleSize) {
06.Options opts = new Options();
07.opts.inSampleSize = sampleSize;
08.return loadFromFile(path, opts);
09.}

3. 载入Bitmap边框

其返回Bitmap为null,但Options.outxxx会被填充值。包括outHeight, outWidth, outMimeType。

只读取其高宽信息的话,就不需要读取全部Bitmap了。可结合上个方法,获取倍数缩小的样图。

01./**
02.* @brief 从文件载入只获边框的Bitmap www.it165.net
03.* @see android.graphics.BitmapFactory.Options#inJustDecodeBounds
04.*/
05.public Options loadJustDecodeBounds(String path) {
06.Options opts = new Options();
07.opts.inJustDecodeBounds = true;
08.loadFromFile(path, opts);
09.return opts;
10.}

4. 保存Bitmap至文件

01./**
02.* @brief 保存Bitmap至文件
03.* @param bm Bitmap
04.* @param path 图片路径
05.* @return 成功与否
06.*/
07.public boolean compressBitmap(Bitmap bm, String path) {
08.FileOutputStream out = null;
09.try {
10.out = new FileOutputStream(path);
11.bm.compress(Bitmap.CompressFormat.JPEG, 100, out);
12.out.flush();
13.catch (Exception e) {
14.return false;
15.} finally {
16.try {
17.if (out != null) {
18.out.close();
19.}
20.catch (IOException e) {
21.}
22.}
23.return true;
24.}

5. 读取图片方向信息

Bitmap图片的方法==!!!

01./**
02.* @brief 读取图片方向信息
03.* @param path 图片路径
04.* @return 角度
05.*/
06.public int readPhotoDegree(String path) {
07.int degree = 0;
08.try {
09.ExifInterface exifInterface = new ExifInterface(path);
10.int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
11.ExifInterface.ORIENTATION_NORMAL);
12.switch (orientation) {
13.case ExifInterface.ORIENTATION_ROTATE_90:
14.degree = 90;
15.break;
16.case ExifInterface.ORIENTATION_ROTATE_180:
17.degree = 180;
18.break;
19.case ExifInterface.ORIENTATION_ROTATE_270:
20.degree = 270;
21.break;
22.default:
23.degree = 0;
24.}
25.catch (IOException e) {
26.e.printStackTrace();
27.}
28.return degree;
29.}

# 处理Bitmap的方法

1. 生成缩略图

1.public Bitmap extractThumbnail(Bitmap src, int width, int height) {
2.return ThumbnailUtils.extractThumbnail(src, width, height,
3.ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
4.}

2. 缩放

01./**
02.* @brief 缩放Bitmap,自动回收原Bitmap
03.* @see ImageUtil#scaleBitmap(Bitmap, int, int, boolean)
04.*/
05.public Bitmap scaleBitmap(Bitmap src, int dstWidth, int dstHeight) {
06.return scaleBitmap(src, dstWidth, dstHeight, true);
07.}
08./**
09.* @brief 缩放Bitmap
10.* @param src 源Bitmap
11.* @param dstWidth 目标宽度
12.* @param dstHeight 目标高度
13.* @param isRecycle 是否回收原图像
14.* @return Bitmap
15.*/
16.public Bitmap scaleBitmap(Bitmap src, int dstWidth, int dstHeight, boolean isRecycle) {
17.if (src.getWidth() == dstWidth && src.getHeight() == dstHeight) {
18.return src;
19.}
20.Bitmap dst = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, false);
21.if (isRecycle && dst != src) {
22.src.recycle();
23.}
24.return dst;
25.}

3. 裁剪

01./**
02.* @brief 裁剪Bitmap,自动回收原Bitmap
03.* @see ImageUtil#cropBitmap(Bitmap, int, int, int, int, boolean)
04.*/
05.public Bitmap cropBitmap(Bitmap src, int x, int y, int width, int height) {
06.return cropBitmap(src, x, y, width, height, true);
07.}
08./**
09.* @brief 裁剪Bitmap
10.* @param src 源Bitmap
11.* @param x 开始x坐标
12.* @param y 开始y坐标
13.* @param width 截取宽度
14.* @param height 截取高度
15.* @param isRecycle 是否回收原图像
16.* @return Bitmap
17.*/
18.public Bitmap cropBitmap(Bitmap src, int x, int y, int width, int height, boolean isRecycle) {
19.if (x == 0 && y == 0 && width == src.getWidth() && height == src.getHeight()) {
20.return src;
21.}
22.Bitmap dst = Bitmap.createBitmap(src, x, y, width, height);
23.if (isRecycle && dst != src) {
24.src.recycle();
25.}
26.return dst;
27.}

4. 旋转

01./**
02.* @brief 旋转Bitmap,自动回收原Bitmap
03.* @see ImageUtil#rotateBitmap(Bitmap, int, boolean)
04.*/
05.public Bitmap rotateBitmap(Bitmap src, int degree) {
06.return rotateBitmap(src, degree, true);
07.}
08./**
09.* @brief 旋转Bitmap,顺时针
10.* @param src 源Bitmap
11.* @param degree 旋转角度
12.* @param isRecycle 是否回收原图像
13.* @return Bitmap
14.*/
15.public Bitmap rotateBitmap(Bitmap src, int degree, boolean isRecycle) {
16.if (degree % 360 == 0) {
17.return src;
18.}
19.int w = src.getWidth();
20.int h = src.getHeight();
21.Matrix matrix = new Matrix();
22.matrix.postRotate(degree);
23.Bitmap dst = Bitmap.createBitmap(src, 0, 0, w, h, matrix, true);
24.if (isRecycle && dst != src) {
25.src.recycle();
26.}
27.return dst;
28.}

# OpenCV处理Bitmap的方法

除了导入OpenCV的jar包,我们只需要libopencv_java.so,就可以下做进行操作了。

1. 常规性的init

1.static {
2.if (!OpenCVLoader.initDebug()) {
3.Log.e(TAG, "OpenCVLoader initDebug failed.");
4.}
5.}

2. 常规性处理流程

bmp -> mat -> 接口处理 -> mat_new -> bmp_new。

01.private interface IHandler {
02.Mat proc(Mat mat_bmp);
03.}
04.private Bitmap handle(Bitmap src, IHandler handler) {
05.Mat mat_bmp = new Mat(src.getHeight(), src.getWidth(), CvType.CV_8UC4);
06.Utils.bitmapToMat(src, mat_bmp, false); // Bitmap->Mat
07.Mat mat_new = handler.proc(mat_bmp); // handle mat
08.Bitmap bmp_new = Bitmap.createBitmap(mat_new.cols(), mat_new.rows(),
09.Bitmap.Config.ARGB_8888);
10.Utils.matToBitmap(mat_new, bmp_new, false); // Mat->Bitmap
11.src.recycle();
12.return bmp_new;
13.}

3. 缩放

01./**
02.* @brief 缩放Bitmap
03.* @param src 源Bitmap
04.* @param dstWidth 目标宽度
05.* @param dstHeight 目标高度
06.* @return Bitmap
07.*/
08.public Bitmap scaleBitmap2(Bitmap src, final int dstWidth, final int dstHeight) {
09.if (src.getWidth() == dstWidth && src.getHeight() == dstHeight) {
10.return src;
11.}
12.return handle(src, new IHandler() {
13.@Override
14.public Mat proc(Mat mat_bmp) {
15.Mat mat_new = new Mat();
16.Imgproc.resize(mat_bmp, mat_new, new Size(dstWidth, dstHeight));
17.return mat_new;
18.}
19.});
20.}

4. 裁剪

01./**
02.* @brief 裁剪Bitmap
03.* @param src 源Bitmap
04.* @param x 开始x坐标
05.* @param y 开始y坐标
06.* @param width 截取宽度
07.* @param height 截取高度
08.* @return Bitmap
09.*/
10.public Bitmap cropBitmap2(Bitmap src, final int x, final int y, final int width,
11.final int height) {
12.if (x == 0 && y == 0 && width == src.getWidth() && height == src.getHeight()) {
13.return src;
14.}
15.if (x + width > src.getWidth()) {
16.throw new IllegalArgumentException("x + width must be <= bitmap.width()");
17.}
18.if (y + height > src.getHeight()) {
19.throw new IllegalArgumentException("y + height must be <= bitmap.height()");
20.}
21.return handle(src, new IHandler() {
22.@Override
23.public Mat proc(Mat mat_bmp) {
24.Rect roi = new Rect(x, y, width, height);
25.Mat mat_new = new Mat(mat_bmp, roi);
26.return mat_new;
27.}
28.});
29.}

5. 旋转

01./**
02.* @brief 旋转Bitmap,逆时针
03.* @param src 源Bitmap
04.* @param degree 旋转角度
05.* @return Bitmap
07.*/
08.public Bitmap rotateBitmap2(Bitmap src, final int degree) {
09.if (degree % 360 == 0) {
10.return src;
11.}
12.return handle(src, new IHandler() {
13.@Override
14.public Mat proc(Mat mat_bmp) {
15.// 计算旋转后图像的宽高
16.double radians = Math.toRadians(degree);
17.double sin = Math.abs(Math.sin(radians));
18.double cos = Math.abs(Math.cos(radians));
19.int width = mat_bmp.width();
20.int height = mat_bmp.height();
21.int newWidth = (int) (width * cos + height * sin);
22.int newHeight = (int) (width * sin + height * cos);
23.// 能把原图像和旋转后图像同时放入的外框
24.int frameWidth = Math.max(width, newWidth);
25.int frameHeight = Math.max(height, newHeight);
26.Size frameSize = new Size(frameWidth, frameHeight);
27.Mat mat_frame = new Mat(frameSize, mat_bmp.type());
28.// 将原图像copy进外框
29.int offsetX = (frameWidth - width) / 2;
30.int offsetY = (frameHeight - height) / 2;
31.Mat mat_frame_submat = mat_frame.submat(offsetY, offsetY + height, offsetX, offsetX
32.+ width);
33.mat_bmp.copyTo(mat_frame_submat);
34.// 旋转外框
35.Point center = new Point(frameWidth / 2, frameHeight / 2);
36.Mat mat_rot = Imgproc.getRotationMatrix2D(center, degree, 1.0);
37.Mat mat_res = new Mat(); // result
38.Imgproc.warpAffine(mat_frame, mat_res, mat_rot, frameSize, Imgproc.INTER_LINEAR,
39.Imgproc.BORDER_CONSTANT, Scalar.all(0));
40.// 从旋转后的外框获取新图像
41.offsetX = (frameWidth - newWidth) / 2;
42.offsetY = (frameHeight - newHeight) / 2;
43.Mat mat_res_submat = mat_res.submat(offsetY, offsetY + newHeight, offsetX, offsetX
44.+ newWidth);
45.return mat_res_submat;
46.}
47.});
48.}

6. Bitmap效果器

001./**
002.* @brief Bitmap效果器
003.* @author join
004.*/
005.public static class Effector {
006.private Config config;
007.private Mat mat;
008.private boolean isGray;
009.private Mat mSepiaKernel;
010./**
011.* @brief 构造函数
012.* @param bmp 源Bitmap
013.* @param config 'ARGB_8888' or 'RGB_565'
014.*/
015.public Effector(Bitmap bmp, Config config) {
016.Mat mat_bmp = new Mat(bmp.getHeight(), bmp.getWidth(), CvType.CV_8UC4);
017.Utils.bitmapToMat(bmp, mat_bmp, false); // Bitmap->Mat
018.this.mat = mat_bmp;
019.this.config = config;
020.this.isGray = false;
021.}
022./**
023.* @brief 构造函数,config默认为RGB_565
024.* @see #BitmapUtil(Bitmap, Config)
025.*/
026.public Effector(Bitmap bmp) {
027.this(bmp, Bitmap.Config.RGB_565);
028.}
029./**
030.* @brief 创建Bitmap
031.* @return Bitmap
032.*/
033.public Bitmap create() {
034.Mat mat_new = this.mat;
035.if (isGray) {
036.Mat mat_gray = new Mat(mat_new.rows(), mat_new.cols(), CvType.CV_8UC4);
037.Imgproc.cvtColor(mat_new, mat_gray, Imgproc.COLOR_GRAY2BGRA, 4); // 转为灰度4通道Mat
038.mat_new = mat_gray;
039.}
040.Bitmap bmp_new = Bitmap.createBitmap(mat_new.cols(), mat_new.rows(), this.config);
041.Utils.matToBitmap(mat_new, bmp_new, false); // Mat->Bitmap
042.return bmp_new;
043.}
044./**
045.* @brief 灰度化Bitmap
046.*/
047.public Effector gray() {
048.Mat mat_bmp = this.mat;
049.Mat mat_gray = new Mat();
050.Imgproc.cvtColor(mat_bmp, mat_gray, Imgproc.COLOR_BGRA2GRAY, 1); // 转为灰度单通道Mat
051.this.mat = mat_gray;
052.this.isGray = true;
053.return this;
054.}
055./**
056.* @brief Bitmap二值化
057.* @pre 需先灰度化{@link #gray()}
058.* @param thresh 阈值。type为THRESH_OTSU时无用,其自适应区域阈值。
059.* @param maxval 最大值。type为THRESH_BINARY或THRESH_BINARY_INV时才使用。
060.* @param type 运算类型
061.* @see Imgproc#threshold(Mat, Mat, double, double, int)
062.* @see THRESH_OTSU: {@link Imgproc#adaptiveThreshold(Mat, Mat, double, int, int, int, double)}
063.*/
064.public Effector threshold(double thresh, double maxval, int type) {
065.if (!isGray) {
066.// throw new IllegalArgumentException("must call gray() before this.");
067.gray();
068.}
069.Mat mat_gray = this.mat;
070.Imgproc.threshold(mat_gray, mat_gray, thresh, maxval, type);
071.return this;
072.}
073./**
074.* @brief Bitmap二值化
075.* @details thresh: 127; maxval: 255; type: THRESH_OTSU;
076.* @see #threshold(double, double, int)
077.*/
078.public Effector threshold() {
079.return threshold(127, 255, Imgproc.THRESH_OTSU);
080.}
081./**
082.* @brief Canny算子边缘检测
083.* @param threshold1 控制边缘连接的下限阈值
084.* @param threshold2 控制强边缘的初始分割的上阈限值
085.*  如果一个像素的梯度大于上阈限值,则被认为是边缘像素,如果小于下限阈值,则被抛弃。
086.*  如果该点的梯度在两者之间则当这个点与高于上阈限值的像素点连接时我们才保留,否则抛弃。
087.*/
088.public Effector canny(final double threshold1, final double threshold2) {
089.Mat mat = this.mat;
090.Imgproc.Canny(mat, mat, threshold1, threshold2, 3, false); // Canny边缘检测
091.return this;
092.}
093./**
094.* @brief Canny边缘检测,返回为RGB_565
095.* @details threshold1: 80; threshold2: 90;
096.* @see #canny(Bitmap, Config)
097.*/
098.public Effector canny() {
099.return canny(80, 90);
100.}
101./**
102.* @brief Sobel处理
103.*/
104.public Effector sobel() {
105.Mat mat = this.mat;
106.Imgproc.Sobel(mat, mat, CvType.CV_8U, 1, 1); // 一阶差分
107.Core.convertScaleAbs(mat, mat, 10, 0); // 线性变换
108.return this;
109.}
110./**
111.* @brief 棕褐色
112.*/
113.public Effector sepia() {
114.Mat mat = this.mat;
115.Core.transform(mat, mat, getSepiaKernel());
116.return this;
117.}
118.private Mat getSepiaKernel() {
119.if (mSepiaKernel != null) {
120.return mSepiaKernel;
121.}
122.mSepiaKernel = new Mat(4, 4, CvType.CV_32F);
123.mSepiaKernel.put(0, 0, /* R */0.189f, 0.769f, 0.393f, 0f);
124.mSepiaKernel.put(1, 0, /* G */0.168f, 0.686f, 0.349f, 0f);
125.mSepiaKernel.put(2, 0, /* B */0.131f, 0.534f, 0.272f, 0f);
126.mSepiaKernel.put(3, 0, /* A */0.000f, 0.000f, 0.000f, 1f);
127.return mSepiaKernel;
128.}
129.}

# Over

常用的一些方法就这样了^^。

Android处理Bitmap的一些方法的更多相关文章

  1. android中Bitmap的放大和缩小的方法

    android中Bitmap的放大和缩小的方法 时间 2013-06-20 19:02:34  CSDN博客原文  http://blog.csdn.net/ada168855/article/det ...

  2. android网络请求库volley方法详解

    使用volley进行网络请求:需先将volley包导入androidstudio中 File下的Project Structrue,点加号导包 volley网络请求步骤: 1. 创建请求队列     ...

  3. Android笔记——Bitmap自动取色(纯搬运)

    2015/6/12更新:发现一个更好的,带demo https://github.com/MichaelEvans/ColorArt 说明: 这个是一个老外写的自动自动从bitmap中取主色与第二主色 ...

  4. android 管理Bitmap内存 - 开发文档翻译

    由于本人英文能力实在有限,不足之初敬请谅解 本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接   Managing Bitmap Memory 管理Bitmap内存 In additi ...

  5. Android中 Bitmap Drawable Paint的获取、转换以及使用

    比如Drawable中有一系列连续的图片,img_0.png, img_1.png, img_2.png ... 如果要动态获取这些图片,通过"R.drawable.img_x"的 ...

  6. Android艺术——Bitmap高效加载和缓存代码分析(2)

    Bitmap的加载与缓存代码分析: 图片的压缩 比如有一张1024*768像素的图像要被载入内存,然而最终你要用到的图片大小其实只有128*96,那么我们会浪费很大一部分内存,这显然是没有必要的,下面 ...

  7. Android图片高斯模糊的一些方法

    高斯模糊 高斯模糊就是将指定像素变换为其与周边像素加权平均后的值,权重就是高斯分布函数计算出来的值. 一种实现 点击打开链接<-这里是一片关于高斯模糊算法的介绍,我们需要首先根据高斯分布函数计算 ...

  8. Android的bitmap和优化

    内存管理是个永恒的话题! 内存溢出:就是分配的内存不足以放下数据项序列.如在一个域中输入的数据超过了它的要求就会引发数据溢出问题,多余的数据就可以作为指令在计算机上运行.就是你要求分配的内存超出了系统 ...

  9. Android笔记--Bitmap(三) 针对不用Android版本的位图管理

    Bitmap(三) | Android不同版本的相应操作 在不同的Android版本中.位图的存储方式是不同的. 1.小于等于 Android 2.2 (API level 8) 垃圾收集器回收内存时 ...

随机推荐

  1. django构建blog--建立数据库部分+admin部分(eclipse+pydev)

    本文介绍的是在eclipse+pydev 平台下,利用django 搭建blog的第1部分:建立数据库+admin部分 步骤一:创建myweb项目+blog应用 1. Eclipse下新建一个djan ...

  2. Json Serialize 忽略特定属性

    Json Serialize 忽略特定属性 Json Serialize SerializeFilter 忽略特定属性 key words:Json Serialize jackson fastjso ...

  3. 事务并发处理: DB+ORM+逻辑代码

    在学习了马士兵有关事务并发处理的视频后, 感觉对事务并发处理的概念,问题以及解决方式有了一定的了解,赶紧记录下来以备后用. 1. 事务:一系列操作要么都完成,要么一个都不完成 2. 事务并发:多个事务 ...

  4. Hibernate SQL方言 (hibernate.dialect)

    数据库 hibernate方言 DB2 org.hibernate.dialect.DB2Dialect DB2 AS/400 org.hibernate.dialect.DB2400Dialect ...

  5. 您可能不知道的ASP.Net小技巧

    <!-- 页码和简介 --> 1.  在提交页面之后,保持滚动条的位置 可以在page指令上加上MaintainScrollPositionOnPostback指令 <%@ Page ...

  6. String、StringBuilder

    public class testString{ public static void main(String[] args) { String a="cool"; String ...

  7. 解决iptables和vsftpd设置的问题

    解决iptables和vsftpd设置的问题 博客分类: linux/centos/ubuntu 防火墙J#工作 解决iptables和vsftpd设置的问题 修改 vi /etc/sysconfig ...

  8. HDU 2048 神、上帝以及老天爷(递归,错排,dp,概率)

    中文题,错排,求概率,不解释,核心思路同 HDU 1465 错排简单思路可看:http://www.cnblogs.com/laiba2004/p/3235934.html //错排,但是我之前叫了几 ...

  9. POJ 2027

    #include<iostream> using namespace std; int main() { int time; cin>>time; int a; int b; ...

  10. javascript 图片延迟加载

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...