zoukankan      html  css  js  c++  java
  • 「脑洞」图片转HTML(支持动画)

    也许是受到很久以前看到的这玩意儿的原因:The Shapes of CSS

    现在开脑洞写了个自动转换,顺便支持了动画……嗯,纯 CSS (:з」∠)

    主要步骤就是用 Python 读图片,然后把像素全转写成 CSS 的 box-shadow ,最后构建一个完整的 HTML 文件输出。

    然后用浏览器打开生成的 HTML 文件,就直接看到图片了,如果输入是一个文件夹的话,就以文件夹里面的图片为帧生成一个带动画的 HTML。

    最新的版本就在这儿了: img2html

      1 #!/usr/bin/env python3
      2 # -*- coding: utf-8 -*-
      3 
      4 ## @package img2html
      5 #  Usage        : img2html.py file1|dir1 [file2|dir2 ...]
      6 #  Description  : generate html uses box-shadow to show picture
      7 #                 or a html to show your image sequence in a folder as css animation
      8 #  Dependencies : Python Image Library, Python 3
      9 #  Note         : Take care of the Super-High-Energy output ( >﹏<。)
     10 #  Date         : 2014-12-19
     11 #  Author       : frantic1048
     12 
     13 
     14 import sys
     15 import os
     16 from PIL import Image
     17 from string import Template
     18 
     19 class UnknownColorMode(Exception): pass
     20 
     21 ## @var tHTML template for constructing entire html document
     22 tHTML = Template('''
     23 <!doctype html>
     24 <html lang="en">
     25 <head>
     26   <meta charset="UTF-8">
     27   <title>~ ${name} ~</title>
     28 </head>
     29 <body>
     30   <style type="text/css">${css}</style>
     31   <div id="image_kun"></div>
     32 </body>
     33 </html>''')
     34 
     35 ## @var tCSSStatic template for constructing static image's css code
     36 tCSSStatic = Template('''
     37 @charset "utf-8";
     38 body{
     39   display:flex;
     40   justify-content:center;
     41   align-items:center;
     42 }
     43 #image_kun{
     44   height: ${height}px;
     45    ${width}px;
     46   position:relative;
     47 }
     48 #image_kun::after{
     49   position:absolute;
     50   height:1px;
     51   1px;
     52   background:${firstPixel};
     53   margin:0;
     54   padding:0;
     55   content:"\200B";/*ZWS*/
     56   box-shadow:
     57   ${boxshadow};
     58 }
     59 ''')
     60 
     61 ## @var tCSSAnimation template for constructing image sequence's css animation code
     62 tCSSAnimation = Template('''
     63 @charset "utf-8";
     64 body{
     65   display:flex;
     66   justify-content:center;
     67   align-items:center;
     68 }
     69 #image_kun{
     70   height: ${height}px;
     71    ${width}px;
     72   position:relative;
     73 }
     74 #image_kun::after{
     75   position:absolute;
     76   height:1px;
     77   1px;
     78   background:transparent;
     79   margin:0;
     80   padding:0;
     81   content:"\200B";/*ZWS*/
     82   animation:ayaya ${animationLength} step-end infinite alternate;
     83 }
     84 ${animationKeyFrames}
     85   ''')
     86 
     87 ## @var tCSSKeyframes template entire CSS keyframes rule
     88 tCSSKeyframes = Template('@keyframes ayaya {${keyframes}}')
     89 
     90 ## @var tCSSKeyframe template for a single CSS keyframe
     91 tCSSKeyframe = Template('${percentage}% {${keyframeRule}}
    ')
     92 
     93 ## @var tCSSKeyframeRule template for a single CSS keyframe inner rule
     94 tCSSKeyframeRule = Template('background:${firstPixel};box-shadow:${boxshadow};')
     95 
     96 ## ensure no trailiing slash in directory name
     97 def toRegularDirName(dirName):
     98 if (os.path.split(dirName)[-1] == ''):
     99   return os.path.split(dirName)[0]
    100 else:
    101   return dirName
    102 
    103 ## write str to a file,named as <exportFileName>.html
    104 def toFile (str,exportFileName):
    105   with open (exportFileName,'w') as html:
    106 html.write(str)
    107 
    108 ## construct HEX Color value for a pixel
    109 #  @param pixel a RGB mode pixel object to be converted
    110 #  @return CSS hex format color value
    111 def toHexColor (pixel):
    112   return '#{0:02x}{1:02x}{2:02x}'.format(*pixel[:])
    113 
    114 ## construct RGBA Color value for a pixel
    115 #  @param pixel a RGBA mode pixle object to be comverted
    116 #  @return CSS rgba format color value
    117 def toRGBAColor (pixel):
    118   return 'rgba({0},{1},{2},{3})'.format(*pixel[:])
    119 
    120 def toCSSColor (pixel, mode):
    121   if (mode == 'RGB'):
    122 return toHexColor(pixel)
    123   elif (mode == 'RGBA'):
    124 return toRGBAColor(pixel)
    125   else:
    126 raise UnknownColorMode
    127 
    128 ## construct single box-shadow param
    129 #  @param color valid CSS color
    130 def toBoxShadowParam (x, y, color):
    131   return format('%spx %spx 0 %s'%(x, y, color))
    132 
    133 ## process single image file to html
    134 #  @param fileName input file's name
    135 #  @param export output callback(doc, exportFileName):
    136 #    doc : generated html string
    137 #    exportFileName : output filename
    138 def mipaStatic(fileName,export=''):
    139   with Image.open(fileName) as im:
    140 ## what called magic
    141 boxshadow = ''
    142 
    143 ## file name as sysname
    144 exportFileName = fileName+'.html'
    145 title = os.path.split(fileName)[-1]
    146 
    147 ## image size
    148 width, height = im.size[0], im.size[1]
    149 
    150 #ensure RGB(A) mode
    151 if (im.mode != 'RGBA' or im.mode != 'RGB'):
    152   im.convert('RGB')
    153 
    154 firstPixel = toCSSColor(im.getpixel((0,0)), im.mode)
    155 for y in range(0, height):
    156   for x in range(0, width):
    157     color = toCSSColor(im.getpixel((x, y)), im.mode)
    158     #link magic
    159     boxshadow += toBoxShadowParam(x, y, color)
    160 
    161     #add a spliter if not the end
    162     if (not (y == height-1 and x == width-1)):
    163       #keep a '
    ' for text editor ˊ_>ˋ
    164       boxshadow += ',' + '
    '
    165 
    166 doc = tHTML.substitute(name = title, css = tCSSStatic.substitute(width = width, height = height, boxshadow = boxshadow, firstPixel=firstPixel))
    167 if (export==''):
    168   print(doc)
    169 else:
    170   export(doc, exportFileName)
    171 
    172 
    173 ## process a image folder
    174 #  files in folder will processed to an animated html
    175 #  process order is filename asend
    176 #  @param dirName input file's name
    177 #  @param export output callback, call with generated html as a string argument
    178 def mipaAnimation(dirName,export=''):
    179   dirName = toRegularDirName(dirName)
    180   title = os.path.basename(dirName)
    181   exportFileName = title + '.html'
    182 
    183   files = os.listdir(dirName)
    184   files.sort()
    185 
    186   FPS = 24
    187   mode = ''
    188   width, height = 0, 0
    189   frameCount = 0
    190   keyframeRules = []
    191   keyframe = ''
    192 
    193   for f in files:
    194 try:
    195   with Image.open(os.path.join(dirName, f)) as im:
    196 
    197     if (export!=''):print('processing file --> ' + f)
    198 
    199     frameCount+=1
    200 
    201     #ensure RGB(A) mode
    202     if (im.mode != 'RGBA' or im.mode != 'RGB'):
    203       im.convert('RGB');
    204 
    205     #collect animation info
    206     if (width == 0) : width, height = im.size[0], im.size[1]
    207     if (mode == '') : mode = im.mode
    208 
    209     firstPixel = toCSSColor(im.getpixel((0,0)), mode)
    210     boxshadow = ''
    211     for y in range(0, height):
    212       for x in range(0, width):
    213     color = toCSSColor(im.getpixel((x, y)), mode)
    214     #link magic
    215     boxshadow += toBoxShadowParam(x, y, color)
    216 
    217     #add a spliter if not the end
    218     if (not (y == height-1 and x == width-1)):
    219       #keep a '
    ' for text editor ˊ_>ˋ
    220       boxshadow += ',' + '
    '
    221     keyframeRules.append(tCSSKeyframeRule.substitute(firstPixel=firstPixel,boxshadow=boxshadow))
    222 except:
    223   pass
    224 
    225   percentUnit= 100/frameCount
    226   for i in range(0,frameCount):
    227 if (i == frameCount - 1):
    228   pc = '100'
    229 elif (i == 0):
    230   pc = '0'
    231 else:
    232   pc = str(percentUnit * i)
    233 keyframe += tCSSKeyframe.substitute(percentage = pc, keyframeRule = keyframeRules[i])
    234 
    235   if (export!=''):print('generating document...')
    236   doc = tHTML.substitute(name = title, css = tCSSAnimation.substitute(animationLength = str((1000 / FPS) * frameCount) + 'ms',
    237                                       animationKeyFrames = tCSSKeyframes.substitute(keyframes = keyframe),
    238                                       height = height,
    239                                       width = width))
    240   #output
    241   if (export==''):
    242 print(doc)
    243   else:
    244 print('Start exporting...')
    245 export(doc, exportFileName)
    246 print('Finished exporting !
    enjoy with your magical ' + exportFileName + ' _(:з」∠)_')
    247 
    248 
    249 for path in sys.argv[1:]:
    250   if os.path.isfile(path):
    251 ##export to stdout
    252 #mipaStatic(path)
    253 
    254 ##export to autonamed file
    255 mipaStatic(path,toFile)
    256   elif os.path.isdir(path):
    257 #mipaAnimation(path)
    258 mipaAnimation(path,toFile)
  • 相关阅读:
    python全栈开发,Day43(引子,协程介绍,Greenlet模块,Gevent模块,Gevent之同步与异步)
    python全栈开发,Day42(Thread类的其他方法,同步锁,死锁与递归锁,信号量,事件,条件,定时器,队列,Python标准模块--concurrent.futures)
    python全栈开发,Day41(线程概念,线程的特点,进程和线程的关系,线程和python理论知识,线程的创建)
    处理大并发之五 使用libevent利器bufferevent
    [转]./configure,make,make install的作用
    [转]Centos安装zeromq和jzmq
    [zhuan] linux 下 wxWidgets 安装,编译
    [转]面向过程的分析(POA),和面向对象的分析(OOA)
    【转】libevent和基于libevent的网络编程
    [转] Linux下 config/configure/Configure、make 、make test/make check、sudo make install 的作用
  • 原文地址:https://www.cnblogs.com/frantic1048/p/img2html.html
Copyright © 2011-2022 走看看