「脑洞」图片转HTML(支持动画)
也许是受到很久以前看到的这玩意儿的原因:The Shapes of CSS
现在开脑洞写了个自动转换,顺便支持了动画……嗯,纯 CSS (:з」∠)
主要步骤就是用 Python 读图片,然后把像素全转写成 CSS 的 box-shadow ,最后构建一个完整的 HTML 文件输出。
然后用浏览器打开生成的 HTML 文件,就直接看到图片了,如果输入是一个文件夹的话,就以文件夹里面的图片为帧生成一个带动画的 HTML。
最新的版本就在这儿了: img2html
#!/usr/bin/env python3
# -*- coding: utf-8 -*- ## @package img2html
# Usage : img2html.py file1|dir1 [file2|dir2 ...]
# Description : generate html uses box-shadow to show picture
# or a html to show your image sequence in a folder as css animation
# Dependencies : Python Image Library, Python 3
# Note : Take care of the Super-High-Energy output ( >﹏<。)
# Date : 2014-12-19
# Author : frantic1048 import sys
import os
from PIL import Image
from string import Template class UnknownColorMode(Exception): pass ## @var tHTML template for constructing entire html document
tHTML = Template('''
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>~ ${name} ~</title>
</head>
<body>
<style type="text/css">${css}</style>
<div id="image_kun"></div>
</body>
</html>''') ## @var tCSSStatic template for constructing static image's css code
tCSSStatic = Template('''
@charset "utf-8";
body{
display:flex;
justify-content:center;
align-items:center;
}
#image_kun{
height: ${height}px;
width: ${width}px;
position:relative;
}
#image_kun::after{
position:absolute;
height:1px;
width:1px;
background:${firstPixel};
margin:0;
padding:0;
content:"\\200B";/*ZWS*/
box-shadow:
${boxshadow};
}
''') ## @var tCSSAnimation template for constructing image sequence's css animation code
tCSSAnimation = Template('''
@charset "utf-8";
body{
display:flex;
justify-content:center;
align-items:center;
}
#image_kun{
height: ${height}px;
width: ${width}px;
position:relative;
}
#image_kun::after{
position:absolute;
height:1px;
width:1px;
background:transparent;
margin:0;
padding:0;
content:"\\200B";/*ZWS*/
animation:ayaya ${animationLength} step-end infinite alternate;
}
${animationKeyFrames}
''') ## @var tCSSKeyframes template entire CSS keyframes rule
tCSSKeyframes = Template('@keyframes ayaya {${keyframes}}') ## @var tCSSKeyframe template for a single CSS keyframe
tCSSKeyframe = Template('${percentage}% {${keyframeRule}}\n') ## @var tCSSKeyframeRule template for a single CSS keyframe inner rule
tCSSKeyframeRule = Template('background:${firstPixel};box-shadow:${boxshadow};') ## ensure no trailiing slash in directory name
def toRegularDirName(dirName):
if (os.path.split(dirName)[-1] == ''):
return os.path.split(dirName)[0]
else:
return dirName ## write str to a file,named as <exportFileName>.html
def toFile (str,exportFileName):
with open (exportFileName,'w') as html:
html.write(str) ## construct HEX Color value for a pixel
# @param pixel a RGB mode pixel object to be converted
# @return CSS hex format color value
def toHexColor (pixel):
return '#{0:02x}{1:02x}{2:02x}'.format(*pixel[:]) ## construct RGBA Color value for a pixel
# @param pixel a RGBA mode pixle object to be comverted
# @return CSS rgba format color value
def toRGBAColor (pixel):
return 'rgba({0},{1},{2},{3})'.format(*pixel[:]) def toCSSColor (pixel, mode):
if (mode == 'RGB'):
return toHexColor(pixel)
elif (mode == 'RGBA'):
return toRGBAColor(pixel)
else:
raise UnknownColorMode ## construct single box-shadow param
# @param color valid CSS color
def toBoxShadowParam (x, y, color):
return format('%spx %spx 0 %s'%(x, y, color)) ## process single image file to html
# @param fileName input file's name
# @param export output callback(doc, exportFileName):
# doc : generated html string
# exportFileName : output filename
def mipaStatic(fileName,export=''):
with Image.open(fileName) as im:
## what called magic
boxshadow = '' ## file name as sysname
exportFileName = fileName+'.html'
title = os.path.split(fileName)[-1] ## image size
width, height = im.size[0], im.size[1] #ensure RGB(A) mode
if (im.mode != 'RGBA' or im.mode != 'RGB'):
im.convert('RGB') firstPixel = toCSSColor(im.getpixel((0,0)), im.mode)
for y in range(0, height):
for x in range(0, width):
color = toCSSColor(im.getpixel((x, y)), im.mode)
#link magic
boxshadow += toBoxShadowParam(x, y, color) #add a spliter if not the end
if (not (y == height-1 and x == width-1)):
#keep a '\n' for text editor ˊ_>ˋ
boxshadow += ',' + '\n' doc = tHTML.substitute(name = title, css = tCSSStatic.substitute(width = width, height = height, boxshadow = boxshadow, firstPixel=firstPixel))
if (export==''):
print(doc)
else:
export(doc, exportFileName) ## process a image folder
# files in folder will processed to an animated html
# process order is filename asend
# @param dirName input file's name
# @param export output callback, call with generated html as a string argument
def mipaAnimation(dirName,export=''):
dirName = toRegularDirName(dirName)
title = os.path.basename(dirName)
exportFileName = title + '.html' files = os.listdir(dirName)
files.sort() FPS = 24
mode = ''
width, height = 0, 0
frameCount = 0
keyframeRules = []
keyframe = '' for f in files:
try:
with Image.open(os.path.join(dirName, f)) as im: if (export!=''):print('processing file --> ' + f) frameCount+=1 #ensure RGB(A) mode
if (im.mode != 'RGBA' or im.mode != 'RGB'):
im.convert('RGB'); #collect animation info
if (width == 0) : width, height = im.size[0], im.size[1]
if (mode == '') : mode = im.mode firstPixel = toCSSColor(im.getpixel((0,0)), mode)
boxshadow = ''
for y in range(0, height):
for x in range(0, width):
color = toCSSColor(im.getpixel((x, y)), mode)
#link magic
boxshadow += toBoxShadowParam(x, y, color) #add a spliter if not the end
if (not (y == height-1 and x == width-1)):
#keep a '\n' for text editor ˊ_>ˋ
boxshadow += ',' + '\n'
keyframeRules.append(tCSSKeyframeRule.substitute(firstPixel=firstPixel,boxshadow=boxshadow))
except:
pass percentUnit= 100/frameCount
for i in range(0,frameCount):
if (i == frameCount - 1):
pc = ''
elif (i == 0):
pc = ''
else:
pc = str(percentUnit * i)
keyframe += tCSSKeyframe.substitute(percentage = pc, keyframeRule = keyframeRules[i]) if (export!=''):print('generating document...')
doc = tHTML.substitute(name = title, css = tCSSAnimation.substitute(animationLength = str((1000 / FPS) * frameCount) + 'ms',
animationKeyFrames = tCSSKeyframes.substitute(keyframes = keyframe),
height = height,
width = width))
#output
if (export==''):
print(doc)
else:
print('Start exporting...')
export(doc, exportFileName)
print('Finished exporting !\nenjoy with your magical ' + exportFileName + ' _(:з」∠)_') for path in sys.argv[1:]:
if os.path.isfile(path):
##export to stdout
#mipaStatic(path) ##export to autonamed file
mipaStatic(path,toFile)
elif os.path.isdir(path):
#mipaAnimation(path)
mipaAnimation(path,toFile)
「脑洞」图片转HTML(支持动画)的更多相关文章
- 《Offer一箩筐》一份高质量「简历」撰写指南,望打扰!!
「MoreThanJava」 宣扬的是 「学习,不止 CODE」. 如果觉得 「不错」 的朋友,欢迎 「关注 + 留言 + 分享」,文末有完整的获取链接,您的支持是我前进的最大的动力! Hi~ 这里是 ...
- SpringBoot图文教程10—模板导出|百万数据Excel导出|图片导出「easypoi」
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...
- iOS图案锁,支持动画、图片、绘图
最近忙着搭建一个聊天用的框架,过几天应该会整理写出来吧,原理不难,但是实现后会省很多事.好久没写博客,周末心血来潮写了个图案锁,这东西没什么技术含量,网上一堆,这次这个图案锁顺便联系了怎么打包使用.a ...
- loj #2037. 「SHOI2015」脑洞治疗仪
#2037. 「SHOI2015」脑洞治疗仪 题目描述 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见 ...
- 「MoreThanJava」Java发展史及起航新世界
「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...
- 一个「学渣」从零开始的Web前端自学之路
从 13 年专科毕业开始,一路跌跌撞撞走了很多弯路,做过餐厅服务员,进过工厂干过流水线,做过客服,干过电话销售可以说经历相当的“丰富”. 最后的机缘巧合下,走上了前端开发之路,作为一个非计算机专业且低 ...
- Android逆向之旅---静态方式分析破解视频编辑应用「Vue」水印问题
一.故事背景 现在很多人都喜欢玩文艺,特别是我身边的UI们,拍照一分钟修图半小时.就是为了能够在朋友圈显得逼格高,不过的确是挺好看的,修图的软件太多了就不多说了,而且一般都没有水印啥的.相比较短视频有 ...
- 零元学Expression Blend 4 - Chapter 18 用实例了解互动控制项「CheckBox」II
原文:零元学Expression Blend 4 - Chapter 18 用实例了解互动控制项「CheckBox」II 延续上一章的CheckBox教学,本章将以实作继续延伸更灵活的运用CheckB ...
- 零元学Expression Blend 4 - Chapter 17 用实例了解互动控制项「CheckBox」I
原文:零元学Expression Blend 4 - Chapter 17 用实例了解互动控制项「CheckBox」I 本章将教大家如何运用CheckBox做实作上的变化:教你如何把CheckBox变 ...
随机推荐
- java学习第18天(map集合)
Map集合是将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值. 存储的是键值对形式的元素,键唯一,值可以重复,有点类似于数据库中的主键加数据.主要功能有: A:添加功能 put ...
- Java日志——2016.6.3
1)二维数组的静态初始化: int[][] arr = new int[][] { {1,2,3}, {4,5}, {6,7}} 2)杨辉三角: /** * 需求: ...
- git乱码问题解决
etc\gitconfig文件中增加以下内容: [gui] encoding = utf-8 [i18n] commitencoding = gbk [svn] pathnam ...
- Kafka报错-as it has seen zxid 0x83808 our last zxid is 0x0 client must try another server
as it has seen zxid 0x83808 our last zxid is 0x0 client must try another server 停止zookeeper,删除datadi ...
- KBMMW 中 IOS IPv6 的解决
自从今年苹果强制新上架的APP 必须支持Ipv6,很多原来需要网络支持的APP 就没法上架了. 别的我们就不说了,先说说kbmmw 中,如何解决这个问题. 要测试你的app 是否支持ipv6, 首先要 ...
- TCP协议疑难杂症全景解析
说明: 1).本文以TCP的发展历程解析容易引起混淆,误会的方方面面2).本文不会贴大量的源码,大多数是以文字形式描述,我相信文字看起来是要比代码更轻松的3).针对对象:对TCP已经有了全面了解的人. ...
- love easily fade
Ubuntu addict and loving it , the answerer 's intro attracted me.When I first read a book on linux ...
- MFC CEdit改变字体大小的方法
方法很多,这里讲解两种比较简单的方法,也是从google上搜索来的. 方法一: CWnd* pEdit; pEdit = GetDlgItem(IDC_EDIT_ONE); ASSERT(pEdit ...
- ubuntu 16 mysql安装包安装 (推荐在线安装)
/etc/init.d/中的文件命名为mysql cp好各种文件后 ./mysql_install_db --user=mysql --datadir=/usr/local/mysql/data/my ...
- 刚看到的感觉会用的到 收藏一下 常用的iOS第三方资源 (转)
原文出处:http://blog.csdn.net/ruiwang321/article/details/50591888 一:第三方插件 1:基于响应式编程思想的oc 地址:https://gith ...