FreeRDP
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 
31 static 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 
122 void 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 
132 static 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 
222 void 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 }