总的来说就是输入任何的文字字符,通过一定的算法,然后转成一些乱七八糟的,而且对称的图片。这大概就是那些区块链app的头像吧。
如上图所示,整体的头像分为三个部分,中心,side,角,其中每个部分都是有不同的图形”组成,一个中心,4个side,4个角。每个部分都是从基础图形库中随机读取出来,再设置不同的图片颜色;白色(0xffffff)和一个随机颜色作为这个图形的背景或者图案的颜色,下面我们分别来介绍每个部分的构成
在中心位置画出中心图形。按照一定的规则从基础图形”库中“随机”选取(随机规则后文会有详细的介绍)一个图形,在对图形中的图案进行上色处理(颜色也是随机获取)
######中心图形选取方法
public int getMiddle(){
return positiveMod(value>>2,34) ;//其中value为伪随机数后文有介绍 34为图形库的总数量
}
其中positiveMode的具体算法为
public static int positiveMod(long i, int m) {
return Math.abs((int) (i % m));
}
//后文都用 positiveMod()这个方法代替
######中心画笔颜色选取规则
int r = 100 + mIdenticonHash.getR() * 8;
int g = 100 + mIdenticonHash.getG() * 8;
int b = 100 + mIdenticonHash.getB() * 8;
return 0xff000000 + r * 0x10000 + g * 0x100 + b;
getR() : positiveMod((value >> 16),16);
getG(): positiveMod((value >> 20),16);
getB(): positiveMod((value >> 24),16);
######中心画图案的画笔,与画背景的画笔选取规则二选一
boolean invert = mIdenticonHash.getInvertMiddle() == 0;
Paint fg = invert ? mFgPaint : mBgPaint; // true 取第一个
Paint bg = invert ? mBgPaint : mFgPaint; // true 取第一个
//画背景的画笔,与画图形颜色的画笔随机选一个
public int getInvertMiddle(){
return positiveMod((value >> 13),2);
}
######主要绘制“中心”代码
private void drawMiddle(Canvas canvas) {
//随机画的颜色为生成的还是白色
boolean invert = mIdenticonHash.getInvertMiddle() == 0; // 去的某个值为0
Paint fg = invert ? mFgPaint : mBgPaint; // true 取第一个
Paint bg = invert ? mBgPaint : mFgPaint; // true 取第一个
canvas.save();
canvas.translate(mTileMeasure.width, mTileMeasure.height); //画布平移 移到中间的的位置,即左上角在中心,通过传入的mTitleMeasure为一个小正方形
getTile(mIdenticonHash.getMiddle()).draw(canvas, mTileMeasure, 0, bg, fg);
canvas.restore();
}
先从最左边(0,height/3)的部分开始画出第一个图形;第二个side图形开始绕着自身中心点先旋转90度,在移动到(width/3,height/2);第三个side图形也绕着自身中心点旋转90度(相对第一个side图形旋转180度),再移动到(2/3*width,height/3);第四个图形也绕着自身旋转90度(相对第一个side图形旋转270度),再移动到(width/3,0);
######背景画笔,图形的选取上和上面“中心”的选取规则是一样的,只是选取的算法不一样
boolean invert = mIdenticonHash.getInvertSides() == 0;
Paint fg = invert ? mFgPaint : mBgPaint;
Paint bg = invert ? mBgPaint : mFgPaint;
public int getInvertCorners(){
return positiveMod((value >> 15),2);
}
######图片选取规则
public int getSides(){
return positiveMod((value >> 8),34);
}
######颜色的选取规则:
protected int getColorSide(){
int r = 100 + mIdenticonHash.getG() * 8;
int g = 100 + mIdenticonHash.getR() * 8;
int b = 100 + mIdenticonHash.getB() * 8;
return 0xff000000 + r * 0x10000 + g * 0x100 + b;
}
//具体的getG() ,getR(),getB()与“中心”的选取规则相同
######side 初始图片旋转的角度选取:
int rotation = mIdenticonHash.getSidesRotation() * 90; //初始旋转角度选取
public int getSidesRotation(){
return positiveMod((value >> 30), 4);
}
######主要绘制“side”代码
/**
* 旋转画四个边的图形(逆时针)
* @param canvas
*/
private void drawSides(Canvas canvas) {
mFgPaint.setColor(getColorSide());
ClassicIdenticonTile.Tiles drawer = getTile(mIdenticonHash.getSides());
boolean invert = mIdenticonHash.getInvertSides() == 0;
int rotation = mIdenticonHash.getSidesRotation() * 90; // 0 1 2 3 *90 只会出现一次
Paint fg = invert ? mFgPaint : mBgPaint;
Paint bg = invert ? mBgPaint : mFgPaint;
canvas.save();
canvas.translate(0, mTileMeasure.height);
drawer.draw(canvas, mTileMeasure, 0 + rotation, bg, fg);
canvas.restore();
canvas.save();
canvas.translate(mTileMeasure.width, mTileMeasure.height2);
drawer.draw(canvas, mTileMeasure, 90 + rotation, bg, fg);
canvas.restore();
canvas.save();
canvas.translate(mTileMeasure.width2, mTileMeasure.height);
drawer.draw(canvas, mTileMeasure, 180 + rotation, bg, fg);
canvas.restore();
canvas.save();
canvas.translate(mTileMeasure.width, 0);
drawer.draw(canvas, mTileMeasure, 270 + rotation, bg, fg);
canvas.restore();
}
先从最左边(0,0)的部分开始画出第一个图形;第二个side图形开始绕着自身中心点先旋转90度,在移动到(0,height);第三个side图形也绕着自身中心点旋转90度(相对第一个side图形旋转180度),再移动到(width,height);第四个图形也绕着自身旋转90度(相对第一个side图形旋转270度),再移动到(width,0);
背景画笔,图形的选取和上面的“中心”,“side”的选取规则是一样的,只是选取的规则不一样
######画笔的选取规则
boolean invert = mIdenticonHash.getInvertCorners() == 0;
Paint fg = invert ? mFgPaint : mBgPaint;
Paint bg = invert ? mBgPaint : mFgPaint;
public int getInvertCorners(){
return positiveMod((value >> 14),2);
}
######图形选取规则
public int getCorners(){
retrun positiveMod((value >> 3), 34);
}
######颜色的选取规则:
protected int getColorConner(){
int r = 100 + mIdenticonHash.getB() * 8;
int g = 100 + mIdenticonHash.getR() * 8;
int b = 100 + mIdenticonHash.getG() * 8;
return 0xff000000 + r * 0x10000 + g * 0x100 + b;
}
//具体的getG() ,getR(),getB()与“中心”,“side”的选取规则相同
######“角” 初始图片旋转的角度选取:
int rotation = mIdenticonHash.getCornersRotation() * 90; //初始旋转角度选取
public int getCornersRotation(){
return positiveMod((value >> 28), 4);
}
######主要绘制“角”代码
/**
/**
* 旋转着画四个边角
* @param canvas
*/
private void drawCorners(Canvas canvas) {
mFgPaint.setColor(getColorConner());
ClassicIdenticonTile.Tiles drawer = getTile(mIdenticonHash.getCorners());
boolean invert = mIdenticonHash.getInvertCorners() == 0;
int rotation = mIdenticonHash.getCornersRotation() * 90;
Paint fg = invert ? mFgPaint : mBgPaint;
Paint bg = invert ? mBgPaint : mFgPaint;
drawer.draw(canvas, mTileMeasure, 0 + rotation, bg, fg);
canvas.save();
canvas.translate(mTileMeasure.width2, 0);
drawer.draw(canvas, mTileMeasure, 90 + rotation, bg, fg);
canvas.restore();
canvas.save();
canvas.translate(mTileMeasure.width2, mTileMeasure.height2);
drawer.draw(canvas, mTileMeasure, 180 + rotation, bg, fg);
canvas.restore();
canvas.save();
canvas.translate(0, mTileMeasure.height2);
drawer.draw(canvas, mTileMeasure, 270 + rotation, bg, fg);
canvas.restore();
}
}
#####补充:
#####伪随机数算法,即前面文字提到的value这个值
/**
* 生成一个伪随机数,整个图形的生成都依据这个随机数
* @param data
* @return
*/
public static int FNVHash1(String data)
{
final int p = 16777619;
int hash = (int)2166136261L;
for(int i=0;i> 7;
hash += hash << 3;
hash ^= hash >> 17;
hash += hash << 5;
return hash;
}
#####基础图形库
这个没什么好说的就是画一些基础图形。一般来说话的图形越多,真个头像的组合就会越丰富。
其实整个随机头像也是由基础的图形,通过绘制不同的颜色,不同的位置,不同的角度组成的,
也很简单。虽然和其他的效果图有一定的不同,但是总的来说还是实现了这个功能,后续还有很多可以改进的地方。
下载地址: demo下载地址,很久以前写的,如果有需要,下载下来凑合着看吧;