1 /* ***** BEGIN LICENSE BLOCK *****
2 *
3 * $Id: downconvert.cpp,v 1.10 2007/03/19 16:19:00 asuraparaju Exp $ $Name: Dirac_1_0_2 $
4 *
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 *
7 * The contents of this file are subject to the Mozilla Public License
8 * Version 1.1 (the "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
14 * the specific language governing rights and limitations under the License.
15 *
16 * The Original Code is BBC Research and Development code.
17 *
18 * The Initial Developer of the Original Code is the British Broadcasting
19 * Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2004.
21 * All Rights Reserved.
22 *
23 * Contributor(s): Richard Felton (Original Author),
24 *                 Thomas Davies
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
28 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
29 * the GPL or the LGPL are applicable instead of those above. If you wish to
30 * allow use of your version of this file only under the terms of the either
31 * the GPL or LGPL and not to allow others to use your version of this file
32 * under the MPL, indicate your decision by deleting the provisions above
33 * and replace them with the notice and other provisions required by the GPL
34 * or LGPL. If you do not delete the provisions above, a recipient may use
35 * your version of this file under the terms of any one of the MPL, the GPL
36 * or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
38 
39 #include <libdirac_motionest/downconvert.h>
40 using namespace dirac;
41 
DownConverter()42 DownConverter::DownConverter()
43 {}
44 
45 
46 #if !defined(HAVE_MMX)
47 //General function - does some admin and calls the correct function
48 //NOTE: The mmx version of this function is defined in downconvert_mmx.cpp
49 //Ensusre that changes made in this function are reflected in the mmx version
50 //as well.
DoDownConvert(const PicArray & old_data,PicArray & new_data)51 void DownConverter::DoDownConvert(const PicArray& old_data, PicArray& new_data)
52 {
53     //Down-convert by a factor of two.
54     m_row_buffer= new ValueType[old_data.LengthX()];
55     //Variables that will be used by the filter calculations
56     int sum;
57     int colpos;
58 
59     // The area of the picture that will be downconverted
60     const int xlen = 2*new_data.LengthX();
61     const int ylen = 2*new_data.LengthY();
62 
63 
64     //There are three y loops to cope with the leading edge, middle
65     //and trailing edge of each column.
66     colpos=0;
67     for( int y=0; y<Stage_I_Size*2 ; y+=2 , colpos++ )
68     {
69         // We are filtering each column but doing it bit by bit.
70         // This means our main loop is in the x direction and
71         // there is a much greater chance the data we need will
72         // be in the cache.
73 
74         for( int x=0 ; x<xlen ; x++ )
75         {
76             // In down conversion we interpolate every pixel
77             // so there is no copying.
78             // Excuse the complicated ternary stuff but it sorts out the edge
79             sum =  (old_data[y][x] + old_data[y+1][x])*StageI_I;
80             sum += (old_data[((y-1)>=0)?(y-1):0][x] + old_data[y+2][x])*StageI_II;
81             sum += (old_data[((y-2)>=0)?(y-2):0][x] + old_data[y+3][x])*StageI_III;
82             sum += (old_data[((y-3)>=0)?(y-3):0][x] + old_data[y+4][x])*StageI_IV;
83             sum += (old_data[((y-4)>=0)?(y-4):0][x] + old_data[y+5][x])*StageI_V;
84             sum += (old_data[((y-5)>=0)?(y-5):0][x] + old_data[y+6][x])*StageI_VI;
85             sum += 1<<(StageI_Shift-1);//do rounding right
86             m_row_buffer[x] = sum >> StageI_Shift;
87         }// x
88         //Speaking of which - the row loop.
89 
90         RowLoop(colpos,new_data);
91     }// y
92 
93     // This loop is like the last one but it deals with the center
94     // section of the image and so the ternary operations are dropped
95     // from the filter section.
96     for( int y=Stage_I_Size*2 ; y<ylen-Stage_I_Size*2 ; y+=2 , colpos++ )
97     {
98         for( int x=0 ; x<xlen ; x++ )
99         {
100 
101             sum =  (old_data[y][x]   + old_data[y+1][x])*StageI_I;
102             sum += (old_data[y-1][x] + old_data[y+2][x])*StageI_II;
103             sum += (old_data[y-2][x] + old_data[y+3][x])*StageI_III;
104             sum += (old_data[y-3][x] + old_data[y+4][x])*StageI_IV;
105             sum += (old_data[y-4][x] + old_data[y+5][x])*StageI_V;
106             sum += (old_data[y-5][x] + old_data[y+6][x])*StageI_VI;
107             sum += 1<<(StageI_Shift-1);//do rounding right
108             m_row_buffer[x] = sum >> StageI_Shift;
109         }// x
110 
111         RowLoop( colpos , new_data );
112     }// y
113 
114     // Another similar loop! - this time we are dealing with
115     // the trailing edge so the ternary stuff is back in the
116     // filter calcs but in the second parameter.
117 
118     for( int y=ylen-(Stage_I_Size*2) ; y<ylen-1 ; y+=2 , colpos++ )
119     {
120         for( int x=0; x<xlen ; x++ )
121         {
122 
123             sum =  (old_data[y][x]   + old_data[((y+1)<ylen)?(y+1):(ylen-1)][x])*StageI_I;
124             sum += (old_data[y-1][x] + old_data[((y+2)<ylen)?(y+2):(ylen-1)][x])*StageI_II;
125             sum += (old_data[y-2][x] + old_data[((y+3)<ylen)?(y+3):(ylen-1)][x])*StageI_III;
126             sum += (old_data[y-3][x] + old_data[((y+4)<ylen)?(y+4):(ylen-1)][x])*StageI_IV;
127             sum += (old_data[y-4][x] + old_data[((y+5)<ylen)?(y+5):(ylen-1)][x])*StageI_V;
128             sum += (old_data[y-5][x] + old_data[((y+6)<ylen)?(y+6):(ylen-1)][x])*StageI_VI;
129 
130             // Do rounding right
131             sum += 1<<(StageI_Shift-1);
132             m_row_buffer[x] = sum >> StageI_Shift;
133 
134         }// x
135 
136         RowLoop( colpos , new_data );
137 
138     }//  y
139 
140     // Tidy up the data
141     delete[] m_row_buffer;
142 
143 }
144 #endif
145 
146 
147 // The loop over the columns is the same every time so lends itself to isolation
148 // as an individual function.
RowLoop(const int colpos,PicArray & new_data)149 void DownConverter::RowLoop( const int colpos , PicArray& new_data)
150 {
151 
152      //Calculation variables
153     int sum;
154     const int xlen = 2*new_data.LengthX();
155     int linepos=0;
156 
157      // Leading Column Edge
158      // Similar loops to the x case in ByHalf_opto, for explanation look there.
159      // Note the factor of two difference as we only want to fill in every other
160      // line as the others have already been created by the line loops.
161 
162     for( int x=0; x<(2*Stage_I_Size) ; x+=2 , linepos++ )
163     {
164         sum =  (m_row_buffer[((x)>=0)?(x):0]     + m_row_buffer[x+1])*StageI_I;
165         sum += (m_row_buffer[((x-1)>=0)?(x-1):0] + m_row_buffer[x+2])*StageI_II;
166         sum += (m_row_buffer[((x-2)>=0)?(x-2):0] + m_row_buffer[x+3])*StageI_III;
167         sum += (m_row_buffer[((x-3)>=0)?(x-3):0] + m_row_buffer[x+4])*StageI_IV;
168         sum += (m_row_buffer[((x-4)>=0)?(x-4):0] + m_row_buffer[x+5])*StageI_V;
169         sum += (m_row_buffer[((x-5)>=0)?(x-5):0] + m_row_buffer[x+6])*StageI_VI;
170         sum += 1<<(StageI_Shift-1);//do rounding right
171 
172         new_data[colpos][linepos] = sum >> StageI_Shift;
173 
174     }
175      //Middle of column
176     for( int x=(2*Stage_I_Size) ; x<xlen-(2*Stage_I_Size) ; x+=2 , linepos++)
177     {
178         sum =  (m_row_buffer[x]   + m_row_buffer[x+1])*StageI_I;
179         sum += (m_row_buffer[x-1] + m_row_buffer[x+2])*StageI_II;
180         sum += (m_row_buffer[x-2] + m_row_buffer[x+3])*StageI_III;
181         sum += (m_row_buffer[x-3] + m_row_buffer[x+4])*StageI_IV;
182         sum += (m_row_buffer[x-4] + m_row_buffer[x+5])*StageI_V;
183         sum += (m_row_buffer[x-5] + m_row_buffer[x+6])*StageI_VI;
184         sum += 1<<(StageI_Shift-1);//do rounding right
185 
186         new_data[colpos][linepos] = sum >> StageI_Shift;
187 
188     }
189      //Trailing column edge
190     for( int x=xlen-(2*Stage_I_Size) ; x< xlen-1 ; x+=2 , linepos++ )
191     {
192         sum =  (m_row_buffer[x]   + m_row_buffer[((x+1)<xlen)?(x+1):(xlen-1)])*StageI_I;
193         sum += (m_row_buffer[x-1] + m_row_buffer[((x+2)<xlen)?(x+2):(xlen-1)])*StageI_II;
194         sum += (m_row_buffer[x-2] + m_row_buffer[((x+3)<xlen)?(x+3):(xlen-1)])*StageI_III;
195         sum += (m_row_buffer[x-3] + m_row_buffer[((x+4)<xlen)?(x+4):(xlen-1)])*StageI_IV;
196         sum += (m_row_buffer[x-4] + m_row_buffer[((x+5)<xlen)?(x+5):(xlen-1)])*StageI_V;
197         sum += (m_row_buffer[x-5] + m_row_buffer[((x+6)<xlen)?(x+6):(xlen-1)])*StageI_VI;
198         sum += 1<<(StageI_Shift-1);//do rounding right
199 
200         new_data[colpos][linepos] = sum >> StageI_Shift;
201 
202     }
203 
204 }
205