7 from athana import getTALstr
12 directories = ["pdfs"]
19 #COMPARE=["xpdf", PDF2SWF+" -s poly2bitmap"]
20 #OUTPUTDIR = "results.poly2bitmap/"
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 runtools(self, filename, page, file1, file2, file12):
97 if COMPARE[0] == "xpdf":
98 unlink("/tmp/test-%06d.ppm" % page)
99 error = system(PDFTOPPM + " -r 72 -f %d -l %d '%s' /tmp/test" % (page, page, filename))
100 if error and "supports 65536" in error:
101 raise TooComplexError(error)
103 raise ConversionError(error)
105 error = system(CONVERT + " /tmp/test-%06d.ppm %s" % (page, file2))
107 raise ConversionError(error)
108 unlink("/tmp/test-%06d.ppm" % page)
110 unlink("/tmp/test.swf")
112 error = system(COMPARE[0]+ " -Q 300 -p%d '%s' -o /tmp/test.swf" % (page, filename))
113 #system("mv svp.ps %s.ps" % randstr())
114 if error and "supports 65536" in error:
115 raise TooComplexError(error)
117 raise ConversionError(error)
119 error = system(SWFRENDER + " /tmp/test.swf -o %s" % file2)
121 raise ConversionError(error)
122 unlink("/tmp/test.swf")
124 unlink("/tmp/test.swf")
125 error = system(COMPARE[1]+ " -Q 300 -p%d '%s' -o /tmp/test.swf" % (page, filename))
127 raise ConversionError(error)
129 error = system(SWFRENDER + " /tmp/test.swf -o %s" % file1)
131 raise ConversionError(error)
132 unlink("/tmp/test.swf")
135 pic1 = Image.open(file1)
137 self.width1 = pic1.size[0]
138 self.height1 = pic1.size[1]
140 pic2 = Image.open(file2)
142 self.width2 = pic2.size[0]
143 self.height2 = pic2.size[1]
145 if abs(self.width1-self.width2)>5 or abs(self.height1!=self.height2)>5:
146 badness += 65536*abs(self.width2-self.width1)*max(self.height1,self.height2)+65536*abs(self.height2-self.height1)*max(self.width1,self.width2)
148 minx = min(self.width1,self.width2)
149 miny = min(self.height1,self.height2)
151 pic1 = pic1.crop((0,0,minx,miny))
152 pic1 = pic1.convert("RGB")
153 pic1 = pic1.filter(ImageFilter.BLUR)
154 pic2 = pic2.crop((0,0,minx,miny))
155 pic2 = pic2.convert("RGB")
156 pic2 = pic2.filter(ImageFilter.BLUR)
158 diffimage = ImageChops.difference(pic1,pic2)
159 diffimage.save(file12, "PNG")
161 # compute quadratical difference
162 diff = diffimage.histogram()
163 for i in range(1,128):
164 badness += (diff[i] + diff[256-i])*float(i*i)
165 badness += (diff[256+i] + diff[256+256-i])*float(i*i)
166 badness += (diff[512+i] + diff[512+256-i])*float(i*i)
168 badness /= (minx*miny)*3
175 self.file1 = str(counter) + ".png"
176 counter = counter + 1
177 self.file2 = str(counter) + ".png"
178 counter = counter + 1
179 self.file12 = str(counter) + ".png"
180 counter = counter + 1
181 self.rating = self.runtools(self.filename, self.page, OUTPUTDIR + self.file1, OUTPUTDIR + self.file2, OUTPUTDIR + self.file12)
183 self.rating = 65534.0
184 self.message = formatException()
186 except ConversionError:
187 self.rating = 65535.0
188 self.message = formatException()
190 except TooComplexError:
191 self.rating = 65536.0
192 self.message = formatException()
195 self.rating = 65537.0
196 self.message = formatException()
202 if abs(self.width1 - self.width2) > 5 or \
203 abs(self.height1 - self.height2) > 5:
204 return '<font color="red">%dx%d <-> %dx%d</font>' % (self.width1, self.height1, self.width2, self.height2)
206 return '%dx%d,%dx%d' % (self.width1, self.height1, self.width2, self.height2)
208 def generatehtml(self):
211 self.html12 = str(counter) + ".html"
212 counter = counter + 1
213 self.htmldiff = str(counter) + ".html"
214 counter = counter + 1
215 fi = open(OUTPUTDIR + self.html12, "wb")
216 fi.write(getTALstr("""
219 <tal:block tal:replace="python:'File: '+self.filename"/><br>
220 <tal:block tal:replace="python:'Page: '+str(self.page)"/><br>
221 <tal:block tal:replace="python:'Rating: '+str(self.rating)"/><br>
222 <pre tal:condition="python:self.message" tal:replace="python:'Message: '+str(self.message)"/><br>
224 <table cellspacing="0" cellpadding="0">
225 <tr><td><img tal:attributes="src python:self.file1"/></td><td><img tal:attributes="src python:self.file2"/></td></tr>
226 <tr><td>pdf2swf Version</td><td>pdftoppm Version</td></tr>
230 </html>""", {"self": self}))
233 fi = open(OUTPUTDIR + self.htmldiff, "wb")
234 fi.write(getTALstr("""
237 <tal:block tal:replace="python:'File: '+self.filename"/><br>
238 <tal:block tal:replace="python:'Page: '+str(self.page)"/><br>
239 <tal:block tal:replace="python:'Rating: '+str(self.rating)"/><br>
240 <pre tal:condition="python:self.message" tal:replace="python:'Message: '+str(self.message)"/><br>
242 <img tal:attributes="src python:self.file12"/>
245 </html>""", {"self": self}))
249 self.htmlmessage = str(counter) + ".html"
250 counter = counter + 1
251 fi = open(OUTPUTDIR + self.htmlmessage, "wb")
252 fi.write(getTALstr("""
255 <pre tal:content="raw python:self.message">
258 </html>""", {"self": self}))
263 def compare_pages(page1,page2):
264 if page1.rating < page2.rating:
266 elif page1.rating > page2.rating:
272 def add_directory(directory):
273 if not os.path.isdir(directory):
274 print "bad directory:",directory
276 for file in os.listdir(directory):
278 filename = os.path.join(directory, file)
279 if file.lower().endswith(".pdf"):
280 filenames += [filename]
282 elif os.path.isdir(filename):
283 add_directory(filename)
290 for file in filenames:
293 for dir in directories:
296 for filename in filenames:
298 unlink("/tmp/test.txt")
299 error = system(PDF2SWF + " -I %s -o /tmp/test.txt" % filename)
301 raise ConversionError(error)
302 fi = open("/tmp/test.txt", "rb")
303 for line in fi.readlines():
305 for param in line.split(" "):
306 key,value = param.split("=")
308 page = int(p["page"])
309 width = int(float(p["width"]))
310 height = int(float(p["height"]))
311 print filename, page, "%dx%d" % (width, height)
312 pdfpage = PDFPage(filename, page, width, height)
315 if width < 2000 and height < 2000:
318 # only consider the first 3 pages
322 except KeyboardInterrupt:
325 pdfpage = PDFPage(filename, -1, -1, -1)
326 pdfpage.rating = 65536.0
327 pdfpage.message = formatException()
330 pages.sort(compare_pages)
335 page.position = position
336 position = position + 1
338 fi = open(OUTPUTDIR + "index.html", "wb")
339 fi.write(getTALstr("""<html>
342 <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>
343 <tal:block tal:repeat="page pages">
345 <td tal:content="python:page.position"/>
346 <td tal:content="python:page.rating"/>
347 <td tal:content="python:page.filename"/>
348 <td tal:content="raw python:page.getsizes()"/>
349 <td tal:content="python:page.page"/>
350 <td><a tal:attributes="href python:page.html12">Side by Side</a></td>
351 <td><a tal:attributes="href python:page.htmldiff">Difference</a></td>
352 <td><a tal:condition="python:page.message" tal:attributes="href python:page.htmlmessage">Error message</a></td>
357 </html>""", {"pages": pages}))