]>
Commit | Line | Data |
---|---|---|
77c25c7b KS |
1 | use super::CB_SELECTORS; |
2 | use super::mv::MV; | |
3 | use super::super::indeo3data::*; | |
4 | use super::{Indeo3Cell, Plane}; | |
5 | ||
6 | pub const MAX_CELL_SIZE: usize = 2400; | |
7 | const DEFAULT_PIXEL: u8 = 0x40; | |
8 | const INTRA_FLAT_THRESHOLD: u32 = 8; | |
9 | const INTER_FLAT_THRESHOLD: u32 = 8; | |
10 | ||
11 | struct IndexWriter<'a> { | |
12 | dst: &'a mut [u8], | |
13 | pos: usize, | |
14 | do_rle: bool, | |
15 | } | |
16 | ||
17 | const SKIP_CELL: u8 = 0xFD; | |
18 | const ZERO_CELL: u8 = 0xFD; | |
19 | ||
20 | impl<'a> IndexWriter<'a> { | |
21 | fn new(dst: &'a mut [u8], do_rle: bool) -> Self { | |
22 | Self { | |
23 | dst, | |
24 | pos: 0, | |
25 | do_rle, | |
26 | } | |
27 | } | |
28 | fn write_pair(&mut self, idx0: u8, idx1: u8, quad_radix: u8, esc: u8) { | |
29 | //xxx: in theory one in theory the other index just has to make output fit byte range | |
30 | if idx0 < quad_radix && idx1 < quad_radix { | |
31 | let quad = idx1 * quad_radix + idx0 + esc; | |
32 | self.dst[self.pos] = quad; | |
33 | self.pos += 1; | |
34 | } else { | |
35 | self.dst[self.pos] = idx0; | |
36 | self.pos += 1; | |
37 | self.dst[self.pos] = idx1; | |
38 | self.pos += 1; | |
39 | } | |
40 | } | |
41 | fn write_byte(&mut self, val: u8) { | |
42 | self.dst[self.pos] = val; | |
43 | self.pos += 1; | |
44 | } | |
45 | fn compact_cell(&mut self, esc_vals: [u8; 4]) { | |
46 | if !self.do_rle { | |
47 | return; | |
48 | } | |
49 | let tail = &self.dst[self.pos - 4..][..4]; | |
50 | let mut count = 0; | |
51 | for (&a, &b) in tail.iter().zip(esc_vals.iter()).rev() { | |
52 | if a != b { | |
53 | break; | |
54 | } | |
55 | count += 1; | |
56 | } | |
57 | if count > 1 { | |
58 | self.pos -= count; | |
59 | self.dst[self.pos] = ZERO_CELL; | |
60 | self.pos += 1; | |
61 | } | |
62 | } | |
63 | fn compact_all_cells(&mut self) { | |
64 | if !self.do_rle { | |
65 | return; | |
66 | } | |
67 | if self.pos > 2 { | |
68 | let mut i = 0; | |
69 | while i + 2 < self.pos { | |
70 | if self.dst[i] == ZERO_CELL && self.dst[i + 1] == ZERO_CELL { | |
71 | let mut last_idx = i; | |
72 | for j in (i + 1)..self.pos { | |
73 | if self.dst[j] != ZERO_CELL { | |
74 | break; | |
75 | } | |
76 | last_idx = j; | |
77 | } | |
78 | let len = (last_idx - i + 1).min(31); | |
79 | if len == 2 { | |
80 | self.dst[i] = 0xFC; | |
81 | move_tail(&mut self.dst[i + 1..self.pos], 1); | |
82 | self.pos -= 1; | |
83 | } else { | |
84 | self.dst[i] = 0xFB; | |
85 | self.dst[i + 1] = len as u8; | |
86 | move_tail(&mut self.dst[i + 2..self.pos], len - 2); | |
87 | self.pos -= len - 2; | |
88 | } | |
89 | } | |
90 | i += 1; | |
91 | } | |
92 | } | |
93 | } | |
94 | fn end(self) -> usize { | |
95 | self.pos | |
96 | } | |
97 | } | |
98 | ||
99 | fn move_tail(buf: &mut [u8], off: usize) { | |
100 | let len = buf.len(); | |
101 | for i in off..len { | |
102 | buf[i - off] = buf[i]; | |
103 | } | |
104 | } | |
105 | ||
106 | #[derive(Default)] | |
107 | struct CodebookSuggester { | |
108 | count: [u16; 16], | |
109 | } | |
110 | ||
111 | const BINNING_FACTORS: [u8; 16] = [3, 7, 9, 12, 14, 16, 18, 40, 2, 3, 4, 5, 6, 7, 8, 9]; | |
112 | ||
113 | impl CodebookSuggester { | |
114 | fn new() -> Self { Self::default() } | |
115 | fn merge(cs1: &Self, cs2: &Self) -> Self { | |
116 | let mut count = [0; 16]; | |
117 | for (dst, (&src1, &src2)) in count.iter_mut().zip(cs1.count.iter().zip(cs2.count.iter())) { | |
118 | *dst = src1 + src2; | |
119 | } | |
120 | Self { count } | |
121 | } | |
122 | fn add_delta(&mut self, delta: u8) { | |
123 | for (i, &fac) in BINNING_FACTORS.iter().enumerate() { | |
124 | let val = if i < 8 { delta + fac - 1 } else { delta }; | |
125 | if (val % fac) == 0 { | |
126 | self.count[i] += 1; | |
127 | } | |
128 | } | |
129 | } | |
130 | fn add_line(&mut self, src: &[i8]) { | |
131 | for &delta in src.iter() { | |
132 | if delta == 0 { | |
133 | continue; | |
134 | } | |
e6aaad5c | 135 | let delta = delta.unsigned_abs(); |
77c25c7b KS |
136 | self.add_delta(delta); |
137 | } | |
138 | } | |
139 | fn add_line_half(&mut self, src: &[i8]) { | |
140 | for &delta in src.iter().step_by(2) { | |
141 | if delta == 0 { | |
142 | continue; | |
143 | } | |
e6aaad5c | 144 | let delta = delta.unsigned_abs(); |
77c25c7b KS |
145 | self.add_delta(delta); |
146 | } | |
147 | } | |
148 | fn get_best(&self) -> u8 { | |
149 | let mut idx = 0; | |
150 | for (i, &cnt) in self.count.iter().enumerate().skip(1) { | |
151 | if cnt > self.count[idx] { | |
152 | idx = i; | |
153 | } | |
154 | } | |
155 | idx as u8 | |
156 | } | |
157 | } | |
158 | ||
159 | pub struct CellEncoder { | |
160 | buf: [u8; MAX_CELL_SIZE + 160], | |
161 | rbuf: [u8; MAX_CELL_SIZE + 160], | |
162 | deltas: [i8; MAX_CELL_SIZE], | |
163 | cell: Indeo3Cell, | |
164 | pub out: [u8; MAX_CELL_SIZE / 2 + 1], | |
165 | pub osize: usize, | |
166 | ||
167 | pub flat_thr_i: u32, | |
168 | pub flat_thr_p: u32, | |
169 | pub do_rle: bool, | |
170 | pub quant: Option<u8>, | |
171 | } | |
172 | ||
173 | impl CellEncoder { | |
174 | pub fn new() -> Self { | |
175 | Self { | |
176 | buf: [0; MAX_CELL_SIZE + 160], | |
177 | rbuf: [0; MAX_CELL_SIZE + 160], | |
178 | deltas: [0; MAX_CELL_SIZE], | |
3ff976b2 | 179 | cell: Indeo3Cell::new(0, 0), |
77c25c7b KS |
180 | out: [0; MAX_CELL_SIZE / 2 + 1], |
181 | osize: 0, | |
182 | ||
183 | flat_thr_i: INTRA_FLAT_THRESHOLD, | |
184 | flat_thr_p: INTER_FLAT_THRESHOLD, | |
185 | do_rle: true, | |
186 | quant: None, | |
187 | } | |
188 | } | |
189 | pub fn read_buffer(&mut self, plane: &Plane, cell: Indeo3Cell) { | |
190 | self.cell = cell; | |
191 | ||
192 | let src = &plane.data[cell.get_x() + cell.get_y() * plane.width..]; | |
193 | let dst_w = cell.get_width(); | |
194 | for (dline, sline) in self.buf.chunks_mut(dst_w).skip(1).zip(src.chunks(plane.width)).take(cell.get_height()) { | |
195 | dline.copy_from_slice(&sline[..dst_w]); | |
196 | } | |
197 | if cell.get_y() > 0 { | |
198 | self.buf[..dst_w].copy_from_slice(&plane.data[cell.get_x() + (cell.get_y() - 1) * plane.width..][..dst_w]); | |
199 | } else { | |
200 | for el in self.buf[..dst_w].iter_mut() { | |
201 | *el = DEFAULT_PIXEL; | |
202 | } | |
203 | } | |
204 | } | |
205 | pub fn read_mv_buffer(&mut self, plane: &Plane, cell: Indeo3Cell, mv: MV) { | |
206 | self.cell = cell; | |
207 | ||
208 | let xoff = (cell.get_x() as isize + isize::from(mv.x)) as usize; | |
209 | let yoff = (cell.get_y() as isize + isize::from(mv.y)) as usize; | |
210 | let src = &plane.data[xoff + yoff * plane.width..]; | |
211 | let dst_w = cell.get_width(); | |
212 | for (dline, sline) in self.rbuf.chunks_mut(dst_w).skip(1).zip(src.chunks(plane.width)).take(cell.get_height()) { | |
213 | dline.copy_from_slice(&sline[..dst_w]); | |
214 | } | |
215 | } | |
216 | pub fn null_mv(&mut self) { | |
217 | let stride = self.cell.get_width(); | |
218 | self.buf[stride..].copy_from_slice(&self.rbuf[stride..]); | |
219 | } | |
220 | pub fn gen_diffs_intra(&mut self) { | |
221 | let stride = self.cell.get_width(); | |
222 | let mut start = stride; | |
223 | for dline in self.deltas.chunks_mut(stride).take(self.cell.get_height()) { | |
224 | let (pprev, cur) = self.buf.split_at(start); | |
225 | let prev = &pprev[pprev.len() - stride..]; | |
226 | ||
227 | for (dst, (&cur, &top)) in dline.iter_mut().zip(cur.iter().zip(prev.iter())) { | |
228 | *dst = (cur as i8) - (top as i8); | |
229 | } | |
230 | ||
231 | start += stride; | |
232 | } | |
233 | } | |
234 | pub fn gen_diffs_inter(&mut self) { | |
235 | let stride = self.cell.get_width(); | |
236 | let prev_iter = self.rbuf.chunks(stride).skip(1); | |
237 | let cur_iter = self.buf.chunks(stride).skip(1); | |
238 | for (dline, (cur, prev)) in self.deltas.chunks_mut(stride).take(self.cell.get_height()).zip(cur_iter.zip(prev_iter)) { | |
239 | for (dst, (&cur, &prev)) in dline.iter_mut().zip(cur.iter().zip(prev.iter())) { | |
240 | *dst = (cur as i8) - (prev as i8); | |
241 | } | |
242 | } | |
243 | } | |
244 | pub fn put_buffer(&self, plane: &mut Plane) { | |
245 | let to_skip = if !self.cell.is_intra() || self.cell.get_y() == 0 { 1 } else { 0 }; | |
246 | ||
247 | let dst = &mut plane.data[self.cell.get_x() + (self.cell.get_y() + to_skip - 1) * plane.width..]; | |
248 | let src_w = self.cell.get_width(); | |
249 | for (sline, dline) in self.buf.chunks(src_w).skip(to_skip).zip(dst.chunks_mut(plane.width)).take(self.cell.get_height() + 1 - to_skip) { | |
250 | dline[..src_w].copy_from_slice(sline); | |
251 | } | |
252 | } | |
253 | fn determine_mode(&self, intra: bool, mut mode_hint: u8) -> (u8, [u8; 2]) { | |
254 | if let Some(qmode) = self.quant { | |
255 | if intra { | |
e6aaad5c | 256 | return (mode_hint, [qmode, qmode]); |
77c25c7b | 257 | } else { |
e6aaad5c | 258 | let qmode = qmode & 7; |
77c25c7b KS |
259 | return (mode_hint, [qmode, qmode]); |
260 | } | |
261 | } | |
262 | ||
263 | let stride = self.cell.get_width(); | |
264 | ||
265 | let mut cb_p = CodebookSuggester::new(); | |
266 | let mut cb_s = CodebookSuggester::new(); | |
267 | if !intra && (self.cell.get_height() & 7 == 0) { | |
268 | let mut vdiff = 0; | |
269 | let mut hdiff = 0; | |
270 | for line_pair in self.deltas.chunks(stride * 2).take(self.cell.get_height() / 2) { | |
271 | let (line1, line2) = line_pair.split_at(stride); | |
272 | for (&el1, &el2) in line1.iter().zip(line2.iter()) { | |
273 | let diff = i32::from(el1) - i32::from(el2); | |
274 | vdiff += (diff * diff) as u32; | |
275 | } | |
276 | } | |
277 | for line in self.deltas.chunks(stride).take(self.cell.get_height()) { | |
278 | for pair in line.chunks(2) { | |
279 | let diff = i32::from(pair[1]) - i32::from(pair[0]); | |
280 | hdiff += (diff * diff) as u32; | |
281 | } | |
282 | } | |
283 | vdiff /= (self.cell.get_width() * self.cell.get_height() / 2) as u32; | |
284 | hdiff /= (self.cell.get_width() * self.cell.get_height() / 2) as u32; | |
285 | ||
286 | mode_hint = match ((vdiff > self.flat_thr_p), (hdiff > self.flat_thr_p)) { | |
287 | (false, false) if (self.cell.get_width() & 7) == 0 => 10, | |
288 | (false, _) => 11, | |
289 | _ => 0, | |
290 | }; | |
291 | } | |
292 | match mode_hint { | |
293 | 0 => { | |
294 | for line_pair in self.deltas.chunks(stride * 2).take(self.cell.get_height() / 2) { | |
295 | let (line1, line2) = line_pair.split_at(stride); | |
296 | cb_p.add_line(line1); | |
297 | cb_s.add_line(line2); | |
298 | } | |
299 | }, | |
300 | 3 => { | |
301 | for line_quad in self.deltas.chunks(stride * 4).take(self.cell.get_height() / 4) { | |
302 | let (line01, line23) = line_quad.split_at(stride * 2); | |
303 | let (_line0, line1) = line01.split_at(stride); | |
304 | let (_line2, line3) = line23.split_at(stride); | |
305 | cb_p.add_line(line1); | |
306 | cb_s.add_line(line3); | |
307 | } | |
308 | }, | |
309 | 10 => { | |
310 | for line_quad in self.deltas.chunks(stride * 4).take(self.cell.get_height() / 4) { | |
311 | let (line01, line23) = line_quad.split_at(stride * 2); | |
312 | let (_line0, line1) = line01.split_at(stride); | |
313 | let (_line2, line3) = line23.split_at(stride); | |
314 | cb_p.add_line_half(line1); | |
315 | cb_s.add_line_half(line3); | |
316 | } | |
317 | }, | |
318 | 11 => { | |
319 | for line_quad in self.deltas.chunks(stride * 4).take(self.cell.get_height() / 4) { | |
320 | let (line01, line23) = line_quad.split_at(stride * 2); | |
321 | let (_line0, line1) = line01.split_at(stride); | |
322 | let (_line2, line3) = line23.split_at(stride); | |
323 | cb_p.add_line(line1); | |
324 | cb_s.add_line(line3); | |
325 | } | |
326 | }, | |
327 | _ => unreachable!(), | |
328 | }; | |
329 | let cb_f = CodebookSuggester::merge(&cb_p, &cb_s).get_best(); | |
330 | let cb_p = cb_p.get_best(); | |
331 | let mut cb_s = cb_s.get_best(); | |
332 | ||
333 | let mut use_single = !intra || mode_hint == 10 || cb_p == cb_s; | |
334 | if !use_single { | |
335 | if cb_s == 0 { // we can adjust to the CB_SELECTORS here | |
336 | cb_s = (((cb_p & 7) + 1) * 2).min(15); | |
337 | } | |
338 | let ncb = (cb_p << 4) + cb_s; | |
339 | use_single = !CB_SELECTORS.contains(&ncb); | |
340 | } | |
341 | ||
342 | if use_single { | |
343 | if intra || cb_f < 8 { // we don't want requant happening in inter mode | |
344 | (mode_hint, [cb_f, cb_f]) | |
345 | } else { | |
346 | (mode_hint, [0, 0]) | |
347 | } | |
348 | } else { | |
349 | (mode_hint + 1, [cb_p, cb_s]) | |
350 | } | |
351 | } | |
352 | pub fn compress_intra(&mut self, mode_hint: u8) { | |
353 | let (mode, vq_idx) = self.determine_mode(true, mode_hint); | |
354 | ||
355 | let cb_no1 = usize::from(vq_idx[1]); | |
356 | let cb_no2 = usize::from(vq_idx[0]); | |
357 | let cb1 = IVI3_DELTA_CBS[cb_no1]; | |
358 | let cb2 = IVI3_DELTA_CBS[cb_no2]; | |
359 | ||
360 | let mut requant_idx = None; | |
361 | if (mode == 1) || (mode == 4) { | |
362 | let aq_idx = (vq_idx[0] << 4) | vq_idx[1]; | |
363 | let mut idx = 42; | |
364 | for (i, &el) in CB_SELECTORS.iter().enumerate() { | |
365 | if el == aq_idx { | |
366 | idx = i; | |
367 | break; | |
368 | } | |
369 | } | |
370 | self.out[0] = (mode << 4) | (idx as u8); | |
77c25c7b KS |
371 | } else { |
372 | self.out[0] = (mode << 4) | (cb_no1 as u8); | |
373 | ||
374 | if (8..=15).contains(&cb_no1) { | |
375 | requant_idx = Some(cb_no1 - 8); | |
376 | } | |
377 | } | |
a6627cc2 | 378 | if self.cell.get_y() == 0 || !matches!(mode, 0 | 3 | 10) { |
77c25c7b KS |
379 | requant_idx = None; |
380 | } | |
381 | ||
382 | let start = 1; | |
383 | let mut iwriter = IndexWriter::new(&mut self.out[start..], self.do_rle); | |
384 | ||
385 | let esc_val1 = (cb1.data.len() / 2) as u8; | |
386 | let esc_val2 = (cb2.data.len() / 2) as u8; | |
387 | ||
388 | let cbs = [cb1, cb2, cb1, cb2]; | |
389 | let esc_vals = [esc_val1, esc_val2, esc_val1, esc_val2]; | |
390 | ||
391 | let mut first_line = self.cell.get_y() == 0; | |
392 | let stride = self.cell.get_width(); | |
393 | ||
394 | if let Some(ridx) = requant_idx {// && !first_line { | |
395 | requant(&mut self.buf[..stride], ridx); | |
396 | } | |
397 | ||
398 | let mut cell4 = [0; 20]; | |
399 | match mode { | |
400 | 0 | 1 | 2 => { | |
401 | for y in (0..self.cell.get_height()).step_by(4) { | |
402 | for x in (0..self.cell.get_width()).step_by(4) { | |
403 | Self::get_cell4(&self.buf, x, y, stride, &mut cell4); | |
404 | // first check if the cell can be coded with zero predictor | |
405 | let mut diff = 0; | |
406 | let mut pivot = 4; | |
407 | for _y in 0..4 { | |
408 | let (top, cur) = cell4.split_at(pivot); | |
409 | let top = &top[top.len() - 4..]; | |
410 | for (&tval, &cval) in top.iter().zip(cur.iter()) { | |
411 | let cdiff = i32::from(tval) - i32::from(cval); | |
412 | diff += cdiff * cdiff; | |
413 | } | |
414 | pivot += 4; | |
415 | } | |
416 | if (diff as u32) < self.flat_thr_i { | |
417 | iwriter.write_byte(ZERO_CELL); | |
418 | let (top, tail) = cell4.split_at_mut(4); | |
419 | for dline in tail.chunks_mut(4) { | |
420 | dline.copy_from_slice(top); | |
421 | } | |
422 | Self::put_cell4(&mut self.buf, x, y, stride, &cell4); | |
423 | continue; | |
424 | } | |
425 | ||
426 | compress_intra_cell(&mut iwriter, &mut cell4, &cbs, esc_vals); | |
427 | Self::put_cell4(&mut self.buf, x, y, stride, &cell4); | |
428 | } | |
429 | } | |
430 | }, | |
431 | 3 | 4 => { | |
432 | for y in (0..self.cell.get_height()).step_by(8) { | |
433 | for x in (0..self.cell.get_width()).step_by(4) { | |
434 | Self::get_cell_mode3(&self.buf, x, y, stride, &mut cell4); | |
435 | compress_intra_cell(&mut iwriter, &mut cell4, &cbs, esc_vals); | |
436 | Self::put_cell_mode3(&mut self.buf, x, y, stride, &cell4, first_line); | |
437 | } | |
438 | first_line = false; | |
439 | } | |
440 | }, | |
441 | 10 => { | |
442 | for y in (0..self.cell.get_height()).step_by(8) { | |
443 | for x in (0..self.cell.get_width()).step_by(8) { | |
444 | Self::get_cell_mode10i(&self.buf, x, y, stride, &mut cell4); | |
445 | compress_intra_cell(&mut iwriter, &mut cell4, &cbs, esc_vals); | |
446 | Self::put_cell_mode10i(&mut self.buf, x, y, stride, &cell4, first_line); | |
447 | } | |
448 | first_line = false; | |
449 | } | |
450 | }, | |
451 | _ => unreachable!(), | |
452 | }; | |
453 | iwriter.compact_all_cells(); | |
454 | ||
455 | self.osize = iwriter.end() + start; | |
456 | } | |
457 | pub fn compress_inter(&mut self) { | |
458 | let (mode, vq_idx) = self.determine_mode(false, 0); | |
459 | ||
460 | let cb_no1 = usize::from(vq_idx[1]); | |
461 | let cb_no2 = usize::from(vq_idx[0]); | |
462 | let cb1 = IVI3_DELTA_CBS[cb_no1]; | |
463 | let cb2 = IVI3_DELTA_CBS[cb_no2]; | |
464 | ||
465 | if (mode == 1) || (mode == 4) { | |
466 | let aq_idx = (vq_idx[0] << 4) | vq_idx[1]; | |
467 | let mut idx = 42; | |
468 | for (i, &el) in CB_SELECTORS.iter().enumerate() { | |
469 | if el == aq_idx { | |
470 | idx = i; | |
471 | break; | |
472 | } | |
473 | } | |
474 | self.out[0] = (mode << 4) | (idx as u8); | |
475 | } else { | |
476 | self.out[0] = (mode << 4) | (cb_no1 as u8); | |
477 | } | |
478 | let start = 1; | |
479 | let mut iwriter = IndexWriter::new(&mut self.out[start..], self.do_rle); | |
480 | ||
481 | let esc_val1 = (cb1.data.len() / 2) as u8; | |
482 | let esc_val2 = (cb2.data.len() / 2) as u8; | |
483 | ||
484 | let cbs = [cb1, cb2, cb1, cb2]; | |
485 | let esc_vals = [esc_val1, esc_val2, esc_val1, esc_val2]; | |
486 | ||
487 | ||
488 | let stride = self.cell.get_width(); | |
489 | let mut ccell4 = [0; 20]; | |
490 | let mut pcell4 = [0; 20]; | |
491 | match mode { | |
492 | 0 | 1 | 2 => { | |
493 | for y in (0..self.cell.get_height()).step_by(4) { | |
494 | for x in (0..self.cell.get_width()).step_by(4) { | |
495 | Self::get_cell4(&self.buf, x, y, stride, &mut ccell4); | |
496 | Self::get_cell4(&self.rbuf, x, y, stride, &mut pcell4); | |
497 | // first check if the cell can be coded with zero predictor | |
498 | let mut diff = 0; | |
499 | for (&pval, &cval) in pcell4[4..].iter().zip(ccell4[4..].iter()) { | |
500 | let cdiff = i32::from(pval) - i32::from(cval); | |
501 | diff += cdiff * cdiff; | |
502 | } | |
503 | if diff < 8 { | |
504 | iwriter.write_byte(SKIP_CELL); | |
505 | Self::put_cell4(&mut self.buf, x, y, stride, &pcell4); | |
506 | continue; | |
507 | } | |
508 | ||
509 | compress_inter_cell(&mut iwriter, &mut ccell4, &pcell4, &cbs, esc_vals); | |
510 | Self::put_cell4(&mut self.buf, x, y, stride, &ccell4); | |
511 | } | |
512 | } | |
513 | }, | |
514 | 10 => { | |
515 | let mut offset = 0; | |
516 | let mut ref_cell = [0; 64]; | |
517 | let mut avg_diff: [i16; 16]; | |
518 | for _y in (0..self.cell.get_height()).step_by(8) { | |
519 | for x in (0..self.cell.get_width()).step_by(8) { | |
520 | for (dline, sline) in ref_cell.chunks_mut(8).zip(self.rbuf[offset + stride + x..].chunks(stride)) { | |
521 | dline.copy_from_slice(&sline[..8]); | |
522 | } | |
523 | avg_diff = [0; 16]; | |
524 | for j in 0..8 { | |
525 | for i in 0..8 { | |
526 | avg_diff[i / 2 + (j / 2) * 4] += i16::from(self.deltas[offset + x + i + j * stride]); | |
527 | } | |
528 | } | |
529 | for el in avg_diff.iter_mut() { | |
530 | *el = (*el + 2) >> 2; | |
531 | } | |
532 | compress_inter_cell_mode10(&mut iwriter, &mut ref_cell, &avg_diff, &cbs, esc_vals); | |
533 | for (sline, dline) in ref_cell.chunks(8).zip(self.buf[offset + stride + x..].chunks_mut(stride)) { | |
534 | dline[..8].copy_from_slice(sline); | |
535 | } | |
536 | } | |
537 | offset += stride * 8; | |
538 | } | |
539 | }, | |
540 | 11 => { | |
541 | let mut offset = 0; | |
542 | let mut ref_cell = [0; 32]; | |
543 | let mut avg_diff: [i16; 16]; | |
544 | for _y in (0..self.cell.get_height()).step_by(8) { | |
545 | for x in (0..self.cell.get_width()).step_by(4) { | |
546 | for (dline, sline) in ref_cell.chunks_mut(4).zip(self.rbuf[offset + stride + x..].chunks(stride)) { | |
547 | dline.copy_from_slice(&sline[..4]); | |
548 | } | |
549 | avg_diff = [0; 16]; | |
550 | for j in 0..8 { | |
551 | for i in 0..4 { | |
552 | avg_diff[i + (j / 2) * 4] += i16::from(self.deltas[offset + x + i + j * stride]); | |
553 | } | |
554 | } | |
555 | for el in avg_diff.iter_mut() { | |
556 | *el = (*el + 1) >> 1; | |
557 | } | |
558 | ||
559 | compress_inter_cell_mode11(&mut iwriter, &mut ref_cell, &avg_diff, &cbs, esc_vals); | |
560 | for (sline, dline) in ref_cell.chunks(4).zip(self.buf[offset + stride + x..].chunks_mut(stride)) { | |
561 | dline[..4].copy_from_slice(sline); | |
562 | } | |
563 | } | |
564 | offset += stride * 8; | |
565 | } | |
566 | }, | |
567 | _ => unreachable!(), | |
568 | }; | |
569 | iwriter.compact_all_cells(); | |
570 | ||
571 | self.osize = iwriter.end() + start; | |
572 | } | |
573 | ||
574 | fn get_cell4(data: &[u8], x: usize, y: usize, stride: usize, cell: &mut [u8; 20]) { | |
575 | for (dst, src) in cell.chunks_mut(4).zip(data[x + y * stride..].chunks(stride)) { | |
576 | dst.copy_from_slice(&src[..4]); | |
577 | } | |
578 | } | |
579 | fn put_cell4(data: &mut [u8], x: usize, y: usize, stride: usize, cell: &[u8; 20]) { | |
580 | for (src, dst) in cell.chunks(4).zip(data[x + y * stride..].chunks_mut(stride)).skip(1) { | |
581 | dst[..4].copy_from_slice(src); | |
582 | } | |
583 | } | |
584 | fn get_cell_mode3(data: &[u8], x: usize, y: usize, stride: usize, cell: &mut [u8; 20]) { | |
585 | let src = &data[x + y * stride..]; | |
586 | for (dline, slines) in cell.chunks_mut(4).zip(src.chunks(stride * 2)) { | |
587 | dline.copy_from_slice(&slines[..4]); | |
588 | } | |
589 | } | |
590 | fn put_cell_mode3(data: &mut [u8], x: usize, y: usize, stride: usize, cell: &[u8; 20], first_line: bool) { | |
591 | let dst = &mut data[x + y * stride..]; | |
592 | let mut dst_idx = stride; | |
593 | for line in 0..4 { | |
594 | for x in 0..4 { | |
595 | let top = cell[line * 4 + x]; | |
596 | let cur = cell[(line + 1) * 4 + x]; | |
597 | dst[dst_idx + x] = (top + cur) >> 1; | |
598 | dst[dst_idx + stride + x] = cur; | |
599 | } | |
600 | dst_idx += stride * 2; | |
601 | } | |
602 | if first_line { | |
603 | dst[stride..][..4].copy_from_slice(&cell[4..8]); | |
604 | } | |
605 | } | |
606 | fn get_cell_mode10i(data: &[u8], x: usize, y: usize, stride: usize, cell: &mut [u8; 20]) { | |
607 | let src = &data[x + y * stride..]; | |
608 | for (dline, src_pair) in cell.chunks_mut(4).zip(src.chunks(stride * 2)) { | |
609 | for (dst, src) in dline.iter_mut().zip(src_pair.chunks(2)) { | |
610 | *dst = src[0]; | |
611 | } | |
612 | } | |
613 | } | |
614 | fn put_cell_mode10i(data: &mut [u8], x: usize, y: usize, stride: usize, cell: &[u8; 20], first_line: bool) { | |
615 | let dst = &mut data[x + y * stride..]; | |
616 | let mut dst_idx = stride; | |
617 | for line in 0..4 { | |
f5c61879 KS |
618 | for x in 0..8 { |
619 | let top = dst[dst_idx - stride + x]; | |
620 | let cur = cell[(line + 1) * 4 + x / 2]; | |
621 | dst[dst_idx + x] = (top + cur) >> 1; | |
622 | dst[dst_idx + stride + x] = cur; | |
77c25c7b KS |
623 | } |
624 | dst_idx += stride * 2; | |
625 | } | |
626 | if first_line { | |
627 | let (top, tail) = dst[stride..].split_at_mut(stride); | |
628 | top[..8].copy_from_slice(&tail[..8]); | |
629 | } | |
630 | } | |
631 | } | |
632 | ||
633 | fn requant(line: &mut [u8], rq_index: usize) { | |
634 | let tab = &REQUANT_TAB[rq_index]; | |
635 | for el in line.iter_mut() { | |
636 | *el = tab[usize::from(*el)]; | |
637 | } | |
638 | } | |
639 | ||
640 | fn compress_intra_cell(iwriter: &mut IndexWriter, cell4: &mut [u8; 20], cbs: &[&IviDeltaCB; 4], esc_vals: [u8; 4]) { | |
641 | let mut pivot = 4; | |
642 | for y in 0..4 { | |
643 | let cb = cbs[y]; | |
644 | let esc_val = esc_vals[y]; | |
645 | ||
646 | let (prev, cur) = cell4.split_at_mut(pivot); | |
647 | let prev = &prev[prev.len() - 4..]; | |
648 | let cur = &mut cur[..4]; | |
e6aaad5c | 649 | let (idx0, idx1) = find_quad(cb.data, prev, cur); |
77c25c7b KS |
650 | |
651 | cur[0] = ((prev[0] as i8) + cb.data[usize::from(idx1) * 2]) as u8; | |
652 | cur[1] = ((prev[1] as i8) + cb.data[usize::from(idx1) * 2 + 1]) as u8; | |
653 | cur[2] = ((prev[2] as i8) + cb.data[usize::from(idx0) * 2]) as u8; | |
654 | cur[3] = ((prev[3] as i8) + cb.data[usize::from(idx0) * 2 + 1]) as u8; | |
655 | ||
656 | iwriter.write_pair(idx0, idx1, cb.quad_radix, esc_val); | |
657 | ||
658 | pivot += 4; | |
659 | } | |
660 | iwriter.compact_cell(esc_vals); | |
661 | } | |
662 | ||
663 | fn compress_inter_cell(iwriter: &mut IndexWriter, ccell4: &mut [u8; 20], pcell: &[u8; 20], cbs: &[&IviDeltaCB; 4], esc_vals: [u8; 4]) { | |
664 | for (y, (prev, cur)) in pcell[4..].chunks(4).zip(ccell4[4..].chunks_mut(4)).enumerate() { | |
665 | let cb = cbs[y]; | |
666 | let esc_val = esc_vals[y]; | |
667 | ||
e6aaad5c | 668 | let (idx0, idx1) = find_quad(cb.data, prev, cur); |
77c25c7b KS |
669 | |
670 | cur[0] = ((prev[0] as i8) + cb.data[usize::from(idx1) * 2]) as u8; | |
671 | cur[1] = ((prev[1] as i8) + cb.data[usize::from(idx1) * 2 + 1]) as u8; | |
672 | cur[2] = ((prev[2] as i8) + cb.data[usize::from(idx0) * 2]) as u8; | |
673 | cur[3] = ((prev[3] as i8) + cb.data[usize::from(idx0) * 2 + 1]) as u8; | |
674 | ||
675 | iwriter.write_pair(idx0, idx1, cb.quad_radix, esc_val); | |
676 | } | |
677 | iwriter.compact_cell(esc_vals); | |
678 | } | |
679 | ||
680 | fn compress_inter_cell_mode10(iwriter: &mut IndexWriter, cell: &mut [u8; 64], diffs: &[i16; 16], cbs: &[&IviDeltaCB; 4], esc_vals: [u8; 4]) { | |
681 | for y in 0..4 { | |
682 | let cb = cbs[y]; | |
683 | let esc_val = esc_vals[y]; | |
684 | let mut indices = [0, 0]; | |
685 | for pair_no in (0..4).step_by(2) { | |
686 | let src_idx = y * 8 * 2 + pair_no * 2; | |
687 | let src0 = [cell[src_idx], cell[src_idx + 1], cell[src_idx + 8], cell[src_idx + 9]]; | |
688 | let src1 = [cell[src_idx + 2], cell[src_idx + 3], cell[src_idx + 10], cell[src_idx + 11]]; | |
689 | ||
690 | let cur_diff = [diffs[y * 4 + pair_no] as i8, diffs[y * 4 + pair_no + 1] as i8]; | |
691 | ||
692 | let mut best_idx = 0; | |
693 | let mut best_dist = pair_dist(&cur_diff, &[0, 0]); | |
694 | for (idx, cbpair) in cb.data.chunks(2).enumerate().skip(1) { | |
695 | let dist = pair_dist(&cur_diff, cbpair); | |
696 | if dist < best_dist { | |
697 | let mut fits = true; | |
698 | for &el in src0.iter() { | |
699 | if !in_range(el as i8, cbpair[0]) { | |
700 | fits = false; | |
701 | break; | |
702 | } | |
703 | } | |
704 | for &el in src1.iter() { | |
705 | if !in_range(el as i8, cbpair[1]) { | |
706 | fits = false; | |
707 | break; | |
708 | } | |
709 | } | |
710 | if fits { | |
711 | best_dist = dist; | |
712 | best_idx = idx; | |
713 | } | |
714 | } | |
715 | } | |
716 | ||
717 | indices[pair_no / 2] = best_idx as u8; | |
718 | ||
719 | let cb_pair = &cb.data[best_idx * 2..]; | |
720 | for row in cell[src_idx..].chunks_mut(8).take(2) { | |
721 | row[0] = ((row[0] as i8) + cb_pair[0]) as u8; | |
722 | row[1] = ((row[1] as i8) + cb_pair[0]) as u8; | |
723 | row[2] = ((row[2] as i8) + cb_pair[1]) as u8; | |
724 | row[3] = ((row[3] as i8) + cb_pair[1]) as u8; | |
725 | } | |
726 | } | |
727 | iwriter.write_pair(indices[1], indices[0], cb.quad_radix, esc_val); | |
728 | } | |
729 | iwriter.compact_cell(esc_vals); | |
730 | } | |
731 | ||
732 | fn compress_inter_cell_mode11(iwriter: &mut IndexWriter, cell: &mut [u8; 32], diffs: &[i16; 16], cbs: &[&IviDeltaCB; 4], esc_vals: [u8; 4]) { | |
733 | for y in 0..4 { | |
734 | let cb = cbs[y]; | |
735 | let esc_val = esc_vals[y]; | |
736 | let mut indices = [0, 0]; | |
737 | for pair_no in (0..4).step_by(2) { | |
738 | let src_idx = y * 4 * 2 + pair_no; | |
739 | let src0 = [cell[src_idx], cell[src_idx + 4]]; | |
740 | let src1 = [cell[src_idx + 1], cell[src_idx + 5]]; | |
741 | ||
742 | let cur_diff = [diffs[y * 4 + pair_no] as i8, diffs[y * 4 + pair_no + 1] as i8]; | |
743 | ||
744 | let mut best_idx = 0; | |
745 | let mut best_dist = pair_dist(&cur_diff, &[0, 0]); | |
746 | for (idx, cbpair) in cb.data.chunks(2).enumerate().skip(1) { | |
747 | let dist = pair_dist(&cur_diff, cbpair); | |
748 | if dist < best_dist { | |
749 | let mut fits = true; | |
750 | for &el in src0.iter() { | |
751 | if !in_range(el as i8, cbpair[0]) { | |
752 | fits = false; | |
753 | break; | |
754 | } | |
755 | } | |
756 | for &el in src1.iter() { | |
757 | if !in_range(el as i8, cbpair[1]) { | |
758 | fits = false; | |
759 | break; | |
760 | } | |
761 | } | |
762 | if fits { | |
763 | best_dist = dist; | |
764 | best_idx = idx; | |
765 | } | |
766 | } | |
767 | } | |
768 | ||
769 | indices[pair_no / 2] = best_idx as u8; | |
770 | ||
771 | let cb_pair = &cb.data[best_idx * 2..]; | |
772 | cell[src_idx] = ((cell[src_idx] as i8) + cb_pair[0]) as u8; | |
773 | cell[src_idx + 4] = ((cell[src_idx + 4] as i8) + cb_pair[0]) as u8; | |
774 | cell[src_idx + 1] = ((cell[src_idx + 1] as i8) + cb_pair[1]) as u8; | |
775 | cell[src_idx + 5] = ((cell[src_idx + 5] as i8) + cb_pair[1]) as u8; | |
776 | } | |
777 | iwriter.write_pair(indices[1], indices[0], cb.quad_radix, esc_val); | |
778 | } | |
779 | iwriter.compact_cell(esc_vals); | |
780 | } | |
781 | ||
782 | fn pair_dist(src: &[i8], pair: &[i8]) -> u32 { | |
e6aaad5c KS |
783 | let d0 = (i32::from(src[0]) - i32::from(pair[0])).unsigned_abs(); |
784 | let d1 = (i32::from(src[1]) - i32::from(pair[1])).unsigned_abs(); | |
77c25c7b KS |
785 | d0 * d0 + d1 * d1 |
786 | } | |
787 | ||
788 | fn in_range(base: i8, delta: i8) -> bool { | |
789 | if let Some(val) = base.checked_add(delta) { | |
790 | val >= 0 | |
791 | } else { | |
792 | false | |
793 | } | |
794 | } | |
795 | ||
796 | fn find_pair(cb_data: &[i8], ppair: &[u8], cpair: &[u8]) -> u8 { | |
797 | let ppair = [ppair[0] as i8, ppair[1] as i8]; | |
798 | let diff = [(cpair[0] as i8) - ppair[0], (cpair[1] as i8) - ppair[1]]; | |
799 | // pair 0 is always zero; | |
800 | if diff == [0, 0] { | |
801 | return 0; | |
802 | } | |
803 | let mut best_idx = 0; | |
804 | let mut best_dist = pair_dist(&diff, &[0, 0]); | |
805 | for (idx, cbpair) in cb_data.chunks(2).enumerate().skip(1) { | |
806 | let dist = pair_dist(&diff, cbpair); | |
807 | if dist < best_dist && in_range(ppair[0], cbpair[0]) && in_range(ppair[1], cbpair[1]) { | |
808 | best_dist = dist; | |
809 | best_idx = idx; | |
810 | } | |
811 | } | |
812 | best_idx as u8 | |
813 | } | |
814 | ||
815 | fn find_quad(cb_data: &[i8], prev: &[u8], cur: &[u8]) -> (u8, u8) { | |
816 | let (ppair1, ppair0) = prev.split_at(2); | |
817 | let (cpair1, cpair0) = cur.split_at(2); | |
818 | let idx1 = find_pair(cb_data, ppair1, cpair1); | |
819 | let idx0 = find_pair(cb_data, ppair0, cpair0); | |
820 | (idx0, idx1) | |
821 | } | |
822 | ||
823 | const REQUANT_TAB: [[u8; 128]; 8] = [ | |
824 | [ | |
825 | 0x00, 0x02, 0x02, 0x04, 0x04, 0x06, 0x06, 0x08, | |
826 | 0x08, 0x0a, 0x0a, 0x0c, 0x0c, 0x0e, 0x0e, 0x10, | |
827 | 0x10, 0x12, 0x12, 0x14, 0x14, 0x16, 0x16, 0x18, | |
828 | 0x18, 0x1a, 0x1a, 0x1c, 0x1c, 0x1e, 0x1e, 0x20, | |
829 | 0x20, 0x22, 0x22, 0x24, 0x24, 0x26, 0x26, 0x28, | |
830 | 0x28, 0x2a, 0x2a, 0x2c, 0x2c, 0x2e, 0x2e, 0x30, | |
831 | 0x30, 0x32, 0x32, 0x34, 0x34, 0x36, 0x36, 0x38, | |
832 | 0x38, 0x3a, 0x3a, 0x3c, 0x3c, 0x3e, 0x3e, 0x40, | |
833 | 0x40, 0x42, 0x42, 0x44, 0x44, 0x46, 0x46, 0x48, | |
834 | 0x48, 0x4a, 0x4a, 0x4c, 0x4c, 0x4e, 0x4e, 0x50, | |
835 | 0x50, 0x52, 0x52, 0x54, 0x54, 0x56, 0x56, 0x58, | |
836 | 0x58, 0x5a, 0x5a, 0x5c, 0x5c, 0x5e, 0x5e, 0x60, | |
837 | 0x60, 0x62, 0x62, 0x64, 0x64, 0x66, 0x66, 0x68, | |
838 | 0x68, 0x6a, 0x6a, 0x6c, 0x6c, 0x6e, 0x6e, 0x70, | |
839 | 0x70, 0x72, 0x72, 0x74, 0x74, 0x76, 0x76, 0x78, | |
840 | 0x78, 0x7a, 0x7a, 0x7c, 0x7c, 0x7e, 0x7e, 0x7e | |
841 | ], [ | |
842 | 0x01, 0x01, 0x04, 0x04, 0x04, 0x07, 0x07, 0x0a, | |
843 | 0x0a, 0x0a, 0x0a, 0x0d, 0x0d, 0x0d, 0x10, 0x10, | |
844 | 0x10, 0x13, 0x13, 0x13, 0x16, 0x16, 0x16, 0x19, | |
845 | 0x19, 0x19, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x1f, | |
846 | 0x22, 0x22, 0x22, 0x25, 0x25, 0x25, 0x28, 0x28, | |
847 | 0x28, 0x2b, 0x2b, 0x2b, 0x2e, 0x2e, 0x2e, 0x31, | |
848 | 0x31, 0x31, 0x34, 0x34, 0x34, 0x37, 0x37, 0x37, | |
849 | 0x3a, 0x3a, 0x3a, 0x3d, 0x3d, 0x3d, 0x40, 0x40, | |
850 | 0x40, 0x43, 0x43, 0x43, 0x46, 0x46, 0x46, 0x49, | |
851 | 0x49, 0x49, 0x4c, 0x4c, 0x4c, 0x4f, 0x4f, 0x4f, | |
852 | 0x52, 0x52, 0x52, 0x55, 0x55, 0x55, 0x58, 0x58, | |
853 | 0x58, 0x5b, 0x5b, 0x5b, 0x5e, 0x5e, 0x5e, 0x61, | |
854 | 0x61, 0x61, 0x64, 0x64, 0x64, 0x67, 0x67, 0x67, | |
855 | 0x6a, 0x6a, 0x6a, 0x6d, 0x6d, 0x6d, 0x70, 0x70, | |
856 | 0x70, 0x73, 0x73, 0x73, 0x76, 0x76, 0x76, 0x76, | |
857 | 0x76, 0x79, 0x7c, 0x7c, 0x7c, 0x7f, 0x7f, 0x7f | |
858 | ], [ | |
859 | 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, | |
860 | 0x08, 0x08, 0x0c, 0x0c, 0x0c, 0x0c, 0x10, 0x10, | |
861 | 0x10, 0x10, 0x14, 0x14, 0x14, 0x14, 0x18, 0x18, | |
862 | 0x18, 0x18, 0x1c, 0x1c, 0x1c, 0x1c, 0x20, 0x20, | |
863 | 0x20, 0x20, 0x24, 0x24, 0x24, 0x24, 0x28, 0x28, | |
864 | 0x28, 0x28, 0x2c, 0x2c, 0x2c, 0x2c, 0x30, 0x30, | |
865 | 0x30, 0x30, 0x34, 0x34, 0x34, 0x34, 0x38, 0x38, | |
866 | 0x38, 0x38, 0x3c, 0x3c, 0x3c, 0x3c, 0x40, 0x40, | |
867 | 0x40, 0x40, 0x44, 0x44, 0x44, 0x44, 0x48, 0x48, | |
868 | 0x48, 0x48, 0x4c, 0x4c, 0x4c, 0x4c, 0x50, 0x50, | |
869 | 0x50, 0x50, 0x54, 0x54, 0x54, 0x54, 0x58, 0x58, | |
870 | 0x58, 0x58, 0x5c, 0x5c, 0x5c, 0x5c, 0x60, 0x60, | |
871 | 0x60, 0x60, 0x64, 0x64, 0x64, 0x64, 0x68, 0x68, | |
872 | 0x68, 0x68, 0x6c, 0x6c, 0x6c, 0x6c, 0x70, 0x70, | |
873 | 0x70, 0x70, 0x74, 0x74, 0x74, 0x74, 0x78, 0x78, | |
874 | 0x78, 0x78, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c | |
875 | ], [ | |
876 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, | |
877 | 0x09, 0x09, 0x09, 0x09, 0x09, 0x0e, 0x0e, 0x0e, | |
878 | 0x0e, 0x0e, 0x13, 0x13, 0x13, 0x13, 0x13, 0x18, | |
879 | 0x18, 0x18, 0x18, 0x18, 0x1d, 0x1d, 0x1d, 0x1d, | |
880 | 0x1d, 0x22, 0x22, 0x22, 0x22, 0x22, 0x27, 0x27, | |
881 | 0x27, 0x27, 0x27, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, | |
882 | 0x31, 0x31, 0x31, 0x31, 0x31, 0x36, 0x36, 0x36, | |
883 | 0x36, 0x36, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x40, | |
884 | 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x45, 0x45, | |
885 | 0x45, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4f, 0x4f, | |
886 | 0x4f, 0x4f, 0x4f, 0x54, 0x54, 0x54, 0x54, 0x54, | |
887 | 0x59, 0x59, 0x59, 0x59, 0x59, 0x5e, 0x5e, 0x5e, | |
888 | 0x5e, 0x5e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x68, | |
889 | 0x68, 0x68, 0x68, 0x68, 0x6d, 0x6d, 0x6d, 0x6d, | |
890 | 0x6d, 0x72, 0x72, 0x72, 0x72, 0x72, 0x77, 0x77, | |
891 | 0x77, 0x77, 0x77, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c | |
892 | ], [ | |
893 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, | |
894 | 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x10, | |
895 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x16, 0x16, 0x16, | |
896 | 0x16, 0x16, 0x16, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, | |
897 | 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x28, | |
898 | 0x28, 0x28, 0x28, 0x28, 0x28, 0x2e, 0x2e, 0x2e, | |
899 | 0x2e, 0x2e, 0x2e, 0x34, 0x34, 0x34, 0x34, 0x34, | |
900 | 0x34, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x40, | |
901 | 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x46, | |
902 | 0x46, 0x46, 0x46, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, | |
903 | 0x4c, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x58, | |
904 | 0x58, 0x58, 0x58, 0x58, 0x58, 0x5e, 0x5e, 0x5e, | |
905 | 0x5e, 0x5e, 0x5e, 0x64, 0x64, 0x64, 0x64, 0x64, | |
906 | 0x64, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x70, | |
907 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x76, 0x76, 0x76, | |
908 | 0x76, 0x76, 0x76, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c | |
909 | ], [ | |
910 | 0x01, 0x01, 0x01, 0x01, 0x08, 0x08, 0x08, 0x08, | |
911 | 0x08, 0x08, 0x08, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, | |
912 | 0x0f, 0x0f, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, | |
913 | 0x16, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, | |
914 | 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x2b, | |
915 | 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x32, 0x32, | |
916 | 0x32, 0x32, 0x32, 0x32, 0x32, 0x39, 0x39, 0x39, | |
917 | 0x39, 0x39, 0x39, 0x39, 0x40, 0x40, 0x40, 0x40, | |
918 | 0x40, 0x40, 0x40, 0x47, 0x47, 0x47, 0x47, 0x47, | |
919 | 0x47, 0x47, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, | |
920 | 0x4e, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, | |
921 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x63, | |
922 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x6a, 0x6a, | |
923 | 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x71, 0x71, 0x71, | |
924 | 0x71, 0x71, 0x71, 0x71, 0x78, 0x78, 0x78, 0x78, | |
925 | 0x78, 0x78, 0x78, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f | |
926 | ], [ | |
927 | 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, | |
928 | 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, | |
929 | 0x10, 0x10, 0x10, 0x10, 0x18, 0x18, 0x18, 0x18, | |
930 | 0x18, 0x18, 0x18, 0x18, 0x20, 0x20, 0x20, 0x20, | |
931 | 0x20, 0x20, 0x20, 0x20, 0x28, 0x28, 0x28, 0x28, | |
932 | 0x28, 0x28, 0x28, 0x28, 0x30, 0x30, 0x30, 0x30, | |
933 | 0x30, 0x30, 0x30, 0x30, 0x38, 0x38, 0x38, 0x38, | |
934 | 0x38, 0x38, 0x38, 0x38, 0x40, 0x40, 0x40, 0x40, | |
935 | 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x48, 0x48, | |
936 | 0x48, 0x48, 0x48, 0x48, 0x50, 0x50, 0x50, 0x50, | |
937 | 0x50, 0x50, 0x50, 0x50, 0x58, 0x58, 0x58, 0x58, | |
938 | 0x58, 0x58, 0x58, 0x58, 0x60, 0x60, 0x60, 0x60, | |
939 | 0x60, 0x60, 0x60, 0x60, 0x68, 0x68, 0x68, 0x68, | |
940 | 0x68, 0x68, 0x68, 0x68, 0x70, 0x70, 0x70, 0x70, | |
941 | 0x70, 0x70, 0x70, 0x70, 0x78, 0x78, 0x78, 0x78, | |
942 | 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78 | |
943 | ], [ | |
944 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x0a, 0x0a, 0x0a, | |
945 | 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x13, 0x13, | |
946 | 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x1c, | |
947 | 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, | |
948 | 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, | |
949 | 0x25, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, | |
950 | 0x2e, 0x2e, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, | |
951 | 0x37, 0x37, 0x37, 0x40, 0x40, 0x40, 0x40, 0x40, | |
952 | 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x49, 0x49, | |
953 | 0x49, 0x49, 0x49, 0x49, 0x49, 0x52, 0x52, 0x52, | |
954 | 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x5b, 0x5b, | |
955 | 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x64, | |
956 | 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, | |
957 | 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, | |
958 | 0x6d, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, | |
959 | 0x76, 0x76, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f | |
960 | ] | |
961 | ]; |