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) 垃圾收集器回收内存时 ... 
随机推荐
- 转载:centos上yum安装apache+php+mysql等
			1. 更新系统内核到最新. [root@linuxfei ~]#yum -y update 系统更新后,如果yum安装时提示错误信息,请执行以下命令修复. [root@linuxfei ~]#rpm ... 
- WinForm Control - DataGridView
			http://blog.csdn.net/fangxing80/article/details/1561011 .NET 2.0 - WinForm Control - DataGridView 编程 ... 
- selenium--上传图片
			html 源码: 上传图片 <input type="file" name="PicFile" style="width: 180px;&quo ... 
- 读《我是一只IT小小鸟》有感
			时间太瘦,指缝太宽.一晃一学期过去了,有些迷茫,但也相信未来是美好的.当我看完<我是一只IT小小鸟>这本书之后,心中更是感慨万千.每一个励志的故事都值得欣赏.深思,甚至我还幻想 ... 
- IT小小鸟读后感
			我是一只小小鸟(读后感) 当我成为闽江学院的一名学子时,我选择了我自己的专业(软件工程).成为大一新生的我对着未来充满着希望憧憬.但现实并不是美好的我得替今后的我想想以后大学毕业了到底我到了社会上要用 ... 
- JAVA 显示图片的简单源码                                                    分类:            Java Game             2014-08-14 10:10    77人阅读    评论(0)    收藏
			此代码的原理就是用JLabel来加载图片,再将JLabel放入JFrame中, package com.mywork; import javax.swing.ImageIcon; import jav ... 
- poi生成excel
			转自:http://www.cnblogs.com/bmbm/archive/2011/12/08/2342261.html 1.首先下载poi-3.6-20091214.jar,下载地址如下: ht ... 
- Feature Engineering versus Feature Extraction: Game On!
			Feature Engineering versus Feature Extraction: Game On! "Feature engineering" is a fancy t ... 
- Map:比较新增加日期的和需要删除的日期 使用方法
			1.场景描述:根据在日历选择的日期,数据库来保持我们选择日期. 2.方法,硬删除的方法,每次全部删除,然后再重新添加选择的新的日期.这样导致如果需要保存create_time的情况,那么每次操作的都是 ... 
- oom日志查看
			这通常会触发 Linux 内核里的 Out of Memory (OOM) killer,OOM killer 会杀掉某个进程以腾出内存留给系统用,不致于让系统立刻崩溃.如果检查相关的日志文件(/va ... 
