7 from athana
import getTALstr
12 directories
= ["pdfs"]
19 COMPARE
=["xpdf", "xpdf -C"]
20 OUTPUTDIR
= "results.clip/"
22 #COMPARE=["xpdf", PDF2SWF+" -s convertgradients"]
23 #OUTPUTDIR = "results.pdf2swf/"
25 #COMPARE=[PDF2SWF, PDF2SWF+" --flatten"]
26 #OUTPUTDIR = "results.flatten/"
31 return md5
.md5(str(random
.random())).hexdigest()[0:8]
40 if ">" not in command
:
41 if os
.system(command
+ " > /tmp/log.txt 2>&1") & 0xff00:
42 error
= open("/tmp/log.txt", "rb").read()
46 if os
.system(command
) & 0xff00:
47 return "Unknown error in "+command
49 class ConversionError
:
50 def __init__(self
, msg
):
55 class TooComplexError
:
56 def __init__(self
, msg
):
62 def __init__(self
, msg
):
67 def formatException():
68 s
= "Exception "+str(sys
.exc_info()[0])
69 info
= sys
.exc_info()[1]
73 for l
in traceback
.extract_tb(sys
.exc_info()[2]):
74 s
+= " File \"%s\", line %d, in %s\n" % (l
[0],l
[1],l
[2])
80 def __init__(self
, filename
, page
, width
, height
):
81 self
.filename
= filename
85 self
.htmlmessage
= None
91 self
.width
,self
.height
= width
,height
93 def runtool(self
, cmd
, filename
, page
, file):
94 if cmd
.startswith("xpdf"):
95 unlink("/tmp/test-%06d.ppm" % page
)
97 error
= system(PDFTOPPM
+ "%s -r 72 -f %d -l %d '%s' /tmp/test" % (args
, page
, page
, filename
))
99 raise ConversionError(error
)
101 error
= system(CONVERT
+ " /tmp/test-%06d.ppm %s" % (page
, file))
103 raise ConversionError(error
)
104 unlink("/tmp/test-%06d.ppm" % page
)
106 unlink("/tmp/test.swf")
108 error
= system(COMPARE
[0]+ " -Q 300 -p%d '%s' -o /tmp/test.swf" % (page
, filename
))
109 #system("mv svp.ps %s.ps" % randstr())
110 if error
and "supports 65536" in error
:
111 raise TooComplexError(error
)
113 raise ConversionError(error
)
115 error
= system(SWFRENDER
+ " /tmp/test.swf -o %s" % file)
117 raise ConversionError(error
)
118 unlink("/tmp/test.swf")
120 def runtools(self
, filename
, page
, file1
, file2
, file12
):
124 self
.runtool(COMPARE
[0], filename
, page
, file2
)
125 self
.runtool(COMPARE
[1], filename
, page
, file1
)
129 pic1
= Image
.open(file1
)
131 self
.width1
= pic1
.size
[0]
132 self
.height1
= pic1
.size
[1]
134 pic2
= Image
.open(file2
)
136 self
.width2
= pic2
.size
[0]
137 self
.height2
= pic2
.size
[1]
139 if abs(self
.width1
-self
.width2
)>5 or abs(self
.height1
!=self
.height2
)>5:
140 badness
+= 65536*abs(self
.width2
-self
.width1
)*max(self
.height1
,self
.height2
)+65536*abs(self
.height2
-self
.height1
)*max(self
.width1
,self
.width2
)
142 minx
= min(self
.width1
,self
.width2
)
143 miny
= min(self
.height1
,self
.height2
)
145 pic1
= pic1
.crop((0,0,minx
,miny
))
146 pic1
= pic1
.convert("RGB")
147 pic1
= pic1
.filter(ImageFilter
.BLUR
)
148 pic2
= pic2
.crop((0,0,minx
,miny
))
149 pic2
= pic2
.convert("RGB")
150 pic2
= pic2
.filter(ImageFilter
.BLUR
)
152 diffimage
= ImageChops
.difference(pic1
,pic2
)
153 diffimage
.save(file12
, "PNG")
155 # compute quadratical difference
156 diff
= diffimage
.histogram()
157 for i
in range(1,128):
158 badness
+= (diff
[i
] + diff
[256-i
])*float(i
*i
)
159 badness
+= (diff
[256+i
] + diff
[256+256-i
])*float(i
*i
)
160 badness
+= (diff
[512+i
] + diff
[512+256-i
])*float(i
*i
)
162 badness
/= (minx
*miny
)*3
169 self
.file1
= str(counter
) + ".png"
170 counter
= counter
+ 1
171 self
.file2
= str(counter
) + ".png"
172 counter
= counter
+ 1
173 self
.file12
= str(counter
) + ".png"
174 counter
= counter
+ 1
175 self
.rating
= self
.runtools(self
.filename
, self
.page
, OUTPUTDIR
+ self
.file1
, OUTPUTDIR
+ self
.file2
, OUTPUTDIR
+ self
.file12
)
177 self
.rating
= 65534.0
178 self
.message
= formatException()
180 except ConversionError
:
181 self
.rating
= 65535.0
182 self
.message
= formatException()
184 except TooComplexError
:
185 self
.rating
= 65536.0
186 self
.message
= formatException()
189 self
.rating
= 65537.0
190 self
.message
= formatException()
196 if abs(self
.width1
- self
.width2
) > 5 or \
197 abs(self
.height1
- self
.height2
) > 5:
198 return '<font color="red">%dx%d <-> %dx%d</font>' % (self
.width1
, self
.height1
, self
.width2
, self
.height2
)
200 return '%dx%d,%dx%d' % (self
.width1
, self
.height1
, self
.width2
, self
.height2
)
202 def generatehtml(self
):
205 self
.html12
= str(counter
) + ".html"
206 counter
= counter
+ 1
207 self
.htmldiff
= str(counter
) + ".html"
208 counter
= counter
+ 1
209 fi
= open(OUTPUTDIR
+ self
.html12
, "wb")
210 fi
.write(getTALstr("""
213 <tal:block tal:replace="python:'File: '+self.filename"/><br>
214 <tal:block tal:replace="python:'Page: '+str(self.page)"/><br>
215 <tal:block tal:replace="python:'Rating: '+str(self.rating)"/><br>
216 <pre tal:condition="python:self.message" tal:replace="python:'Message: '+str(self.message)"/><br>
218 <table cellspacing="0" cellpadding="0">
219 <tr><td><img tal:attributes="src python:self.file1"/></td><td><img tal:attributes="src python:self.file2"/></td></tr>
220 <tr><td>pdf2swf Version</td><td>pdftoppm Version</td></tr>
224 </html>""", {"self": self
}))
227 fi
= open(OUTPUTDIR
+ self
.htmldiff
, "wb")
228 fi
.write(getTALstr("""
231 <tal:block tal:replace="python:'File: '+self.filename"/><br>
232 <tal:block tal:replace="python:'Page: '+str(self.page)"/><br>
233 <tal:block tal:replace="python:'Rating: '+str(self.rating)"/><br>
234 <pre tal:condition="python:self.message" tal:replace="python:'Message: '+str(self.message)"/><br>
236 <img tal:attributes="src python:self.file12"/>
239 </html>""", {"self": self
}))
243 self
.htmlmessage
= str(counter
) + ".html"
244 counter
= counter
+ 1
245 fi
= open(OUTPUTDIR
+ self
.htmlmessage
, "wb")
246 fi
.write(getTALstr("""
249 <pre tal:content="raw python:self.message">
252 </html>""", {"self": self
}))
257 def compare_pages(page1
,page2
):
258 if page1
.rating
< page2
.rating
:
260 elif page1
.rating
> page2
.rating
:
266 def add_directory(directory
):
267 if not os
.path
.isdir(directory
):
268 print "bad directory:",directory
270 for file in os
.listdir(directory
):
272 filename
= os
.path
.join(directory
, file)
273 if file.lower().endswith(".pdf"):
274 filenames
+= [filename
]
276 elif os
.path
.isdir(filename
):
277 add_directory(filename
)
284 for file in filenames
:
287 for dir in directories
:
290 for filename
in filenames
:
292 unlink("/tmp/test.txt")
293 error
= system(PDF2SWF
+ " -I %s -o /tmp/test.txt" % filename
)
295 raise ConversionError(error
)
296 fi
= open("/tmp/test.txt", "rb")
297 for line
in fi
.readlines():
299 for param
in line
.split(" "):
300 key
,value
= param
.split("=")
302 page
= int(p
["page"])
303 width
= int(float(p
["width"]))
304 height
= int(float(p
["height"]))
305 print filename
, page
, "%dx%d" % (width
, height
)
306 pdfpage
= PDFPage(filename
, page
, width
, height
)
309 if width
< 2000 and height
< 2000:
312 # only consider the first 3 pages
316 except KeyboardInterrupt:
319 pdfpage
= PDFPage(filename
, -1, -1, -1)
320 pdfpage
.rating
= 65536.0
321 pdfpage
.message
= formatException()
324 pages
.sort(compare_pages
)
329 page
.position
= position
330 position
= position
+ 1
332 fi
= open(OUTPUTDIR
+ "index.html", "wb")
333 fi
.write(getTALstr("""<html>
336 <table border="1"><tr><th>Position</th><th>Rating</th><th>File</th><th>Size</th><th>Page</th><th>Images</th><th>Diff</th><th>Further Info</th></tr>
337 <tal:block tal:repeat="page pages">
339 <td tal:content="python:page.position"/>
340 <td tal:content="python:page.rating"/>
341 <td tal:content="python:page.filename"/>
342 <td tal:content="raw python:page.getsizes()"/>
343 <td tal:content="python:page.page"/>
344 <td><a tal:attributes="href python:page.html12">Side by Side</a></td>
345 <td><a tal:attributes="href python:page.htmldiff">Difference</a></td>
346 <td><a tal:condition="python:page.message" tal:attributes="href python:page.htmlmessage">Error message</a></td>
351 </html>""", {"pages": pages
}))