Java 图片 滑动 解锁「建议收藏」

Java 图片 滑动 解锁「建议收藏」滑动解锁功能大家都不陌生,类似于如下这种:公司近期也要求实现类似的功能,百度各种文章,总算实现了一个比较糙的版本,保密等原因就不贴完成图了。我觉得难点在于滑块图和背景图的处理。图片处理原理我粗略的理解,图片就是一个二维的直角坐标系的一部分,(x,y)就是对应位置的一个像素点,可以操作某一个像素点,比如改变颜色,设置透明度等。Java中使用BufferedImage完成图…

大家好,又见面了,我是你们的朋友全栈君。

滑动解锁功能大家都不陌生,类似于如下这种:

Java 图片 滑动 解锁「建议收藏」

公司近期也要求实现类似的功能,百度各种文章,总算实现了一个比较糙的版本,保密等原因就不贴完成图了。

我觉得难点在于滑块图和背景图的处理。

图片处理原理

Java 图片 滑动 解锁「建议收藏」

我粗略的理解,图片就是一个二维的直角坐标系的一部分,(x,y)就是对应位置的一个像素点,可以操作某一个像素点,比如改变颜色,设置透明度等。

Java中使用BufferedImage完成图片处理等操作,先来段代码热热身:

/**
* 读取图片获取高宽
*/
String oldFileName = "E:\\images\\black_300_150.png";
BufferedImage image = ImageIO.read(new File(oldFileName));
int height = image.getHeight();
int width = image.getWidth();

在内存中生成图片,并保存到磁盘中:

BufferedImage dest = new BufferedImage(140,120,BufferedImage.TYPE_4BYTE_ABGR);
        try {
            FileOutputStream fos = new FileOutputStream(new File("E:\\images\\piece" + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".png"));
            ImageIO.write(dest, "png", fos);
            fos.flush();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

大概就是这样吧,抛个砖引一下各位的玉。

热完身上重点,就一句话:将背景图指定位置的像素值拷贝并设置到滑块图中,并将背景图抠图位置进行处理

具体步骤:

1.创建内存中创建一个指定大小的滑块图。

2.根据背景图宽高和滑块图宽高随机设置一个抠图点。

3.复制背景图的抠图区域的像素值到滑块图上。

4.处理背景图抠图位置。

划块图形状

有多种方式实现,如果几何方面编码足够六,可以使用代码生成形状,也可以直接用美工生成一个透明背景的图片,下面的生成滑块图代码,是我抄来的:

    static int targetLength=55;//小图长
    static int targetWidth=45;//小图宽
    static int circleR=6;//半径
    static int r1=3;//距离点
    private static int[][] getBlockData() {
        int[][] data = new int[targetLength][targetWidth];
        double x2 = targetLength-circleR;
        //随机生成圆的位置
        double h1 = circleR + Math.random() * (targetWidth-3*circleR-r1);
        double po = circleR*circleR;
        double xbegin = targetLength-circleR-r1;
        double ybegin = targetWidth-circleR-r1;
        for (int i = 0; i < targetLength; i++) {
            for (int j = 0; j < targetWidth; j++) {
                double d3 = Math.pow(i - x2,2) + Math.pow(j - h1,2);
                double d2 = Math.pow(j-2,2) + Math.pow(i - h1,2);
                if ((j <= ybegin && d2 <= po)||(i >= xbegin && d3 >= po)) {
                    data[i][j] = 0;
                }  else {
                    data[i][j] = 1;
                }

            }
        }
        return data;
    }

如你所见,这是个二维数组,刚才说过一个图片就是一个平面直角坐标系,而二维数组就相当于一个图片。

当然也可以根据美工提供的透明背景图片来反向分析出此二维数组,这里利用的原理是图片每个RGB的高8位为0代表透明:

/**
     * 根据切图图片转化为切图数组
     * @param image 切图图片
     */
    public static int[][] convertAryByImage(BufferedImage image) {
        int[][] blockData = null;
        if (image != null) {
            int width = image.getWidth();
            int height = image.getHeight();
            blockData = new int[width][height];
            for (int i = 0; i < width; i++) {
                for (int j = 0; j < height; j++) {
                    int rgb = image.getRGB(i, j);
                    int x = rgb & 0xff000000;
                    blockData[i][j] = x == 0 ? 0 : 1;
                }
            }
        }
        return blockData;
    }

背景图处理

有了上一步的二维数据,那么我们就可以开始抠图了:

/**
* oriImage 原图
  targetImage 滑块图
  templateImage 数组
  x,y 在原图中抠图位置
*/
private static void cutByTemplate(BufferedImage oriImage,BufferedImage targetImage, int[][] templateImage, int x,int y){
        for (int i = 0; i < targetImage.getWidth(); i++) {
            for (int j = 0; j < targetImage.getHeight(); j++) {
                int rgb = templateImage[i][j];
                // 原图中对应位置变色处理
                int rgb_ori = oriImage.getRGB(x + i, y + j);
                if (rgb == 1) {
                    //抠图上复制对应颜色值
                    targetImage.setRGB(i, j, rgb_ori);
                    //原图对应位置颜色变化
                    oriImage.setRGB(x + i, y + j, rgb_ori & 0x363636 );
                }else{
                    //这里把背景设为透明
                    targetImage.setRGB(i, j, rgb_ori & 0x00ffffff);
                }
            }
        }
    }

处理完之后滑块图大概是这个样子的:

Java 图片 滑动 解锁「建议收藏」

原图是这样的:

Java 图片 滑动 解锁「建议收藏」

这里原图的处理,也可以使用高斯模糊(转来的,转侵删):

https://cloud.tencent.com/developer/article/1005568

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/150114.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 延时函数如何延时

    延时函数如何延时延时函数如何延时**函数样例编译软件编译后的汇编指令Delay_ms(200);…

    2022年6月22日
    31
  • Java面试之JDBC & Hibernate

    Java面试之JDBC & HibernateJava面试之JDBC & Hibernate

    2022年4月22日
    44
  • uu怎么卸载_卸载deepin引导

    uu怎么卸载_卸载deepin引导ubutun干净卸载删除wineQQ博主原本想要在ubuntu18.04安装wineQQ,在安装完成后却显示QQ版本过低无法运行,只能卸载重装,不然那个QQ标志在软件列表非常碍眼。这个是之前安装wineQQ的教程【QQ版本已过期】问题:卸载不掉该软件且网上大多数指令都过期了解决方案:在deepinwine的应用容器中,用sudoaptremove软件包主名命令来删除。比如d…

    2025年9月19日
    8
  • SpringCloud和dubbo的区别[通俗易懂]

    SpringCloud和dubbo的区别[通俗易懂]SpringCloud跟dubbo的区别从架构层面上来说SpringCloud跟dubbo都是微服务架构在公司开发技术选型中:SpringCloud的维护成本比较高,但是SpringCloud中提供了很多框架、整合了5大组件(全家桶:Ribbon负载均衡、eureka注册中心、Hystrix熔断器、gateway网关、feign服务调用)使用都非常方便,后期便于维护,分布式单一互不影响原则…

    2022年4月30日
    70
  • java中Scanner用法

    java中Scanner用法1.导入包,idea可自动导入importjava.util.Scanner;2.创建一个扫描器对象,用于接收用户输入的数据Scannerscanner=newScanner(System.in);3.创建完成后的接收以及判断<1>用next方法接收System.out.println(“使用next方式接收:”);//判断用户有没有输入字符串if(scanner.hasNext()){Stringstr=

    2022年7月7日
    35
  • HttpClient详细解释

    HttpClient详细解释Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会

    2025年6月1日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号