Skip to content

Commit

Permalink
Initial commit of binvis.
Browse files Browse the repository at this point in the history
binvis uses space-filling curves to visualize binary files. This patch also
flips some curves to make them work better with the unrolled binvis view.
  • Loading branch information
cortesi committed Dec 21, 2011
1 parent e0b065d commit 473480f
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 9 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,3 +1,4 @@
.DS_Store
build
*.swp
*.pyc
Expand Down
137 changes: 137 additions & 0 deletions binvis
@@ -0,0 +1,137 @@
#!/usr/bin/env python
import os.path, math, string
import scurve
from scurve import progress
import Image, ImageDraw


class CharHilbert:
def __init__(self, data):
self.data = data
self.csource = scurve.fromSize("hilbert", 3, 256**3)
self.step = len(self.csource)/float(256)

def __len__(self):
return len(self.data)

def point(self, x):
c = ord(self.data[x])
return self.csource.point(int(c*self.step))



class CharClass:
def __init__(self, data):
self.data = data

def __len__(self):
return len(self.data)

def point(self, x):
c = ord(self.data[x])
if c == 0:
return [0, 0, 0]
elif c == 255:
return [255, 255, 255]
elif chr(c) in string.printable:
return [55, 126, 184]
return [228, 26, 28]


def drawmap_unrolled(map, size, csource, name, prog):
prog.set_target((size**2)*4)
map = scurve.fromSize(map, 2, size**2)
c = Image.new("RGB", (size, size*4))
cd = ImageDraw.Draw(c)
step = len(csource)/float(len(map)*4)

sofar = 0
for quad in range(4):
for i, p in enumerate(map):
off = (i + (quad * size**2))
color = csource.point(
int(off * step)
)
x, y = tuple(p)
cd.point(
(x, y + (size * quad)),
fill=tuple(color)
)
if not sofar%100:
prog.tick(sofar)
sofar += 1
c.save(name)


def drawmap_square(map, size, csource, name, prog):
prog.set_target((size**2))
map = scurve.fromSize(map, 2, size**2)
c = Image.new("RGB", map.dimensions())
cd = ImageDraw.Draw(c)
step = len(csource)/float(len(map))
for i, p in enumerate(map):
color = csource.point(int(i*step))
cd.point(tuple(p), fill=tuple(color))
if not i%100:
prog.tick(i)
c.save(name)


def main():
from optparse import OptionParser, OptionGroup
parser = OptionParser(
usage = "%prog [options] infile output",
version="%prog 0.1",
)
parser.add_option(
"-c", "--color", action="store",
type="choice", dest="color", default="class",
choices=["class", "hilbert"]
)
parser.add_option(
"-m", "--map", action="store",
type="str", dest="map", default="hilbert"
)
parser.add_option(
"-s", "--size", action="store",
type="int", dest="size", default=None
)
parser.add_option(
"-t", "--type", type="choice",
dest="type", default="unrolled",
choices=["unrolled", "square"]
)
parser.add_option(
"-q", "--quiet", action="store_true",
dest="quiet", default=False
)
options, args = parser.parse_args()
if len(args) != 2:
parser.error("Please specify input and output file.")

d = file(args[0]).read()
if options.size:
size = options.size
else:
size = int(math.ceil(math.sqrt(len(d))))

if options.color == "class":
csource = CharClass(d)
else:
csource = CharHilbert(d)

if options.quiet:
prog = progress.Dummy()
else:
prog = progress.Progress(None)

if options.type == "unrolled":
drawmap_unrolled(options.map, size, csource, args[1], prog)
elif options.type == "square":
drawmap_square(options.map, size, csource, args[1], prog)
prog.clear()



main()

10 changes: 7 additions & 3 deletions scurve/progress.py
Expand Up @@ -35,10 +35,10 @@ class Progress(Inplace):
def __init__(self, target, title="", width=40, stream=sys.stderr):
Inplace.__init__(self, title, stream=stream)
self.width, self.target = width, target
self.prev = -1
self.prev = -1
self.startTime = None
self.window = None

def tick(self, val):
if not self.stream:
return
Expand All @@ -65,6 +65,9 @@ def tick(self, val):
)
Inplace.tick(self, s)

def set_target(self, t):
self.target = t

def restoreTerm(self):
if self.window:
#begin nocover
Expand All @@ -86,9 +89,10 @@ def full(self):


class Dummy:
def __init__(self, *args, **kwargs): pass
def __init__(self, *args, **kwargs): pass
def tick(self, *args, **kwargs): pass
def restoreTerm(self, *args, **kwargs): pass
def clear(self, *args, **kwargs): pass
def full(self, *args, **kwargs): pass
def set_target(self, *args, **kwargs): pass

4 changes: 2 additions & 2 deletions scurve/zigzag.py
Expand Up @@ -40,7 +40,7 @@ def dimensions(self):
def index(self, p):
idx = 0
flip = False
for power, i in enumerate(p):
for power, i in enumerate(reversed(list(p))):
power = self.dimension-power-1
if flip:
fi = self.size-i-1
Expand All @@ -64,4 +64,4 @@ def point(self, idx):
p.append(v)
if v%2:
flip = not flip
return p
return reversed(p)
2 changes: 2 additions & 0 deletions scurve/zorder.py
Expand Up @@ -40,6 +40,7 @@ def dimensions(self):
return [2**self.bits]*self.dimension

def index(self, p):
p.reverse()
idx = 0
iwidth = self.bits * self.dimension
for i in range(iwidth):
Expand All @@ -55,4 +56,5 @@ def point(self, idx):
for i in range(iwidth):
b = utils.bitrange(idx, iwidth, i, i+1) << (iwidth-i-1)/self.dimension
p[i%self.dimension] |= b
p.reverse()
return p
8 changes: 4 additions & 4 deletions test/test_zorder.py
Expand Up @@ -10,12 +10,12 @@ def test_dimensions(self):

def test_point(self):
z = zorder.ZOrder(2, 2)
assert z.point(utils.bits2int([0, 1, 0, 1])) == [0, 3]
assert z.point(utils.bits2int([0, 1, 0, 1])) == [3, 0]
assert z.point(utils.bits2int([0, 0, 0, 0])) == [0, 0]
assert z.point(utils.bits2int([1, 0, 0, 0])) == [2, 0]
assert z.point(utils.bits2int([1, 0, 1, 0])) == [3, 0]
assert z.point(utils.bits2int([1, 0, 0, 0])) == [0, 2]
assert z.point(utils.bits2int([1, 0, 1, 0])) == [0, 3]
assert z.point(utils.bits2int([1, 1, 1, 1])) == [3, 3]

z = zorder.ZOrder(2, 3)
assert z.point(utils.bits2int([1, 1, 1, 1, 1, 1])) == [7, 7]

Expand Down

0 comments on commit 473480f

Please sign in to comment.