Flutter Engine
The Flutter Engine
generate_fir_coeff.py
Go to the documentation of this file.
1#!/usr/bin/python
2
3'''
4Copyright 2013 Google Inc.
5
6Use of this source code is governed by a BSD-style license that can be
7found in the LICENSE file.
8'''
9
10
11from __future__ import print_function
12import math
13import pprint
14
15
17 """Returns the percent of samples within n std deviations of the normal."""
18 return math.erf(n / math.sqrt(2))
19
20
22 """Returns the percent of samples within the std deviation range a, b"""
23 if b < a:
24 return 0;
25
26 if a < 0:
27 if b < 0:
28 return (withinStdDev(-a) - withinStdDev(-b)) / 2;
29 else:
30 return (withinStdDev(-a) + withinStdDev(b)) / 2;
31 else:
32 return (withinStdDev(b) - withinStdDev(a)) / 2;
33
34
35# We have some smudged samples which represent the average coverage of a range.
36# We have a 'center' which may not line up with those samples.
37# From center make a normal where 5 sample widths out is at 3 std deviations.
38# The first and last samples may not be fully covered.
39
40# This is the sub-sample shift for each set of FIR coefficients
41# (the centers of the lcds in the samples)
42# Each subpxl takes up 1/3 of a pixel,
43# so they are centered at x=(i/n+1/2n), or 1/6, 3/6, 5/6 of a pixel.
44# Each sample takes up 1/4 of a pixel,
45# so the results fall at (x*4)%1, or 2/3, 0, 1/3 of a sample.
46samples_per_pixel = 4
47subpxls_per_pixel = 3
48#sample_offsets is (frac, int) in sample units.
49sample_offsets = [
50 math.modf(
51 (float(subpxl_index)/subpxls_per_pixel + 1.0/(2.0*subpxls_per_pixel))
52 * samples_per_pixel
53 ) for subpxl_index in range(subpxls_per_pixel)
54]
55
56#How many samples to consider to the left and right of the subpxl center.
57sample_units_width = 5
58
59#The std deviation at sample_units_width.
60std_dev_max = 3
61
62#The target sum is in some fixed point representation.
63#Values larger the 1 in fixed point simulate ink spread.
64target_sum = 0x110
65
66for sample_offset, sample_align in sample_offsets:
67 coeffs = []
68 coeffs_rounded = []
69
70 #We start at sample_offset - sample_units_width
71 current_sample_left = sample_offset - sample_units_width
72 current_std_dev_left = -std_dev_max
73
74 done = False
75 while not done:
76 current_sample_right = math.floor(current_sample_left + 1)
77 if current_sample_right > sample_offset + sample_units_width:
78 done = True
79 current_sample_right = sample_offset + sample_units_width
80 current_std_dev_right = current_std_dev_left + (
81 (current_sample_right - current_sample_left) / sample_units_width
82 ) * std_dev_max
83
84 coverage = withinStdDevRange(current_std_dev_left, current_std_dev_right)
85 coeffs.append(coverage * target_sum)
86 coeffs_rounded.append(int(round(coverage * target_sum)))
87
88 current_sample_left = current_sample_right
89 current_std_dev_left = current_std_dev_right
90
91 # Have the numbers, but rounding needs to add up to target_sum.
92 delta = 0
93 coeffs_rounded_sum = sum(coeffs_rounded)
94 if coeffs_rounded_sum > target_sum:
95 # The coeffs add up to too much.
96 # Subtract 1 from the ones which were rounded up the most.
97 delta = -1
98
99 if coeffs_rounded_sum < target_sum:
100 # The coeffs add up to too little.
101 # Add 1 to the ones which were rounded down the most.
102 delta = 1
103
104 if delta:
105 print("Initial sum is 0x%0.2X, adjusting." % (coeffs_rounded_sum,))
106 coeff_diff = [(coeff_rounded - coeff) * delta
107 for coeff, coeff_rounded in zip(coeffs, coeffs_rounded)]
108
110 def __init__(self, index, item):
111 self.index = index
112 self.item = item
113 def __lt__(self, other):
114 return self.item < other.item
115 def __repr__(self):
116 return "arr[%d] == %s" % (self.index, repr(self.item))
117
118 coeff_pkg = [IndexTracker(i, diff) for i, diff in enumerate(coeff_diff)]
119 coeff_pkg.sort()
120
121 # num_elements_to_force_round better be < (2 * sample_units_width + 1) or
122 # * our math was wildy wrong
123 # * an awful lot of the curve is out side our sample
124 # either is pretty bad, and probably means the results will not be useful.
125 num_elements_to_force_round = abs(coeffs_rounded_sum - target_sum)
126 for i in xrange(num_elements_to_force_round):
127 print("Adding %d to index %d to force round %f." % (
128 delta, coeff_pkg[i].index, coeffs[coeff_pkg[i].index]))
129 coeffs_rounded[coeff_pkg[i].index] += delta
130
131 print("Prepending %d 0x00 for allignment." % (sample_align,))
132 coeffs_rounded_aligned = ([0] * int(sample_align)) + coeffs_rounded
133
134 print(', '.join(["0x%0.2X" % coeff_rounded
135 for coeff_rounded in coeffs_rounded_aligned]))
136 print(sum(coeffs), hex(sum(coeffs_rounded)))
137 print()
static void round(SkPoint *p)
def print(*args, **kwargs)
Definition: run_tests.py:49
SIN Vec< N, float > abs(const Vec< N, float > &x)
Definition: SkVx.h:707
Definition: zip.py:1
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741