[计算机] android仿区块链头像自动生成

查看:899 |回复:1 | 2021-4-15 11:35:18

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 智慧鼓励师 于 2021-4-16 00:50 编辑

总的来说就是输入任何的文字字符,通过一定的算法,然后转成一些乱七八糟的,而且对称的图片。这大概就是那些区块链app的头像吧。

先来看下头像的效果图 image.png


头像的构成示意图 image.png

如上图所示,整体的头像分为三个部分,中心,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();

        }
side部分
先从最左边(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<data.length();i++) {
            hash = (hash ^ data.charAt(i)) * p;
        }
        hash += hash << 13;
        hash ^= hash >> 7;
        hash += hash << 3;
        hash ^= hash >> 17;
        hash += hash << 5;
        return hash;
    }


#####基础图形库
这个没什么好说的就是画一些基础图形。一般来说话的图形越多,真个头像的组合就会越丰富。

总结
其实整个随机头像也是由基础的图形,通过绘制不同的颜色,不同的位置,不同的角度组成的,
也很简单。虽然和其他的效果图有一定的不同,但是总的来说还是实现了这个功能,后续还有很多可以改进的地方。
————————————————
版权声明:本文为CSDN博主「abao_kevin520」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/abao_kevin520/article/details/80373079



2021-4-15 11:35:18  
 赞 赞 1

使用道具 登录

1个回答,把该问题分享到群,邀请大神一起回答。
2#
回复 收起回复
2023-3-1 12:10:40   回复
 赞 赞 1

使用道具 登录

CG 游戏行业专业问题

程序逻辑文章算法
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表