实训第一周(1)

 

实训项目:研发一个可以通过键盘和语音实现输入个性化手写字体的聊天应用,并添加多点触控交互技术。

我本周的任务是:根据触摸位置与中心位置的偏置实现相应的字体局部变形。

这个功能的主要作用是实现异形文字,即同一文字的不同外形。比如即使是同一个人把一个字母写两遍,它们也不会完全相同。

1.文字手写绘入及保存:

绘制我们使用了canvas画布,实现非常简单,主要在ImageView的监听器中定义如下

showBitmap = Bitmap.createBitmap(iv_canvas.getWidth(),
                                iv_canvas.getHeight(), Bitmap.Config.ARGB_8888);
                        show_canvas = new Canvas(showBitmap);
                        show_canvas.drawColor(Color.WHITE);

图片的保存

/*
* 保存图片到SD卡上
*/
protected void saveBitmap() {
    try {
        // 保存图片到SD卡上
        File file = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + ".png");
        FileOutputStream stream = new FileOutputStream(file);
        baseBitmap.compress(CompressFormat.PNG, 100, stream);
        Toast.makeText(MainActivity.this, "保存图片成功", Toast.LENGTH_LONG).show();


        // Android设备Gallery应用只会在启动的时候扫描系统文件夹
        // 这里模拟一个媒体装载的广播,用于使保存的图片可以在Gallery中查看
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_MEDIA_MOUNTED);
        intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory()));
        sendBroadcast(intent);
    } catch (Exception e) {
        Toast.makeText(MainActivity.this, "保存图片失败", Toast.LENGTH_LONG).show();
        e.printStackTrace();
    }

}

2.交互式变形

一开始我们从网上找各种方法,一个比较好的是canvas的drawBitmapMesh网格变形方法。但经过大量的实验发现没法把变形后的bitmap提取出来,但我们必须要保存它,所以最后放弃了。

之后我自己写了一个比网格变形粗糙的方法,但因为效果比较显著且简单,所以就用了这个方法


方法如图所示:中间圆点为触摸点,根据它与图片中心的偏置来相应的拉扯图片(将每行、每列像素放大),然后将新图片每个点的颜色反向映射到原图像对应点的颜色。

 protected int[][] distort(int[][] pixels_copy, int dx, int dy, int row, int col) {
        int[][] result_pixels1 = new int[row][col];
        int[][] result_pixels2 = new int[row][col];

        int currentY, currentX;//当前要拉伸的行数
        int xAdd1, yAdd1, xAdd, yAdd;

        //逐行拉伸
        for (currentY = 0; currentY < row; currentY++) {
            //对于每一行要扩展的像素数
            if (currentY <= dy) {
                xAdd = currentY * Math.abs(dx - col / 2) / dy;
            } else {
                xAdd = (row - currentY) * Math.abs(dx - col / 2) / (row - dy);
            }
            //判断往左还是往右拉伸
            if (dx <= (col / 2)) {
                //往左拉伸
                xAdd1 = xAdd;
            } else {
                xAdd1 = 0;
            }
            //反向映射当前像素点的颜色
            for (int x = 0; x < col; x++) {
                int x0 = (x + xAdd1) * col / (col + xAdd);//对应的原图x坐标
                result_pixels1[currentY][x] = pixels_copy[currentY][x0];
            }
        }

        //逐列拉伸
        for (currentX = 0; currentX < col; currentX++) {
            //对于每一列要扩展的像素数
            if (currentX <= dx) {
                yAdd = currentX * Math.abs(dy - row / 2) / dx;
            } else {
                yAdd = (col - currentX) * Math.abs(dy - row / 2) / (col - dx);
            }
            //判断往上还是往下拉伸
            if (dy <= row / 2) {
                yAdd1 = yAdd;
            } else {
                yAdd1 = 0;
            }
            //反向映射颜色值
            for (int y = 0; y < row; y++) {
                int y0 = (y + yAdd1) * row / (row + yAdd);
                result_pixels2[y][currentX] = result_pixels1[y0][currentX];
            }
        }
        return result_pixels2;
    }

效果如下:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值