Android处理Bitmap的一些方法
http://www.it165.net/pro/html/201305/5795.html
# 文件与Bitmap间的方法
1. 从文件载入Bitmap
01./**02.* @brief 从文件载入Bitmap03.* @param path 图片路径04.* @param opts 选项05.* @return Bitmap06.*/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 从文件载入Bitmap21.* @param path 图片路径22.* @return Bitmap23.*/24.public Bitmap loadFromFile(String path) {25.return loadFromFile(path, null);26.}2. 载入取样的Bitmap
原宽度和高度的各1/sampleSize大小。
显示图片文件时一般都是取样图,否则很容易outofmemory。
01./**02.* @brief 从文件载入采样后的Bitmap03.* @see android.graphics.BitmapFactory.Options#inSampleSize04.*/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.net03.* @see android.graphics.BitmapFactory.Options#inJustDecodeBounds04.*/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 Bitmap04.* @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,自动回收原Bitmap03.* @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 缩放Bitmap10.* @param src 源Bitmap11.* @param dstWidth 目标宽度12.* @param dstHeight 目标高度13.* @param isRecycle 是否回收原图像14.* @return Bitmap15.*/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,自动回收原Bitmap03.* @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 裁剪Bitmap10.* @param src 源Bitmap11.* @param x 开始x坐标12.* @param y 开始y坐标13.* @param width 截取宽度14.* @param height 截取高度15.* @param isRecycle 是否回收原图像16.* @return Bitmap17.*/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,自动回收原Bitmap03.* @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 源Bitmap11.* @param degree 旋转角度12.* @param isRecycle 是否回收原图像13.* @return Bitmap14.*/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->Mat07.Mat mat_new = handler.proc(mat_bmp); // handle mat08.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->Bitmap11.src.recycle();12.return bmp_new;13.}3. 缩放
01./**02.* @brief 缩放Bitmap03.* @param src 源Bitmap04.* @param dstWidth 目标宽度05.* @param dstHeight 目标高度06.* @return Bitmap07.*/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.@Override14.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 裁剪Bitmap03.* @param src 源Bitmap04.* @param x 开始x坐标05.* @param y 开始y坐标06.* @param width 截取宽度07.* @param height 截取高度08.* @return Bitmap09.*/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.@Override23.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 源Bitmap04.* @param degree 旋转角度05.* @return Bitmap06.* @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.@Override14.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, offsetX32.+ 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(); // result38.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, offsetX44.+ newWidth);45.return mat_res_submat;46.}47.});48.}6. Bitmap效果器
001./**002.* @brief Bitmap效果器003.* @author join004.*/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 源Bitmap013.* @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->Mat018.this.mat = mat_bmp;019.this.config = config;020.this.isGray = false;021.}022./**023.* @brief 构造函数,config默认为RGB_565024.* @see #BitmapUtil(Bitmap, Config)025.*/026.public Effector(Bitmap bmp) {027.this(bmp, Bitmap.Config.RGB_565);028.}029./**030.* @brief 创建Bitmap031.* @return Bitmap032.*/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通道Mat038.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->Bitmap042.return bmp_new;043.}044./**045.* @brief 灰度化Bitmap046.*/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); // 转为灰度单通道Mat051.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_565095.* @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) 垃圾收集器回收内存时 ...
随机推荐
- Python中的高阶函数与匿名函数
Python中的高阶函数与匿名函数 高阶函数 高阶函数就是把函数当做参数传递的一种函数.其与C#中的委托有点相似,个人认为. def add(x,y,f): return f( x)+ f( y) p ...
- ASP.NET MVC 如何在一个同步方法(非async)方法中等待async方法
问题 首先,在ASP.NET MVC 环境下对async返回的Task执行Wait()会导致线程死锁.例: public ActionResult Asv2() { //dead lock var t ...
- 【Ubuntu】NAT配置
1.简介 2.配置 1.简介 NAT(Network Address Translation,网络地址转换)是将IP 数据包头中的IP 地址转换为另一个IP 地址的过程.在实际应用中,NAT 主要用于 ...
- ZOJ Monthly, July 2015
B http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5552 输入n,表示有n个数1到n.A先拿,B后拿,依次拿,每次可以拿任意一 ...
- 一个perfect 的解决 阴影拉伸的方法 shadow map strech
因为在场景中做了,有的物体产生阴影比如人物,有的物体不产生阴影比如地面,这样在地面凹下去的地方,悬崖,池塘边,就会有阴影的拉伸. 实际上, 没办法上传图片.... L是光源 A 点(人物身上)产生阴影 ...
- color mask
https://msdn.microsoft.com/zh-cn/library/windows/desktop/bb173595(v=vs.85).aspx void OMSetBlendState ...
- CSS3弹性盒模型,Flex布局教程
布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现. CSS3中引入flex的弹性盒模型 ...
- explicit构造函数的作用
explicit构造函数是用来防止隐式转换的.请看下面的代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ...
- Nagios 快速实现数据可视化的几种方式
Nagios 是一款强大的开源监控软件,但他本身不能绘图,只能查看当前数据,不能看历史数据以及趋势,也正因此,想要更舒适的使用就要搭配绘图软件,现在可搭配的绘图软件有很多,例如 pnp4nagios, ...
- 【六】PHP正则表达式方法
PHP中正则表达式的声明格式有两种方式,一种是POSIX老版模式,已经不常用.还有一种是其他语言中常见的PCRE方法. 1.正则表达式的匹配方法并返回匹配的项:array preg_grep(stri ...