牙叔教程 简单易懂
效果展示
为什么做
看到别人的头像是这种风格, 虽然我不会去修改自己的头像,
但是我想知道如何实现这样的效果,
虽然写出来了, 不过我感觉还是不完全像抖音的效果, 可能还缺点啥
环境
手机: Mi 11 Pro
Android版本: 11
Autojs版本: 9.0.10
思路
- 抖音的logo看起来像两张图片重叠的效果
- 两张图片是透明的
- 还加了偏移
- 从原图搞两张透明图片, 再叠加
你将学到以下知识点
- 设置seekbar监听事件
- 在seekbar监听事件中, img设置图片, 然后回收图片
- 由于修改图片是耗时操作, 所以要放到多线程中
- 合并透明图片
- byte数组转换成16进制字符串
- 判断图片类型
- 修改mat各个通道的值
- mat转bitmap
代码讲解
1. 导入类, 基本只要你在autojs使用opencv就会用到这些类
console.time("导入类"); runtime.images.initOpenCvIfNeeded(); importClass(org.opencv.core.MatOfByte); importClass(org.opencv.core.Scalar); importClass(org.opencv.core.Point); importClass(org.opencv.core.CvType); importClass(java.util.List); importClass(java.util.ArrayList); importClass(java.util.LinkedList); importClass(org.opencv.imgproc.Imgproc); importClass(org.opencv.imgcodecs.Imgcodecs); importClass(org.opencv.core.Core); importClass(org.opencv.core.Mat); importClass(org.opencv.core.MatOfDMatch); importClass(org.opencv.core.MatOfKeyPoint); importClass(org.opencv.core.MatOfRect); importClass(org.opencv.core.Size); importClass(org.opencv.features2d.DescriptorMatcher); importClass(org.opencv.features2d.Features2d); importClass(org.opencv.core.MatOfPoint2f); importClass(android.graphics.Bitmap); importClass(org.opencv.android.Utils); importClass(java.lang.StringBuilder); importClass(java.io.FileInputStream); importClass(java.io.File); console.timeEnd("导入类");
2. 界面
ui.layout( <vertical> <img id="img"></img> <text id="info" textSize="22sp" textColor="#fbfbfe" bg="#00afff" w="*" gravity="center"> 牙叔教程 </text> <horizontal margin="8"> <text>画笔透明度: </text> <text id="paintAlphaValue">0</text> <seekbar id="paintAlphaSeekbar" margin="9" w="*"></seekbar> </horizontal> <horizontal margin="8"> <text>图片透明度: </text> <text id="channelAlphaValue">0</text> <seekbar id="channelAlphaSeekbar" margin="9" w="*"></seekbar> </horizontal> <horizontal margin="8"> <text>图片偏移: </text> <text id="offsetValue">0</text> <seekbar id="offsetSeekbar" margin="9" w="*"></seekbar> </horizontal> </vertical> );
3. 设置监听
ui.channelAlphaValue.setText(String(channelAlpha)); ui.channelAlphaSeekbar.setMax(255); ui.channelAlphaSeekbar.setProgress(channelAlpha); ui.channelAlphaSeekbar.setOnSeekBarChangeListener({ onStopTrackingTouch: function (seekBar) { let progress = seekBar.getProgress(); let lastImg = currentImg; ui.channelAlphaValue.setText(String(progress)); channelAlpha = parseInt(progress); ui.post(function () { threads.start(function () { currentImg = updateImg(); }); lastImg.recycle(); }); }, });
4. 修改图片
function updateImg() { let modifiedMat = modifyChannelValue(mat); let modifiedBitmap = mat2bitmap(modifiedMat); modifiedMat.release(); let modifiedMat2 = modifyChannelValue2(mat); let modifiedBitmap2 = mat2bitmap(modifiedMat2); modifiedMat2.release(); let newImg = merge(grayBitmap, modifiedBitmap, modifiedBitmap2); ui.img.setImageBitmap(newImg.bitmap); modifiedBitmap.recycle(); modifiedBitmap2.recycle(); return newImg; }
5. mat转bitmap
function mat2bitmap(mat) { let width = mat.width(); let height = mat.height(); let bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Utils.matToBitmap(mat, bitmap); return bitmap; }
6. byte数组转换成16进制字符串
function bytesToHexString(src) { let stringBuilder = new StringBuilder(); if (src == null || src.length <= 0) { return null; } for (let i = 0; i < src.length; i++) { let v = src[i] & 0xff; let hv = java.lang.Integer.toHexString(v); if (hv.length < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); }
7. 释放资源
events.on("exit", function () { ui.post(function () { img.recycle(); grayBitmap.recycle(); grayImg.recycle(); currentImg.recycle(); log("退出回收资源"); }); });
名人名言
思路是最重要的, 其他的百度, bing, stackoverflow, github, 安卓文档, autojs文档, 最后才是群里问问
--- 牙叔教程
声明
部分内容来自网络
本教程仅用于学习, 禁止用于其他用途