Android绘图(二)
来源:互联网 发布:北部战区山东知乎 编辑:程序博客网 时间:2024/05/16 15:24
(《群英传》)整理笔记:
图像处理之色彩特效处理:
(这一块不太懂,先记录下一个例子)
package com.android.utils;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.ColorMatrix;import android.graphics.ColorMatrixColorFilter;import android.graphics.Paint;/** * 设置图像矩阵的代码 * @author Administrator * */public class ImageHelper { public static Bitmap handleImageEffect(Bitmap bm, float hue, float saturation, float lum) { Bitmap bmp = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bmp); Paint paint = new Paint(); ColorMatrix hueMatrix = new ColorMatrix(); hueMatrix.setRotate(0, hue); hueMatrix.setRotate(1, hue); hueMatrix.setRotate(2, hue); ColorMatrix saturationMatrix = new ColorMatrix(); saturationMatrix.setSaturation(saturation); ColorMatrix lumMatrix = new ColorMatrix(); lumMatrix.setScale(lum, lum, lum, 1); ColorMatrix imageMatrix = new ColorMatrix(); imageMatrix.postConcat(hueMatrix); imageMatrix.postConcat(saturationMatrix); imageMatrix.postConcat(lumMatrix); paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix)); canvas.drawBitmap(bm, 0, 0, paint); return bmp; } public static Bitmap handleImageNegative(Bitmap bm) { int width = bm.getWidth(); int height = bm.getHeight(); int color; int r, g, b, a; Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); int[] oldPx = new int[width * height]; int[] newPx = new int[width * height]; bm.getPixels(oldPx, 0, width, 0, 0, width, height); for (int i = 0; i < width * height; i++) { color = oldPx[i]; r = Color.red(color); g = Color.green(color); b = Color.blue(color); a = Color.alpha(color); r = 255 - r; g = 255 - g; b = 255 - b; if (r > 255) { r = 255; } else if (r < 0) { r = 0; } if (g > 255) { g = 255; } else if (g < 0) { g = 0; } if (b > 255) { b = 255; } else if (b < 0) { b = 0; } newPx[i] = Color.argb(a, r, g, b); } bmp.setPixels(newPx, 0, width, 0, 0, width, height); return bmp; } public static Bitmap handleImagePixelsOldPhoto(Bitmap bm) { Bitmap bmp = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), Bitmap.Config.ARGB_8888); int width = bm.getWidth(); int height = bm.getHeight(); int color = 0; int r, g, b, a, r1, g1, b1; int[] oldPx = new int[width * height]; int[] newPx = new int[width * height]; bm.getPixels(oldPx, 0, bm.getWidth(), 0, 0, width, height); for (int i = 0; i < width * height; i++) { color = oldPx[i]; a = Color.alpha(color); r = Color.red(color); g = Color.green(color); b = Color.blue(color); r1 = (int) (0.393 * r + 0.769 * g + 0.189 * b); g1 = (int) (0.349 * r + 0.686 * g + 0.168 * b); b1 = (int) (0.272 * r + 0.534 * g + 0.131 * b); if (r1 > 255) { r1 = 255; } if (g1 > 255) { g1 = 255; } if (b1 > 255) { b1 = 255; } newPx[i] = Color.argb(a, r1, g1, b1); } bmp.setPixels(newPx, 0, width, 0, 0, width, height); return bmp; } public static Bitmap handleImagePixelsRelief(Bitmap bm) { Bitmap bmp = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), Bitmap.Config.ARGB_8888); int width = bm.getWidth(); int height = bm.getHeight(); int color = 0, colorBefore = 0; int a, r, g, b; int r1, g1, b1; int[] oldPx = new int[width * height]; int[] newPx = new int[width * height]; bm.getPixels(oldPx, 0, bm.getWidth(), 0, 0, width, height); for (int i = 1; i < width * height; i++) { colorBefore = oldPx[i - 1]; a = Color.alpha(colorBefore); r = Color.red(colorBefore); g = Color.green(colorBefore); b = Color.blue(colorBefore); color = oldPx[i]; r1 = Color.red(color); g1 = Color.green(color); b1 = Color.blue(color); r = (r - r1 + 127); g = (g - g1 + 127); b = (b - b1 + 127); if (r > 255) { r = 255; } if (g > 255) { g = 255; } if (b > 255) { b = 255; } newPx[i] = Color.argb(a, r, g, b); } bmp.setPixels(newPx, 0, width, 0, 0, width, height); return bmp; }}
import com.android.utils.ImageHelper;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.widget.ImageView;import android.widget.SeekBar;import android.widget.SeekBar.OnSeekBarChangeListener;/** * 色调、饱和度、亮度调整图片 * @author Administrator * */public class MyView3 extends Activity implements OnSeekBarChangeListener{ private static int MAX_VALUE = 255; private static int MID_VALUE = 127; private ImageView mImageView; private SeekBar mSeekbarhue, mSeekbarSaturation, mSeekbarLum; private float mHue, mStauration, mLum; private Bitmap bitmap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_view3); bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.qie); mImageView = (ImageView) findViewById(R.id.imageview); mSeekbarhue = (SeekBar) findViewById(R.id.seekbarHue); mSeekbarSaturation = (SeekBar) findViewById(R.id.seekbarSaturation); mSeekbarLum = (SeekBar) findViewById(R.id.seekbatLum); mSeekbarhue.setOnSeekBarChangeListener(this); mSeekbarSaturation.setOnSeekBarChangeListener(this); mSeekbarLum.setOnSeekBarChangeListener(this); mSeekbarhue.setMax(MAX_VALUE); mSeekbarSaturation.setMax(MAX_VALUE); mSeekbarLum.setMax(MAX_VALUE); mSeekbarhue.setProgress(MID_VALUE); mSeekbarSaturation.setProgress(MID_VALUE); mSeekbarLum.setProgress(MID_VALUE); mImageView.setImageBitmap(bitmap); } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { switch (seekBar.getId()) { case R.id.seekbarHue: mHue = (progress - MID_VALUE) * 1.0F / MID_VALUE * 180; break; case R.id.seekbarSaturation: mStauration = progress * 1.0F / MID_VALUE; break; case R.id.seekbatLum: mLum = progress * 1.0F / MID_VALUE; break; } mImageView.setImageBitmap(ImageHelper.handleImageEffect( bitmap, mHue, mStauration, mLum)); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { }}
程序运行后可拖动三个属性条实时改变图像。
(留待以后学习)
【色彩矩阵、颜色矩阵ColorMatrix、常用图像颜色矩阵处理效果(灰度、图像反转、怀旧、去色、高饱和度)、像素点、常用像素点处理效果(底片、老照片、浮雕)】
图像处理之图形特效处理
图像的变形处理包含四类基本变换
Translate:平移变换
Rotate:旋转变换
Scale:缩放变换
Skew:错切变换
像素块分析
drawBitmapMeshh():将图像分成了一个个小块,然后通过改变每一个图像块来修改整个图像。基本上可以实现所有的图像特效。
canvas.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint);
Bitmap:将要扭曲的图像;meshWidth:需要的横向网格数目;meshHeight:需要的纵向网格数目;verts:网格交叉点坐标数组;vertOffset:verts数组中开始跳过的(x, y)坐标对的数目。
示例:旗帜飞扬
核心思想:让图片中每个交织点的横坐标较之前坐标不断变化
import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.util.AttributeSet;import android.view.View;public class DrawBitmapMesh extends View { private final int WIDTH = 200; private final int HEIGHT = 200; private int COUNT = (WIDTH + 1) * (HEIGHT + 1); private float[] verts = new float[COUNT * 2]; private float[] orig = new float[COUNT * 2]; private Bitmap bitmap; private float A; private float k = 1; public DrawBitmapMesh(Context context) { super(context); initView(context); } public DrawBitmapMesh(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public DrawBitmapMesh(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(context); } private void initView(Context context) { setFocusable(true); // 第一步:获取交叉点的坐标,保存在orig数组中 bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.test); float bitmapWidth = bitmap.getWidth(); float bitmapHeight = bitmap.getHeight(); // 通过循环遍历所有的交叉线,并按比例获取其坐标 int index = 0; for (int y = 0; y <= HEIGHT; y++) { float fy = bitmapHeight * y / HEIGHT; for (int x = 0; x <= WIDTH; x++) { float fx = bitmapWidth * x / WIDTH; orig[index * 2 + 0] = verts[index * 2 + 0] = fx; // 为了避免扭曲后被屏幕遮挡,人为将坐标+100为了让图像下移 orig[index * 2 + 1] = verts[index * 2 + 1] = fy + 100; index += 1; } } A = 50; } @Override protected void onDraw(Canvas canvas) { flagWave(); // 第四步:将处理后的图像绘制出来。每次绘制的时候通过改变相位来改变偏移量,从而造成动态的效果 k += 0.1F; canvas.drawBitmapMesh(bitmap, WIDTH, HEIGHT, verts, 0, null, 0, null); invalidate(); } // 第二步:改变交叉点的纵坐标的值,使用sin x 来改变交叉点纵坐标的值,保存到vert数组中 private void flagWave() { for (int j = 0; j <= HEIGHT; j++) { for (int i = 0; i <= WIDTH; i++) { verts[(j * (WIDTH + 1) + i) * 2 + 0] += 0; // 第三步:让图像动起来。利用函数的周期性 float offsetY = (float) Math.sin((float) i / WIDTH * 2 * Math.PI + Math.PI * k); verts[(j * (WIDTH + 1) + i) * 2 + 1] = orig[(j * WIDTH + i) * 2 + 1] + offsetY * A; } } }}
Android图像处理值画笔特效处理:
各种各样的画笔:记号笔、毛笔、蜡笔等。
1、PorterDuffXfermode:
PorterDuffXfermode设置的是两个图层交际区域的显示方式,dst是先画的图形,而src是后画的图形,通过控制遮罩层的图形,来控制下面被这招图形的显示效果,最常用的就是通过DST_IN、SRC_IN模式来实现将一个矩形图片变成圆角图片或者圆形图片的效果。
import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;/** * 刮刮卡效果 * * @author Administrator * */public class ProterDuffXfermode extends View { private Bitmap mBgBitmap, mFgBitmap; private Paint mPaint; private Canvas mCanvas; private Path mPath; public ProterDuffXfermode(Context context, AttributeSet attrs) { super(context, attrs); init(); } /** * 第一步:做一些初始化工作。例如准备好图片,设置好Paint的一些属性 */ private void init() { mPaint = new Paint(); // 将画笔的透明度置为0,这样才能显示出擦除的效果 mPaint.setAlpha(0); // 第三步:使用DST_IN模式 mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); mPaint.setStyle(Paint.Style.STROKE); // 让笔触和连接处更加圆滑一点Paint.Join.ROUND,Paint.Cap.ROUND mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeWidth(60); mPaint.setStrokeCap(Paint.Cap.ROUND); mPath = new Path(); mBgBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.qie); mFgBitmap = Bitmap.createBitmap(mBgBitmap.getWidth(), mBgBitmap.getHeight(), Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mFgBitmap); mCanvas.drawColor(Color.GRAY); } // 第二步:获取用户手指滑动所产生的路径,使用Path保存用户手指划过的路径(贝塞尔曲线会有更好的显示效果) @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPath.reset(); mPath.moveTo(event.getX(), event.getY()); break; case MotionEvent.ACTION_MOVE: mPath.lineTo(event.getX(), event.getY()); break; } mCanvas.drawPath(mPath, mPaint); invalidate(); return true; } @Override protected void onDraw(Canvas canvas) { // 第四步:将路径绘制到前面覆盖的图层上面即可 canvas.drawBitmap(mBgBitmap, 0, 0, null); canvas.drawBitmap(mFgBitmap, 0, 0, null); }}
2、Shader
着色器、渲染器。用来实现一系列的渐变、渲染效果。
Android中的Shader包括以下几种:
(1)BitmapShader位图:产生的是一个图像,作用是通过Paint对画布进行指定Bitmap的填充。填充的模式:CLAMP拉伸;REPEAT重复;MIRROR镜像。
(2)LinearGradient线性;
(3)RadialGradient光束;
(4)SweepGradient梯度;
(5)ComposeShader混合。
// 用一张图片创建了一支具有图像填充功能的画笔,并使用这支画笔绘制了一个圆形。mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); mPaint = new Paint(); mPaint.setShader(mBitmapShader); canvas.drawCircle(250, 250, 200, mPaint);
// LinearGradient的使用:只需要指定渐变起始的颜色就可以了。 mPaint = new Paint(); mPaint.setShader(new LinearGradient(0, 0, 200, 200, Color.BLUE, Color.YELLOW, Shader.TileMode.REPEAT)); canvas.drawRect(0,0,800,800,mPaint);
但是这些渐变效果不会直接使用在程序里,通常情况下把这种渐变效果作为一个遮罩层来使用。
import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.LinearGradient;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.Shader;import android.util.AttributeSet;import android.view.View;public class DaoYing extends View { private Bitmap mSrcBitmap, mRefBitmap; private Paint mPaint; private PorterDuffXfermode mXfermode; public DaoYing(Context context) { super(context); initRes(context); } public DaoYing(Context context, AttributeSet attrs) { super(context, attrs); initRes(context); } public DaoYing(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initRes(context); } /** * 第一步:把原图复制一份并进行翻转 * * @param context */ private void initRes(Context context) { mSrcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.qie); Matrix matrix = new Matrix(); // 使用matrix.setScale(1F, -1F)方法来实现图片的垂直翻转。水平翻转同理 matrix.setScale(1F, -1F); mRefBitmap = Bitmap.createBitmap(mSrcBitmap, 0, 0, mSrcBitmap.getWidth(), mSrcBitmap.getHeight(), matrix, true); mPaint = new Paint(); mPaint.setShader(new LinearGradient(0, mSrcBitmap.getHeight(), 0, mSrcBitmap.getHeight() + mSrcBitmap.getHeight() / 4, 0XDD000000, 0X10000000, Shader.TileMode.CLAMP)); mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN); } @Override protected void onDraw(Canvas canvas) { // 第二步:绘制两张图片即原图和倒影图 canvas.drawColor(Color.BLACK); canvas.drawBitmap(mSrcBitmap, 0, 0, null); canvas.drawBitmap(mRefBitmap, 0, mSrcBitmap.getHeight(), null); mPaint.setXfermode(mXfermode); // 第三步:绘制渐变效果矩形,并通过Mode.DST_IN模式绘制到倒影图上,形成一个具有过度效果的渐变层 canvas.drawRect(0, mSrcBitmap.getHeight(), mRefBitmap.getWidth(), mSrcBitmap.getHeight() * 2, mPaint); mPaint.setXfermode(null); }}
- Android绘图(二)
- Android绘图机制(二)--2D绘图基础
- Android的2D绘图(二)
- Android绘图机制(二) ViewGroup类
- Android绘图机制(二) ViewGroup类
- Android xml绘图(二)-----------Shape
- Android手指绘图(二)
- Android 绘图(二) Canvas
- Android绘图机制二
- Android绘图机制与处理技巧(二)Android绘图技巧
- 决策树绘图(二)
- 简单绘图(二)
- 我的android绘图学习笔记(二)
- Android绘图相关类文档学习与翻译(二)
- Android—图形用户界面之绘图Paint(二)
- Android UI效果之绘图篇(二):Canvas
- Android群英传--绘图机制和处理技巧(二)
- Android自定义控件:绘图(二)------路径及文字
- 多线程中的timer
- Spring MVC 返回类型为字符串时, 返回中文变成"?"处理
- Win7(64位系统)中用Python连接access数据库(access2010)
- 数据库中批量授权与回收权限
- Linux下mount命令解析
- Android绘图(二)
- 响应式网站设计与制作
- 小爬虫1.0
- 14:类初步使用
- 优惠码,开启了您的奖学金征程
- AngularJS基础——MVC、$scope的作用域、依赖注入的代码压缩以及run方法
- 【搜索】BZOJ 3990: 【Sdoi 2015】排序
- CocoaPods安装和使用教程
- 浅谈MVC架构模式