先来一张效果图

这些头像都来自微信好友的,放大看这不过是一张众多头像拼成的大图,缩小或远看能够发现这些头像其实拼出了一个有趣的图案。这个实现思路并不复杂(这个思路暂时只针对黑白的图片,如果要支持彩图会更复杂一点,可以了解下 foto-mosaik-edda)

  • 首先需要一张“参考图片”和大量小图片(最好都是方形的,头像是个很好的选择)
  • 计算每一张方形小图片的平均灰度值,计算公式为 gray = (77*red + 150*green + 29*blue + 128) >> 8,这个公式是根据人对于不同色彩敏感程度而得出的
  • 每张图片计算出的平均灰度值都在0~255,再按照灰度值区间分成4组,每个区间的跨度是256/4=64,当然也可以多一点,这是为了更容易匹配对应的像素点。
  • 将参考图片压缩成较小的尺寸,上面这张图是压成50x50,计算每个像素点的灰度值,同样划分为4个区间,最后在区间对应分组里随机选择一张图片摆在对应的像素点上。
  • 这个随机选择的算法也是有一定讲究的,我们希望的效果是尽量避免相同的图片相邻摆放

代码实现

GraphicsMosaicHandler.java(用于处理主要逻辑)

package com.yotwei.core;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** Created by YotWei on 2018/3/26.*/
public class GraphicsMosaicHandler {public int handle(String srcPath, String dstPath) throws Exception {//read origin imageUtil.message("正在读入图片...");BufferedImage inputImg = ImageIO.read(new File(srcPath));BufferedImage outputImg = new BufferedImage(inputImg.getWidth() * GMConfig.MOSAIC_WIDTH,inputImg.getHeight() * GMConfig.MOSAIC_HEIGHT,BufferedImage.TYPE_INT_RGB);//read mosaic imagesUtil.message("正在读入马赛克...");Map<String, List<String>> filenames = new HashMap<>();Map<String, FileNameList> fnameMap = new HashMap<>();File pDir = new File(GMConfig.MOSAIC_PROC_PATH);for (String name : pDir.list()) {String key = name.substring(0, name.indexOf("_"));if (!filenames.containsKey(key)) {filenames.put(key, new ArrayList<>());}filenames.get(key).add(name);}for (Map.Entry<String, List<String>> entry : filenames.entrySet()) {fnameMap.put(entry.getKey(), new FileNameList(entry.getValue()));}int rgb, gray;String k;Util.message("正在绘制...");for (int y = 0; y < inputImg.getHeight(); y++) {for (int x = 0; x < inputImg.getWidth(); x++) {rgb = inputImg.getRGB(x, y);gray = ((77 * ((rgb & 0xff0000) >> 16))+ (150 * ((rgb & 0x00ff00) >> 8))+ (29 * (rgb & 0x0000ff))) >> 8;k = "L" + (gray / GMConfig.GRAY_LEVEL_INTERVAL);BufferedImage mosaicImg = ImageIO.read(new File(GMConfig.MOSAIC_PROC_PATH, fnameMap.get(k).next()));outputImg.getGraphics().drawImage(mosaicImg,x * GMConfig.MOSAIC_WIDTH,y * GMConfig.MOSAIC_HEIGHT,GMConfig.MOSAIC_WIDTH,GMConfig.MOSAIC_HEIGHT, null);}}Util.message("绘制完成,正在写入文件...");ImageIO.write(outputImg, "jpg", new File(dstPath, "out_" + System.currentTimeMillis() + ".jpg"));Util.message("写入成功!");return 0;}public void processOriginResources() throws IOException {String procPath = GMConfig.MOSAIC_PROC_PATH;File dir = new File(procPath);if (!dir.isDirectory() || dir.list().length == 0) {if (!dir.exists() && !dir.mkdirs()) {throw new IOException("无法创建文件夹: " + procPath);}String originPath = GMConfig.MOSAIC_ORIGIN_PATH;File originDir = new File(originPath);if (!originDir.isDirectory()) {throw new IOException(String.format("文件夹\"%s\"不存在", originPath));}//开始读取图片源地ExecutorService executor = Executors.newFixedThreadPool(10);for (File file : originDir.listFiles()) {BufferedImage readImg = ImageIO.read(file);if (readImg == null) {continue;}executor.execute(new CompressTaskRunnable(readImg));}executor.shutdown();}}static class FileNameList {public FileNameList(List<String> list) {if (list != null) {this.list = list;Collections.shuffle(list);}}public String next() {if (list == null) {return null;}if (counter == list.size()) {counter = 0;Collections.shuffle(list);}return list.get(counter++);}private List<String> list;private int counter = 0;}static class CompressTaskRunnable implements Runnable {private BufferedImage src;CompressTaskRunnable(BufferedImage src) {this.src = src;}@Overridepublic void run() {BufferedImage compress = Util.compressImage(src, GMConfig.MOSAIC_WIDTH, GMConfig.MOSAIC_HEIGHT);int gray = Util.getAvgGray(compress);try {String fileName = "L" + (gray / GMConfig.GRAY_LEVEL_INTERVAL) + "_" +System.currentTimeMillis() + ".jpg";ImageIO.write(compress, "jpg", new File(GMConfig.MOSAIC_PROC_PATH, fileName));} catch (IOException e) {e.printStackTrace();}}}
}

Util.java

package com.yotwei.core;import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Collections;/*** 工具类*/
public class Util {public static BufferedImage compressImage(BufferedImage src, int dstWidth, int dstHeight) {BufferedImage compress = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_RGB);compress.getGraphics().drawImage(src.getScaledInstance(dstWidth, dstHeight, Image.SCALE_SMOOTH),0, 0, dstWidth, dstHeight, null);return compress;}/*** 平均灰度值*/public static int getAvgGray(BufferedImage img) {int x, y, temp, graySum = 0;for (y = 0; y < img.getHeight(); y++) {for (x = 0; x < img.getWidth(); x++) {temp = img.getRGB(x, y);graySum += (((77 * ((temp & 0xff0000) >> 16))+ (150 * ((temp & 0x00ff00) >> 8))+ (29 * (temp & 0x0000ff))) >> 8);}}return graySum / (img.getWidth() * img.getHeight());}public static void message(String message) {System.out.println(message);}
}

