Android图片处理(Matrix,ColorMatrix)
- 格式:doc
- 大小:671.50 KB
- 文档页数:13
内参矩阵的使用内参矩阵是在图像处理和计算机视觉领域中常用的一种技术。
它是一种用来衡量图像的亮度、对比度和颜色信息的矩阵。
内参矩阵的使用可以帮助我们更好地理解和分析图像,并在图像处理过程中提供有价值的信息。
本文将介绍内参矩阵的定义、作用和使用方法。
内参矩阵是指相机的内部参数矩阵,也称为相机矩阵。
它是一个3x3的矩阵,其中包含了相机的焦距、主点位置和图像的旋转和平移信息。
通过内参矩阵,我们可以计算出图像中每个像素点的真实世界坐标,从而实现图像到现实世界的映射。
内参矩阵在计算机视觉和图像处理中的应用非常广泛。
首先,内参矩阵可以用于相机标定。
相机标定是指确定相机的内部参数和外部参数的过程,其中内参矩阵就是相机的内部参数之一。
通过相机标定,我们可以得到准确的内参矩阵,从而提高图像处理的精度和准确性。
内参矩阵可以用于图像纠正。
在拍摄过程中,相机可能会产生畸变,如径向畸变和切向畸变。
通过内参矩阵,我们可以对图像进行畸变校正,使得图像中的直线保持直线,圆形保持圆形,从而提高图像的质量和准确性。
内参矩阵还可以用于图像的特征提取和匹配。
在计算机视觉中,特征提取是指从图像中提取出具有独特性质的点或区域,以用于后续的图像处理和分析。
通过内参矩阵,我们可以将图像坐标转换为世界坐标,从而实现对图像中特征点的准确提取和匹配。
在使用内参矩阵时,我们需要注意几个关键点。
首先,内参矩阵的计算需要相机标定的数据,包括相机拍摄的多组图像和相应的真实世界坐标。
其次,内参矩阵的计算需要使用特定的算法,如点对点对应法、直线对应法等。
最后,内参矩阵的使用需要结合其他的图像处理技术和算法,如图像增强、边缘检测、图像分割等。
内参矩阵的使用在图像处理和计算机视觉领域中具有重要的意义。
它可以帮助我们更好地理解和分析图像,并在图像处理过程中提供有价值的信息。
通过相机标定和图像校正,内参矩阵可以提高图像处理的精度和准确性。
通过特征提取和匹配,内参矩阵可以实现对图像中特征点的准确提取和匹配。
标题:深度解析 matrix.scalem 偏移量的理解一、引言在计算机图形学中,矩阵是起着非常重要作用的数学工具。
而在Android 开发中,matrix 类中的 scalem 方法更是被广泛运用于图形的变换和绘制中。
本文将深入探讨 matrix.scalem 方法中的偏移量,以期帮助读者更全面、深刻地理解该方法。
二、matrix.scalem 方法概述在 Android 的开发中,matrix 类主要用于对图像进行变换。
其中,matrix.scalem 方法用于对图像进行缩放的变换。
其方法签名为:```public boolean scalem (float[] m, int mOffset, float x, float y,float z)```其中,m 为原始的变换矩阵,mOffset 表示矩阵中偏移的位置,x、y、z 分别表示在对应轴上的缩放因子。
三、偏移量的理解在 matrix.scalem 方法中,偏移量指的是 mOffset 参数,它表示了矩阵中的偏移位置。
在实际使用中,我们需要确保偏移量的正确性,以避免对矩阵的修改错误。
理解偏移量是十分重要的。
偏移量的正确性意味着在对矩阵进行缩放变换时,能够正确地定位到需要进行缩放的部分。
如果我们希望对图像的某个特定区域进行缩放,就需要确保偏移量指向该区域在矩阵中的位置,以保证缩放效果的准确性。
四、对 matrix.scalem 方法的理解与实践在实际开发中,我们可以通过以下步骤来正确地理解和使用matrix.scalem 方法中的偏移量:1. 确定需要进行缩放的图像或区域,并理解其在矩阵中的位置;2. 在调用 matrix.scalem 方法时,将正确的偏移量传入,以确保缩放操作作用于预期的图像或区域;3. 结合其他变换方法,如平移、旋转等,综合运用 matrix 类中的方法,以实现更加复杂的图形变换。
通过实践,我们能够更加深入地理解 matrix.scalem 方法中偏移量的作用,并且能够灵活地运用于实际的图形变换中。
pixelcopy 用法Pixelcopy 是一个用于在 Android 应用程序中进行位图复制和像素操作的实用工具类。
它提供了一些便捷的方法,让开发者能够轻松地复制、修改和处理位图上的像素数据。
首先,要使用 Pixelcopy,需要在 Android 设备上运行 Android 8.0(API 级别26)或更高版本的系统。
Pixelcopy 提供了以下几个主要的用法:1. 复制位图:使用 Pixelcopy,开发者可以轻松地复制一个位图。
只需将目标位图和源位图(要复制的位图)作为参数传递给 Pixelcopy.request() 方法即可。
一旦操作完成,复制后的位图将存储在目标位图中,可以对其进行进一步的操作。
2. 获取像素数据:Pixelcopy 允许开发者获取位图上指定区域内的像素数据。
通过调用Pixelcopy.request() 方法,并传递目标位图、源位图和要复制的区域作为参数,可以快速获取指定区域的像素数据。
返回的像素数据可以用于分析、处理或展示。
3. 修改像素数据:使用 Pixelcopy,可以修改位图上像素的颜色值。
通过获取位图的像素数据,可以对每个像素进行操作,例如更改颜色、应用滤镜效果或进行其他图像处理操作。
修改像素数据后,可以通过将修改后的像素数组重新应用到位图上来更新位图的外观。
总的来说,Pixelcopy 是一个有用的工具,可帮助开发者在 Android 应用程序中进行位图复制和像素操作。
它提供了简单且易于使用的 API,使开发者能够快速复制、获取和修改位图上的像素数据。
如果你需要在应用程序中进行位图处理或图像分析,Pixelcopy 是一个值得考虑的选择。
Android部分⼿机拍照后获取的图⽚被旋转问题的解决⽅法调⽤Android系统拍照功能后,三星⼿机拍摄后的照⽚被旋转了90度,横着拍给你变成竖的,竖的拍给你变成横的。
其它品牌的⼿机都是正常的,就三星出现这个怪事。
在Android适配上,我原来⼀直以为国内的⼩⽶⼿机够奇葩了,结果还有更奇葩的!你说你没事旋转照⽚⼲啥,实在是猜不透其居⼼何在,纯粹是在给开发者制造⿇烦啊!解决办法是获取到拍照后照⽚被旋转的⾓度,再旋转回去就好了。
具体思路:1、⾸先在调⽤拍照⽅法时,保存拍照后的相⽚原图,得到原图路径,(PhotoBitmapUtils是我⾃⼰写的⼀个⼯具类)String fileName = "";/*** 启动相机拍照*/private void addBitmapShoots() {Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 设置图⽚要保存的根路径+⽂件名fileName = PhotoBitmapUtils.getPhotoFileName(getContext());File file = new File(fileName);if (!file.exists()) {try {file.createNewFile();} catch (IOException e) {e.printStackTrace();}}intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));startActivityForResult(intent, OPEN_CAMERA);}2、在获取相机返回的回调⽅法onActivityResult()中,修复被旋转的图⽚并取得修复后的图⽚路径,有了这个路径后就可以展⽰出来了@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);// 获取相机拍照返回if (resultCode == Activity.RESULT_OK && requestCode == OPEN_CAMERA) {// 得到修复后的照⽚路径String filepath = PhotoBitmapUtils.amendRotatePhoto(fileName, getContext());}}PhotoBitmapUtils类:/*** 集合⼀些图⽚⼯具** Created by zhuwentao on 2016-07-22.*/public class PhotoBitmapUtils {/*** 存放拍摄图⽚的⽂件夹*/private static final String FILES_NAME = "/MyPhoto";/*** 获取的时间格式*/public static final String TIME_STYLE = "yyyyMMddHHmmss";/*** 图⽚种类*/public static final String IMAGE_TYPE = ".png";// 防⽌实例化private PhotoBitmapUtils() {}/*** 获取⼿机可存储路径** @param context 上下⽂* @return ⼿机可存储路径*/private static String getPhoneRootPath(Context context) {// 是否有SD卡if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)|| !Environment.isExternalStorageRemovable()) {// 获取SD卡根⽬录return context.getExternalCacheDir().getPath();} else {// 获取apk包下的缓存路径return context.getCacheDir().getPath();}}/*** 使⽤当前系统时间作为上传图⽚的名称** @return 存储的根路径+图⽚名称*/public static String getPhotoFileName(Context context) {File file = new File(getPhoneRootPath(context) + FILES_NAME);// 判断⽂件是否已经存在,不存在则创建if (!file.exists()) {file.mkdirs();}// 设置图⽚⽂件名称SimpleDateFormat format = new SimpleDateFormat(TIME_STYLE, Locale.getDefault()); Date date = new Date(System.currentTimeMillis());String time = format.format(date);String photoName = "/" + time + IMAGE_TYPE;return file + photoName;}/*** 保存Bitmap图⽚在SD卡中* 如果没有SD卡则存在⼿机中** @param mbitmap 需要保存的Bitmap图⽚* @return 保存成功时返回图⽚的路径,失败时返回null*/public static String savePhotoToSD(Bitmap mbitmap, Context context) {FileOutputStream outStream = null;String fileName = getPhotoFileName(context);try {outStream = new FileOutputStream(fileName);// 把数据写⼊⽂件,100表⽰不压缩press(pressFormat.PNG, 100, outStream);return fileName;} catch (Exception e) {e.printStackTrace();return null;} finally {try {if (outStream != null) {// 记得要关闭流!outStream.close();}if (mbitmap != null) {mbitmap.recycle();}} catch (Exception e) {e.printStackTrace();}}}/*** 把原图按1/10的⽐例压缩** @param path 原图的路径* @return 压缩后的图⽚*/public static Bitmap getCompressPhoto(String path) {BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = false;options.inSampleSize = 10; // 图⽚的⼤⼩设置为原来的⼗分之⼀Bitmap bmp = BitmapFactory.decodeFile(path, options);options = null;return bmp;}/*** 处理旋转后的图⽚* @param originpath 原图路径* @param context 上下⽂* @return 返回修复完毕后的图⽚路径*/public static String amendRotatePhoto(String originpath, Context context) {// 取得图⽚旋转⾓度int angle = readPictureDegree(originpath);// 把原图压缩后得到Bitmap对象Bitmap bmp = getCompressPhoto(originpath);;// 修复图⽚被旋转的⾓度Bitmap bitmap = rotaingImageView(angle, bmp);// 保存修复后的图⽚并返回保存后的图⽚路径return savePhotoToSD(bitmap, context);}/*** 读取照⽚旋转⾓度** @param path 照⽚路径* @return ⾓度*/public static int readPictureDegree(String path) {int degree = 0;try {ExifInterface exifInterface = new ExifInterface(path);int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) {case ExifInterface.ORIENTATION_ROTATE_90:degree = 90;break;case ExifInterface.ORIENTATION_ROTATE_180:degree = 180;break;case ExifInterface.ORIENTATION_ROTATE_270:degree = 270;break;}} catch (IOException e) {e.printStackTrace();}return degree;}/*** 旋转图⽚* @param angle 被旋转⾓度* @param bitmap 图⽚对象* @return 旋转后的图⽚*/public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {Bitmap returnBm = null;// 根据旋转⾓度,⽣成旋转矩阵Matrix matrix = new Matrix();matrix.postRotate(angle);try {// 将原始图⽚按照旋转矩阵进⾏旋转,并得到新的图⽚returnBm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);} catch (OutOfMemoryError e) {}if (returnBm == null) {returnBm = bitmap;}if (bitmap != returnBm) {bitmap.recycle();}return returnBm;}}在调⽤修复图⽚⾓度⽅法的时候需要注意,现在的⼿机像素越来越⼤,拍完后⼀张照⽚有近10M,所以我们需要对图⽚进⾏压缩处理。
android透明度原理
Android 中的透明度原理涉及到图形处理和界面渲染的相关知识。
在 Android 中,透明度是通过颜色的 alpha 通道来控制的,alpha 通道的取值范围是 0 到 255,其中 0 表示完全透明,255 表示完全不透明。
Android 中的透明度原理主要涉及到以下几个方面:
1. 图形处理,在 Android 中,绘制图形和控件时,可以通过设置颜色的 alpha 通道来控制透明度。
比如,可以使用 ARGB (Alpha、Red、Green、Blue)来表示颜色,其中 Alpha 通道就是用来表示透明度的。
2. 界面渲染,在界面渲染过程中,系统会根据设置的透明度来混合不同的图层,从而实现整体界面的透明效果。
这涉及到了界面的层叠和混合计算,以及硬件加速和 GPU 渲染等技术。
3. XML 属性,在 Android 的布局文件中,可以通过设置控件的 alpha 属性来控制透明度,这样可以在不修改代码的情况下实现界面元素的透明效果。
总体来说,Android 中的透明度原理是通过控制颜色的 alpha
通道来实现的,涉及到图形处理、界面渲染和 XML 属性等多个方面。
这种透明度原理的实现方式能够让开发者灵活地控制界面元素的透
明效果,从而实现更加丰富多彩的界面设计。
android bitmap修改饱和度原理在Android中修改位图(Bitmap)的饱和度,实际上是通过对位图的每个像素进行处理来改变图像的颜色饱和度。
要理解具体的操作原理,我们需要了解以下几个概念和算法:色彩模型、色彩空间转换,以及调整饱和度的算法。
一、色彩模型和色彩空间转换:1. 色彩模型:色彩模型是指用于描述和表示色彩的方式,常见的有RGB(红绿蓝)、CMYK(青、品红、黄、黑)和HSV(色调、饱和度、明度)等。
在Android中,位图以RGB色彩模型来存储图像的像素信息。
2. 色彩空间转换:色彩空间转换是指将一个色彩模型转换为另一个色彩模型的过程。
在修改位图的饱和度之前,我们需要将RGB色彩模型转换为HSV色彩模型。
HSV色彩模型中的H分量表示色调(0-360度),S分量表示饱和度(0-1),V分量表示明度(0-1)。
二、调整饱和度的算法:1. RGB转HSV算法:RGB转HSV的算法如下:```float r, g, b;float h, s, v;float max = max(r, max(g, b)); float min = min(r, min(g, b));v = max; // 明度float delta = max - min;if (max != 0) {s = delta / max; // 饱和度} else {s = 0;h = -1;return;}if (delta == 0) {h = 0;} else {if (r == max) {h = (g - b) / delta; // 色调} else if (g == max) {h = 2 + (b - r) / delta;} else {h = 4 + (r - g) / delta;}h *= 60;if (h < 0) {h += 360;}}```2. 修改饱和度算法:修改饱和度的算法如下:```float h, s, v; // HSV分量float saturation; // 饱和度增量s += saturation; // 调整饱和度if (s > 1) {s = 1;} else if (s < 0) {s = 0;}```三、位图修改饱和度的原理:根据上述算法,我们可以通过对位图的每个像素进行遍历和修改来改变位图的饱和度。
android hwc service的处理流程Android HWC Service的处理流程概述Android HWC(Hardware Composer)Service是Android系统中负责处理图形合成和显示的重要组件之一。
它负责接收来自应用程序和系统服务的请求,将图形元素合成为最终的图像帧,并通过硬件接口将图像显示到屏幕上。
本文将详细说明Android HWC Service的处理流程。
流程一:接收请求在Android系统中,应用程序和系统服务通过SurfaceFlinger将图形请求发送给HWC Service。
HWC Service会按照请求的先后顺序接收并处理这些请求。
流程二:合成图像HWC Service将接收到的多个图形请求进行合成,生成最终的图像帧。
图像合成过程包括以下几个步骤: - 图层排序:根据每个图层的显示顺序和属性,对所有图层进行排序,确定它们在最终图像中的叠放次序。
- 图层合成:将排序后的图层依次合成到一个缓冲区中。
在合成过程中,HWC Service可能会使用硬件加速功能,例如GPU加速,以提高合成效率。
- 混合模式:根据每个图层的设置,将它们合成到最终图像中,并应用相应的混合模式,例如正常混合、透明混合等。
流程三:交给显示引擎合成完成后,HWC Service将最终的图像帧交给显示引擎,通过硬件接口将图像显示到屏幕上。
流程四:VSync同步为了保证图像显示的流畅性,Android系统采用了VSync(垂直同步)机制。
HWC Service会监听VSync信号,并在信号到来时将当前的图像帧发送到显示引擎,以进行显示。
这样,图像的更新频率将与显示设备的刷新率保持同步,避免出现画面撕裂等问题。
结论通过以上的流程,Android HWC Service可以高效地处理图形合成和显示任务,确保应用程序和系统界面在屏幕上的流畅显示。
了解HWC Service的处理流程对于开发者来说是非常重要的,可以帮助他们优化图形渲染和图层合成的性能,提升用户体验。
Android应用使用WebP格式优化图片资源Android应用的用户界面中通常包含大量的图片资源,而这些图片资源对应用的性能和用户体验有着重要的影响。
在过去的几年中,WebP格式作为一种高效的图片压缩格式受到了广泛的关注和应用。
本文将介绍WebP格式的特点和优势,并探讨在Android应用中如何使用WebP格式来优化图片资源。
一、什么是WebP格式WebP是一种由Google开发的用于图像压缩的格式,它旨在提供更高的压缩率同时保持较高的图像质量。
WebP格式的一个特点是它支持有损和无损压缩,并提供了透明度和动画的支持。
与传统的图片格式如JPEG和PNG相比,WebP格式可以实现更小的文件大小,从而减少网络传输和存储成本。
二、WebP格式的优势1. 更高的压缩率:WebP格式相比JPEG和PNG可以实现更高的压缩率,这意味着可以使用更少的存储空间来保存同样质量的图片。
对于网络传输来说,WebP格式可以减少带宽的使用,提高加载速度和用户体验。
2. 较高的图像质量:尽管WebP格式实现了较高的压缩率,但它仍然可以保持相对较高的图像质量。
这意味着应用中的图片资源可以以更小的文件大小展示出更清晰、更细腻的效果,提高用户对应用的好感度。
3. 透明度和动画的支持:WebP格式支持透明度和动画的处理,这对于一些需要展示动态效果或者需要透明背景的图片资源尤为重要。
通过使用WebP格式,开发者可以实现更灵活、更多样化的界面设计。
三、使用WebP格式优化图片资源在Android应用中使用WebP格式优化图片资源可以通过以下几个步骤进行:1. 转换图片格式:将原有的图片资源转换为WebP格式。
可以使用一些图片编辑软件或者在线转换工具来完成这一步骤。
转换的过程中需要注意选择合适的压缩率和质量设置,以保证转换后的图片在文件大小和清晰度之间达到一个平衡。
2. 适配WebP格式:在应用中使用转换后的WebP格式图片资源。
Android系统从Android 4.0(API level 14)开始正式支持WebP格式,开发者可以直接在布局文件或者代码中引用WebP格式的图片资源。
Android 3.1 r1 API中文文档(6)——ImageView前言本章内容是android.widget.ImageView,为早前发布版本的完整版,版本为Android 3.1 r1,翻译来自"cnmahj"和"农民伯伯",欢迎大家访问"cnmahj"的博客:,再次感谢"/cnmahj"!欢迎你一起参与Android的中文翻译,联系我over140@。
声明欢迎转载,但请保留文章原始出处:)博客园:/Android中文翻译组:http://goo.gl/6vJQlImageView译者署名:cnmahj、农民伯伯译者博客:/cnmahj版本:Android 3.1 r1结构继承关系public class View.OnClickListner extends Viewng.Objectandroid.view.Viewandroid.widget.ImageView直接子类ImageButton, QuickContactBadge间接子类ZoomButton类概述显示任意图像,例如图标。
ImageView类可以加载各种来源的图片(如资源或图片库),需要计算图像的尺寸,比便它可以在其他布局中使用,并提供例如缩放和着色(渲染)各种显示选项。
嵌套类enum ImageView.ScaleType将图片边界缩放,以适应视图边界时的可选项XML属性公共方法public final void clearColorFilter ()(译者注:清除颜色过滤,参见这里)public int getBaseline ()返回部件顶端到文本基线的偏移量。
如果小部件不支持基线对齐,该方法返回-1。
返回值小部件顶端到文本基线的偏移量;或者是-1 当小部件不支持基线对齐时。
public boolean getBaselineAlignBottom ()返回当前视图基线是否将考虑视图的底部。
android android读取资源文件的方法Android开发中,我们经常需要读取应用程序中的资源文件,如图片、文字、xml等。
Android提供了一套API供我们方便地读取这些资源文件。
本文将介绍几种读取资源文件的方法。
一、读取图片资源文件1.通过资源ID读取图片资源在我们的应用程序中,通常会将图片存放在res/drawable文件夹下。
我们可以通过资源ID来获取这些图片。
```ImageView imageView = findViewById(R.id.imageView);imageView.setImageResource(R.drawable.my_image);```其中,R.drawable.my_image是图片资源文件的ID。
通过调用setImageResource方法,我们可以将该资源文件设置给ImageView。
2.通过文件名读取图片资源有时候,我们可能需要根据文件名来读取图片资源。
可以使用以下方法来实现:```String fileName = "my_image.png";Resources resources = getResources();int resId = resources.getIdentifier(fileName, "drawable", getPackageName());imageView.setImageResource(resId);```首先,我们需要获取Resources对象,然后调用getIdentifier方法,传入文件名、资源类型和包名,最后获取到资源ID。
接下来,就可以通过setImageResource方法将资源文件设置给ImageView。
二、读取文字资源文件在应用程序中,我们可能需要读取文字资源文件,如strings.xml。
可以使用以下方法来读取:```String textValue =getResources().getString(R.string.my_text);textView.setText(textValue);```其中,R.string.my_text是文字资源文件的ID。
手机图像处理▏认识和设置Snapseed
关于SnapseedNik Software公司牛逼的图像处理插件,对于经常使用Photoshop来处理图像的人来说并不陌生,比如Nik Software Color Efex Pro。
Snapseed就是Nik Software旗下一款手机端图像编辑APP。
2012年9月,Nik Software嫁给了Google,Nik Software 从此改姓,就如Google Nik Software Silver Efex Pro,Snapseed自然也改姓Google,从那时起,用户可以更轻松使用,原本需要付费的电脑端Nik Software系列优秀的PS插件连Snapseed全部都免费了。
优秀的软件都有一个共性,表面看起来很简单,但如果想要达到玩家级,就不那么简单了,你得费不少功夫去深入研究。
Snapseed就是这么一款需要脑洞的图像处理APP,简洁直观但不简单。
在开始教程之前,先来对手机做必要的调整:请关闭屏幕自动亮度,设置亮度为80%以上,过低的亮度是很难把握调整效果滴。
(爱护眼睛,请勿在全黑或者过暗的环境下使用手机)。
本教程以安卓系统为例,Snapseed版本2.11(苹果系统在文件打开和保存稍有区别之外,APP里的调整设置基本一致)。
认识Snapseed界面
简洁的界面,点击“打开照片”导入需要处理的图片。
找到需要处理的图片。
android rendereffect 原理-回复Android RenderEffect的原理Android RenderEffect是Android平台上用于图像渲染和效果处理的一个功能模块。
它可以通过一系列的操作和转换,对图像进行多种多样的效果处理,比如模糊、边缘检测、滤镜等。
在本文中,我将逐步介绍Android RenderEffect的原理。
1. GPU加速Android RenderEffect利用了GPU的并行计算能力进行图像处理和渲染操作。
在Android平台上,GPU被广泛用于图形渲染和图像处理,因为它相比于CPU具有更高的并行计算和向量计算能力。
通过利用GPU 的并行计算能力,Android RenderEffect能够更高效地处理图像,并实时渲染出效果。
2. RenderEffect的调用方式在Android中,可以通过在View的canvas上调用RenderEffect的方法来应用特定的效果。
常用的方法有两种:- `setRenderEffect(RenderEffect effect)`:将RenderEffect应用到整个画布上。
- `View#setRenderEffect(RenderEffect effect, Rect localBounds)`:将RenderEffect应用到指定区域的画布。
这些方法可以通过给定的参数,将RenderEffect应用到画布上的特定区域,或是整个画布。
3. RenderEffect的类型Android RenderEffect提供了几种不同的效果类型,每种效果类型可以通过不同的参数来调整效果效果程度和样式。
常见的效果类型包括:- `RenderEffect.createBlurEffect(float radiusX, float radiusY, TileMode mode)`:创建模糊效果。
通过设置半径和TileMode来调整模糊程度和样式。
android手把手开发一个图片浏览器这次我给大家讲解一个Android图片浏览器的应用。
AndroidAndroid是基于Linux内核的软件平台和操作系统,早期由Google开发,后由开放手机联盟Open Handset Alliance)开发。
它采用了软件堆层(software stack,又名以软件叠层)的架构,主要分为三部分。
低层以Linux内核工作为基础,只提供基本功能;其他的应用软件则由各公司自行开发,以Java作为编写程序的一部分。
另外,为了推广此技术,Google和其它几十个手机公司建立了开放手机联盟。
Android在未公开之前常被传闻为Google电话或gPhone。
大多传闻认为Google开发的是自己的手机电话产品,而不是一套软件平台。
到了2010年1月,Google开始发表自家品牌手机电话的Nexus One。
目前最新版本为Android2.1。
下图是它的结构:简单来讲,Android就是一个开源的手机软件开发工具。
我主要给大家讲应用方面,大家如果有兴趣,可以了解相关基本知识。
要开发一个Android应用,首先得搭建Android开发环境:下载并安装Android sdk(Software Development Kit, 即软件开发工具包)。
由于Android 开发是集成在Eclipse中,需下载并安装ADT (Eclipse集成Android sdk插件)。
搭建环境会用一个专门的章节为大家详细讲解,这里我就不再赘述。
Android开发环境搭好后,我们先启动Eclipse创建一个Android的应用程序,然后在左上角单击File,New,Android Project,如下图所示:如果在图中Java Project找不到Android Project:在左上角单击File,New,Other:在弹出框中Android文件件中选中Android Project,然后单击Next进入下一步:弹出一个列表框:下面对这个列表的一些重要属性进行讲解:1.应用程序名称以及内容栏:2.工具栏:采用的编译工具即Android模拟器:3.属性栏:即应用程序中的相关属性:Android 这就是我们刚才创建的一个Android应用程序如下图:在这里面,我们最关心的是界面(main.xml)与后台(Test1.java):单击main.xml:我们先看看中间视图:这是一个页面编辑器模式:在左下角点击main.xml切换到界面编码模式:这就是刚才页面视图的源码:下面让我们看看后台(Test1.java)源码:单击Test1.java:以下将此类程序称之为activity(活动),该activity运行时会自动调用onCreate方法:而上图中onCreate方法是启动res文件夹下的layout下的main.xml界面。
android 高斯模糊scriptintrinsicblur的实现原理Android中的高斯模糊效果是一种常见的图像处理技术,可以使图像变得更加柔和,更加美观。
而在实现高斯模糊效果的过程中,ScriptIntrinsicBlur是一种非常常用的方法。
那么,ScriptIntrinsicBlur的实现原理是什么呢?首先,ScriptIntrinsicBlur是Android提供的一种基于RenderScript 的图像处理方法,它可以对图像进行高斯模糊处理。
在使用ScriptIntrinsicBlur进行高斯模糊处理时,需要先创建一个RenderScript对象,然后再创建一个ScriptIntrinsicBlur对象,并将需要进行处理的图像传递给ScriptIntrinsicBlur对象。
接下来,ScriptIntrinsicBlur对象会对图像进行高斯模糊处理,并将处理后的图像返回。
那么,ScriptIntrinsicBlur是如何实现高斯模糊效果的呢?其实,ScriptIntrinsicBlur的实现原理就是基于高斯滤波器的卷积运算。
在进行高斯模糊处理时,ScriptIntrinsicBlur会先根据指定的半径计算出高斯滤波器的权重系数,然后再将权重系数应用到图像的每个像素上,从而实现高斯模糊效果。
具体来说,ScriptIntrinsicBlur会先将图像转换为一维数组,然后再根据高斯滤波器的权重系数对每个像素进行卷积运算。
在卷积运算中,ScriptIntrinsicBlur会将当前像素及其周围的像素与高斯滤波器的权重系数进行乘积运算,并将乘积结果相加,从而得到当前像素的新值。
这个过程会对图像中的每个像素都进行一次,从而实现高斯模糊效果。
需要注意的是,ScriptIntrinsicBlur的半径值越大,处理后的图像就会越模糊。
同时,半径值过大也会导致处理时间变长,因此需要根据实际情况进行调整。
如何使用Android的图像识别和二维码识别功能进行开发Android平台作为全球最流行的移动操作系统之一,提供了丰富的功能和开发工具,为开发者们提供了极大的便利。
其中,图像识别和二维码识别功能在应用开发中扮演着重要的角色。
本文将探讨如何在Android平台上利用这些功能进行开发,帮助开发者们实现更加智能的应用。
1. 图像识别技术在Android应用中的应用图像识别技术是一种将图像转化为可理解的信息的计算机技术,可以通过对图像进行分析和比对,实现图像内容的识别与理解。
在Android应用中,图像识别技术可以被广泛运用于各个领域。
例如,通过拍摄一张食品照片,应用可以判断出所拍摄的食品类型、卡路里含量等信息,帮助用户快速了解食物的健康信息。
在Android平台上,图像识别功能可以通过开发工具包(SDK)来实现。
Google提供的移动视觉API(Mobile Vision API)是一种常用的工具,它提供了图像识别、面部识别、文本识别等功能,开发者只需集成相应的库文件即可快速实现图像识别。
2. 如何使用Android的图像识别功能进行开发在Android平台上使用图像识别功能进行开发,需要进行以下几个步骤:集成移动视觉API首先,在应用的文件中添加相应的依赖项,引入移动视觉API库文件。
然后,在文件中加入使用该功能所需的权限声明,如相机权限、存储读取权限等。
调用图像识别功能在应用中,可以通过启动相机或从相册中选择一张照片来进行图像识别。
调用移动视觉API提供的接口,将图像传入图像识别引擎,即可获取识别结果。
根据识别结果,应用可以进行相应的业务处理,展示给用户所需的信息。
进行后续处理在获取到图像识别结果后,开发者可以根据应用需求进行后续处理。
例如,可以将识别结果与数据库中的数据进行匹配,提供更详细的信息;或者将识别结果与其他功能进行结合,实现更加智能化的应用。
3. 二维码识别技术在Android应用中的应用二维码是一种以方块为基础的矩阵条形码,可以在不同方向上存储更多的信息。
android skia渲染原理Android Skia渲染原理Skia是一个跨平台的2D图形库,被广泛应用于Android系统中的图形绘制和图像处理。
Skia的渲染原理涉及到图形的绘制、颜色的渲染和图像的处理等方面。
本文将从这几个方面详细介绍Android Skia的渲染原理。
一、图形的绘制Skia通过绘制图形对象来实现图形的绘制,常见的图形对象包括矩形、圆形、椭圆等。
当绘制图形时,Skia会根据给定的图形对象和绘制参数,通过图形路径的描述来确定绘制的形状和位置。
在绘制过程中,Skia会根据颜色、画笔样式和渐变等属性来确定图形的外观效果。
二、颜色的渲染Skia支持多种颜色的渲染方式,包括纯色、渐变色和图像纹理等。
在渲染颜色时,Skia会根据颜色属性和绘制对象的形状来计算每个像素的颜色值。
对于纯色渲染,Skia会直接使用给定的颜色值进行填充。
对于渐变色渲染,Skia会根据渐变类型和渐变颜色的设置,计算每个像素的颜色值。
对于图像纹理渲染,Skia会使用给定的图像作为纹理,根据纹理坐标和绘制对象的形状来计算每个像素的颜色值。
三、图像的处理Skia支持对图像进行多种处理操作,包括缩放、旋转和裁剪等。
在图像处理过程中,Skia会根据给定的处理参数和图像数据,通过变换操作来生成新的图像数据。
例如,当进行缩放操作时,Skia会根据缩放比例和插值算法来计算每个像素的值,从而生成新的图像数据。
对于旋转和裁剪操作,Skia会根据给定的旋转角度和裁剪区域,对图像进行相应的变换和截取。
总结:Android Skia渲染原理涉及到图形的绘制、颜色的渲染和图像的处理等方面。
Skia通过绘制图形对象、渲染颜色和处理图像数据来实现图形的绘制和图像的处理。
通过了解Skia的渲染原理,可以更好地理解Android系统中的图形绘制和图像处理机制,从而提高应用程序的界面效果和用户体验。
(注:文章内容仅供参考,具体细节请参考相关资料和文档。
Android实现图⽚浮动随意拖拽效果本⽂实例为⼤家分享了Android实现图⽚浮动拖拽效果的具体代码,供⼤家参考,具体内容如下实现步骤1.先⾃定义⼀个浮动⼯具类public class MoveImage extends ImageView {/**** 浮动⼯具类**/private int lastX = 0;private int lastY = 0;private int dx;private int dy;private float movex = 0;private float movey = 0;private int screenWidth;private int screenHeight;public MoveImage(Context context, AttributeSet attrs) {super(context, attrs);screenWidth = ScreenUtils.getWidth(context);screenHeight = ScreenUtils.getHeight(context);}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:lastX = (int) event.getRawX();lastY = (int) event.getRawY();movex = lastX;movey = lastY;break;case MotionEvent.ACTION_MOVE:dx = (int) event.getRawX() - lastX;dy = (int) event.getRawY() - lastY;int left = getLeft() + dx;int top = getTop() + dy;int right = getRight() + dx;int bottom = getBottom() + dy;if (left < 0) {left = 0;right = left + getWidth();}if (right > screenWidth) {right = screenWidth;left = right - getWidth();}if (top < 0) {top = 0;bottom = top + getHeight();}if (bottom > screenHeight) {bottom = screenHeight;top = bottom - getHeight();}layout(left, top, right, bottom);lastX = (int) event.getRawX();lastY = (int) event.getRawY();break;case MotionEvent.ACTION_UP://避免滑出触发点击事件if ((int) (event.getRawX() - movex) != 0|| (int) (event.getRawY() - movey) != 0) {return true;}break;default:break;}return super.onTouchEvent(event);}}2.xml布局的引⽤<com.zjtd.bzcommunity.text.MoveImageandroid:id="@+id/iv_phone_bar"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_alignParentRight="true"android:layout_marginBottom="70dp"android:src="@drawable/my_qiandao_icon" />3.activity的实现private MoveImage iv_phone_bar;//签到图⽚iv_phone_bar = (MoveImage) view.findViewById(R.id.iv_phone_bar);iv_phone_bar.setOnClickListener(this);// 签到case R.id.iv_phone_bar:startActivity(new Intent(getActivity(), SignAcitvity.class));//点击跳转页⾯break;以上就是这篇⽂章的全部内容了,希望本⽂的内容对⼤家的学习或者⼯作具有⼀定的参考学习价值,如果有疑问⼤家可以留⾔交流,谢谢⼤家对的⽀持。
Android中实现⽑玻璃效果的3种⽅法最近在做⼀款叫叽叽的App(男银懂的),其中有⼀个功能需要对图⽚处理实现⽑玻璃的特效进过⼀番预研,找到了3中实现⽅案,其中各有优缺点:1、如果系统的api在16以上,可以使⽤系统提供的⽅法直接处理图⽚复制代码代码如下:if (VERSION.SDK_INT > 16) {Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);final RenderScript rs = RenderScript.create(context);final Allocation input = Allocation.createFromBitmap(rs, sentBitmap, Allocation.MipmapControl.MIPMAP_NONE, AGE_SCRIPT);final Allocation output = Allocation.createTyped(rs, input.getType());final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));script.setRadius(radius /* e.g. 3.f */);script.setInput(input);script.forEach(output);output.copyTo(bitmap);return bitmap;}2、如果Api条件不满⾜,可以使⽤如下⽅法复制代码代码如下:@SuppressLint("NewApi")public static Bitmap fastblur(Context context, Bitmap sentBitmap, int radius) {Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);if (radius < 1) {return (null);}int w = bitmap.getWidth();int h = bitmap.getHeight();int[] pix = new int[w * h];// Log.e("pix", w + " " + h + " " + pix.length);bitmap.getPixels(pix, 0, w, 0, 0, w, h);int wm = w - 1;int hm = h - 1;int wh = w * h;int div = radius + radius + 1;int r[] = new int[wh];int g[] = new int[wh];int b[] = new int[wh];int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;int vmin[] = new int[Math.max(w, h)];int divsum = (div + 1) >> 1;divsum *= divsum;int temp = 256 * divsum;int dv[] = new int[temp];for (i = 0; i < temp; i++) {dv[i] = (i / divsum);}yw = yi = 0;int[][] stack = new int[div][3];int stackpointer;int stackstart;int[] sir;int rbs;int r1 = radius + 1;int routsum, goutsum, boutsum;int rinsum, ginsum, binsum;for (y = 0; y < h; y++) {rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; for (i = -radius; i <= radius; i++) {p = pix[yi + Math.min(wm, Math.max(i, 0))];sir = stack[i + radius];sir[0] = (p & 0xff0000) >> 16;sir[1] = (p & 0x00ff00) >> 8;sir[2] = (p & 0x0000ff);rbs = r1 - Math.abs(i);rsum += sir[0] * rbs;gsum += sir[1] * rbs;bsum += sir[2] * rbs;if (i > 0) {rinsum += sir[0];ginsum += sir[1];binsum += sir[2];} else {routsum += sir[0];goutsum += sir[1];boutsum += sir[2];}}stackpointer = radius;for (x = 0; x < w; x++) {r[yi] = dv[rsum];g[yi] = dv[gsum];b[yi] = dv[bsum];rsum -= routsum;gsum -= goutsum;bsum -= boutsum;stackstart = stackpointer - radius + div;sir = stack[stackstart % div];routsum -= sir[0];goutsum -= sir[1];boutsum -= sir[2];if (y == 0) {vmin[x] = Math.min(x + radius + 1, wm);}p = pix[yw + vmin[x]];sir[0] = (p & 0xff0000) >> 16;sir[1] = (p & 0x00ff00) >> 8;sir[2] = (p & 0x0000ff);rinsum += sir[0];ginsum += sir[1];binsum += sir[2];bsum += binsum;stackpointer = (stackpointer + 1) % div;sir = stack[(stackpointer) % div];routsum += sir[0];goutsum += sir[1];boutsum += sir[2];rinsum -= sir[0];ginsum -= sir[1];binsum -= sir[2];yi++;}yw += w;}for (x = 0; x < w; x++) {rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; yp = -radius * w;for (i = -radius; i <= radius; i++) {yi = Math.max(0, yp) + x;sir = stack[i + radius];sir[0] = r[yi];sir[1] = g[yi];sir[2] = b[yi];rbs = r1 - Math.abs(i);rsum += r[yi] * rbs;gsum += g[yi] * rbs;bsum += b[yi] * rbs;if (i > 0) {rinsum += sir[0];ginsum += sir[1];binsum += sir[2];} else {routsum += sir[0];goutsum += sir[1];boutsum += sir[2];}if (i < hm) {yp += w;}}yi = x;stackpointer = radius;for (y = 0; y < h; y++) {// Preserve alpha channel: ( 0xff000000 & pix[yi] )pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];rsum -= routsum;gsum -= goutsum;bsum -= boutsum;stackstart = stackpointer - radius + div;sir = stack[stackstart % div];routsum -= sir[0];if (x == 0) {vmin[y] = Math.min(y + r1, hm) * w;}p = x + vmin[y];sir[0] = r[p];sir[1] = g[p];sir[2] = b[p];rinsum += sir[0];ginsum += sir[1];binsum += sir[2];rsum += rinsum;gsum += ginsum;bsum += binsum;stackpointer = (stackpointer + 1) % div;sir = stack[stackpointer];routsum += sir[0];goutsum += sir[1];boutsum += sir[2];rinsum -= sir[0];ginsum -= sir[1];binsum -= sir[2];yi += w;}}// Log.e("pix", w + " " + h + " " + pix.length);bitmap.setPixels(pix, 0, w, 0, 0, w, h);return (bitmap);}3、以上⽅法都存在⼀个问题,性能较低,下⾯提供⼀个C实现复制代码代码如下:static int* StackBlur(int* pix, int w, int h, int radius) {int wm = w - 1;int hm = h - 1;int wh = w * h;int div = radius + radius + 1;int *r = (int *)malloc(wh * sizeof(int));int *g = (int *)malloc(wh * sizeof(int));int *b = (int *)malloc(wh * sizeof(int));int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;int *vmin = (int *)malloc(MAX(w,h) * sizeof(int));int divsum = (div + 1) >> 1;divsum *= divsum;int *dv = (int *)malloc(256 * divsum * sizeof(int));for (i = 0; i < 256 * divsum; i++) {dv[i] = (i / divsum);}yw = yi = 0;int(*stack)[3] = (int(*)[3])malloc(div * 3 * sizeof(int));int stackpointer;int stackstart;int *sir;int rbs;int r1 = radius + 1;int routsum, goutsum, boutsum;int rinsum, ginsum, binsum;for (y = 0; y < h; y++) {rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; for (i = -radius; i <= radius; i++) {p = pix[yi + (MIN(wm, MAX(i, 0)))];sir = stack[i + radius];sir[0] = (p & 0xff0000) >> 16;sir[1] = (p & 0x00ff00) >> 8;sir[2] = (p & 0x0000ff);rbs = r1 - ABS(i);rsum += sir[0] * rbs;gsum += sir[1] * rbs;bsum += sir[2] * rbs;if (i > 0) {rinsum += sir[0];ginsum += sir[1];binsum += sir[2];}else {routsum += sir[0];goutsum += sir[1];boutsum += sir[2];}}stackpointer = radius;for (x = 0; x < w; x++) {r[yi] = dv[rsum];g[yi] = dv[gsum];b[yi] = dv[bsum];rsum -= routsum;gsum -= goutsum;bsum -= boutsum;stackstart = stackpointer - radius + div;sir = stack[stackstart % div];routsum -= sir[0];goutsum -= sir[1];boutsum -= sir[2];if (y == 0) {vmin[x] = MIN(x + radius + 1, wm);}p = pix[yw + vmin[x]];sir[0] = (p & 0xff0000) >> 16;sir[1] = (p & 0x00ff00) >> 8;sir[2] = (p & 0x0000ff);rinsum += sir[0];ginsum += sir[1];binsum += sir[2];stackpointer = (stackpointer + 1) % div;sir = stack[(stackpointer) % div];routsum += sir[0];goutsum += sir[1];boutsum += sir[2];rinsum -= sir[0];ginsum -= sir[1];binsum -= sir[2];yi++;}yw += w;}for (x = 0; x < w; x++) {rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; yp = -radius * w;for (i = -radius; i <= radius; i++) {yi = MAX(0, yp) + x;sir = stack[i + radius];sir[0] = r[yi];sir[1] = g[yi];sir[2] = b[yi];rbs = r1 - ABS(i);rsum += r[yi] * rbs;gsum += g[yi] * rbs;bsum += b[yi] * rbs;if (i > 0) {rinsum += sir[0];ginsum += sir[1];binsum += sir[2];}else {routsum += sir[0];goutsum += sir[1];boutsum += sir[2];}if (i < hm) {yp += w;}}yi = x;stackpointer = radius;for (y = 0; y < h; y++) {// Preserve alpha channel: ( 0xff000000 & pix[yi] )pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];rsum -= routsum;gsum -= goutsum;bsum -= boutsum;stackstart = stackpointer - radius + div;sir = stack[stackstart % div];if (x == 0) {vmin[y] = MIN(y + r1, hm) * w;}p = x + vmin[y];sir[0] = r[p];sir[1] = g[p];sir[2] = b[p];rinsum += sir[0];ginsum += sir[1];binsum += sir[2];rsum += rinsum;gsum += ginsum;bsum += binsum;stackpointer = (stackpointer + 1) % div; sir = stack[stackpointer];routsum += sir[0];goutsum += sir[1];boutsum += sir[2];rinsum -= sir[0];ginsum -= sir[1];binsum -= sir[2];yi += w;}}free(r);free(g);free(b);free(vmin);free(dv);free(stack);return(pix);}。
Android使⽤webp格式图⽚的步骤webp是Android推荐使⽤的⼀种图⽚格式,内存占⽤很⼩。
使⽤webp图⽚是app瘦⾝和内存优化的很好的⽅式之⼀。
下⾯是webp的使⽤步骤介绍:1.下载webp⼯具,这个google提供给我们将jpg和png等图⽚转为webp格式图⽚的⼯具2.解压并进⼊到下载好的bin⽬录下,即\libwebp-1.0.0-windows-x64\bin,打开cmd窗⼝输⼊ cwebp ,会提⽰使⽤⽅法 C:\libwebp-1.0.0-windows-x64\bin>cwebp Usage: cwebp [options] -q quality input.png -o output.webp //⽐如:cwebp -q 80 test.png -o test.webp ,其中-q表⽰质量参数,其值0到100,可省略,默认80,即cwebp test.png -o test.webp3.下⾯是⼀个批量转化的批处理脚本 @echo off for %%a in (D:\src\*.jpg,D:\src\*.png) do ( //这⼀⾏的意思是遍历 D:\src\ ⽬录下的所有jpg和png⽂件,可根据⾃⼰的情况修改为⾃⼰的⽬录路径 cwebp %%a -o D:\dest\%%~na.webp ) 然后复制上⾯的⽂本保存为 webp.bat⽂件,并将该webp.bat⽂件放在\libwebp-1.0.0-windows-x64\bin⽬录下即可。
然后就可以把需要转化的jpg和png⽂件放在 D:\src\ ⽬录下,再然后就是双击 webp.bat脚本⽂件,等待执⾏完后就可以在 D:\src\ ⽬录下看到转化后的webp图⽚了。
在编程中有时候需要对图片做特殊的处理,比如将图片做出黑白的,或者老照片的效果,有时候还要对图片进行变换,以拉伸,扭曲等等。
这些效果在android中有很好的支持,通过颜色矩阵(ColorMatrix)和坐标变换矩阵(Matrix)可以完美的做出上面的所说的效果。
下面将分别介绍这两个矩阵的用法和相关的函数。 颜色矩阵 android中可以通过颜色矩阵(ColorMatrix类)方面的操作颜色,颜色矩阵是一个5x4 的矩阵(如图1.1)
可以用来方面的修改图片中RGBA各分量的值,颜色矩阵以一维数组的方式存储如下: [ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t ] 他通过RGBA四个通道来直接操作对应颜色,如果会使用Photoshop就会知道有时处理图片通过控制RGBA各颜色通道来做出特殊的效果。
这个矩阵对颜色的作用计算方式如1.3示:
矩阵的运算规则是矩阵A的一行乘以矩阵C的一列作为矩阵R的一行, C矩阵是图片中包含的ARGB信息,R矩阵是用颜色矩阵应用于C之后的新的颜色分量,运算结果如下:
R' = a*R + b*G + c*B + d*A + e; G' = f*R + g*G + h*B + i*A + j; B' = k*R + l*G + m*B + n*A + o; A' = p*R + q*G + r*B + s*A + t;
颜色矩阵并不是看上去那么深奥,其实需要使用的参数很少,而且很有规律第一行决定红色第二行决定绿色 第三行决定蓝色,第四行决定了透明度,第五列是颜色的偏移量。下面是一个实际中使用的颜色矩阵。
如果把这个矩阵作用于各颜色分量的话,R=A*C,计算后会发现,各个颜色分量实际上没有任何的改变(R'=R G'=G B'=B A'=A)。
图1.5所示矩阵计算后会发现红色分量增加100,绿色分量增加100, 这样的效果就是图片偏黄,因为红色和绿色混合后得到黄色,黄色增加了100,图片当然就偏黄了。
改变各颜色分量不仅可以通过修改第5列的颜色偏移量也可如上面矩阵所示将对应的颜色值乘以一个倍数,直接放大。
上图1.6是将绿色分量乘以2变为原来的2倍。相信读者至此已经明白了如何通过颜色矩阵来改变各颜色分量。
下面编写一段代码来,通过调整颜色矩阵来获得不同的颜色效果,JavaCode如下: 复制到剪贴板 Java代码
1 CMatrix类: 2 public class CMatrix extends Activity { 3 4 private Button change; 5 private EditText [] et=new EditText[20]; 6 private float []carray=new float[20]; 7 private MyImage sv; 8 @Override 9 public void onCreate(Bundle savedInstanceState) { 10 super.onCreate(savedInstanceState); 11 setContentView(R.layout.main); 12 13 change=(Button)findViewById(R.id.set); 14 sv=(MyImage)findViewById(R.id.MyImage); 15 16 for(int i=0;i<20;i++){ 17 18 et[i]=(EditText)findViewById(R.id.indexa+i); 19 carray[i]=Float.valueOf(et[i].getText().toString()); 20 } 21 22 change.setOnClickListener(l); 23 } 24 25 private Button.OnClickListener l=new Button.OnClickListener(){ 26 27 @Override 28 public void onClick(View arg0) { 29 // TODO Auto-generated method stub 30 getValues(); 31 sv.setValues(carray); 32 sv.invalidate(); 33 } 34 35 }; 36 public void getValues(){ 37 for(int i=0;i<20;i++){ 38 39 carray[i]=Float.valueOf(et[i].getText().toString()); 40 } 41 42 } 43 44 45 } 46 MyImage类继承自View类: 47 public class MyImage extends View { 48 private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 49 private Bitmap mBitmap; 50 private float [] array=new float[20]; 51 52 private float mAngle; 53 54 public MyImage(Context context,AttributeSet attrs) { 55 super(context,attrs); 56 57 mBitmap = BitmapFactory.decodeResource(context.getResources(), 58 R.drawable.test); 59 invalidate(); 60 } 61 62 63 public void setValues(float [] a){ 64 for(int i=0;i<20;i++){ 65 array[i]=a[i]; 66 } 67 68 } 69 70 @Override protected void onDraw(Canvas canvas) { 71 Paint paint = mPaint; 72 73 74 75 paint.setColorFilter(null); 76 canvas.drawBitmap(mBitmap, 0, 0, paint); 77 78 ColorMatrix cm = new ColorMatrix(); 79 //设置颜色矩阵 80 cm.set(array); 81 //颜色滤镜,将颜色矩阵应用于图片 82 paint.setColorFilter(new ColorMatrixColorFilter(cm)); 83 //绘图 84 canvas.drawBitmap(mBitmap, 0, 0, paint); 85 Log.i("CMatrix", "--------->onDraw"); 86 87 88 } 89 90 }
复制代码 CMatrix类主要负责 接收颜色矩阵的设置和重绘,没有要说的。MyImage类中进行绘图工作,首先设置颜色矩阵cm.set(..)从一维数组中读取数据20个数据给颜色矩 阵赋值,paint.setColorFilter(..)设置颜色滤镜,然后绘图,效果就出来了(这个过程和PS差不多)如下: 看到这里,相信大家对颜色矩阵的作用已经有了一个直观的感受,现在也可以尝试做一个照片特效的软件。
但是各种效果并不能让用户手动调节颜色矩阵,这里需要计算公式,由于本人并不是做图形软件的也不能提供,可以参考这个链接: http://www.adobe.com/devnet/flash/articles/matrix_transformations/ColorMatrixDemo.swf
坐标变换矩阵 坐标变换矩阵是一个3*3的矩阵如图2.1,用来对图形进行坐标变化,将原来的坐标点转移到新的坐标点,
因为一个图片是有点阵和每一点上的颜色信息组成的,所以对坐标的变换,就是对每一点进行搬移形成新的图片。
具体的说图形的放大缩小,移动,旋转,透视,扭曲这些效果都可以用此矩阵来完成。
这个矩阵的作用是对坐标x,y进行变换计算结果如下: x'=a*x+b*y+c y'=d*x+e*y+f 通常情况下g=h=0,这样使1=0*x+0*y+1恒成立。和颜色矩阵一样,坐标变换矩阵真正使用的参数很少也很有规律。 上图就是一个坐标变换矩阵的简单例子,计算后发现x'=x+50,y'=y+50. 可见图片的每一点都在x和y方向上平移到了(50,50)点处,这种效果就是平移效果,将图片转移到了(50,50)处。
计算上面得矩阵x'=2*x,y‘=2*y.经过颜色矩阵和上面转移效果学习,相信读者可以明白这个矩阵的作用了,这个矩阵对图片进行了放大,具体的说是放大了二倍。 下面将介绍几种常用的变换矩阵: 1. 旋转
绕原点逆时针旋转θ度角的变换公式是 x' = xcosθ − ysinθ 与 y。' = xsinθ + ycosθ 2. 缩放
变换后长宽分别放大x'=scale*x;y'=scale*y.