在python中将LaTeX转为mathml或svg代码

python代码如下:

import cgi
import cgitb; cgitb.enable() # Show errors to browser.
import sys
import os
import time
import md5
import re
sys.stderr = sys.stdout
cgi.maxlen = 10*1024

bin_dir = '/home/jason/local/bin/'
os.environ['PATH'] += os.pathsep+bin_dir

debug = False
redirect = True
verify_code = True  # Verifies the LaTeX code with Texvc for security

if debug:
    print 'Content-type: text/html\n\n'

# For some reason (apache?) this comes pre unquoted, which makes pluses 
# not work because even though they started as '%2B', now that they're '+' they are treated as ' '
# TODO: Spaces seem to get encoded as pluses, dammit.
#os.environ['QUERY_STRING'] = os.environ['QUERY_STRING'].replace('+', '%2B')
if os.environ.has_key('QUERY_STRING') and \
        os.environ.has_key('REQUEST_URI') and \
        len(os.environ['REQUEST_URI'].split('?')) >= 2: # Only for GET, not POST
    os.environ['QUERY_STRING'] = os.environ['REQUEST_URI'].split('?')[1]

form = cgi.FieldStorage(strict_parsing=True)
time.sleep(0.1) # Throttle requests
if debug:
    print 'Debug mode of ltaex2svg.py\n'
    form = cgi.FieldStorage()
    if not form:
        print "<h1>No Form Keys</h1>"
    else:
        print "<h2>Environ</h2><ul>"
        for key in os.environ.keys():
            value = os.environ[key]
            print "<li>", cgi.escape(key), ":", cgi.escape(value), '</li>'
        print '</ul>'
        print "<h2>Form Keys</h2><ul>"
        for key in form.keys():
            value = form[key].value
            print "<li>", cgi.escape(key), ":", cgi.escape(value), '</li>'
        print '</ul>'
    print '<pre>'
latex = form['latex'].value
#type = form['type'].value  # inline or whatever
#redirect = form['redirect'].value

md5hex = md5.new(latex).hexdigest()

base_dir = 'files/'

def extensionToFile(ext):
    #return os.path.join(base_dir, 'files/'+md5hex+'.'+ext)
    #return os.path.abspath(base_dir+md5hex+'.'+ext)
    return md5hex+'.'+ext

tex_name = extensionToFile("tex")
aux_name = extensionToFile("aux")
log_name = extensionToFile("log")
ps_name = extensionToFile("ps")
dvi_name = extensionToFile("dvi")
svg_name = extensionToFile("svg")
out_name = extensionToFile("out")
zoom_name = 'zoom_'+svg_name

def execute_cmd(cmd):
    (child_stdin, child_stdout, child_stderr) = os.popen3(cmd)
    str_stdout = child_stdout.read() # Read until the process quits.
    str_stderr = child_stderr.read() # Read until the process quits.
    if debug:
        print cmd+'\n'
        print 'stdout:'+str_stdout+'\n'
        print 'stderr:'+str_stderr+'\n'
    return str_stdout

header = """
\\nonstopmode
\\documentclass[12pt]{article}
\\pagestyle{empty}
\\usepackage{amsmath}
\\usepackage{amssymb}
\\usepackage[latin1]{inputenc}
\\begin{document}
\\[
"""

footer = """
\\]
\\end{document}
"""

zoom = 10

# If the result doesn't already exist in cached form, create it
if True or not os.path.isfile(base_dir+svg_name):
    tex_file = open(base_dir+tex_name, 'w')
    tex_file.write(header)
    tex_file.write(latex)
    tex_file.write(footer)
    tex_file.close()
    
    def escapeshell(code):
        #return code.replace('"', '\\"')
        return code.replace('\n',' ').replace('\r',' ')  # This seems to do the right thing
     
    stdout = execute_cmd('cd '+base_dir+'; texvc . . "'+escapeshell(latex)+'" iso-8859-1')
    # First character must be an indication of success
    if verify_code and '+cmlCMLX'.find(stdout[0]) == -1:
        print 'Content-type: text/plain\n\n'
        print 'Error parsing TeX'
        print stdout
        sys.exit()
        
    #print ('latex -output-directory=' + base_dir + ' -halt-on-error ' + tex_name  + ' > ' + out_name)
    execute_cmd('cd '+base_dir+'; latex ' + tex_name  + ' > ' + out_name)
    execute_cmd('cd '+base_dir+'; dvips -q -f -e 0 -E -D 10000 -x ' + str(1000*zoom) +' -o '+ps_name +' '+dvi_name)
    #execute_cmd('pstoedit -f plot-svg -dt -ssp '+ps_name+' '+svg_name)
    execute_cmd('cd '+base_dir+'; pstoedit -f plot-svg -dt -ssp ' + ps_name + ' ' + svg_name + '> ' + out_name)

    svg_file = open(base_dir+svg_name)
    zoom_file = open(base_dir+zoom_name, 'w')
    for line in svg_file:
        zoom_file.write( re.sub('translate\(.*\) scale\(1,-1\) scale\(0.0017361\)',  'scale(1,-1) scale('+str(0.0017361/zoom)+')',  line) )
    svg_file.close()
    zoom_file.close()

