2021SC@SDUSC
目录
案例——draw_compare
scaleBitmap方法
public static Bitmap scaleBitmap(Bitmap target, int w, int h) {
if (target == null || target.isRecycled()) return target;
int width = target.getWidth(), height = target.getHeight();
Matrix matrix = new Matrix();
matrix.postScale(((float) w / width), ((float) h / height));
return Bitmap.createBitmap(target, 0, 0, width, height, matrix, true);
}
该方法用于目标bitmap进行缩放。参数target为目标bitmap,w为新的宽度,h为新的高度,返回值为缩放后的bitmap。
这里首先要进行判断,判断target是否为空,以及是否已经被回收,如果是,则直接返回target。否则,则进行下面的操作。实例化width为target的宽,height为target的高。创建一个新的Matrix对象,通过调用matrix的postScale方法完成对图像的缩放。
Android matrix.postScale的用法:
public boolean postScale(float sx,float sy,float px,float py)
者个api的第一个参数sx是x轴的缩放大小,第二个参数sy是y轴的缩放大小,px、py是缩放的中心位置。 这个中心点不一定在图片的中心位置,有可能在图片的外面。例如下面的图中:
我们现在用到的是只有前两个参数的形式,较为简单。
除了postScale之外,还有preScale、setScale两个操作。它们在内部都是通过修改MSCALE_X、MSCALE_Y来实现的。那么它们有什么区别呢?
1)setScale(sx,sy),首先会将该Matrix设置为对角矩阵,即相当于调用reset()方法,然后再设置该Matrix的MSCALE_X和MSCALE_Y直接设置为sx,sy的值;
2)preSclae(sx,sy),不会重置Matrix,而是直接与Matrix之前的MSCALE_X和MSCALE_Y值结合起来(相乘),M'=M*S(sx,sy);
3)postScale(sx,sy),和preScale的操作一样。但是它们的执行顺序有区别。
isLookLikePaintColor方法
private static boolean isLookLikePaintColor(int r, int g, int b) {
for (int[] color : mPaintColors) {
int dither = 10; //允许色值的抖动范围是10 (max = 255)
int redDither = Math.abs(color[0] - r);
int greenDither = Math.abs(color[1] - g);
int blueDither = Math.abs(color[2] - b);
if (redDither < dither && greenDither < dither && blueDither < dither)
return true;
}
return false;
}
该方法主要用于根据色值判断和目标颜色是否近似。如果色值得抖动小于10,就返回true。
Math.abs()方法返回参数的绝对值。
checkNearItemIsHit方法
private static boolean checkNearItemIsHit(int nearCount, int[][] targetPixels, Point currentPos) {
//先初始化数据
int length = nearCount * 2 + 1;
int[][] state = new int[length][length];
int verticalCount = targetPixels.length;
int horizontalCount = targetPixels[0].length;
Queue<Point> queue = new ArrayDeque<>(); //这个是应该查找的点的队列
queue.offer(new Point(nearCount, nearCount)); //当前pos先入队
state[nearCount][nearCount] = 1; //标记该点无效(已经被用过)
while (!queue.isEmpty()) { //有任务未完成
Point header = queue.poll(); //队头出队
List<Point> directions = getCanArrivePos(state, header); //获取队头周边8个可到达的点 (注意是可到达,不包括已经走过的点)
//遍历获取到的周边点
for (int i = 0; i < directions.size(); i++) {
Point direction = directions.get(i);
//调整坐标
int x = direction.x < length ? currentPos.x - direction.x : currentPos.x + direction.x;
int y = direction.y < length ? currentPos.y - direction.y : currentPos.y + direction.y;
//检查越界
if (!isOutside(direction.x, direction.y, verticalCount, horizontalCount)
&& !isOutside(x, y, verticalCount, horizontalCount)) {
//等于1表示查找到了匹配的点
if (targetPixels[y][x] == 1)
return true;
//否则将这个点入队,需要查找这个点的周围
else
queue.offer(direction);
}
}
}
//任务队列为空,且还没返回,自然是找不到了
return false;
}
该方法以广度优先的遍历方法,以currentPos为起点,来查找现金滚nearCount个像素点的色值是否近似于目标颜色。参数nearCount为需要查找周边像素的个数,targetPixels为色值表,cuurrentPos为当前坐标。返回值为是否查找到。
首先进行数据的初始化。定义quene为应该查找的点的队列,当前pos先入队。将state[nearCount][nearCount]标记为无效(已经被用过了)。然后检查如果有任务未完成,则进入while循环。while循环中的主要操作为队头出队,然后获取队头周边8个可到达的点(不包括已经走过的点)。遍历获取到的周边点,调整坐标,然后用isOutSide来检查越界。如果未越界,则判断targetPixels[y][x]是否等于1,如果是则返回true,否则将这个点入队,需要查找这个点的周围的点。最终如果任务队列为空,还未返回时,则说明未找到,返回false。
isOutSide方法
private static boolean isOutside(int x, int y, int verticalCount, int horizontalCount) {
return x < 0 || y < 0 || x > horizontalCount - 1 || y > verticalCount - 1;
}
该函数用于检查目标pos是否越界。通过参数中的坐标与边界的对比可以判断是否越界。