1//----------------------------------------------------------------------------
2// Anti-Grain Geometry - Version 2.4
3// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4//
5// Permission to copy, use, modify, sell and distribute this software
6// is granted provided this copyright notice appears in all copies.
7// This software is provided "as is" without express or implied
8// warranty, and with no claim as to its suitability for any purpose.
9//
10//----------------------------------------------------------------------------
11// Contact: mcseem@antigrain.com
12//          mcseemagg@yahoo.com
13//          http://www.antigrain.com
14//----------------------------------------------------------------------------
15//
16// Filtering class image_filter_lut implemantation
17//
18//----------------------------------------------------------------------------
19
20
21#include "agg_image_filters.h"
22
23
24namespace agg
25{
26    //--------------------------------------------------------------------
27    void image_filter_lut::realloc_lut(double radius)
28    {
29        m_radius = radius;
30        m_diameter = uceil(radius) * 2;
31        m_start = -int(m_diameter / 2 - 1);
32        unsigned size = m_diameter << image_subpixel_shift;
33        if(size > m_weight_array.size())
34        {
35            m_weight_array.resize(size);
36        }
37    }
38
39
40
41    //--------------------------------------------------------------------
42    // This function normalizes integer values and corrects the rounding
43    // errors. It doesn't do anything with the source floating point values
44    // (m_weight_array_dbl), it corrects only integers according to the rule
45    // of 1.0 which means that any sum of pixel weights must be equal to 1.0.
46    // So, the filter function must produce a graph of the proper shape.
47    //--------------------------------------------------------------------
48    void image_filter_lut::normalize()
49    {
50        unsigned i;
51        int flip = 1;
52
53        for(i = 0; i < image_subpixel_scale; i++)
54        {
55            for(;;)
56            {
57                int sum = 0;
58                unsigned j;
59                for(j = 0; j < m_diameter; j++)
60                {
61                    sum += m_weight_array[j * image_subpixel_scale + i];
62                }
63
64                if(sum == image_filter_scale) break;
65
66                double k = double(image_filter_scale) / double(sum);
67                sum = 0;
68                for(j = 0; j < m_diameter; j++)
69                {
70                    sum +=     m_weight_array[j * image_subpixel_scale + i] =
71                        iround(m_weight_array[j * image_subpixel_scale + i] * k);
72                }
73
74                sum -= image_filter_scale;
75                int inc = (sum > 0) ? -1 : 1;
76
77                for(j = 0; j < m_diameter && sum; j++)
78                {
79                    flip ^= 1;
80                    unsigned idx = flip ? m_diameter/2 + j/2 : m_diameter/2 - j/2;
81                    int v = m_weight_array[idx * image_subpixel_scale + i];
82                    if(v < image_filter_scale)
83                    {
84                        m_weight_array[idx * image_subpixel_scale + i] += inc;
85                        sum += inc;
86                    }
87                }
88            }
89        }
90
91        unsigned pivot = m_diameter << (image_subpixel_shift - 1);
92
93        for(i = 0; i < pivot; i++)
94        {
95            m_weight_array[pivot + i] = m_weight_array[pivot - i];
96        }
97        unsigned end = (diameter() << image_subpixel_shift) - 1;
98        m_weight_array[0] = m_weight_array[end];
99    }
100
101
102}
103
104