outname = base_dir+svg_name
outname = base_dir+zoom_name
mime = 'image/svg+xml'
    
if redirect:
    print 'Location: '+outname+'\r\n\r\n'
else:
    outfile = open( outname, 'rb')
    image = outfile.read()
    #image = image.replace('scale(0.0017361)', 'scale('+str(0.0017361/zoom)+')')
    #image = re.sub('translate\(.*\) scale\(1,-1\) scale\(0.0017361\)', 
    #                'scale(1,-1) scale('+str(0.0017361/zoom)+')', 
    #                image)

    if not debug:
        sys.stdout.write('Content-type: '+mime+'\r\n\r\n')
        sys.stdout.write(image)
    outfile.close()

python调用方法:

import urllib
import urllib2

def latex2svg(latexcode):
    txdata = urllib.urlencode({"latex": latexcode})
    url = "http://localhost:8080/cgi-bin/latex2svg.py"
    req = urllib2.Request(url, txdata)
    return urllib2.urlopen(req).read()

print latex2svg("2+2=4")
print latex2svg("\\frac{1}{2\\pi}")

输出结果为:

{"speakText":"2 2=4","svg":"<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"6.586ex\" height=\"2.176ex\" style=\"vertical-align: -0.338ex;\" viewBox=\"0 -791.3 2835.6 936.9\" role=\"img\" focusable=\"false\" xmlns=\"http://www.w3.org/2000/svg\" aria-labelledby=\"MathJax-SVG-1-Title\">\n<title id=\"MathJax-SVG-1-Title\">2 2=4</title>\n<defs aria-hidden=\"true\">\n<path stroke-width=\"1\" id=\"E1-MJMAIN-32\" d=\"M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z\"></path>\n<path stroke-width=\"1\" id=\"E1-MJMAIN-3D\" d=\"M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z\"></path>\n<path stroke-width=\"1\" id=\"E1-MJMAIN-34\" d=\"M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z\"></path>\n</defs>\n<g stroke=\"currentColor\" fill=\"currentColor\" stroke-width=\"0\" transform=\"matrix(1 0 0 -1 0 0)\" aria-hidden=\"true\">\n <use xlink:href=\"#E1-MJMAIN-32\" x=\"0\" y=\"0\"></use>\n <use xlink:href=\"#E1-MJMAIN-32\" x=\"500\" y=\"0\"></use>\n <use xlink:href=\"#E1-MJMAIN-3D\" x=\"1278\" y=\"0\"></use>\n <use xlink:href=\"#E1-MJMAIN-34\" x=\"2335\" y=\"0\"></use>\n</g>\n</svg>","width":"6.586ex","height":"2.176ex","style":"vertical-align: -0.338ex;"}{"speakText":"\\\\frac{1}{2\\\\pi}","svg":"<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"100ex\" height=\"5.343ex\" style=\"vertical-align: -3.505ex; max-width: 60000px;\" viewBox=\"0 -791.3 43055.4 2300.3\" role=\"img\" focusable=\"false\" xmlns=\"http://www.w3.org/2000/svg\" aria-labelledby=\"MathJax-SVG-1-Title\">\n<title id=\"MathJax-SVG-1-Title\">\\\\frac{1}{2\\\\pi}</title>\n<defs aria-hidden=\"true\">\n<path stroke-width=\"1\" id=\"E1-MJMATHI-66\" d=\"M118 -162Q120 -162 124 -164T135 -167T147 -168Q160 -168 171 -155T187 -126Q197 -99 221 27T267 267T289 382V385H242Q195 385 192 387Q188 390 188 397L195 425Q197 430 203 430T250 431Q298 431 298 432Q298 434 307 482T319 540Q356 705 465 705Q502 703 526 683T550 630Q550 594 529 578T487 561Q443 561 443 603Q443 622 454 636T478 657L487 662Q471 668 457 668Q445 668 434 658T419 630Q412 601 403 552T387 469T380 433Q380 431 435 431Q480 431 487 430T498 424Q499 420 496 407T491 391Q489 386 482 386T428 385H372L349 263Q301 15 282 -47Q255 -132 212 -173Q175 -205 139 -205Q107 -205 81 -186T55 -132Q55 -95 76 -78T118 -61Q162 -61 162 -103Q162 -122 151 -136T127 -157L118 -162Z\"></path>\n<path stroke-width=\"1\" id=\"E1-MJMATHI-72\" d=\"M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z\"></path>\n<path stroke-width=\"1\" id=\"E1-MJMATHI-61\" d=\"M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z\"></path>\n<path stroke-width=\"1\" id=\"E1-MJMATHI-63\" d=\"M34 159Q34 268 120 355T306 442Q362 442 394 418T427 355Q427 326 408 306T360 285Q341 285 330 295T319 325T330 359T352 380T366 386H367Q367 388 361 392T340 400T306 404Q276 404 249 390Q228 381 206 359Q162 315 142 235T121 119Q121 73 147 50Q169 26 205 26H209Q321 26 394 111Q403 121 406 121Q410 121 419 112T429 98T420 83T391 55T346 25T282 0T202 -11Q127 -11 81 37T34 159Z\"></path>\n<path stroke-width=\"1\" id=\"E1-MJMAIN-31\" d=\"M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z\"></path>\n<path stroke-width=\"1\" id=\"E1-MJMAIN-32\" d=\"M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z\"></path>\n<path stroke-width=\"1\" id=\"E1-MJMATHI-70\" d=\"M23 287Q24 290 25 295T30 317T40 348T55 381T75 411T101 433T134 442Q209 442 230 378L240 387Q302 442 358 442Q423 442 460 395T497 281Q497 173 421 82T249 -10Q227 -10 210 -4Q199 1 187 11T168 28L161 36Q160 35 139 -51T118 -138Q118 -144 126 -145T163 -148H188Q194 -155 194 -157T191 -175Q188 -187 185 -190T172 -194Q170 -194 161 -194T127 -193T65 -192Q-5 -192 -24 -194H-32Q-39 -187 -39 -183Q-37 -156 -26 -148H-6Q28 -147 33 -136Q36 -130 94 103T155 350Q156 355 156 364Q156 405 131 405Q109 405 94 377T71 316T59 280Q57 278 43 278H29Q23 284 23 287ZM178 102Q200 26 252 26Q282 26 310 49T356 107Q374 141 392 215T411 325V331Q411 405 350 405Q339 405 328 402T306 393T286 380T269 365T254 350T243 336T235 326L232 322Q232 321 229 308T218 264T204 212Q178 106 178 102Z\"></path>\n<path stroke-width=\"1\" id=\"E1-MJMATHI-69\" d=\"M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z\"></path>\n</defs>\n<g stroke=\"currentColor\" fill=\"currentColor\" stroke-width=\"0\" transform=\"matrix(1 0 0 -1 0 0)\" aria-hidden=\"true\">\n<g transform=\"translate(19870,0)\">\n <use xlink:href=\"#E1-MJMATHI-66\" x=\"0\" y=\"0\"></use>\n <use xlink:href=\"#E1-MJMATHI-72\" x=\"550\" y=\"0\"></use>\n <use xlink:href=\"#E1-MJMATHI-61\" x=\"1002\" y=\"0\"></use>\n <use xlink:href=\"#E1-MJMATHI-63\" x=\"1531\" y=\"0\"></use>\n <use xlink:href=\"#E1-MJMAIN-31\" x=\"1965\" y=\"0\"></use>\n<g transform=\"translate(2465,0)\">\n <use xlink:href=\"#E1-MJMAIN-32\" x=\"0\" y=\"0\"></use>\n<g transform=\"translate(0,-1200)\">\n <use xlink:href=\"#E1-MJMATHI-70\" x=\"0\" y=\"0\"></use>\n <use xlink:href=\"#E1-MJMATHI-69\" x=\"503\" y=\"0\"></use>\n</g>\n</g>\n</g>\n</g>\n</svg>","width":"100ex","height":"5.343ex","style":"vertical-align: -3.505ex; max-width: 60000px;"}

源码下载地址:https://download.csdn.net/download/jlq_diligence/12366038

猜你喜欢

转载自blog.csdn.net/jlq_diligence/article/details/105783282