用开源项目CropImage实现图片的裁剪(不推荐)
之前介绍过一个截图的办法(http://www.cnblogs.com/tianzhijiexian/p/3900241.html),这里再分享个开源项目。它也是截图,但是效果不是很好,首先还是对于小图片没有进行考虑,然后裁剪框也没有正对图片的大小做适配。虽然其代码比较简单,但我还是不推荐用这个做复杂的裁剪。然而里面有个“裁剪框不动,图片可缩放”的效果还是很实用的。因此,我还是来介绍一下。
首先还是导入项目,然后在项目中新建一个类,主要是用来继承Application。便于以后保存到sd卡中
package com.kale.cropimagetest; import android.app.Application; /**
* @author:Jack Tony
* @tips :在application标签下要有这个内部类的名字
* 如:android:name="com.kale.cropimagetest.DemoApp"
* <application
android:name="com.kale.cropimagetest.DemoApp"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
* @date :2014-8-9
*/
public class App extends Application
{
private static App instance; @Override
public void onCreate()
{
super.onCreate();
instance = this; } public static App getInstance()
{
return instance;
} }
写好后,在manifest中的application中写上这个类
android:name="com.kale.cropimagetest.App"
<application
android:allowBackup="true"
android:name="com.kale.cropimagetest.App"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
……
然后在建立一个类,用来保存截图。根据实际需要可以自行修改
package com.kale.cropimagetest; import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile; import android.graphics.Bitmap;
import android.os.Environment; /**
*
* 与文件相关的类,主要负责文件的读写
*
* @author 杨龙辉 2012.04.07
*
*/
/**
* @author:Jack Tony
* @tips : 需要有读取sd卡的权限
* @date :2014-8-9
*/
public final class FileUtil
{ // ------------------------------ 手机系统相关 ------------------------------
public static final String NEWLINE = System.getProperty("line.separator");// 系统的换行符
public static final String APPROOT = "UMMoka";// 程序的根目录
public static final String ASSERT_PATH="file:///android_asset";//apk的assert目录
public static final String RES_PATH="file:///android_res";//apk的assert目录 //----------------------------------存放文件的路径后缀------------------------------------
public static final String CACHE_IMAGE_SUFFIX=File.separator + APPROOT+ File.separator + "images" + File.separator;
public static final String CACHE_VOICE_SUFFIX=File.separator + APPROOT+ File.separator + "voice" + File.separator;
public static final String CACHE_MATERIAL_SUFFIX=File.separator + APPROOT + File.separator + "material" + File.separator;
public static final String LOG_SUFFIX=File.separator + APPROOT + File.separator + "Log" + File.separator; // ------------------------------------数据的缓存目录-------------------------------------------------------
public static String SDCARD_PAHT ;// SD卡路径
public static String LOCAL_PATH ;// 本地路径,即/data/data/目录下的程序私有目录
public static String CURRENT_PATH = "";// 当前的路径,如果有SD卡的时候当前路径为SD卡,如果没有的话则为程序的私有目录 static
{
init();
} public static void init()
{
SDCARD_PAHT = Environment.getExternalStorageDirectory().getPath();// SD卡路径
LOCAL_PATH = App.getInstance().getApplicationContext().getFilesDir().getAbsolutePath();// 本地路径,即/data/data/目录下的程序私有目录 if(android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
{
CURRENT_PATH = SDCARD_PAHT;
}
else
{
CURRENT_PATH = LOCAL_PATH;
}
} /**
* 得到与当前存储路径相反的路径(当前为/data/data目录,则返回/sdcard目录;当前为/sdcard,则返回/data/data目录)
* @return
*/
public static String getDiffPath()
{
if(CURRENT_PATH.equals(SDCARD_PAHT))
{
return LOCAL_PATH;
}
return SDCARD_PAHT;
} public static String getDiffPath(String pathIn)
{
return pathIn.replace(CURRENT_PATH, getDiffPath());
} // ------------------------------------文件的相关方法--------------------------------------------
/**
* 将数据写入一个文件
*
* @param destFilePath
* 要创建的文件的路径
* @param data
* 待写入的文件数据
* @param startPos
* 起始偏移量
* @param length
* 要写入的数据长度
* @return 成功写入文件返回true,失败返回false
*/
public static boolean writeFile(String destFilePath, byte[] data, int startPos, int length)
{
try
{
if (!createFile(destFilePath))
{
return false;
}
FileOutputStream fos = new FileOutputStream(destFilePath);
fos.write(data, startPos, length);
fos.flush();
if (null != fos)
{
fos.close();
fos = null;
}
return true; } catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return false;
} /**
* 从一个输入流里写文件
*
* @param destFilePath
* 要创建的文件的路径
* @param in
* 要读取的输入流
* @return 写入成功返回true,写入失败返回false
*/
public static boolean writeFile(String destFilePath, InputStream in)
{
try
{
if (!createFile(destFilePath))
{
return false;
}
FileOutputStream fos = new FileOutputStream(destFilePath);
int readCount = 0;
int len = 1024;
byte[] buffer = new byte[len];
while ((readCount = in.read(buffer)) != -1)
{
fos.write(buffer, 0, readCount);
}
fos.flush();
if (null != fos)
{
fos.close();
fos = null;
}
if (null != in)
{
in.close();
in = null;
}
return true;
} catch (IOException e)
{
e.printStackTrace();
} return false;
} public static boolean appendFile(String filename,byte[]data,int datapos,int datalength)
{
try { createFile(filename); RandomAccessFile rf= new RandomAccessFile(filename, "rw");
rf.seek(rf.length());
rf.write(data, datapos, datalength);
if(rf!=null)
{
rf.close();
} } catch (Exception e) {
e.printStackTrace();
} return true;
} /**
* 读取文件,返回以byte数组形式的数据
*
* @param filePath
* 要读取的文件路径名
* @return
*/
public static byte[] readFile(String filePath)
{
try
{
if (isFileExist(filePath))
{
FileInputStream fi = new FileInputStream(filePath);
return readInputStream(fi);
}
} catch (FileNotFoundException e)
{
e.printStackTrace();
}
return null;
} /**
* 从一个数量流里读取数据,返回以byte数组形式的数据。
* </br></br>
* 需要注意的是,如果这个方法用在从本地文件读取数据时,一般不会遇到问题,但如果是用于网络操作,就经常会遇到一些麻烦(available()方法的问题)。所以如果是网络流不应该使用这个方法。
* @param in
* 要读取的输入流
* @return
* @throws IOException
*/
public static byte[] readInputStream(InputStream in)
{
try
{
ByteArrayOutputStream os = new ByteArrayOutputStream(); byte[] b = new byte[in.available()];
int length = 0;
while ((length = in.read(b)) != -1)
{
os.write(b, 0, length);
} b = os.toByteArray(); in.close();
in = null; os.close();
os = null; return b; } catch (IOException e)
{
e.printStackTrace();
}
return null;
} /**
* 读取网络流
* @param in
* @return
*/
public static byte[] readNetWorkInputStream(InputStream in)
{
ByteArrayOutputStream os=null;
try
{
os = new ByteArrayOutputStream(); int readCount = 0;
int len = 1024;
byte[] buffer = new byte[len];
while ((readCount = in.read(buffer)) != -1)
{
os.write(buffer, 0, readCount);
} in.close();
in = null; return os.toByteArray(); } catch (IOException e)
{
e.printStackTrace();
}finally{
if(null!=os)
{
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
os = null;
}
}
return null;
} /**
* 将一个文件拷贝到另外一个地方
* @param sourceFile 源文件地址
* @param destFile 目的地址
* @param shouldOverlay 是否覆盖
* @return
*/
public static boolean copyFiles(String sourceFile, String destFile,boolean shouldOverlay)
{
try
{
if(shouldOverlay)
{
deleteFile(destFile);
}
FileInputStream fi = new FileInputStream(sourceFile);
writeFile(destFile, fi);
return true;
} catch (FileNotFoundException e)
{
e.printStackTrace();
}
return false;
} /**
* 判断文件是否存在
*
* @param filePath
* 路径名
* @return
*/
public static boolean isFileExist(String filePath)
{
File file = new File(filePath);
return file.exists();
} /**
* 创建一个文件,创建成功返回true
*
* @param filePath
* @return
*/
public static boolean createFile(String filePath)
{
try
{
File file = new File(filePath);
if (!file.exists())
{
if (!file.getParentFile().exists())
{
file.getParentFile().mkdirs();
} return file.createNewFile();
}
} catch (IOException e)
{
e.printStackTrace();
}
return true;
} /**
* 删除一个文件
*
* @param filePath
* 要删除的文件路径名
* @return true if this file was deleted, false otherwise
*/
public static boolean deleteFile(String filePath)
{
try {
File file = new File(filePath);
if (file.exists())
{
return file.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
} /**
* 删除 directoryPath目录下的所有文件,包括删除删除文件夹
* @param directoryPath
*/
public static void deleteDirectory(File dir)
{
if (dir.isDirectory())
{
File[] listFiles = dir.listFiles();
for (int i = 0; i < listFiles.length ; i++)
{
deleteDirectory(listFiles[i]);
}
}
dir.delete();
} /**
* 字符串转流
* @param str
* @return
*/
public static InputStream String2InputStream(String str)
{
ByteArrayInputStream stream = new ByteArrayInputStream(str.getBytes());
return stream;
} /**
* 流转字符串
* @param is
* @return
*/
public static String inputStream2String(InputStream is)
{
BufferedReader in = new BufferedReader(new InputStreamReader(is));
StringBuffer buffer = new StringBuffer();
String line = ""; try
{
while ((line = in.readLine()) != null)
{
buffer.append(line);
}
} catch (IOException e)
{
e.printStackTrace();
}
return buffer.toString();
} //批量更改文件后缀
public static void reNameSuffix(File dir,String oldSuffix,String newSuffix)
{
if (dir.isDirectory())
{
File[] listFiles = dir.listFiles();
for (int i = 0; i < listFiles.length ; i++)
{
reNameSuffix(listFiles[i],oldSuffix,newSuffix);
}
}
else
{
dir.renameTo(new File(dir.getPath().replace(oldSuffix, newSuffix)));
}
} public static void writeImage(Bitmap bitmap,String destPath,int quality)
{
try {
FileUtil.deleteFile(destPath);
if (FileUtil.createFile(destPath))
{
FileOutputStream out = new FileOutputStream(destPath);
if (bitmap.compress(Bitmap.CompressFormat.JPEG,quality, out))
{
out.flush();
out.close();
out = null;
}
}
} catch (IOException e) {
e.printStackTrace();
}
} }
这样准备工作就做好了。下面就是项目的使用了~
1.建立布局文件
注意:<com.open.crop.CropImageView ……/>,不同的效果要用不同的控件来实现。如:CropImageView ,CropImageView2,CropImageView3,CropImageView4
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <com.open.crop.CropImageView
android:id="@+id/cropImg"
android:layout_weight="1.0"
android:layout_width="match_parent"
android:layout_height="0dp"/> <Button
android:id="@+id/save"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="save"/>
</LinearLayout>
2.处理裁剪事务。
想用别的控件的话,这里用到的类的名字换一下就行,比如
final CropImageView mCropImage=(CropImageView)findViewById(R.id.cropImg);
final CropImageView2 mCropImage=(CropImageView2)findViewById(R.id.cropImg);
final CropImageView3 mCropImage=(CropImageView3)findViewById(R.id.cropImg);
final CropImageView4 mCropImage=(CropImageView4)findViewById(R.id.cropImg);
package com.kale.cropimagetest; import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener; import com.open.crop.CropImageView; public class CropImageTest01 extends Activity{ @Override
protected void onCreate(Bundle savedInstanceState) {
// TODO 自动生成的方法存根
super.onCreate(savedInstanceState);
setContentView(R.layout.test01);
final CropImageView mCropImage=(CropImageView)findViewById(R.id.cropImg);
//设置要裁剪的图片和默认的裁剪区域
mCropImage.setDrawable(getResources().getDrawable(R.drawable.right),300,300); findViewById(R.id.save).setOnClickListener(new OnClickListener() { /* (非 Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
* 开启一个新线程来保存图片
*/
@Override
public void onClick(View v) { new Thread(new Runnable(){ @Override
public void run() {
//得到裁剪好的图片
Bitmap bitmap = mCropImage.getCropImage(); FileUtil.writeImage(bitmap, FileUtil.SDCARD_PAHT+"/crop.png", 100); Intent mIntent=new Intent();
mIntent.putExtra("cropImagePath", FileUtil.SDCARD_PAHT+"/crop.png");
setResult(RESULT_OK, mIntent);
finish();
}
}).start();
}
});
}
}
最后在主Activity中接收图片的路径,载入显示截图即可。
package com.kale.cropimagetest; import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} public void buttonListener(View v) {
Intent intent = new Intent();
Class<?> cls = null;
switch (v.getId()) { case R.id.crop01_button:
cls = CropImageTest01.class;
break;
case R.id.crop02_button:
cls = CropImageTest02.class;
break;
case R.id.crop03_button:
cls = CropImageTest03.class;
break;
case R.id.crop04_button:
cls = CropImageTest04.class;
break;
default:
break;
}
intent.setClass(getApplicationContext(), cls);
startActivityForResult(intent, 100);
} @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
ImageView iv = (ImageView) findViewById(R.id.imageView); if (requestCode == 100 && resultCode == RESULT_OK) {
String path = data.getStringExtra("cropImagePath");
iv.setImageDrawable(BitmapDrawable.createFromPath(path));
} super.onActivityResult(requestCode, resultCode, data);
}
}
源码下载:http://download.csdn.net/detail/shark0017/7733207
用开源项目CropImage实现图片的裁剪(不推荐)的更多相关文章
- 用开源项目FlipImageView实现图片的翻转效果
开源项目地址:https://github.com/castorflex/FlipImageView 本实例我没做什么改动,就是添加了注释,方便大家阅读.和之前一样,导入library和工程 ...
- 用开源项目PhotoView实现图片的双指缩放和双击放大缩小
项目地址:https://github.com/chrisbanes/PhotoView 用开源项目有个好处,一是实现简单,二是bug少.那么我们就来说下这个项目能够实现的效果: 1.单个图片的双指缩 ...
- 讲解开源项目:用 Python 生成有“灵魂”的二维码
本文作者:HelloGitHub-LITTLECHIEH 这是 HelloGitHub 推出的<讲解开源项目>系列,今天给大家推荐一个 Python 开源生成二维码的项目--qrcode ...
- 用开源项目cropper实现对图片中任意部分进行裁剪
红色区域为截图控件的区域. 开源项目地址:https://github.com/edmodo/cropper croper这个开源项目可以对一个图片进行任意区域的街区,并且可以设置图片的旋转角 ...
- Android 图片加载[常见开源项目汇总]
该文主要是讲一下目前有哪些使用比较多的 图片加载开源项目,并简单介绍该如果使用 以及各开源项目之间有什么区别, 我们该如何去选择适合的开源项目应用到我们的项目中? 一.Android-Universa ...
- Android Studio导入GitHub上的项目常见问题(以图片轮播开源项目为实例)
前言:github对开发者而言无疑是个宝藏,但想利用它可不是件简单的事,用Android studio导入开源项目会遇到各种问题,今天我就以github上的一个图片轮播项目为例,解决导入过程中的常见问 ...
- Github上关于iOS的各种开源项目集合(强烈建议大家收藏,查看,总有一款你需要)
下拉刷新 EGOTableViewPullRefresh - 最早的下拉刷新控件. SVPullToRefresh - 下拉刷新控件. MJRefresh - 仅需一行代码就可以为UITableVie ...
- 2015-2016最火的Android开源项目--github开源项目集锦(不看你就out了)
标签: Android开发开源项目最火Android项目github 2015-2016最火的Android开源项目 本文整理与集结了近期github上使用最广泛最火热与最流行的开源项目,想要充电与提 ...
- swift开源项目精选
Swift 开源项目精选-v1.0 2016-03-07 22:11 542人阅读 评论(0) 收藏 举报 分类: iOS(55) Swift(4) 目录(?)[+] 转自 http: ...
随机推荐
- Springbatch Miscellanea Notes
1.scope="step",如下图,这是一种后绑定的方式,生成Step的时候,才去创建bean <bean id="testTasklet" paren ...
- linux网络管理基本命令
1.last 显示所有用户的登录情况 2.lastlog 显示那些用户有登录过,那些用户从来没登录过 3.traceroute 探测我指定网站的路径,来跟踪路由 .如:traceroute www ...
- 如何使用 Java 删除 ArrayList 中的重复元素
如何使用 Java 删除 ArrayList 中的重复元素 (How to Remove Duplicates from ArrayList in Java) Given an ArrayList w ...
- cos,sina,tan,cot
这些都是三角形的公式. 三角形总之就是一个直角两个锐角. cos就是余弦定理,就是锐角的邻边除以三角形的斜边. sin就是正弦定理,就是锐角的对边除以三角形的斜边. tan就是正切定理,就是锐角的对边 ...
- 004 @PathVariable映射URL绑定的占位符
一: 1.介绍 带占位符的URL是spring 3.0新增的功能,是向REST发展的重要阶段. @PathVariable可以将URL中占位符参数绑定到控制器处理的方法的入参中:URL中的{xxx}占 ...
- C#并行编程(6):线程同步面面观
理解线程同步 线程的数据访问 在并行(多线程)环境中,不可避免地会存在多个线程同时访问某个数据的情况.多个线程对共享数据的访问有下面3种情形: 多个线程同时读取数据: 单个线程更新数据,此时其他线程读 ...
- IO写 PrintWriter
private static final String FILENAME = "c:\\temp\\out.txt"; PrintWriter pw = null; try { p ...
- View 的滑动
View 的滑动 学习自 <Android开发艺术探索> 滑动漫谈 因为Android手机屏幕大小的原因,所以为了显式更多的信息,我们必须采用滚动的方式来处理,因为滚动就涉及到了滑动,有的 ...
- 【HDU5909】Tree Cutting(FWT)
[HDU5909]Tree Cutting(FWT) 题面 vjudge 题目大意: 给你一棵\(n\)个节点的树,每个节点都有一个小于\(m\)的权值 定义一棵子树的权值为所有节点的异或和,问权值为 ...
- notepad++ 如何选择10000行-20000行之间的文本?
最近要上传导入一批数据,但是数据太多,一次上传不了,所以就要分批上传,而且数据全部在一个txt里面,这时就想一次复制一部分出来导入,直到导入完成,但是问题来了,数据太多,选择1到10000行,鼠标要拉 ...