CMConfig.java(常量都在这里)

package com.yotwei.core;/*** Created by YotWei on 2018/3/26.*/
public class GMConfig {public static final String MOSAIC_ORIGIN_PATH = "weixinAvatars/";    //头像原文件夹public static final String MOSAIC_PROC_PATH = "process-resources/";    //对文件进一步处理后把图片放在这里public static final int MOSAIC_WIDTH = 32;    //马赛克图片的宽度public static final int MOSAIC_HEIGHT = 32;    //马赛克图片的高度public static final int GRAY_LEVEL_INTERVAL = 256 / 4;
}

调用

package com.yotwei.client;import com.yotwei.core.GraphicsMosaicHandler;/*** Created by YotWei on 2018/3/26.*/
public class GMClient {public static void main(String[] args) throws Exception {GraphicsMosaicHandler handler = new GraphicsMosaicHandler();System.out.println("GM process with return code: " + handler.handle("imgs/trust.png","imgs/"));}
}

最后再放几张效果图

用Java实现简单的“马赛克拼图”相关推荐

  1. 用Java实现的简易马赛克拼图

    用Java实现的简易马赛克拼图 什么是马赛克拼图 效果图 原理 所有代码 什么是马赛克拼图 马赛克拼图 简单来说就是远远看上去是一张大图,放大之后会发现其实是由许多张不同的小图组成 效果图 如果准备的 ...

  2. opengl实现三维动画简单代码_使用Python简单实现马赛克拼图!内附完整代码

    今天小编带大家使用python简单实现马赛克拼图,内容比以往会稍长一些,各位看官老爷可以慢慢细读,若有不足之处还望请斧正,闲话不多说,请看文章. 先看原图: 效果图: 思路: 拼图的原理其实很简单,就 ...

  3. 使用Python简单实现马赛克拼图

    先上效果图 这是原图: 思路: 拼图的原理其实很简单,就是把原图划分成很多个小块,然后根据灰度或者rgb搜索图库中最相似的图片进行替换.接下来的问题就是如何实现图片搜索.这里可以参考阮一峰的博客 上代 ...

  4. python 马赛克拼图_使用 python 做到马赛克拼图

    死宅一枚.爬取5000张二次元妹子的图片,生成了头图. 接下来看看怎么实现的: 使用 Scrapy 框架爬取5000张二次元图 使用 opencv 批量格式化图片 将图片按照RGB值的均方根排序,实现 ...

  5. PHP 蒙太奇马赛克拼图,AndreaMosaic制作一幅马赛克拼图

    大家在网上应该都见过用很多幅图片拼成的马赛克图片,今天小编就为大家介绍AndreaMosaic制作一幅马赛克拼图方法,不会的朋友快快来学习吧! 软件名称:AndreaMosaic(蒙太奇图片制作软件) ...

  6. 【Python3.6爬虫学习记录】(十五)Scrapy爬虫框架的应用及马赛克拼图生成

    目录 目录 前言 1.Scrapy框架应用 1.1.Scrapy准备 1.2.创建项目及配置 1.3.网页分析及代码实现 1.3.1 items.py 中定义存储的数据 1.3.2 spiders文件 ...

  7. Matlab 蒙太奇马赛克拼图(小图拼成大图)

    文章目录 0. 介绍 1. 框架型 2. 叠加型 3. 组合图 3.1 resize 3.2 区间分类 3.2.1 灰度级映射 3.2.2 根据RGB选取合适的图像 3.2.3 灰度分类主程序 3.2 ...

  8. TurboMosaic for Mac如何制作个性化的照片马赛克拼图

    由您的家庭照片制作的个性化照片马赛克拼图是您孩子最好的礼物之一. 但是,你怎么能做一个? 在本文中,我们将向您展示如何通过几个简单的步骤制作一个photomosaic拼图. TurboMosaic f ...

  9. 【有利可图网】PS实战系列:巧用PS设计制作超酷的马赛克拼图效果

    本篇教大家如何巧用photoshop设计制作一个超酷的马赛克拼图效果!教程简单易学,感兴趣的小伙伴赶快收藏参考练习下!

