Android处理Bitmap的一些方法
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
06.
* @see <a href="http://stackoverflow.com/questions/12852578/image-rotation-with-opencv-in-android-cuts-off-the-edges-of-an-image">More</a>
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的一些方法的更多相关文章
- android中Bitmap的放大和缩小的方法
android中Bitmap的放大和缩小的方法 时间 2013-06-20 19:02:34 CSDN博客原文 http://blog.csdn.net/ada168855/article/det ...
- android网络请求库volley方法详解
使用volley进行网络请求:需先将volley包导入androidstudio中 File下的Project Structrue,点加号导包 volley网络请求步骤: 1. 创建请求队列 ...
- Android笔记——Bitmap自动取色(纯搬运)
2015/6/12更新:发现一个更好的,带demo https://github.com/MichaelEvans/ColorArt 说明: 这个是一个老外写的自动自动从bitmap中取主色与第二主色 ...
- android 管理Bitmap内存 - 开发文档翻译
由于本人英文能力实在有限,不足之初敬请谅解 本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接 Managing Bitmap Memory 管理Bitmap内存 In additi ...
- Android中 Bitmap Drawable Paint的获取、转换以及使用
比如Drawable中有一系列连续的图片,img_0.png, img_1.png, img_2.png ... 如果要动态获取这些图片,通过"R.drawable.img_x"的 ...
- Android艺术——Bitmap高效加载和缓存代码分析(2)
Bitmap的加载与缓存代码分析: 图片的压缩 比如有一张1024*768像素的图像要被载入内存,然而最终你要用到的图片大小其实只有128*96,那么我们会浪费很大一部分内存,这显然是没有必要的,下面 ...
- Android图片高斯模糊的一些方法
高斯模糊 高斯模糊就是将指定像素变换为其与周边像素加权平均后的值,权重就是高斯分布函数计算出来的值. 一种实现 点击打开链接<-这里是一片关于高斯模糊算法的介绍,我们需要首先根据高斯分布函数计算 ...
- Android的bitmap和优化
内存管理是个永恒的话题! 内存溢出:就是分配的内存不足以放下数据项序列.如在一个域中输入的数据超过了它的要求就会引发数据溢出问题,多余的数据就可以作为指令在计算机上运行.就是你要求分配的内存超出了系统 ...
- Android笔记--Bitmap(三) 针对不用Android版本的位图管理
Bitmap(三) | Android不同版本的相应操作 在不同的Android版本中.位图的存储方式是不同的. 1.小于等于 Android 2.2 (API level 8) 垃圾收集器回收内存时 ...
随机推荐
- django构建blog--建立数据库部分+admin部分(eclipse+pydev)
本文介绍的是在eclipse+pydev 平台下,利用django 搭建blog的第1部分:建立数据库+admin部分 步骤一:创建myweb项目+blog应用 1. Eclipse下新建一个djan ...
- Json Serialize 忽略特定属性
Json Serialize 忽略特定属性 Json Serialize SerializeFilter 忽略特定属性 key words:Json Serialize jackson fastjso ...
- 事务并发处理: DB+ORM+逻辑代码
在学习了马士兵有关事务并发处理的视频后, 感觉对事务并发处理的概念,问题以及解决方式有了一定的了解,赶紧记录下来以备后用. 1. 事务:一系列操作要么都完成,要么一个都不完成 2. 事务并发:多个事务 ...
- Hibernate SQL方言 (hibernate.dialect)
数据库 hibernate方言 DB2 org.hibernate.dialect.DB2Dialect DB2 AS/400 org.hibernate.dialect.DB2400Dialect ...
- 您可能不知道的ASP.Net小技巧
<!-- 页码和简介 --> 1. 在提交页面之后,保持滚动条的位置 可以在page指令上加上MaintainScrollPositionOnPostback指令 <%@ Page ...
- String、StringBuilder
public class testString{ public static void main(String[] args) { String a="cool"; String ...
- 解决iptables和vsftpd设置的问题
解决iptables和vsftpd设置的问题 博客分类: linux/centos/ubuntu 防火墙J#工作 解决iptables和vsftpd设置的问题 修改 vi /etc/sysconfig ...
- HDU 2048 神、上帝以及老天爷(递归,错排,dp,概率)
中文题,错排,求概率,不解释,核心思路同 HDU 1465 错排简单思路可看:http://www.cnblogs.com/laiba2004/p/3235934.html //错排,但是我之前叫了几 ...
- POJ 2027
#include<iostream> using namespace std; int main() { int time; cin>>time; int a; int b; ...
- javascript 图片延迟加载
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...