1 /* ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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.
16 * The Original Code is BBC Research and Development code.
18 * The Initial Developer of the Original Code is the British Broadcasting
20 * Portions created by the Initial Developer are Copyright (C) 2004.
21 * All Rights Reserved.
23 * Contributor(s): Richard Felton (Original Author),
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
37 * ***** END LICENSE BLOCK ***** */
39 #include <libdirac_motionest/downconvert.h>
40 using namespace dirac
;
42 DownConverter::DownConverter()
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
51 void DownConverter::DoDownConvert(const PicArray
& old_data
, PicArray
& new_data
)
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
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();
64 //There are three y loops to cope with the leading edge, middle
65 //and trailing edge of each column.
67 for( int y
=0; y
<Stage_I_Size
*2 ; y
+=2 , colpos
++ )
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
74 for( int x
=0 ; x
<xlen
; x
++ )
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
;
88 //Speaking of which - the row loop.
90 RowLoop(colpos
,new_data
);
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
++ )
98 for( int x
=0 ; x
<xlen
; x
++ )
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
;
111 RowLoop( colpos
, new_data
);
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.
118 for( int y
=ylen
-(Stage_I_Size
*2) ; y
<ylen
-1 ; y
+=2 , colpos
++ )
120 for( int x
=0; x
<xlen
; x
++ )
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
;
131 sum
+= 1<<(StageI_Shift
-1);
132 m_row_buffer
[x
] = sum
>> StageI_Shift
;
136 RowLoop( colpos
, new_data
);
141 delete[] m_row_buffer
;
147 // The loop over the columns is the same every time so lends itself to isolation
148 // as an individual function.
149 void DownConverter::RowLoop( const int colpos
, PicArray
& new_data
)
152 //Calculation variables
154 const int xlen
= 2*new_data
.LengthX();
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.
162 for( int x
=0; x
<(2*Stage_I_Size
) ; x
+=2 , linepos
++ )
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
172 new_data
[colpos
][linepos
] = sum
>> StageI_Shift
;
176 for( int x
=(2*Stage_I_Size
) ; x
<xlen
-(2*Stage_I_Size
) ; x
+=2 , linepos
++)
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
186 new_data
[colpos
][linepos
] = sum
>> StageI_Shift
;
189 //Trailing column edge
190 for( int x
=xlen
-(2*Stage_I_Size
) ; x
< xlen
-1 ; x
+=2 , linepos
++ )
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
200 new_data
[colpos
][linepos
] = sum
>> StageI_Shift
;