最新文章

  1. access汇总含义_2020最新大厂内部 PHP 高级工程师面试题汇总(二)
  2. (转)另一篇:VC导出数据到EXCEL
  3. hdu2492 数状数组或者线段树
  4. java接口常用_java的常用接口
  5. apache mysql php 安装配置_Windows下Apache,MySql,PHP安装配置
  6. linux下的raid及mdadm的命令详解
  7. 搭建php环境,更换织梦服务器
  8. 提供一个文档下载接口,用httpclient下载文件
  9. 【UE编辑器怎么添加新的语法高亮】
  10. 【毕业设计全篇论文和源码】基于SSM的实体商城商户在线租赁以及信息管理系统的设计与实现(多人在线聊天室,微信扫码支付,在线签字,PDF合同在线生成,商户评分)
  11. 渗透测试之敏感信息收集
  12. 全球AMR调度系统分析(RMS、TMS)
  13. C4D材质原理揭秘笔记-初学必看
  14. vue+ts的书写规范
  15. Codeforces Round #620 (Div. 2)(D. Shortest and Longest LIS)(O(n log n)的最长上升子序列或者贪心)
  16. 【谷粒学院】001-项目概述、Mybatis Plus入门
  17. ArcPy - 入门学习
  18. 论文解读2019INFOCOM_Calibrate: Frequency Estimation and Heavy Hitter Identification with LDP
  19. DolphinScheduler技术分析(八)
  20. Java中先按照姓名排序(姓名相同)在按照年龄排序(年龄相同)按照编号 排序呢 策略模式

热门文章

  1. Linux i2ctool 工具的使用方法
  2. 技术图文:如何利用BigOne的API制作自动化交易系统--网格交易法
  3. [全网首发]一款好看的个人主页源码
  4. iPhone使用过程中提示:“无线局域网似乎未接入互联网”,点击继续使用可正常上网
  5. 服务器蓝屏报硬件故障,服务器蓝屏,错误代码为:STOP: 0x000000D1 - Microsoft Community...
  6. VMProtect进行加壳
  7. Vue 中 CSS scoped 的原理
  8. 扫描---实验一:端口扫描(X-scan)
  9. LAMP兄弟连PHP开源框架免费在线课报名中
  10. 12 个最佳的免费网络监控工具、免费网站监控工具超级好用的有那些