实现图像的编辑和合成

01.package demo.camera; 
02.import java.io.FileNotFoundException; 
03.import android.app.Activity; 
04.import android.content.Intent; 
05.import android.graphics.Bitmap; 
06.import android.graphics.BitmapFactory; 
07.import android.graphics.Canvas; 
08.import android.graphics.ColorMatrix; 
09.import android.graphics.ColorMatrixColorFilter; 
10.import android.graphics.Matrix; 
11.import android.graphics.Paint; 
12.import android.graphics.PorterDuff; 
13.import android.graphics.PorterDuffXfermode; 
14.import android.net.Uri; 
15.import android.os.Bundle; 
16.import android.provider.MediaStore; 
17.import android.util.Log; 
18.import android.view.Menu; 
19.import android.view.MenuItem; 
20.import android.view.View; 
21.import android.widget.Button; 
22.import android.widget.ImageView; 
23./**
24. * 在Android中我们可以对图像进行编辑处理等操作
25. * 包括放大缩小,旋转,偏移,裁剪,以及更改亮度,饱和度等
26. * 
27. * 1、首先,从SDCard中选择图片,采用Android自带的Callery应用获得
28. * Gallery是Android自带的图片和视频管理应用
29. * 使用Intent来启动Gallery应用,需要指定两个参数,一个是Action,另一个是多媒体存放的URI
30. * Action是一个通用的Action叫ACTION_PICK,来告诉Gallery,我们想检索数据。
31. * 第二个是Data,是一个URI,这里当然是MediaStore.Images.Media.EXTERNAL_CONTENT_URI
32. * 当在Gallery中选择了一个图片的时候,返回的Intent中的Data域就是所选图片对应的URI
33. * 
34. * @author Administrator
35. *
36. */ 
37.public class PhotoProcess extends Activity{ 
38.    public static final int FIRST_PIC = 0; 
39.    public static final int SECOND_PIC = 1; 
40.    public static final int MAX_WIDTH = 240; 
41.    public static final int MAX_HEIGHT = 180; 
42.    private Button btnSelect,btnSelect2; 
43.    private ImageView srcImageView, dstImageView; 
44.     
45.    private Bitmap srcBitmap, dstBitmap; 
46.    private Uri imageUri; 
47.     
48.     
49.    public void onCreate(Bundle savedInstanceState){ 
50.        super.onCreate(savedInstanceState); 
51.        this.setContentView(R.layout.process); 
52.         
53.        this.btnSelect = (Button)this.findViewById(R.id.btn_select); 
54.        btnSelect.setOnClickListener(clickListener); 
55.        this.btnSelect2 = (Button)this.findViewById(R.id.btn_select2); 
56.        btnSelect2.setOnClickListener(clickListener2); 
57.        srcImageView = (ImageView)this.findViewById(R.id.img_src); 
58.        dstImageView = (ImageView)this.findViewById(R.id.img_dst); 
59.    } 
60.     
61.    private View.OnClickListener clickListener = new View.OnClickListener() { 
62.         
63.        @Override 
64.        public void onClick(View arg0) { 
65.            // 启动Gallery应用 
66.            Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 
67.            startActivityForResult(intent, FIRST_PIC); 
68.        } 
69.    }; 
70.    private View.OnClickListener clickListener2 = new View.OnClickListener() { 
71.         
72.        @Override 
73.        public void onClick(View arg0) { 
74.            // 启动Gallery应用 
75.            Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 
76.            startActivityForResult(intent, SECOND_PIC); 
77.             
78.        } 
79.    };   
80.     
81.    public boolean onCreateOptionsMenu(Menu menu){ 
82.        //super.onCreateOptionsMenu(menu); 
83.        //MenuInflater menuInflater = new MenuInflater(this); 
84.        //menuInflater.inflate(R.layout.image, menu) 
85.        menu.add(Menu.NONE,1,Menu.NONE,"复制"); 
86.        menu.add(Menu.NONE,2,Menu.NONE,"变换"); 
87.        menu.add(Menu.NONE,3,Menu.NONE,"亮度"); 
88.        menu.add(Menu.NONE,4,Menu.NONE,"合成"); 
89.        return super.onCreateOptionsMenu(menu); 
90.    } 
91.     
92.    public boolean onOptionsItemSelected(MenuItem item){ 
93.        int id = item.getItemId(); 
94.        switch(id){ 
95.        case 1: 
96.            //复制一个图像 
97.            if(srcBitmap != null){ 
98.                dstBitmap = getDstImage(null);//这里没有变换 
99.                dstImageView.setImageBitmap(dstBitmap); 
100.            } 
101.            break; 
102.        case 2: 
103.            //对复制后的图像进行变换 
104.            if(srcBitmap != null){ 
105.                dstBitmap = transferImage(); 
106.                dstImageView.setImageBitmap(dstBitmap); 
107.            } 
108.            break; 
109.        case 3: 
110.            //改变图像的色彩 
111.            if(srcBitmap != null){ 
112.                dstBitmap = ajustImage(); 
113.                dstImageView.setImageBitmap(dstBitmap); 
114.            } 
115.            break; 
116.        case 4: 
117.            if(srcBitmap != null && dstBitmap != null){ 
118.                dstBitmap = compositeImages(); 
119.                dstImageView.setImageBitmap(dstBitmap); 
120.            } 
121.            break; 
122.        } 
123.        return true; 
124.    } 
125.     
126.    /**
127.     * 为了创建一个图像的副本,我们可以在创建一个新的空的Bitmap,然后在这个Bitmap上绘制一个Bitmap
128.     * 这个空的Bitmap应该和已存在的Bitmap具有相同的尺寸和颜色深度
129.     * 
130.     * 然后我们需要一个Canvas对象,一个Canvas简单说,就是一个画布,存放Bitmap,在构造时,就可以传入Bitmap对象
131.     * 同时,Canvas中定义了很多便捷的画图方法,方便我们绘制各种图形
132.     * 接下来,如果我们需要处理颜色和对比度,我们需要一个Paint对象,通过Paint我们可以设置画笔的各种特性。
133.     * 
134.     * 最后,我们调用Canvas的drawBitmap就可以将原Bitmap绘制在dstBitmap上了
135.     * 
136.     */ 
137.    private Bitmap getDstImage(Matrix matrix){ 
138.         
139.        Bitmap bmp = null; 
140.        //下面这个Bitmap中创建的函数就可以创建一个空的Bitmap 
141.        //返回的是一个可以改变的Bitmap对象,这样我们后面就可以对其进行变换和颜色调整等操作了 
142.        bmp = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig()); 
143.        //创建Canvas对象, 
144.        Canvas canvas = new Canvas(bmp);  
145.        //创建Paint对象,这里先不用 
146.        Paint paint = new Paint(); 
147.        //在Canvas上绘制一个已经存在的Bitmap。这样,dstBitmap就和srcBitmap一摸一样了 
148.         
149.        if(matrix != null){ 
150.            //如果matrix存在,则采用变换 
151.            canvas.drawBitmap(dstBitmap, matrix, paint); 
152.        }else{ 
153.            canvas.drawBitmap(srcBitmap, 0, 0, paint); 
154.        } 
155.         
156.         
157.        return bmp; 
158. 
159.    } 
160.     
161.     
162.    /**
163.     * 重载getDstImage函数,传入定制的Paint对象
164.     * @param matrix
165.     * @param paint
166.     * @return
167.     */ 
168.    private Bitmap getDstImage(Matrix matrix, Paint paint){ 
169.         
170.        Bitmap bmp = null; 
171.        //下面这个Bitmap中创建的函数就可以创建一个空的Bitmap 
172.        //返回的是一个可以改变的Bitmap对象,这样我们后面就可以对其进行变换和颜色调整等操作了 
173.        bmp = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig()); 
174.        //创建Canvas对象, 
175.        Canvas canvas = new Canvas(bmp);  
176.         
177.        //在Canvas上绘制一个已经存在的Bitmap。这样,dstBitmap就和srcBitmap一摸一样了 
178.         
179.        if(matrix != null){ 
180.            //如果matrix存在,则采用变换 
181.            canvas.drawBitmap(dstBitmap, matrix, paint); 
182.        }else{ 
183.            canvas.drawBitmap(srcBitmap, 0, 0, paint); 
184.        } 
185.         
186.         
187.        return bmp; 
188. 
189.    }    
190.     
191.    /**
192.     * 为了放大缩小、旋转图像,我们要使用Matrix类。Matrix类是一个三维矩阵。
193.     * 在Android屏幕中,图像的每个像素对应都是一个坐标,一个坐标由x/y/z组成
194.     * ------------------------
195.     * cosX -sinX translateX
196.     * sinX cosX  translateY
197.     * 0    0     scale
198.     * ------------------------
199.     * 第一行的值,影响着x坐标。比如 1 0 0 =>x = 1*x + 0*y + 0*z
200.     * 第二行的值,影响着y坐标。比如0 1 0 => y = 0*x + 1*y + 0*z
201.     * 第三行的值,影响着z坐标。比如 0 0 1 => z = 0*x + 0*y + 1*z
202.     * 
203.     * 我们自己计算一个矩阵然后通过Matrax.setValues设置。
204.     * 这样,在调用canvas的drawBitmap方法时,传入matrix
205.     * 
206.     * Matrix类并不提倡我们使用这种方式来操作变换,Matrix针对不同的变换都相应的有pre,set,post三种方法
207.     * 可以使用。
208.     * pre是矩阵前乘
209.     * set是直接设置
210.     * post是矩阵后乘
211.     */ 
212.    private Bitmap transferImage(){ 
213.        Matrix matrix = new Matrix(); 
214.        matrix.setValues(new float[]{ 
215.            .5f,0,0,//这里只会影响到x轴,所以,图片的长度将是原来的一半 
216.            0,1,0, 
217.            0,0,1 
218.        }); 
219.        return this.getDstImage(matrix); 
220.    } 
221.     
222.    /**
223.     * 该方法中我们将对图像的颜色,亮度,对比度等进行设置
224.     * 需要用到ColorMatrix类。ColorMatrix类是一个四行五列的矩阵
225.     * 每一行影响着[R,G,B,A]中的一个
226.     * -------------------------
227.     * a1 b1 c1 d1 e1
228.     * a2 b2 c2 d2 e2
229.     * a3 b3 c3 d3 e3
230.     * a4 b4 c4 d4 e4
231.     * -------------------------
232.     * Rnew => a1*R+b1*G+c1*B+d1*A+e1
233.     * Gnew => a2*R+b2*G+c2*B+d2*A+e2
234.     * Bnew => a3*R+b3*G+c3*B+d3*A+e3
235.     * Gnew => a4*R+b4*G+c4*B+d4*A+e4
236.     * 其中R,G,B的值是128,A的值是0
237.     * 
238.     * 最后将颜色的修改,通过Paint.setColorFilter应用到Paint对象中。
239.     * 主要对于ColorMatrix,需要将其包装成ColorMatrixColorFilter对象,再传给Paint对象
240.     * 
241.     * 同样的,ColorMatrix提供给我们相应的方法,setSaturation()就可以设置一个饱和度
242.     */ 
243.    private Bitmap ajustImage(){ 
244.        ColorMatrix cMatrix = new ColorMatrix(); 
245.//      int brightIndex = -25; 
246.//      int doubleColor = 2; 
247.//      cMatrix.set(new float[]{ 
248.//              doubleColor,0,0,0,brightIndex, //这里将1改为2则我们让Red的值为原来的两倍 
249.//              0,doubleColor,0,0,brightIndex,//改变最后一列的值,我们可以不改变RGB同道颜色的基础上,改变亮度 
250.//              0,0,doubleColor,0,brightIndex, 
251.//              0,0,0,doubleColor,0 
252.//      }); 
253.        //cMatrix.setSaturation(2.0f);//设置饱和度 
254.        cMatrix.setScale(2.0f, 2.0f, 2.0f, 2.0f);//设置颜色同道色彩缩放 
255.        Paint paint = new Paint(); 
256.        paint.setColorFilter(new ColorMatrixColorFilter(cMatrix)); 
257.        return this.getDstImage(null, paint); 
258.    } 
259.     
260.    /**
261.     * 图像的合成,可以通过在同一个Canvas中绘制两张图片。
262.     * 只是在绘制第二章图片的时候,需要给Paint指定一个变幻模式TransferMode。
263.     * 在Android中有一个XFermode所有的变幻模式都是这个类的子类
264.     * 我们需要用到它的一个子类PorterDuffXfermode,关于这个类,其中用到PorterDuff类
265.     * 这个类很简单,就包含一个Enum是Mode,其中定义了一组规则,这组规则就是如何将
266.     * 一张图像和另一种图像进行合成
267.     * 关于图像合成有四种模式,LIGHTEN,DRAKEN,MULTIPLY,SCREEN
268.     */ 
269.    private Bitmap compositeImages(){ 
270.         
271.        Bitmap bmp = null; 
272.        //下面这个Bitmap中创建的函数就可以创建一个空的Bitmap 
273.        bmp = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig()); 
274.        Paint paint = new Paint(); 
275.        Canvas canvas = new Canvas(bmp); 
276.        //首先绘制第一张图片,很简单,就是和方法中getDstImage一样 
277.        canvas.drawBitmap(srcBitmap, 0, 0, paint);       
278.         
279.        //在绘制第二张图片的时候,我们需要指定一个Xfermode 
280.        //这里采用Multiply模式,这个模式是将两张图片的对应的点的像素相乘 
281.        //,再除以255,然后以新的像素来重新绘制显示合成后的图像 
282.        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)); 
283.        canvas.drawBitmap(dstBitmap, 0, 0, paint); 
284.         
285.        return bmp; 
286.    } 
287.    public void onActivityResult(int requestCode, int resultCode, Intent data){ 
288.        super.onActivityResult(requestCode, resultCode, data); 
289.         
290.        Log.v("Result OK Value:", resultCode+""); 
291.        Log.v("RequestCode Value", requestCode+""); 
292.         
293.        if(resultCode == RESULT_OK){ 
294.            imageUri = data.getData();   
295.            if(requestCode == FIRST_PIC){ 
296.                //在Gallery中选中一个图片时,返回来的Intent中的Data就是选择图片的Uri 
297.                srcBitmap = getSrcImage(imageUri); 
298.                srcImageView.setImageBitmap(srcBitmap);              
299.            }else if(requestCode == SECOND_PIC){ 
300.                //这里处理用户选择的第二张图片 
301.                 
302.                dstBitmap = getSrcImage(imageUri); 
303.                dstImageView.setImageBitmap(dstBitmap); 
304.            } 
305.        } 
306.    } 
307.     
308.    /**
309.     * 需要加载的图片可能是大图,我们需要对其进行合适的缩小处理
310.     * @param imageUri
311.     */ 
312.    private Bitmap getSrcImage(Uri imageUri){ 
313.        //Display display = this.getWindowManager().getDefaultDisplay(); 
314.        try { 
315.            BitmapFactory.Options ops = new BitmapFactory.Options(); 
316.            ops.inJustDecodeBounds = true; 
317.            Bitmap bmp = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(imageUri),null,ops); 
318.            int wRatio = (int)Math.ceil(ops.outWidth/(float)MAX_WIDTH); 
319.            int hRatio = (int)Math.ceil(ops.outHeight/(float)MAX_HEIGHT); 
320.             
321.            if(wRatio > 1 && hRatio > 1){ 
322.                if(wRatio > hRatio){ 
323.                    ops.inSampleSize = wRatio; 
324.                }else{ 
325.                    ops.inSampleSize = hRatio; 
326.                } 
327.            } 
328.             
329.            ops.inJustDecodeBounds = false; 
330.            bmp = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(imageUri),null,ops); 
331.             
332.            return bmp; 
333.             
334.        } catch (FileNotFoundException e) { 
335.            // TODO Auto-generated catch block 
336.            e.printStackTrace(); 
337.            Log.e(this.getClass().getName(), e.getMessage()); 
338.        } 
339.         
340.        return null; 
341.    } 
342.} 


本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/chenjie19891104/archive/2011/04/14/6323423.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值