mirror of
https://github.com/stevenrobertson/cuburn.git
synced 2025-02-05 03:30:05 -05:00
Another incompatible update to the genome format
This commit is contained in:
parent
ed885534d6
commit
c80b8a07a7
@ -11,7 +11,7 @@ _CODE = '''
|
||||
#include<math_constants.h>
|
||||
|
||||
__global__
|
||||
void colorclip(float4 *pixbuf, float gamma, float vibrancy, float highpow,
|
||||
void colorclip(float4 *pixbuf, float gamma, float vibrance, float highpow,
|
||||
float linrange, float lingam, float3 bkgd,
|
||||
int fbsize, int blend_background_color) {
|
||||
int i = threadIdx.x + blockDim.x * (blockIdx.x + gridDim.x * blockIdx.y);
|
||||
@ -42,7 +42,7 @@ void colorclip(float4 *pixbuf, float gamma, float vibrancy, float highpow,
|
||||
return;
|
||||
}
|
||||
|
||||
float ls = vibrancy * alpha / pix.w;
|
||||
float ls = vibrance * alpha / pix.w;
|
||||
alpha = fminf(1.0f, fmaxf(0.0f, alpha));
|
||||
|
||||
float maxc = fmaxf(pix.x, fmaxf(pix.y, pix.z));
|
||||
@ -71,9 +71,9 @@ void colorclip(float4 *pixbuf, float gamma, float vibrancy, float highpow,
|
||||
}
|
||||
}
|
||||
|
||||
pix.x += (1.0f - vibrancy) * powf(opix.x, gamma);
|
||||
pix.y += (1.0f - vibrancy) * powf(opix.y, gamma);
|
||||
pix.z += (1.0f - vibrancy) * powf(opix.z, gamma);
|
||||
pix.x += (1.0f - vibrance) * powf(opix.x, gamma);
|
||||
pix.y += (1.0f - vibrance) * powf(opix.y, gamma);
|
||||
pix.z += (1.0f - vibrance) * powf(opix.z, gamma);
|
||||
|
||||
pix.x += (1.0f - alpha) * bkgd.x;
|
||||
pix.y += (1.0f - alpha) * bkgd.y;
|
||||
@ -318,7 +318,7 @@ class Filtering(object):
|
||||
|
||||
# TODO: implement integration over cubic splines?
|
||||
gam = f32(1 / gnm.color.gamma(tc))
|
||||
vib = f32(gnm.color.vibrancy(tc))
|
||||
vib = f32(gnm.color.vibrance(tc))
|
||||
hipow = f32(gnm.color.highlight_power(tc))
|
||||
lin = f32(gnm.color.gamma_threshold(tc))
|
||||
lingam = f32(lin ** (gam-1.0) if lin > 0 else 0)
|
||||
|
BIN
cuburn/code/primes.bin
Normal file
BIN
cuburn/code/primes.bin
Normal file
Binary file not shown.
@ -7,6 +7,8 @@ import tempita
|
||||
|
||||
def crep(s):
|
||||
"""Escape for PTX assembly"""
|
||||
if isinstance(s, unicode):
|
||||
s = s.encode('utf-8')
|
||||
return '"%s"' % s.encode("string_escape")
|
||||
|
||||
class Template(tempita.Template):
|
||||
|
114
cuburn/genome.py
114
cuburn/genome.py
@ -1,7 +1,8 @@
|
||||
import json
|
||||
import base64
|
||||
import numpy as np
|
||||
|
||||
from code.util import crep
|
||||
|
||||
class SplEval(object):
|
||||
_mat = np.matrix([[1.,-2, 1, 0], [2,-3, 0, 1],
|
||||
[1,-1, 0, 0], [-2, 3, 0, 0]])
|
||||
@ -80,14 +81,12 @@ class SplEval(object):
|
||||
return list(self.knots.T.flat)
|
||||
|
||||
class Palette(object):
|
||||
"""Wafer-thin wrapper around palettes. For the future!"""
|
||||
def __init__(self, datastr, fmt='rgb8'):
|
||||
if fmt != 'rgb8':
|
||||
def __init__(self, datastrs):
|
||||
if datastrs[0] != 'rgb8':
|
||||
raise NotImplementedError
|
||||
if len(datastr) != 768:
|
||||
raise ValueError("Unsupported palette width")
|
||||
self.width = 256
|
||||
pal = np.reshape(np.fromstring(datastr, np.uint8), (256, 3))
|
||||
raw = base64.b64decode(''.join(datastrs[1:]))
|
||||
pal = np.reshape(np.fromstring(raw, np.uint8), (256, 3))
|
||||
self.data = np.ones((256, 4), np.float32)
|
||||
self.data[:,:3] = pal / 255.0
|
||||
|
||||
@ -106,36 +105,61 @@ class _AttrDict(dict):
|
||||
return dct
|
||||
|
||||
class Genome(_AttrDict):
|
||||
"""
|
||||
Load a genome description, wrapping all data structures in _AttrDicts,
|
||||
converting lists of numbers to splines, and deriving some values. Derived
|
||||
values are stored as instance properties, rather than replacing the
|
||||
original values, such that JSON-encoding this structure should always
|
||||
print a valid genome.
|
||||
"""
|
||||
# For now, we base the Genome class on an _AttrDict, letting its structure
|
||||
# be defined implicitly by the way it is used in device code. More formal
|
||||
# unpacking will happen soon.
|
||||
def __init__(self, gnm, base_den):
|
||||
# be defined implicitly by the way it is used in device code, except for
|
||||
# these derived properties.
|
||||
def __init__(self, gnm):
|
||||
super(Genome, self).__init__(gnm)
|
||||
for k, v in self.items():
|
||||
if not isinstance(v, dict):
|
||||
continue
|
||||
v = _AttrDict(v)
|
||||
# These two properties must be handled separately
|
||||
if k not in ('info', 'time'):
|
||||
_AttrDict._wrap(v)
|
||||
self[k] = v
|
||||
# TODO: this is a hack, figure out how to solve it more elegantly
|
||||
self.spp = SplEval(self.camera.density.knotlist)
|
||||
self.spp.knots[1] *= base_den
|
||||
# TODO: decide how to handle palettes. For now, it's the caller's
|
||||
# responsibility to replace this list with actual palettes.
|
||||
pal = self.color.palette
|
||||
|
||||
self.decoded_palettes = map(Palette, self.palettes)
|
||||
print self.color
|
||||
pal = self.color.palette_times
|
||||
if isinstance(pal, basestring):
|
||||
self.color.palette = [(0.0, pal), (1.0, pal)]
|
||||
elif isinstance(pal, list):
|
||||
self.color.palette = zip(pal[::2], pal[1::2])
|
||||
self.palette_times = [(0.0, int(pal)), (1.0, int(pal))]
|
||||
else:
|
||||
self.palette_times = zip(pal[::2], map(int, pal[1::2]))
|
||||
|
||||
# TODO: caller also needs to call set_timing()
|
||||
self.adj_frame_width = None
|
||||
self.canonical_right = (not self.get('link') or not self.link == 'self'
|
||||
or not self.link.get('right'))
|
||||
self.adj_frame_width, self.spp = None, None
|
||||
self.canonical_right = not (self.get('link') and
|
||||
(self.link == 'self' or self.link.get('right')))
|
||||
|
||||
def set_timing(self, base_dur, fps, offset=0.0, err_spread=True):
|
||||
def set_profile(self, prof, offset=0.0, err_spread=True):
|
||||
"""
|
||||
Set frame timing. Must be called at least once prior to rendering.
|
||||
Sets the instance props which are dependent on a profile. Also
|
||||
calculates timing information, which is returned instead of being
|
||||
attached to the genome. May be called multiple times to set different
|
||||
options.
|
||||
|
||||
``prof`` is a profile dictionary. ``offset`` is the time in seconds
|
||||
that the first frame's effective presentation time should be offset
|
||||
from the natural presentation time. ``err_spread`` will spread the
|
||||
rounding error in this frame across all frames, such that PTS+(1/FPS)
|
||||
is exactly equal to the requested duration.
|
||||
|
||||
Returns ``(err, times)``, where ``err`` is the rounding error in
|
||||
seconds (taking ``offset`` into account), and ``times`` is a list of
|
||||
the central time of each frame in the animation in relative-time
|
||||
coordinates. Also sets the ``spp`` and ``adj_frame_width`` properties.
|
||||
"""
|
||||
self.spp = SplEval(self.camera.density.knotlist)
|
||||
self.spp.knots[1] *= prof['quality']
|
||||
fps, base_dur = prof['fps'], prof['duration']
|
||||
|
||||
# TODO: test!
|
||||
dur = self.time.duration
|
||||
if isinstance(dur, basestring):
|
||||
@ -162,3 +186,43 @@ class Genome(_AttrDict):
|
||||
epts = np.linspace(-2*np.pi, 2*np.pi, nframes)
|
||||
times = times + 0.5 * err * (np.tanh(epts) + 1)
|
||||
return err, times
|
||||
|
||||
def json_encode_genome(obj, indent=0):
|
||||
"""
|
||||
Encode an object into JSON notation. This serializer only works on the
|
||||
subset of JSON used in genomes.
|
||||
"""
|
||||
# TODO: test, like so many other things
|
||||
isnum = lambda v: isinstance(v, (float, int, np.number))
|
||||
|
||||
def wrap(pairs, delims):
|
||||
do, dc = delims
|
||||
i = ' ' * indent
|
||||
out = ''.join([do, ', '.join(pairs), dc])
|
||||
if '\n' not in out and len(out) + indent < 70:
|
||||
return out
|
||||
return ''.join(['\n', i, do, ' ', ('\n'+i+', ').join(pairs),
|
||||
'\n', i, dc])
|
||||
|
||||
if isinstance(obj, dict):
|
||||
if not obj:
|
||||
return '{}'
|
||||
ks, vs = zip(*sorted(obj.items()))
|
||||
if ks == ('b', 'g', 'r'):
|
||||
ks, vs = reversed(ks), reversed(vs)
|
||||
ks = [crep('%.8g' % k if isnum(k) else str(k)) for k in ks]
|
||||
vs = [json_encode_genome(v, indent+2) for v in vs]
|
||||
return wrap(['%s: %s' % p for p in zip(ks, vs)], '{}')
|
||||
elif isinstance(obj, list):
|
||||
vs = [json_encode_genome(v, indent+2) for v in obj]
|
||||
if vs and len(vs) % 2 == 0 and isnum(obj[0]):
|
||||
vs = map(', '.join, zip(vs[::2], vs[1::2]))
|
||||
return wrap(vs, '[]')
|
||||
elif isinstance(obj, SplEval):
|
||||
return json_encode_genome(obj.knotlist, indent)
|
||||
elif isinstance(obj, basestring):
|
||||
return crep(obj)
|
||||
elif isnum(obj):
|
||||
return '%.8g' % obj
|
||||
raise TypeError("Don't know how to serialize %s of type %s" %
|
||||
(obj, type(obj)))
|
||||
|
@ -250,15 +250,13 @@ class Renderer(object):
|
||||
info_size = 4 * len(self._iter.packer) * ntemporal_samples
|
||||
d_infos = cuda.mem_alloc(info_size)
|
||||
|
||||
pals = genome.color.palette
|
||||
if isinstance(pals, basestring):
|
||||
pals = [0.0, pals, 1.0, pals]
|
||||
ptimes, pidxs = zip(*genome.palette_times)
|
||||
palint_times = np.empty(len(genome_times[0]), f32)
|
||||
palint_times.fill(100.0)
|
||||
palint_times[:len(pals)] = [p[0] for p in pals]
|
||||
palint_times.fill(1e10)
|
||||
palint_times[:len(ptimes)] = ptimes
|
||||
d_palint_times = cuda.to_device(palint_times)
|
||||
d_palint_vals = cuda.to_device(
|
||||
np.concatenate([p[1].data for p in pals]))
|
||||
pvals = [genome.decoded_palettes[i].data for i in pidxs]
|
||||
d_palint_vals = cuda.to_device(np.concatenate(pvals))
|
||||
|
||||
if self.acc_mode in ('deferred', 'atomic'):
|
||||
palette_fun = self.mod.get_function("interp_palette_hsv_flat")
|
||||
|
Loading…
Reference in New Issue
Block a user