用開源項目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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM