FreeRDP
Loading...
Searching...
No Matches
rfx_dwt.c
1
20#include <winpr/assert.h>
21#include <winpr/cast.h>
22
23#include <freerdp/config.h>
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include "rfx_dwt.h"
30
31static INLINE void rfx_dwt_2d_decode_block(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT idwt,
32 size_t subband_width)
33{
34 const size_t total_width = subband_width << 1;
35
36 /* Inverse DWT in horizontal direction, results in 2 sub-bands in L, H order in tmp buffer idwt.
37 */
38 /* The 4 sub-bands are stored in HL(0), LH(1), HH(2), LL(3) order. */
39 /* The lower part L uses LL(3) and HL(0). */
40 /* The higher part H uses LH(1) and HH(2). */
41
42 const INT16* ll = buffer + subband_width * subband_width * 3;
43 const INT16* hl = buffer;
44 INT16* l_dst = idwt;
45
46 const INT16* lh = buffer + subband_width * subband_width;
47 const INT16* hh = buffer + subband_width * subband_width * 2;
48 INT16* h_dst = idwt + subband_width * subband_width * 2;
49
50 for (size_t y = 0; y < subband_width; y++)
51 {
52 /* Even coefficients */
53 l_dst[0] = WINPR_ASSERTING_INT_CAST(int16_t, ll[0] - ((hl[0] + hl[0] + 1) >> 1));
54 h_dst[0] = WINPR_ASSERTING_INT_CAST(int16_t, lh[0] - ((hh[0] + hh[0] + 1) >> 1));
55 for (size_t n = 1; n < subband_width; n++)
56 {
57 const size_t x = n << 1;
58 l_dst[x] = WINPR_ASSERTING_INT_CAST(int16_t, ll[n] - ((hl[n - 1] + hl[n] + 1) >> 1));
59 h_dst[x] = WINPR_ASSERTING_INT_CAST(int16_t, lh[n] - ((hh[n - 1] + hh[n] + 1) >> 1));
60 }
61
62 /* Odd coefficients */
63 size_t n = 0;
64 for (; n < subband_width - 1; n++)
65 {
66 const size_t x = n << 1;
67
68 const int ld = (hl[n] << 1) + ((l_dst[x] + l_dst[x + 2]) >> 1);
69 const int hd = (hh[n] << 1) + ((h_dst[x] + h_dst[x + 2]) >> 1);
70
71 l_dst[x + 1] = WINPR_ASSERTING_INT_CAST(INT16, ld);
72 h_dst[x + 1] = WINPR_ASSERTING_INT_CAST(INT16, hd);
73 }
74
75 const size_t x = n << 1;
76
77 const int ld = (hl[n] << 1) + (l_dst[x]);
78 const int hd = (hh[n] << 1) + (h_dst[x]);
79 l_dst[x + 1] = WINPR_ASSERTING_INT_CAST(INT16, ld);
80 h_dst[x + 1] = WINPR_ASSERTING_INT_CAST(INT16, hd);
81
82 ll += subband_width;
83 hl += subband_width;
84 l_dst += total_width;
85
86 lh += subband_width;
87 hh += subband_width;
88 h_dst += total_width;
89 }
90
91 /* Inverse DWT in vertical direction, results are stored in original buffer. */
92 for (size_t x = 0; x < total_width; x++)
93 {
94 const INT16* l = idwt + x;
95 const INT16* h = idwt + x + subband_width * total_width;
96 INT16* dst = buffer + x;
97
98 const int dd = *l - ((*h * 2 + 1) >> 1);
99 *dst = WINPR_ASSERTING_INT_CAST(INT16, dd);
100
101 for (size_t n = 1; n < subband_width; n++)
102 {
103 l += total_width;
104 h += total_width;
105
106 /* Even coefficients */
107 const int d2 = *l - ((*(h - total_width) + *h + 1) >> 1);
108 dst[2 * total_width] = WINPR_ASSERTING_INT_CAST(INT16, d2);
109
110 /* Odd coefficients */
111 const int d = (*(h - total_width) << 1) + ((*dst + dst[2 * total_width]) >> 1);
112 dst[total_width] = WINPR_ASSERTING_INT_CAST(INT16, d);
113
114 dst += 2 * total_width;
115 }
116
117 const int d = (*h << 1) + ((*dst * 2) >> 1);
118 dst[total_width] = WINPR_ASSERTING_INT_CAST(INT16, d);
119 }
120}
121
122void rfx_dwt_2d_decode(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT dwt_buffer)
123{
124 WINPR_ASSERT(buffer);
125 WINPR_ASSERT(dwt_buffer);
126
127 rfx_dwt_2d_decode_block(&buffer[3840], dwt_buffer, 8);
128 rfx_dwt_2d_decode_block(&buffer[3072], dwt_buffer, 16);
129 rfx_dwt_2d_decode_block(&buffer[0], dwt_buffer, 32);
130}
131
132static void rfx_dwt_2d_encode_block(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT dwt,
133 UINT32 subband_width)
134{
135 INT16* src = NULL;
136 INT16* l = NULL;
137 INT16* h = NULL;
138 INT16* l_src = NULL;
139 INT16* h_src = NULL;
140 INT16* hl = NULL;
141 INT16* lh = NULL;
142 INT16* hh = NULL;
143 INT16* ll = NULL;
144
145 const UINT32 total_width = subband_width << 1;
146
147 /* DWT in vertical direction, results in 2 sub-bands in L, H order in tmp buffer dwt. */
148 for (UINT32 x = 0; x < total_width; x++)
149 {
150 for (UINT32 n = 0; n < subband_width; n++)
151 {
152 UINT32 y = n << 1;
153 l = dwt + 1ULL * n * total_width + x;
154 h = l + 1ULL * subband_width * total_width;
155 src = buffer + 1ULL * y * total_width + x;
156
157 /* H */
158 *h = WINPR_ASSERTING_INT_CAST(
159 int16_t, (src[total_width] -
160 ((src[0] + src[n < subband_width - 1 ? 2 * total_width : 0]) >> 1)) >>
161 1);
162
163 /* L */
164 *l = WINPR_ASSERTING_INT_CAST(int16_t,
165 src[0] + (n == 0 ? *h : (*(h - total_width) + *h) >> 1));
166 }
167 }
168
169 /* DWT in horizontal direction, results in 4 sub-bands in HL(0), LH(1), HH(2), LL(3) order,
170 * stored in original buffer. */
171 /* The lower part L generates LL(3) and HL(0). */
172 /* The higher part H generates LH(1) and HH(2). */
173
174 ll = buffer + 3ULL * subband_width * subband_width;
175 hl = buffer;
176 l_src = dwt;
177
178 lh = buffer + 1ULL * subband_width * subband_width;
179 hh = buffer + 2ULL * subband_width * subband_width;
180 h_src = dwt + 2ULL * subband_width * subband_width;
181
182 for (size_t y = 0; y < subband_width; y++)
183 {
184 /* L */
185 for (UINT32 n = 0; n < subband_width; n++)
186 {
187 UINT32 x = n << 1;
188
189 /* HL */
190 hl[n] = WINPR_ASSERTING_INT_CAST(
191 int16_t,
192 (l_src[x + 1] - ((l_src[x] + l_src[n < subband_width - 1 ? x + 2 : x]) >> 1)) >> 1);
193 /* LL */
194 ll[n] = WINPR_ASSERTING_INT_CAST(
195 int16_t, l_src[x] + (n == 0 ? hl[n] : (hl[n - 1] + hl[n]) >> 1));
196 }
197
198 /* H */
199 for (UINT32 n = 0; n < subband_width; n++)
200 {
201 UINT32 x = n << 1;
202
203 /* HH */
204 hh[n] = WINPR_ASSERTING_INT_CAST(
205 int16_t,
206 (h_src[x + 1] - ((h_src[x] + h_src[n < subband_width - 1 ? x + 2 : x]) >> 1)) >> 1);
207 /* LH */
208 lh[n] = WINPR_ASSERTING_INT_CAST(
209 int16_t, h_src[x] + (n == 0 ? hh[n] : (hh[n - 1] + hh[n]) >> 1));
210 }
211
212 ll += subband_width;
213 hl += subband_width;
214 l_src += total_width;
215
216 lh += subband_width;
217 hh += subband_width;
218 h_src += total_width;
219 }
220}
221
222void rfx_dwt_2d_encode(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT dwt_buffer)
223{
224 WINPR_ASSERT(buffer);
225 WINPR_ASSERT(dwt_buffer);
226
227 rfx_dwt_2d_encode_block(&buffer[0], dwt_buffer, 32);
228 rfx_dwt_2d_encode_block(&buffer[3072], dwt_buffer, 16);
229 rfx_dwt_2d_encode_block(&buffer[3840], dwt_buffer, 8);
230}