| 1 | use nihav_core::codecs::*; |
| 2 | use nihav_core::io::byteio::*; |
| 3 | |
| 4 | struct Glyphs { |
| 5 | data: [[[u8; 16]; 256]; 2], |
| 6 | glyph8: [[u8; 64]; 256], |
| 7 | glyph8_init: bool, |
| 8 | } |
| 9 | |
| 10 | impl Glyphs { |
| 11 | fn new() -> Self { |
| 12 | Self { |
| 13 | data: [[[0; 16]; 256]; 2], |
| 14 | glyph8: [[0; 64]; 256], |
| 15 | glyph8_init: false, |
| 16 | } |
| 17 | } |
| 18 | fn make_glyphs_4(&mut self, mode: u8) { |
| 19 | for i in (1..16).step_by(2) { |
| 20 | let cy = (i as u8) + mode; |
| 21 | for j in 0..16 { |
| 22 | let dst = &mut self.data[0][(i / 2) * 16 + j]; |
| 23 | |
| 24 | let cx = (j as u8) + mode; |
| 25 | let avg = mode + (((i + j) >> 1) as u8); |
| 26 | if avg == cx || avg == cy { |
| 27 | dst[ 0] = cx; dst[ 1] = cy; dst[ 2] = cx; dst[ 3] = cy; |
| 28 | dst[ 4] = cy; dst[ 5] = cx; dst[ 6] = cy; dst[ 7] = cy; |
| 29 | dst[ 8] = cx; dst[ 9] = cy; dst[10] = cx; dst[11] = cy; |
| 30 | dst[12] = cx; dst[13] = cx; dst[14] = cy; dst[15] = cx; |
| 31 | } else { |
| 32 | let c0 = avg; |
| 33 | let c1 = ((u16::from(avg) + u16::from(cy)) >> 1) as u8; |
| 34 | let c2 = ((u16::from(avg) + u16::from(cx)) >> 1) as u8; |
| 35 | dst[ 0] = c0; dst[ 1] = c0; dst[ 2] = c1; dst[ 3] = cy; |
| 36 | dst[ 4] = c0; dst[ 5] = c0; dst[ 6] = c1; dst[ 7] = cy; |
| 37 | dst[ 8] = c2; dst[ 9] = c2; dst[10] = c0; dst[11] = c1; |
| 38 | dst[12] = cx; dst[13] = cx; dst[14] = c2; dst[15] = c0; |
| 39 | } |
| 40 | } |
| 41 | } |
| 42 | for i in (0..16).step_by(2) { |
| 43 | let cy = (i as u8) + mode; |
| 44 | for j in 0..16 { |
| 45 | let dst = &mut self.data[0][128 + (i / 2) * 16 + j]; |
| 46 | |
| 47 | let cx = (j as u8) + mode; |
| 48 | let avg = mode + (((i + j) >> 1) as u8); |
| 49 | if avg == cx || avg == cy { |
| 50 | dst[ 0] = cy; dst[ 1] = cy; dst[ 2] = cx; dst[ 3] = cy; |
| 51 | dst[ 4] = cy; dst[ 5] = cy; dst[ 6] = cy; dst[ 7] = cx; |
| 52 | dst[ 8] = cx; dst[ 9] = cy; dst[10] = cx; dst[11] = cx; |
| 53 | dst[12] = cy; dst[13] = cx; dst[14] = cy; dst[15] = cx; |
| 54 | } else { |
| 55 | let c1 = ((u16::from(avg) + u16::from(cy)) >> 1) as u8; |
| 56 | let c2 = ((u16::from(avg) + u16::from(cx)) >> 1) as u8; |
| 57 | dst[ 0] = cy; dst[ 1] = cy; dst[ 2] = c1; dst[ 3] = cx; |
| 58 | dst[ 4] = cy; dst[ 5] = cy; dst[ 6] = c1; dst[ 7] = cx; |
| 59 | dst[ 8] = c1; dst[ 9] = c1; dst[10] = cx; dst[11] = c2; |
| 60 | dst[12] = cx; dst[13] = cx; dst[14] = c2; dst[15] = cx; |
| 61 | } |
| 62 | } |
| 63 | } |
| 64 | } |
| 65 | fn make_glyphs_5(&mut self, mode: u8) { |
| 66 | for i in 0..8 { |
| 67 | let cy = (i as u8) + mode; |
| 68 | for j in 0..8 { |
| 69 | let dst = &mut self.data[0][i * 8 + j]; |
| 70 | |
| 71 | let cx = (j as u8) + mode; |
| 72 | let avg = mode + (((i + j) >> 1) as u8); |
| 73 | let c0 = avg; |
| 74 | let c1 = ((u16::from(avg) + u16::from(cy)) >> 1) as u8; |
| 75 | let c2 = ((u16::from(avg) + u16::from(cx)) >> 1) as u8; |
| 76 | |
| 77 | dst[ 0] = c0; dst[ 1] = c0; dst[ 2] = c1; dst[ 3] = cy; |
| 78 | dst[ 4] = c0; dst[ 5] = c0; dst[ 6] = c1; dst[ 7] = cy; |
| 79 | dst[ 8] = c2; dst[ 9] = c2; dst[10] = c0; dst[11] = c1; |
| 80 | dst[12] = cx; dst[13] = cx; dst[14] = c2; dst[15] = c0; |
| 81 | } |
| 82 | } |
| 83 | for i in 0..8 { |
| 84 | let cy = (i as u8) + mode; |
| 85 | for j in 0..8 { |
| 86 | let dst = &mut self.data[0][i * 8 + j + 64]; |
| 87 | |
| 88 | let cx = (j as u8) + mode; |
| 89 | let avg = mode + (((i + j) >> 1) as u8); |
| 90 | let c0 = avg; |
| 91 | let c2 = ((u16::from(avg) + u16::from(cx)) >> 1) as u8; |
| 92 | |
| 93 | dst[ 0] = cy; dst[ 1] = cy; dst[ 2] = cy; dst[ 3] = cy; |
| 94 | dst[ 4] = c0; dst[ 5] = c0; dst[ 6] = c0; dst[ 7] = c0; |
| 95 | dst[ 8] = c2; dst[ 9] = c2; dst[10] = c2; dst[11] = c2; |
| 96 | dst[12] = cx; dst[13] = cx; dst[14] = cx; dst[15] = cx; |
| 97 | } |
| 98 | } |
| 99 | for i in 0..8 { |
| 100 | let cy = (i as u8) + mode; |
| 101 | for j in 0..8 { |
| 102 | let dst = &mut self.data[0][i * 8 + j + 128]; |
| 103 | |
| 104 | let cx = (j as u8) + mode; |
| 105 | let avg = mode + (((i + j) >> 1) as u8); |
| 106 | let c0 = avg; |
| 107 | let c1 = ((u16::from(avg) + u16::from(cy)) >> 1) as u8; |
| 108 | let c2 = ((u16::from(avg) + u16::from(cx)) >> 1) as u8; |
| 109 | |
| 110 | dst[ 0] = cy; dst[ 1] = cy; dst[ 2] = c1; dst[ 3] = c0; |
| 111 | dst[ 4] = cy; dst[ 5] = cy; dst[ 6] = c1; dst[ 7] = c0; |
| 112 | dst[ 8] = c1; dst[ 9] = c1; dst[10] = c0; dst[11] = c2; |
| 113 | dst[12] = c0; dst[13] = c0; dst[14] = c2; dst[15] = cx; |
| 114 | } |
| 115 | } |
| 116 | for i in 0..8 { |
| 117 | let cy = (i as u8) + mode; |
| 118 | for j in 0..8 { |
| 119 | let dst = &mut self.data[0][i * 8 + j + 192]; |
| 120 | |
| 121 | let cx = (j as u8) + mode; |
| 122 | let avg = mode + (((i + j) >> 1) as u8); |
| 123 | let c0 = avg; |
| 124 | let c2 = ((u16::from(avg) + u16::from(cx)) >> 1) as u8; |
| 125 | |
| 126 | dst[ 0] = cy; dst[ 1] = c0; dst[ 2] = c2; dst[ 3] = cx; |
| 127 | dst[ 4] = cy; dst[ 5] = c0; dst[ 6] = c2; dst[ 7] = cx; |
| 128 | dst[ 8] = cy; dst[ 9] = c0; dst[10] = c2; dst[11] = cx; |
| 129 | dst[12] = cy; dst[13] = c0; dst[14] = c2; dst[15] = cx; |
| 130 | } |
| 131 | } |
| 132 | } |
| 133 | fn read_additional(&mut self, br: &mut ByteReader, add: u16) -> DecoderResult<()> { |
| 134 | if add > 0 { |
| 135 | validate!(add <= 256); |
| 136 | let mut gbuf = [0; 8]; |
| 137 | for glyph in self.data[1].iter_mut().take(add as usize) { |
| 138 | br.read_buf(&mut gbuf)?; |
| 139 | for (pair, &b) in glyph.chunks_mut(2).zip(gbuf.iter()) { |
| 140 | pair[0] = b >> 4; |
| 141 | pair[1] = b & 0xF; |
| 142 | } |
| 143 | } |
| 144 | } |
| 145 | Ok(()) |
| 146 | } |
| 147 | fn make_glyphs_47(&mut self) { |
| 148 | super::make_glyphs_47(&mut self.data[0], &mut self.glyph8); |
| 149 | self.glyph8_init = true; |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | struct FrameData { |
| 154 | info: NACodecInfoRef, |
| 155 | pal: [u8; 768], |
| 156 | fpal: [u16; 768], |
| 157 | pdelta: [u16; 768], |
| 158 | width: usize, |
| 159 | height: usize, |
| 160 | frm0: Vec<u8>, |
| 161 | frm1: Vec<u8>, |
| 162 | frm2: Vec<u8>, |
| 163 | } |
| 164 | |
| 165 | impl FrameData { |
| 166 | fn new() -> Self { |
| 167 | Self { |
| 168 | info: NACodecInfoRef::default(), |
| 169 | pal: [0; 768], |
| 170 | fpal: [0; 768], |
| 171 | pdelta: [0; 768], |
| 172 | width: 0, |
| 173 | height: 0, |
| 174 | frm0: Vec::new(), |
| 175 | frm1: Vec::new(), |
| 176 | frm2: Vec::new(), |
| 177 | } |
| 178 | } |
| 179 | fn init(&mut self, info: NACodecInfoRef) -> DecoderResult<()> { |
| 180 | if let NACodecTypeInfo::Video(vinfo) = info.get_properties() { |
| 181 | self.width = vinfo.get_width(); |
| 182 | self.height = vinfo.get_height(); |
| 183 | self.width = (self.width + 7) & !7; |
| 184 | self.height = (self.height + 7) & !7; |
| 185 | let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, PAL8_FORMAT)); |
| 186 | self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref(); |
| 187 | if let Some(edata) = info.get_extradata() { |
| 188 | validate!(edata.len() > 768); |
| 189 | self.pal.copy_from_slice(&edata[1..][..768]); |
| 190 | } |
| 191 | |
| 192 | self.frm0.resize(self.width * self.height, 0); |
| 193 | self.frm1.resize(self.width * self.height, 0); |
| 194 | self.frm2.resize(self.width * self.height, 0); |
| 195 | Ok(()) |
| 196 | } else { |
| 197 | Err(DecoderError::InvalidData) |
| 198 | } |
| 199 | } |
| 200 | #[inline] |
| 201 | fn set_pixel(&mut self, xoff: i16, yoff: i16, x: usize, y: usize, pix: u8) { |
| 202 | let xpos = (xoff as isize) + (x as isize); |
| 203 | if xpos < 0 { return; } |
| 204 | let xpos = xpos as usize; |
| 205 | let ypos = (yoff as isize) + (y as isize); |
| 206 | if ypos < 0 { return; } |
| 207 | let ypos = ypos as usize; |
| 208 | if xpos < self.width && ypos < self.height { |
| 209 | self.frm0[xpos + ypos * self.width] = pix; |
| 210 | } |
| 211 | } |
| 212 | fn get_pixel(&mut self, xoff: i16, yoff: i16, x: usize, y: usize) -> u8 { |
| 213 | let xpos = (xoff as isize) + (x as isize); |
| 214 | if xpos < 0 { return 0; } |
| 215 | let xpos = xpos as usize; |
| 216 | let ypos = (yoff as isize) + (y as isize); |
| 217 | if ypos < 0 { return 0; } |
| 218 | let ypos = ypos as usize; |
| 219 | if xpos < self.width && ypos < self.height { |
| 220 | self.frm0[xpos + ypos * self.width] |
| 221 | } else { |
| 222 | 0 |
| 223 | } |
| 224 | } |
| 225 | fn loop_filter(&mut self, _xoff: i16, _yoff: i16, _x: usize, _y: usize) { |
| 226 | /* let xpos = (xoff as isize) + (x as isize); |
| 227 | if xpos < 0 { return; } |
| 228 | let xpos = xpos as usize; |
| 229 | let ypos = (yoff as isize) + (y as isize); |
| 230 | if ypos < 0 { return; } |
| 231 | let ypos = ypos as usize; |
| 232 | if xpos < self.width && ypos < self.height { |
| 233 | let start = xpos + ypos * self.width; |
| 234 | if xpos > 0 { |
| 235 | for row in self.frm0[start - 1..].chunks_mut(self.width).take(4) { |
| 236 | let x0 = row[0]; |
| 237 | let x1 = row[1]; |
| 238 | row[1] = 0x80 | (x0.wrapping_add(x1) >> 1); |
| 239 | } |
| 240 | } |
| 241 | if ypos > 0 { |
| 242 | for i in 0..4 { |
| 243 | let y0 = self.frm0[start + i]; |
| 244 | let y1 = &mut self.frm0[start + i + self.width]; |
| 245 | *y1 = 0x80 | (y1.wrapping_add(y0) >> 1); |
| 246 | } |
| 247 | } |
| 248 | }*/ |
| 249 | } |
| 250 | fn get_frame(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { |
| 251 | let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 0)?; |
| 252 | if let Some(ref mut vbuf) = bufinfo.get_vbuf() { |
| 253 | let stride = vbuf.get_stride(0); |
| 254 | let paloff = vbuf.get_offset(1); |
| 255 | let data = vbuf.get_data_mut().unwrap(); |
| 256 | for (dst, src) in data.chunks_mut(stride).zip(self.frm0.chunks(self.width).take(self.height)) { |
| 257 | dst[..self.width].copy_from_slice(src); |
| 258 | } |
| 259 | data[paloff..][..768].copy_from_slice(&self.pal); |
| 260 | } else { |
| 261 | return Err(DecoderError::Bug); |
| 262 | } |
| 263 | |
| 264 | let is_intra = pkt.keyframe; |
| 265 | let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo); |
| 266 | frm.set_keyframe(is_intra); |
| 267 | frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P }); |
| 268 | Ok(frm.into_ref()) |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | fn do_mc(dst: &mut [u8], src: &[u8], stride: usize, xoff: isize, yoff: isize, w: usize, h: usize) { |
| 273 | let mut pos = xoff + yoff * (stride as isize); |
| 274 | for row in dst.chunks_mut(stride).take(4) { |
| 275 | for i in 0..4 { |
| 276 | row[i] = if pos >= 0 && (pos as usize) < w + (h - 1) * stride { |
| 277 | src[pos as usize] |
| 278 | } else { 0 }; |
| 279 | pos += 1; |
| 280 | } |
| 281 | pos -= 4; |
| 282 | pos += stride as isize; |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | #[allow(clippy::too_many_arguments)] |
| 287 | fn do_block47(br: &mut ByteReader, dst: &mut [u8], frm1: &[u8], frm2: &[u8], x: usize, y: usize, stride: usize, bsize: usize, clr: &[u8; 6], glyphs: &Glyphs) -> DecoderResult<()> { |
| 288 | let op = br.read_byte()?; |
| 289 | match op { |
| 290 | 0xFF if bsize > 2 => { |
| 291 | let hsize = bsize / 2; |
| 292 | do_block47(br, dst, frm1, frm2, x, y, stride, hsize, clr, glyphs)?; |
| 293 | do_block47(br, &mut dst[hsize..], frm1, frm2, x + hsize, y, stride, bsize / 2, clr, glyphs)?; |
| 294 | do_block47(br, &mut dst[hsize * stride..], frm1, frm2, x, y + hsize, stride, hsize, clr, glyphs)?; |
| 295 | do_block47(br, &mut dst[hsize * (stride + 1)..], frm1, frm2, x + hsize, y + hsize, stride, bsize / 2, clr, glyphs)?; |
| 296 | }, |
| 297 | 0xFF => { |
| 298 | br.read_buf(&mut dst[..2])?; |
| 299 | br.read_buf(&mut dst[stride..][..2])?; |
| 300 | }, |
| 301 | 0xFE => { |
| 302 | let pix = br.read_byte()?; |
| 303 | for dst in dst.chunks_mut(stride).take(bsize) { |
| 304 | for el in dst[..bsize].iter_mut() { |
| 305 | *el = pix; |
| 306 | } |
| 307 | } |
| 308 | }, |
| 309 | 0xFD => { |
| 310 | let idx = br.read_byte()? as usize; |
| 311 | let mut clr = [0; 2]; |
| 312 | clr[1] = br.read_byte()?; |
| 313 | clr[0] = br.read_byte()?; |
| 314 | let mut glyph = if bsize == 8 { glyphs.glyph8[idx].iter() } else { glyphs.data[0][idx].iter() }; |
| 315 | |
| 316 | for dst in dst.chunks_mut(stride).take(bsize) { |
| 317 | for el in dst[..bsize].iter_mut() { |
| 318 | *el = clr[*glyph.next().unwrap_or(&0) as usize]; |
| 319 | } |
| 320 | } |
| 321 | }, |
| 322 | 0xFC => { |
| 323 | let off = x + y * stride; |
| 324 | let src = &frm1[off..]; |
| 325 | for (dst, src) in dst.chunks_mut(stride).zip(src.chunks(stride)).take(bsize) { |
| 326 | dst[..bsize].copy_from_slice(&src[..bsize]); |
| 327 | } |
| 328 | }, |
| 329 | 0xF8..=0xFB => { |
| 330 | let pix = clr[(op & 7) as usize]; |
| 331 | for dst in dst.chunks_mut(stride).take(bsize) { |
| 332 | for el in dst[..bsize].iter_mut() { |
| 333 | *el = pix; |
| 334 | } |
| 335 | } |
| 336 | }, |
| 337 | _ => { |
| 338 | let mx = C47_MV[0][op as usize][0] as isize; |
| 339 | let my = C47_MV[0][op as usize][1] as isize; |
| 340 | let off = (x as isize) + mx + ((y as isize) + my) * (stride as isize); |
| 341 | validate!(off >= 0); |
| 342 | let src = &frm2[off as usize..]; |
| 343 | for (dst, src) in dst.chunks_mut(stride).zip(src.chunks(stride)).take(bsize) { |
| 344 | dst[..bsize].copy_from_slice(&src[..bsize]); |
| 345 | } |
| 346 | }, |
| 347 | }; |
| 348 | Ok(()) |
| 349 | } |
| 350 | |
| 351 | macro_rules! c48_mv { |
| 352 | (index; $dst: expr, $src: expr, $br: expr, $x: expr, $y: expr, $stride: expr, $size: expr, $mvsel: expr) => ({ |
| 353 | for yy in (0..8).step_by($size) { |
| 354 | for xx in (0..8).step_by($size) { |
| 355 | let idx = $br.read_byte()? as usize; |
| 356 | validate!(idx < 255); |
| 357 | let mx = C47_MV[$mvsel][idx][0] as isize; |
| 358 | let my = C47_MV[$mvsel][idx][1] as isize; |
| 359 | c48_mv!(common; &mut $dst[xx + yy * $stride..], $src, $x + xx, $y + yy, mx, my, $stride, $size) |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | }); |
| 364 | (offset; $dst: expr, $src: expr, $br: expr, $x: expr, $y: expr, $w: expr, $stride: expr, $size: expr) => ({ |
| 365 | for yy in (0..8).step_by($size) { |
| 366 | for xx in (0..8).step_by($size) { |
| 367 | let offset = $br.read_u16le()? as i16 as isize; |
| 368 | let mx = offset % ($w as isize); |
| 369 | let my = offset / ($w as isize); |
| 370 | c48_mv!(common; &mut $dst[xx + yy * $stride..], $src, $x + xx, $y + yy, mx, my, $stride, $size) |
| 371 | } |
| 372 | } |
| 373 | }); |
| 374 | (common; $dst: expr, $src: expr, $x: expr, $y: expr, $mx: expr, $my: expr, $stride: expr, $size: expr) => {{ |
| 375 | let srcpos = ($x as isize) + $mx + (($y as isize) + $my) * ($stride as isize); |
| 376 | validate!(srcpos >= 0); |
| 377 | for (dst, src) in $dst.chunks_mut($stride).zip($src[srcpos as usize..].chunks($stride)).take($size) { |
| 378 | let size = dst.len().min(src.len()).min($size); |
| 379 | dst[..size].copy_from_slice(&src[..size]); |
| 380 | } |
| 381 | }} |
| 382 | } |
| 383 | |
| 384 | fn scale2x(block: &[u8; 16], dst: &mut [u8], stride: usize) { |
| 385 | for (drow, src) in dst.chunks_mut(stride * 2).zip(block.chunks_exact(4)) { |
| 386 | for row in drow.chunks_mut(stride) { |
| 387 | for (dpair, &el) in row.chunks_exact_mut(2).zip(src.iter()) { |
| 388 | dpair[0] = el; |
| 389 | dpair[1] = el; |
| 390 | } |
| 391 | } |
| 392 | } |
| 393 | } |
| 394 | |
| 395 | struct Smush1Decoder { |
| 396 | glyphs: Glyphs, |
| 397 | pic: FrameData, |
| 398 | version: u8, |
| 399 | prev_seq: u16, |
| 400 | reorder: u8, |
| 401 | filter: [[u8; 256]; 256], |
| 402 | } |
| 403 | |
| 404 | impl Smush1Decoder { |
| 405 | fn new() -> Self { |
| 406 | Self { |
| 407 | glyphs: Glyphs::new(), |
| 408 | pic: FrameData::new(), |
| 409 | version: 0, |
| 410 | prev_seq: 0, |
| 411 | reorder: 0, |
| 412 | filter: [[0; 256]; 256], |
| 413 | } |
| 414 | } |
| 415 | |
| 416 | fn decode_rle(br: &mut ByteReader, dst: &mut [u8], w: usize, h: usize, stride: usize) -> DecoderResult<()> { |
| 417 | let mut x = 0; |
| 418 | let mut y = 0; |
| 419 | let mut len = 0; |
| 420 | let mut clr = 0; |
| 421 | let mut run = false; |
| 422 | while (x != 0) || (y != h) { |
| 423 | if len == 0 { |
| 424 | let op = br.read_byte()?; |
| 425 | run = (op & 1) != 0; |
| 426 | if run { |
| 427 | clr = br.read_byte()?; |
| 428 | } |
| 429 | len = ((op >> 1) + 1) as usize; |
| 430 | } |
| 431 | if run { |
| 432 | dst[x + y * stride] = clr; |
| 433 | } else { |
| 434 | dst[x + y * stride] = br.read_byte()?; |
| 435 | } |
| 436 | len -= 1; |
| 437 | x += 1; |
| 438 | if x == w { |
| 439 | x = 0; |
| 440 | y += 1; |
| 441 | } |
| 442 | } |
| 443 | validate!(len == 0); |
| 444 | |
| 445 | Ok(()) |
| 446 | } |
| 447 | |
| 448 | fn decode_1(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, transparent: bool) -> DecoderResult<()> { |
| 449 | for yy in 0..h { |
| 450 | let len = u64::from(br.read_u16le()?); |
| 451 | let end = br.tell() + len; |
| 452 | let mut xx = 0; |
| 453 | while (br.tell() < end) && (xx < w) { |
| 454 | let op = br.read_byte()?; |
| 455 | let len = ((op >> 1) + 1) as usize; |
| 456 | if (op & 1) == 0 { |
| 457 | for _ in 0..len { |
| 458 | let clr = br.read_byte()?; |
| 459 | if !transparent || clr != 0 { |
| 460 | self.pic.set_pixel(x, y, xx, yy, clr); |
| 461 | } |
| 462 | xx += 1; |
| 463 | } |
| 464 | } else { |
| 465 | let clr = br.read_byte()?; |
| 466 | if !transparent || clr != 0 { |
| 467 | for _ in 0..len { |
| 468 | self.pic.set_pixel(x, y, xx, yy, clr); |
| 469 | xx += 1; |
| 470 | } |
| 471 | } else { |
| 472 | xx += len; |
| 473 | } |
| 474 | } |
| 475 | } |
| 476 | validate!(br.tell() == end && xx == w); |
| 477 | } |
| 478 | |
| 479 | Ok(()) |
| 480 | } |
| 481 | #[allow(clippy::verbose_bit_mask)] |
| 482 | fn decode_2(&mut self, br: &mut ByteReader, x: i16, y: i16, _w: usize, _h: usize, len: usize) -> DecoderResult<()> { |
| 483 | |
| 484 | validate!((len & 3) == 0); |
| 485 | let mut xpos = x; |
| 486 | let mut ypos = y; |
| 487 | for _ in 0..len/4 { |
| 488 | let xoff = br.read_u16le()? as i16; |
| 489 | let yoff = i16::from(br.read_byte()?); |
| 490 | let pix = br.read_byte()?; |
| 491 | |
| 492 | xpos += xoff; |
| 493 | ypos += yoff; |
| 494 | self.pic.set_pixel(xpos, ypos, 0, 0, pix); |
| 495 | } |
| 496 | Ok(()) |
| 497 | } |
| 498 | #[allow(clippy::too_many_arguments)] |
| 499 | fn decode_4(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, mode: u8, add: u16) -> DecoderResult<()> { |
| 500 | self.glyphs.make_glyphs_4(mode); |
| 501 | self.glyphs.read_additional(br, add)?; |
| 502 | |
| 503 | for col in (0..w).step_by(4) { |
| 504 | let mut mask = 0; |
| 505 | let mut bits = 0; |
| 506 | for row in (0..h).step_by(4) { |
| 507 | let bit = if add > 0 { |
| 508 | if bits == 0 { |
| 509 | mask = br.read_byte()?; |
| 510 | bits = 8; |
| 511 | } |
| 512 | let bit = (mask & 0x80) != 0; |
| 513 | mask <<= 1; |
| 514 | bits -= 1; |
| 515 | bit |
| 516 | } else { |
| 517 | false |
| 518 | }; |
| 519 | |
| 520 | let tile_no = br.read_byte()? as usize; |
| 521 | if !bit && (tile_no == 0x80) { |
| 522 | continue; |
| 523 | } |
| 524 | let src = &self.glyphs.data[bit as usize][tile_no]; |
| 525 | for (y1, srow) in src.chunks(4).enumerate() { |
| 526 | for (x1, &pix) in srow.iter().enumerate() { |
| 527 | self.pic.set_pixel(x, y, col + x1, row + y1, pix); |
| 528 | } |
| 529 | } |
| 530 | if !bit { |
| 531 | self.pic.loop_filter(x, y, col, row); |
| 532 | } |
| 533 | } |
| 534 | } |
| 535 | |
| 536 | Ok(()) |
| 537 | } |
| 538 | #[allow(clippy::too_many_arguments)] |
| 539 | fn decode_5(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, mode: u8, add: u16) -> DecoderResult<()> { |
| 540 | self.glyphs.make_glyphs_5(mode); |
| 541 | self.glyphs.read_additional(br, add)?; |
| 542 | |
| 543 | for col in (0..w).step_by(4) { |
| 544 | let mut mask = 0; |
| 545 | let mut bits = 0; |
| 546 | for row in (0..h).step_by(4) { |
| 547 | let bit = if add > 0 { |
| 548 | if bits == 0 { |
| 549 | mask = br.read_byte()?; |
| 550 | bits = 8; |
| 551 | } |
| 552 | let bit = (mask & 0x80) != 0; |
| 553 | mask <<= 1; |
| 554 | bits -= 1; |
| 555 | bit |
| 556 | } else { |
| 557 | false |
| 558 | }; |
| 559 | |
| 560 | let tile_no = br.read_byte()? as usize; |
| 561 | let src = &self.glyphs.data[bit as usize][tile_no]; |
| 562 | for (y1, srow) in src.chunks(4).enumerate() { |
| 563 | for (x1, &pix) in srow.iter().enumerate() { |
| 564 | self.pic.set_pixel(x, y, col + x1, row + y1, pix); |
| 565 | } |
| 566 | } |
| 567 | if !bit { |
| 568 | self.pic.loop_filter(x, y, col, row); |
| 569 | } |
| 570 | } |
| 571 | } |
| 572 | |
| 573 | Ok(()) |
| 574 | } |
| 575 | fn decode_21(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, size: usize) -> DecoderResult<()> { |
| 576 | let end = br.tell() + (size as u64); |
| 577 | for yy in 0..h { |
| 578 | if br.tell() >= end { break; } |
| 579 | let len = u64::from(br.read_u16le()?); |
| 580 | let end = br.tell() + len; |
| 581 | let mut xx = 0; |
| 582 | let mut skip = true; |
| 583 | while (br.tell() < end) && (xx <= w) { |
| 584 | let len = br.read_u16le()? as usize; |
| 585 | if !skip { |
| 586 | for _ in 0..=len { |
| 587 | let pix = br.read_byte()?; |
| 588 | self.pic.set_pixel(x, y, xx, yy, pix); |
| 589 | xx += 1; |
| 590 | } |
| 591 | } else { |
| 592 | for _ in 0..len { |
| 593 | self.pic.set_pixel(x, y, xx, yy, 0); |
| 594 | xx += 1; |
| 595 | } |
| 596 | } |
| 597 | skip = !skip; |
| 598 | } |
| 599 | validate!(br.tell() == end && xx == w + 1); |
| 600 | } |
| 601 | |
| 602 | Ok(()) |
| 603 | } |
| 604 | #[allow(clippy::too_many_arguments)] |
| 605 | fn decode_23(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, bias: u8, add: u16, old: bool) -> DecoderResult<()> { |
| 606 | let mut lut = [0; 256]; |
| 607 | if old { |
| 608 | for (i, el) in lut.iter_mut().enumerate() { |
| 609 | *el = (i as u8).wrapping_add(bias.wrapping_sub(0x30)); |
| 610 | } |
| 611 | } else if add != 256 { |
| 612 | for (i, el) in lut.iter_mut().enumerate() { |
| 613 | *el = (i as u8).wrapping_add(add as u8); |
| 614 | } |
| 615 | } else { |
| 616 | br.read_buf(&mut lut)?; |
| 617 | } |
| 618 | for yy in 0..h { |
| 619 | let len = u64::from(br.read_u16le()?); |
| 620 | let end = br.tell() + len; |
| 621 | let mut xx = 0; |
| 622 | let mut skip = true; |
| 623 | while (br.tell() < end) && (xx <= w) { |
| 624 | let len = br.read_byte()? as usize; |
| 625 | if !skip { |
| 626 | for _ in 0..len { |
| 627 | let pix = self.pic.get_pixel(x, y, xx, yy); |
| 628 | self.pic.set_pixel(x, y, xx, yy, lut[pix as usize]); |
| 629 | xx += 1; |
| 630 | } |
| 631 | } else { |
| 632 | xx += len; |
| 633 | } |
| 634 | skip = !skip; |
| 635 | } |
| 636 | validate!(br.tell() == end && xx == w + 1); |
| 637 | } |
| 638 | |
| 639 | Ok(()) |
| 640 | } |
| 641 | fn decode_37(&mut self, br: &mut ByteReader, x: i16, y: i16, mut w: usize, mut h: usize) -> DecoderResult<()> { |
| 642 | let compr = br.read_byte()?; |
| 643 | let mv_off = br.read_byte()? as usize; |
| 644 | validate!(mv_off <= 2); |
| 645 | let seq = br.read_u16le()?; |
| 646 | let _unp_size = br.read_u32le()?; |
| 647 | let _packed_size = br.read_u32le()?; |
| 648 | let flags = br.read_byte()?; |
| 649 | br.read_skip(3)?; |
| 650 | |
| 651 | w = (w + 3) & !3; |
| 652 | h = (h + 3) & !3; |
| 653 | |
| 654 | validate!(x >= 0 && y >= 0); |
| 655 | let x = x as usize; |
| 656 | let y = y as usize; |
| 657 | validate!((x + w <= self.pic.width) && (y + h <= self.pic.height)); |
| 658 | |
| 659 | if compr == 0 || compr == 2 { |
| 660 | for el in self.pic.frm1.iter_mut() { |
| 661 | *el = 0; |
| 662 | } |
| 663 | for el in self.pic.frm2.iter_mut() { |
| 664 | *el = 0; |
| 665 | } |
| 666 | } else if ((seq & 1) != 0) || ((flags & 1) == 0) { |
| 667 | std::mem::swap(&mut self.pic.frm0, &mut self.pic.frm2); |
| 668 | } |
| 669 | |
| 670 | let stride = self.pic.width; |
| 671 | let dst = &mut self.pic.frm0[x + y * stride..]; |
| 672 | let prv = &self.pic.frm2[x + y * stride..]; |
| 673 | match compr { |
| 674 | 0 => { |
| 675 | for line in dst.chunks_mut(stride).take(h) { |
| 676 | br.read_buf(&mut line[..w])?; |
| 677 | } |
| 678 | }, |
| 679 | 1 => { |
| 680 | let mut len = -1; |
| 681 | let mut run = false; |
| 682 | let mut code = 0; |
| 683 | for (row_no, row) in dst.chunks_mut(stride * 4).take(h / 4).enumerate() { |
| 684 | for col in (0..w).step_by(4) { |
| 685 | let skip_code = if len < 0 { |
| 686 | let op = br.read_byte()?; |
| 687 | len = (op >> 1) as i8; |
| 688 | run = (op & 1) != 0; |
| 689 | false |
| 690 | } else { |
| 691 | run |
| 692 | }; |
| 693 | if !skip_code { |
| 694 | code = br.read_byte()?; |
| 695 | if code == 0xFF { |
| 696 | len -= 1; |
| 697 | for drow in row[col..].chunks_mut(stride) { |
| 698 | for el in drow[..4].iter_mut() { |
| 699 | if len < 0 { |
| 700 | let op = br.read_byte()?; |
| 701 | len = (op >> 1) as i8; |
| 702 | run = (op & 1) != 0; |
| 703 | if run { |
| 704 | code = br.read_byte()?; |
| 705 | } |
| 706 | } |
| 707 | if run { |
| 708 | *el = code; |
| 709 | } else { |
| 710 | *el = br.read_byte()?; |
| 711 | } |
| 712 | len -= 1; |
| 713 | } |
| 714 | } |
| 715 | continue; |
| 716 | } |
| 717 | } |
| 718 | let idx = code as usize; |
| 719 | let mx = C37_MV[mv_off][idx * 2] as isize; |
| 720 | let my = C37_MV[mv_off][idx * 2 + 1] as isize; |
| 721 | do_mc(&mut row[col..], &self.pic.frm2, stride, |
| 722 | (x as isize) + (col as isize) + mx, |
| 723 | (y as isize) + (row_no as isize) * 4 + my, |
| 724 | self.pic.width, self.pic.height); |
| 725 | len -= 1; |
| 726 | } |
| 727 | } |
| 728 | }, |
| 729 | 2 => { |
| 730 | Self::decode_rle(br, dst, w, h, stride)?; |
| 731 | }, |
| 732 | 3 | 4 => { |
| 733 | let has_fills = (flags & 4) != 0; |
| 734 | let has_skips = compr == 4; |
| 735 | let mut skip_run = 0; |
| 736 | for (row_no, row) in dst.chunks_mut(stride * 4).take(h / 4).enumerate() { |
| 737 | for col in (0..w).step_by(4) { |
| 738 | if skip_run > 0 { |
| 739 | for (drow, srow) in row[col..].chunks_mut(stride).zip(prv[col + row_no * 4 * stride..].chunks(stride)) { |
| 740 | drow[..4].copy_from_slice(&srow[..4]); |
| 741 | } |
| 742 | skip_run -= 1; |
| 743 | continue; |
| 744 | } |
| 745 | let opcode = br.read_byte()?; |
| 746 | match opcode { |
| 747 | 0xFF => { |
| 748 | for drow in row[col..].chunks_mut(stride) { |
| 749 | br.read_buf(&mut drow[..4])?; |
| 750 | } |
| 751 | }, |
| 752 | 0xFE if has_fills => { |
| 753 | for drow in row[col..].chunks_mut(stride) { |
| 754 | let clr = br.read_byte()?; |
| 755 | for el in drow[..4].iter_mut() { |
| 756 | *el = clr; |
| 757 | } |
| 758 | } |
| 759 | }, |
| 760 | 0xFD if has_fills => { |
| 761 | let clr = br.read_byte()?; |
| 762 | for drow in row[col..].chunks_mut(stride) { |
| 763 | for el in drow[..4].iter_mut() { |
| 764 | *el = clr; |
| 765 | } |
| 766 | } |
| 767 | }, |
| 768 | 0 if has_skips => { |
| 769 | skip_run = br.read_byte()?; |
| 770 | for (drow, srow) in row[col..].chunks_mut(stride).zip(prv[col + row_no * 4 * stride..].chunks(stride)) { |
| 771 | drow[..4].copy_from_slice(&srow[..4]); |
| 772 | } |
| 773 | }, |
| 774 | _ => { |
| 775 | let idx = opcode as usize; |
| 776 | let mx = C37_MV[mv_off][idx * 2] as isize; |
| 777 | let my = C37_MV[mv_off][idx * 2 + 1] as isize; |
| 778 | do_mc(&mut row[col..], &self.pic.frm2, stride, |
| 779 | (x as isize) + (col as isize) + mx, |
| 780 | (y as isize) + (row_no as isize) * 4 + my, |
| 781 | self.pic.width, self.pic.height); |
| 782 | }, |
| 783 | }; |
| 784 | } |
| 785 | } |
| 786 | }, |
| 787 | _ => return Err(DecoderError::InvalidData), |
| 788 | }; |
| 789 | |
| 790 | Ok(()) |
| 791 | } |
| 792 | fn decode_47(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize) -> DecoderResult<()> { |
| 793 | let seq = br.read_u16le()?; |
| 794 | let compr = br.read_byte()?; |
| 795 | let reorder = br.read_byte()?; |
| 796 | let flags = br.read_byte()?; |
| 797 | br.read_skip(3)?; |
| 798 | let mut clr = [0; 6]; |
| 799 | br.read_buf(&mut clr)?; |
| 800 | let _dec_size = br.read_u32le()?; |
| 801 | br.read_skip(4)?; |
| 802 | br.read_skip(4)?; |
| 803 | |
| 804 | if (flags & 1) != 0 { |
| 805 | for i in 0..256 { |
| 806 | for j in i..256 { |
| 807 | let val = br.read_byte()?; |
| 808 | self.filter[i][j] = val; |
| 809 | self.filter[j][i] = val; |
| 810 | } |
| 811 | } |
| 812 | } |
| 813 | |
| 814 | if compr == 2 && !self.glyphs.glyph8_init { |
| 815 | self.glyphs.make_glyphs_47(); |
| 816 | } |
| 817 | |
| 818 | if seq == 0 { |
| 819 | for el in self.pic.frm1.iter_mut() { |
| 820 | *el = 0; |
| 821 | } |
| 822 | for el in self.pic.frm2.iter_mut() { |
| 823 | *el = 0; |
| 824 | } |
| 825 | } |
| 826 | |
| 827 | validate!(x >= 0 && y >= 0); |
| 828 | let x = x as usize; |
| 829 | let y = y as usize; |
| 830 | validate!((x + w <= self.pic.width) && (y + h <= self.pic.height)); |
| 831 | |
| 832 | let stride = self.pic.width; |
| 833 | let dst = &mut self.pic.frm0[x + y * stride..]; |
| 834 | match compr { |
| 835 | 0 => { |
| 836 | for line in dst.chunks_mut(stride).take(h) { |
| 837 | br.read_buf(&mut line[..w])?; |
| 838 | } |
| 839 | }, |
| 840 | 1 => { |
| 841 | for row in dst.chunks_mut(stride * 2).take((h + 1) / 2) { |
| 842 | for col in (0..w).step_by(2) { |
| 843 | let pix = br.read_byte()?; |
| 844 | row[col] = pix; |
| 845 | row[col + 1] = pix; |
| 846 | row[col + stride] = pix; |
| 847 | row[col + stride + 1] = pix; |
| 848 | } |
| 849 | } |
| 850 | }, |
| 851 | 2 => { |
| 852 | for (row_no, row) in dst.chunks_mut(stride * 8).take((h + 7) / 8).enumerate() { |
| 853 | for col in (0..w).step_by(8) { |
| 854 | do_block47(br, &mut row[col..], &self.pic.frm1, &self.pic.frm2, col, row_no * 8, stride, 8, &clr, &self.glyphs)?; |
| 855 | } |
| 856 | } |
| 857 | }, |
| 858 | 3 => { |
| 859 | self.pic.frm0.copy_from_slice(&self.pic.frm2); |
| 860 | }, |
| 861 | 4 => { |
| 862 | self.pic.frm0.copy_from_slice(&self.pic.frm1); |
| 863 | }, |
| 864 | 5 => { |
| 865 | Self::decode_rle(br, dst, w, h, stride)?; |
| 866 | }, |
| 867 | _ => return Err(DecoderError::InvalidData), |
| 868 | }; |
| 869 | |
| 870 | self.reorder = if seq == 0 || seq == self.prev_seq + 1 { reorder } else { 0 }; |
| 871 | self.prev_seq = seq; |
| 872 | |
| 873 | Ok(()) |
| 874 | } |
| 875 | fn decode_48(&mut self, br: &mut ByteReader, x: i16, y: i16, mut w: usize, mut h: usize) -> DecoderResult<()> { |
| 876 | let compr = br.read_byte()?; |
| 877 | let mvsel = br.read_byte()? as usize; |
| 878 | validate!(mvsel < 2); |
| 879 | let _seq = br.read_u16le()?; |
| 880 | let _packed_size = br.read_u32le()?; |
| 881 | let _unpacked_size = br.read_u32le()?; |
| 882 | let flags = br.read_byte()?; |
| 883 | br.read_skip(3)?; |
| 884 | if (flags & 8) != 0 { |
| 885 | for i in 0..256 { |
| 886 | for j in i..256 { |
| 887 | let val = br.read_byte()?; |
| 888 | self.filter[i][j] = val; |
| 889 | self.filter[j][i] = val; |
| 890 | } |
| 891 | } |
| 892 | } |
| 893 | |
| 894 | w = (w + 7) & !7; |
| 895 | h = (h + 7) & !7; |
| 896 | std::mem::swap(&mut self.pic.frm0, &mut self.pic.frm2); |
| 897 | |
| 898 | validate!(x >= 0 && y >= 0); |
| 899 | let x = x as usize; |
| 900 | let y = y as usize; |
| 901 | validate!((x + w <= self.pic.width) && (y + h <= self.pic.height)); |
| 902 | |
| 903 | let stride = self.pic.width; |
| 904 | let dst = &mut self.pic.frm0[x + y * stride..]; |
| 905 | match compr { |
| 906 | 0 => { |
| 907 | for line in dst.chunks_mut(stride).take(h) { |
| 908 | br.read_buf(&mut line[..w])?; |
| 909 | } |
| 910 | }, |
| 911 | 2 => { |
| 912 | Self::decode_rle(br, dst, w, h, stride)?; |
| 913 | }, |
| 914 | 3 => { |
| 915 | let mut block = [0; 16]; |
| 916 | for (row_no, row) in dst.chunks_mut(stride * 8).take((h + 7) / 8).enumerate() { |
| 917 | for col in (0..w).step_by(8) { |
| 918 | let op = br.read_byte()?; |
| 919 | match op { |
| 920 | 0xFF => { |
| 921 | let val = br.read_byte()?; |
| 922 | |
| 923 | // it should be interpolated which means reading top pixels... |
| 924 | for el in block.iter_mut() { |
| 925 | *el = val; |
| 926 | } |
| 927 | scale2x(&block, &mut row[col..], stride); |
| 928 | }, |
| 929 | 0xFE => { |
| 930 | c48_mv!(offset; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, w, stride, 8); |
| 931 | }, |
| 932 | 0xFD => { |
| 933 | block[ 5] = br.read_byte()?; |
| 934 | block[ 7] = br.read_byte()?; |
| 935 | block[13] = br.read_byte()?; |
| 936 | block[15] = br.read_byte()?; |
| 937 | |
| 938 | // it should be interpolated which means reading top pixels... |
| 939 | block[ 0] = block[ 5]; |
| 940 | block[ 1] = block[ 5]; |
| 941 | block[ 4] = block[ 5]; |
| 942 | block[ 2] = block[ 7]; |
| 943 | block[ 3] = block[ 7]; |
| 944 | block[ 6] = block[ 7]; |
| 945 | block[ 8] = block[13]; |
| 946 | block[ 9] = block[13]; |
| 947 | block[12] = block[13]; |
| 948 | block[10] = block[15]; |
| 949 | block[11] = block[15]; |
| 950 | block[14] = block[15]; |
| 951 | scale2x(&block, &mut row[col..], stride); |
| 952 | }, |
| 953 | 0xFC => { |
| 954 | c48_mv!(index; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, stride, 4, mvsel); |
| 955 | }, |
| 956 | 0xFB => { |
| 957 | c48_mv!(offset; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, w, stride, 4); |
| 958 | }, |
| 959 | 0xFA => { |
| 960 | br.read_buf(&mut block)?; |
| 961 | scale2x(&block, &mut row[col..], stride); |
| 962 | }, |
| 963 | 0xF9 => { |
| 964 | c48_mv!(index; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, stride, 2, mvsel); |
| 965 | }, |
| 966 | 0xF8 => { |
| 967 | c48_mv!(offset; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, w, stride, 2); |
| 968 | }, |
| 969 | 0xF7 => { |
| 970 | for line in row[col..].chunks_mut(stride) { |
| 971 | br.read_buf(&mut line[..8])?; |
| 972 | } |
| 973 | }, |
| 974 | _ => { |
| 975 | br.seek(SeekFrom::Current(-1))?; |
| 976 | c48_mv!(index; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, stride, 8, mvsel); |
| 977 | }, |
| 978 | }; |
| 979 | } |
| 980 | } |
| 981 | }, |
| 982 | 5 => { |
| 983 | for row in dst.chunks_mut(stride * 2).take((h + 1) / 2) { |
| 984 | let mut last = br.read_byte()?; |
| 985 | row[0] = last; |
| 986 | for col in (1..w).step_by(2) { |
| 987 | let new = br.read_byte()?; |
| 988 | row[col] = self.filter[last as usize][new as usize]; |
| 989 | row[col + 1] = new; |
| 990 | last = new; |
| 991 | } |
| 992 | } |
| 993 | let mut off0 = 0; |
| 994 | let mut off1 = stride; |
| 995 | let mut off2 = stride * 2; |
| 996 | for _ in (1..h).step_by(2) { |
| 997 | for i in 0..w { |
| 998 | dst[off1 + i] = self.filter[dst[off0 + i] as usize][dst[off2 + i] as usize]; |
| 999 | } |
| 1000 | off0 = off2; |
| 1001 | off1 += stride * 2; |
| 1002 | off2 += stride * 2; |
| 1003 | } |
| 1004 | }, |
| 1005 | _ => return Err(DecoderError::InvalidData), |
| 1006 | }; |
| 1007 | Ok(()) |
| 1008 | } |
| 1009 | } |
| 1010 | |
| 1011 | impl NADecoder for Smush1Decoder { |
| 1012 | fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { |
| 1013 | if let Some(edata) = info.get_extradata() { |
| 1014 | validate!(!edata.is_empty() && edata[0] <= 2); |
| 1015 | self.version = edata[0]; |
| 1016 | } |
| 1017 | self.pic.init(info) |
| 1018 | } |
| 1019 | fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { |
| 1020 | let src = pkt.get_buffer(); |
| 1021 | validate!(src.len() > 8); |
| 1022 | |
| 1023 | let mut mr = MemoryReader::new_read(&src); |
| 1024 | let mut br = ByteReader::new(&mut mr); |
| 1025 | |
| 1026 | let mut store = false; |
| 1027 | while br.left() > 0 { |
| 1028 | let tag = br.read_tag()?; |
| 1029 | let size = br.read_u32be()? as usize; |
| 1030 | validate!((size as i64) <= br.left()); |
| 1031 | match &tag { |
| 1032 | b"NPAL" => { |
| 1033 | validate!((size % 3) == 0); |
| 1034 | br.read_buf(&mut self.pic.pal[..size])?; |
| 1035 | }, |
| 1036 | b"XPAL" => { |
| 1037 | let cmd = br.read_u32be()?; |
| 1038 | match cmd { |
| 1039 | 0 => { |
| 1040 | validate!(size == 0x604); |
| 1041 | for el in self.pic.pdelta.iter_mut() { |
| 1042 | *el = br.read_u16le()?; |
| 1043 | } |
| 1044 | for (dst, &src) in self.pic.fpal.iter_mut().zip(self.pic.pal.iter()) { |
| 1045 | *dst = u16::from(src) << 7; |
| 1046 | } |
| 1047 | }, |
| 1048 | 1 => { |
| 1049 | validate!(size == 4 || size == 6); |
| 1050 | for i in 0..768 { |
| 1051 | self.pic.fpal[i] = self.pic.fpal[i].wrapping_add(self.pic.pdelta[i]); |
| 1052 | self.pic.pal[i] = (self.pic.fpal[i] >> 7) as u8; |
| 1053 | } |
| 1054 | br.read_skip((size as usize) - 4)?; |
| 1055 | }, |
| 1056 | 2 => { |
| 1057 | validate!(size == 0x904); |
| 1058 | for el in self.pic.pdelta.iter_mut() { |
| 1059 | *el = br.read_u16le()?; |
| 1060 | } |
| 1061 | br.read_buf(&mut self.pic.pal)?; |
| 1062 | }, |
| 1063 | _ => return Err(DecoderError::InvalidData), |
| 1064 | }; |
| 1065 | }, |
| 1066 | b"FTCH" => { |
| 1067 | br.read_skip(size)?; |
| 1068 | self.pic.frm0.copy_from_slice(&self.pic.frm1); |
| 1069 | }, |
| 1070 | b"STOR" => { |
| 1071 | store = true; |
| 1072 | br.read_skip(size)?; |
| 1073 | }, |
| 1074 | b"FOBJ" => { |
| 1075 | validate!(size >= 14); |
| 1076 | let end = br.tell() + (size as u64); |
| 1077 | let compression = br.read_byte()?; |
| 1078 | let cparam = br.read_byte()?; |
| 1079 | let x = br.read_u16le()? as i16; |
| 1080 | let y = br.read_u16le()? as i16; |
| 1081 | let w = br.read_u16le()? as usize; |
| 1082 | let h = br.read_u16le()? as usize; |
| 1083 | let _ = br.read_u16le()?; |
| 1084 | let param2 = br.read_u16le()?; |
| 1085 | |
| 1086 | match compression { |
| 1087 | 1 | 3 => self.decode_1(&mut br, x, y, w, h, (compression == 1) ^ (self.version != 1))?, |
| 1088 | 2 => self.decode_2(&mut br, x, y, w, h, size - 14)?, |
| 1089 | 4 | 33 => self.decode_4(&mut br, x, y, w, h, cparam, param2)?, |
| 1090 | 5 | 34 => self.decode_5(&mut br, x, y, w, h, cparam, param2)?, |
| 1091 | 21 | 44 => self.decode_21(&mut br, x, y, w, h, size - 14)?, |
| 1092 | 23 => self.decode_23(&mut br, x, y, w, h, cparam, param2, self.version == 1)?, |
| 1093 | 37 => { |
| 1094 | let start = br.tell() as usize; |
| 1095 | let end = start + size - 14; |
| 1096 | let mut mr = MemoryReader::new_read(&src[start..end]); |
| 1097 | let mut br = ByteReader::new(&mut mr); |
| 1098 | self.decode_37(&mut br, x, y, w, h)?; |
| 1099 | }, |
| 1100 | 47 => { |
| 1101 | let start = br.tell() as usize; |
| 1102 | let end = start + size - 14; |
| 1103 | let mut mr = MemoryReader::new_read(&src[start..end]); |
| 1104 | let mut br = ByteReader::new(&mut mr); |
| 1105 | self.decode_47(&mut br, x, y, w, h)?; |
| 1106 | }, |
| 1107 | 48 => { |
| 1108 | let start = br.tell() as usize; |
| 1109 | let end = start + size - 14; |
| 1110 | let mut mr = MemoryReader::new_read(&src[start..end]); |
| 1111 | let mut br = ByteReader::new(&mut mr); |
| 1112 | self.decode_48(&mut br, x, y, w, h)?; |
| 1113 | }, |
| 1114 | _ => return Err(DecoderError::NotImplemented), |
| 1115 | }; |
| 1116 | validate!(br.tell() <= end); |
| 1117 | let tail = end - br.tell(); |
| 1118 | br.read_skip(tail as usize)?; |
| 1119 | if store { |
| 1120 | self.pic.frm1.copy_from_slice(&self.pic.frm0); |
| 1121 | store = false; |
| 1122 | } |
| 1123 | }, |
| 1124 | _ => br.read_skip(size)?, |
| 1125 | }; |
| 1126 | } |
| 1127 | |
| 1128 | let ret = self.pic.get_frame(pkt); |
| 1129 | |
| 1130 | if self.reorder == 2 { |
| 1131 | std::mem::swap(&mut self.pic.frm1, &mut self.pic.frm2); |
| 1132 | } |
| 1133 | if self.reorder != 0 { |
| 1134 | std::mem::swap(&mut self.pic.frm0, &mut self.pic.frm2); |
| 1135 | } |
| 1136 | self.reorder = 0; |
| 1137 | |
| 1138 | ret |
| 1139 | } |
| 1140 | fn flush(&mut self) { |
| 1141 | } |
| 1142 | } |
| 1143 | |
| 1144 | impl NAOptionHandler for Smush1Decoder { |
| 1145 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } |
| 1146 | fn set_options(&mut self, _options: &[NAOption]) { } |
| 1147 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } |
| 1148 | } |
| 1149 | |
| 1150 | |
| 1151 | pub fn get_decoder_video_v1() -> Box<dyn NADecoder + Send> { |
| 1152 | Box::new(Smush1Decoder::new()) |
| 1153 | } |
| 1154 | |
| 1155 | #[cfg(test)] |
| 1156 | mod test { |
| 1157 | use nihav_core::codecs::RegisteredDecoders; |
| 1158 | use nihav_core::demuxers::RegisteredDemuxers; |
| 1159 | use nihav_codec_support::test::dec_video::*; |
| 1160 | use crate::game_register_all_decoders; |
| 1161 | use crate::game_register_all_demuxers; |
| 1162 | // samples from Rebel Assault |
| 1163 | #[test] |
| 1164 | fn test_smush_anim_v1() { |
| 1165 | let mut dmx_reg = RegisteredDemuxers::new(); |
| 1166 | game_register_all_demuxers(&mut dmx_reg); |
| 1167 | let mut dec_reg = RegisteredDecoders::new(); |
| 1168 | game_register_all_decoders(&mut dec_reg); |
| 1169 | |
| 1170 | test_decoding("smush", "smushv1", "assets/Game/smush/c1block.anm", Some(42), &dmx_reg, &dec_reg, |
| 1171 | ExpectedTestResult::MD5([0x39339398, 0x7ce83788, 0xaac917d4, 0xaef9d653])); |
| 1172 | test_decoding("smush", "smushv1", "assets/Game/smush/c1c3po.anm", Some(42), &dmx_reg, &dec_reg, |
| 1173 | ExpectedTestResult::MD5([0x9c1c2422, 0x2121aa7a, 0xc06418bc, 0xd82d704b])); |
| 1174 | test_decoding("smush", "smushv1", "assets/Game/smush/o1option.anm", Some(4), &dmx_reg, &dec_reg, |
| 1175 | ExpectedTestResult::MD5([0x21ea3ee9, 0x3d88bcee, 0x9b71a87a, 0xc5e0a006])); |
| 1176 | } |
| 1177 | #[test] |
| 1178 | fn test_smush_anim_v2() { |
| 1179 | let mut dmx_reg = RegisteredDemuxers::new(); |
| 1180 | game_register_all_demuxers(&mut dmx_reg); |
| 1181 | let mut dec_reg = RegisteredDecoders::new(); |
| 1182 | game_register_all_decoders(&mut dec_reg); |
| 1183 | |
| 1184 | // sample from The Dig |
| 1185 | test_decoding("smush", "smushv1", "assets/Game/smush/PIGOUT.SAN", Some(42), &dmx_reg, &dec_reg, |
| 1186 | ExpectedTestResult::MD5([0x74794559, 0x78a1e484, 0x379a1eec, 0x0609e0b2])); |
| 1187 | // sample from Full Throttle |
| 1188 | test_decoding("smush", "smushv1", "assets/Game/smush/FIRE.SAN", Some(16), &dmx_reg, &dec_reg, |
| 1189 | ExpectedTestResult::MD5([0x442f73b9, 0x0b98d80f, 0xee2f0e19, 0xa555a33d])); |
| 1190 | // sample from Mortimer and the Riddles of the Medallion |
| 1191 | test_decoding("smush", "smushv1", "assets/Game/smush/FOREST1.SAN", Some(24), &dmx_reg, &dec_reg, |
| 1192 | ExpectedTestResult::MD5([0xd5b71505, 0x0ffe79dd, 0xc274dbaf, 0x8b952271])); |
| 1193 | // sample from Curse of Monkey Island |
| 1194 | test_decoding("smush", "smushv1", "assets/Game/smush/ZAP010.SAN", None, &dmx_reg, &dec_reg, |
| 1195 | ExpectedTestResult::MD5([0x369839f1, 0x2daab242, 0x23995d80, 0x501fbe09])); |
| 1196 | // sample from Jedi Knight: Mysteries of the Sith |
| 1197 | test_decoding("smush", "smushv1", "assets/Game/smush/S2L4ECS.SAN", Some(42), &dmx_reg, &dec_reg, |
| 1198 | ExpectedTestResult::MD5([0x4525b5f3, 0x9fe5fb23, 0xf5f27980, 0x12589ce1])); |
| 1199 | } |
| 1200 | } |
| 1201 | |
| 1202 | const C37_MV: [[i8; 255 * 2]; 3] = [ |
| 1203 | [ |
| 1204 | 0, 0, 1, 0, 2, 0, 3, 0, 5, 0, 8, 0, 13, 0, 21, |
| 1205 | 0, -1, 0, -2, 0, -3, 0, -5, 0, -8, 0, -13, 0, -17, 0, |
| 1206 | -21, 0, 0, 1, 1, 1, 2, 1, 3, 1, 5, 1, 8, 1, 13, |
| 1207 | 1, 21, 1, -1, 1, -2, 1, -3, 1, -5, 1, -8, 1, -13, 1, |
| 1208 | -17, 1, -21, 1, 0, 2, 1, 2, 2, 2, 3, 2, 5, 2, 8, |
| 1209 | 2, 13, 2, 21, 2, -1, 2, -2, 2, -3, 2, -5, 2, -8, 2, |
| 1210 | -13, 2, -17, 2, -21, 2, 0, 3, 1, 3, 2, 3, 3, 3, 5, |
| 1211 | 3, 8, 3, 13, 3, 21, 3, -1, 3, -2, 3, -3, 3, -5, 3, |
| 1212 | -8, 3, -13, 3, -17, 3, -21, 3, 0, 5, 1, 5, 2, 5, 3, |
| 1213 | 5, 5, 5, 8, 5, 13, 5, 21, 5, -1, 5, -2, 5, -3, 5, |
| 1214 | -5, 5, -8, 5, -13, 5, -17, 5, -21, 5, 0, 8, 1, 8, 2, |
| 1215 | 8, 3, 8, 5, 8, 8, 8, 13, 8, 21, 8, -1, 8, -2, 8, |
| 1216 | -3, 8, -5, 8, -8, 8, -13, 8, -17, 8, -21, 8, 0, 13, 1, |
| 1217 | 13, 2, 13, 3, 13, 5, 13, 8, 13, 13, 13, 21, 13, -1, 13, |
| 1218 | -2, 13, -3, 13, -5, 13, -8, 13, -13, 13, -17, 13, -21, 13, 0, |
| 1219 | 21, 1, 21, 2, 21, 3, 21, 5, 21, 8, 21, 13, 21, 21, 21, |
| 1220 | -1, 21, -2, 21, -3, 21, -5, 21, -8, 21, -13, 21, -17, 21, -21, |
| 1221 | 21, 0, -1, 1, -1, 2, -1, 3, -1, 5, -1, 8, -1, 13, -1, |
| 1222 | 21, -1, -1, -1, -2, -1, -3, -1, -5, -1, -8, -1, -13, -1, -17, |
| 1223 | -1, -21, -1, 0, -2, 1, -2, 2, -2, 3, -2, 5, -2, 8, -2, |
| 1224 | 13, -2, 21, -2, -1, -2, -2, -2, -3, -2, -5, -2, -8, -2, -13, |
| 1225 | -2, -17, -2, -21, -2, 0, -3, 1, -3, 2, -3, 3, -3, 5, -3, |
| 1226 | 8, -3, 13, -3, 21, -3, -1, -3, -2, -3, -3, -3, -5, -3, -8, |
| 1227 | -3, -13, -3, -17, -3, -21, -3, 0, -5, 1, -5, 2, -5, 3, -5, |
| 1228 | 5, -5, 8, -5, 13, -5, 21, -5, -1, -5, -2, -5, -3, -5, -5, |
| 1229 | -5, -8, -5, -13, -5, -17, -5, -21, -5, 0, -8, 1, -8, 2, -8, |
| 1230 | 3, -8, 5, -8, 8, -8, 13, -8, 21, -8, -1, -8, -2, -8, -3, |
| 1231 | -8, -5, -8, -8, -8, -13, -8, -17, -8, -21, -8, 0, -13, 1, -13, |
| 1232 | 2, -13, 3, -13, 5, -13, 8, -13, 13, -13, 21, -13, -1, -13, -2, |
| 1233 | -13, -3, -13, -5, -13, -8, -13, -13, -13, -17, -13, -21, -13, 0, -17, |
| 1234 | 1, -17, 2, -17, 3, -17, 5, -17, 8, -17, 13, -17, 21, -17, -1, |
| 1235 | -17, -2, -17, -3, -17, -5, -17, -8, -17, -13, -17, -17, -17, -21, -17, |
| 1236 | 0, -21, 1, -21, 2, -21, 3, -21, 5, -21, 8, -21, 13, -21, 21, |
| 1237 | -21, -1, -21, -2, -21, -3, -21, -5, -21, -8, -21, -13, -21, -17, -21 |
| 1238 | ], [ |
| 1239 | 0, 0, -8, -29, 8, -29, -18, -25, 17, -25, 0, -23, -6, -22, 6, |
| 1240 | -22, -13, -19, 12, -19, 0, -18, 25, -18, -25, -17, -5, -17, 5, -17, |
| 1241 | -10, -15, 10, -15, 0, -14, -4, -13, 4, -13, 19, -13, -19, -12, -8, |
| 1242 | -11, -2, -11, 0, -11, 2, -11, 8, -11, -15, -10, -4, -10, 4, -10, |
| 1243 | 15, -10, -6, -9, -1, -9, 1, -9, 6, -9, -29, -8, -11, -8, -8, |
| 1244 | -8, -3, -8, 3, -8, 8, -8, 11, -8, 29, -8, -5, -7, -2, -7, |
| 1245 | 0, -7, 2, -7, 5, -7, -22, -6, -9, -6, -6, -6, -3, -6, -1, |
| 1246 | -6, 1, -6, 3, -6, 6, -6, 9, -6, 22, -6, -17, -5, -7, -5, |
| 1247 | -4, -5, -2, -5, 0, -5, 2, -5, 4, -5, 7, -5, 17, -5, -13, |
| 1248 | -4, -10, -4, -5, -4, -3, -4, -1, -4, 0, -4, 1, -4, 3, -4, |
| 1249 | 5, -4, 10, -4, 13, -4, -8, -3, -6, -3, -4, -3, -3, -3, -2, |
| 1250 | -3, -1, -3, 0, -3, 1, -3, 2, -3, 4, -3, 6, -3, 8, -3, |
| 1251 | -11, -2, -7, -2, -5, -2, -3, -2, -2, -2, -1, -2, 0, -2, 1, |
| 1252 | -2, 2, -2, 3, -2, 5, -2, 7, -2, 11, -2, -9, -1, -6, -1, |
| 1253 | -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3, |
| 1254 | -1, 4, -1, 6, -1, 9, -1, -31, 0, -23, 0, -18, 0, -14, 0, |
| 1255 | -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, -2, 0, -1, 0, 0, |
| 1256 | -31, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, |
| 1257 | 14, 0, 18, 0, 23, 0, 31, 0, -9, 1, -6, 1, -4, 1, -3, |
| 1258 | 1, -2, 1, -1, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, |
| 1259 | 6, 1, 9, 1, -11, 2, -7, 2, -5, 2, -3, 2, -2, 2, -1, |
| 1260 | 2, 0, 2, 1, 2, 2, 2, 3, 2, 5, 2, 7, 2, 11, 2, |
| 1261 | -8, 3, -6, 3, -4, 3, -2, 3, -1, 3, 0, 3, 1, 3, 2, |
| 1262 | 3, 3, 3, 4, 3, 6, 3, 8, 3, -13, 4, -10, 4, -5, 4, |
| 1263 | -3, 4, -1, 4, 0, 4, 1, 4, 3, 4, 5, 4, 10, 4, 13, |
| 1264 | 4, -17, 5, -7, 5, -4, 5, -2, 5, 0, 5, 2, 5, 4, 5, |
| 1265 | 7, 5, 17, 5, -22, 6, -9, 6, -6, 6, -3, 6, -1, 6, 1, |
| 1266 | 6, 3, 6, 6, 6, 9, 6, 22, 6, -5, 7, -2, 7, 0, 7, |
| 1267 | 2, 7, 5, 7, -29, 8, -11, 8, -8, 8, -3, 8, 3, 8, 8, |
| 1268 | 8, 11, 8, 29, 8, -6, 9, -1, 9, 1, 9, 6, 9, -15, 10, |
| 1269 | -4, 10, 4, 10, 15, 10, -8, 11, -2, 11, 0, 11, 2, 11, 8, |
| 1270 | 11, 19, 12, -19, 13, -4, 13, 4, 13, 0, 14, -10, 15, 10, 15, |
| 1271 | -5, 17, 5, 17, 25, 17, -25, 18, 0, 18, -12, 19, 13, 19, -6, |
| 1272 | 22, 6, 22, 0, 23, -17, 25, 18, 25, -8, 29, 8, 29, 0, 31 |
| 1273 | ], [ |
| 1274 | 0, 0, -6, -22, 6, -22, -13, -19, 12, -19, 0, -18, -5, -17, 5, |
| 1275 | -17, -10, -15, 10, -15, 0, -14, -4, -13, 4, -13, 19, -13, -19, -12, |
| 1276 | -8, -11, -2, -11, 0, -11, 2, -11, 8, -11, -15, -10, -4, -10, 4, |
| 1277 | -10, 15, -10, -6, -9, -1, -9, 1, -9, 6, -9, -11, -8, -8, -8, |
| 1278 | -3, -8, 0, -8, 3, -8, 8, -8, 11, -8, -5, -7, -2, -7, 0, |
| 1279 | -7, 2, -7, 5, -7, -22, -6, -9, -6, -6, -6, -3, -6, -1, -6, |
| 1280 | 1, -6, 3, -6, 6, -6, 9, -6, 22, -6, -17, -5, -7, -5, -4, |
| 1281 | -5, -2, -5, -1, -5, 0, -5, 1, -5, 2, -5, 4, -5, 7, -5, |
| 1282 | 17, -5, -13, -4, -10, -4, -5, -4, -3, -4, -2, -4, -1, -4, 0, |
| 1283 | -4, 1, -4, 2, -4, 3, -4, 5, -4, 10, -4, 13, -4, -8, -3, |
| 1284 | -6, -3, -4, -3, -3, -3, -2, -3, -1, -3, 0, -3, 1, -3, 2, |
| 1285 | -3, 3, -3, 4, -3, 6, -3, 8, -3, -11, -2, -7, -2, -5, -2, |
| 1286 | -4, -2, -3, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2, 3, |
| 1287 | -2, 4, -2, 5, -2, 7, -2, 11, -2, -9, -1, -6, -1, -5, -1, |
| 1288 | -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3, |
| 1289 | -1, 4, -1, 5, -1, 6, -1, 9, -1, -23, 0, -18, 0, -14, 0, |
| 1290 | -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, -2, 0, -1, 0, 0, |
| 1291 | -23, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, |
| 1292 | 14, 0, 18, 0, 23, 0, -9, 1, -6, 1, -5, 1, -4, 1, -3, |
| 1293 | 1, -2, 1, -1, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, |
| 1294 | 5, 1, 6, 1, 9, 1, -11, 2, -7, 2, -5, 2, -4, 2, -3, |
| 1295 | 2, -2, 2, -1, 2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, |
| 1296 | 5, 2, 7, 2, 11, 2, -8, 3, -6, 3, -4, 3, -3, 3, -2, |
| 1297 | 3, -1, 3, 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, 6, 3, |
| 1298 | 8, 3, -13, 4, -10, 4, -5, 4, -3, 4, -2, 4, -1, 4, 0, |
| 1299 | 4, 1, 4, 2, 4, 3, 4, 5, 4, 10, 4, 13, 4, -17, 5, |
| 1300 | -7, 5, -4, 5, -2, 5, -1, 5, 0, 5, 1, 5, 2, 5, 4, |
| 1301 | 5, 7, 5, 17, 5, -22, 6, -9, 6, -6, 6, -3, 6, -1, 6, |
| 1302 | 1, 6, 3, 6, 6, 6, 9, 6, 22, 6, -5, 7, -2, 7, 0, |
| 1303 | 7, 2, 7, 5, 7, -11, 8, -8, 8, -3, 8, 0, 8, 3, 8, |
| 1304 | 8, 8, 11, 8, -6, 9, -1, 9, 1, 9, 6, 9, -15, 10, -4, |
| 1305 | 10, 4, 10, 15, 10, -8, 11, -2, 11, 0, 11, 2, 11, 8, 11, |
| 1306 | 19, 12, -19, 13, -4, 13, 4, 13, 0, 14, -10, 15, 10, 15, -5, |
| 1307 | 17, 5, 17, 0, 18, -12, 19, 13, 19, -6, 22, 6, 22, 0, 23 |
| 1308 | ] |
| 1309 | ]; |
| 1310 | |
| 1311 | const C47_MV: [[[i8; 2]; 255]; 2] = [ |
| 1312 | [ |
| 1313 | [ 0, 0], [ -1, -43], [ 6, -43], [ -9, -42], [ 13, -41], |
| 1314 | [-16, -40], [ 19, -39], [-23, -36], [ 26, -34], [ -2, -33], |
| 1315 | [ 4, -33], [-29, -32], [ -9, -32], [ 11, -31], [-16, -29], |
| 1316 | [ 32, -29], [ 18, -28], [-34, -26], [-22, -25], [ -1, -25], |
| 1317 | [ 3, -25], [ -7, -24], [ 8, -24], [ 24, -23], [ 36, -23], |
| 1318 | [-12, -22], [ 13, -21], [-38, -20], [ 0, -20], [-27, -19], |
| 1319 | [ -4, -19], [ 4, -19], [-17, -18], [ -8, -17], [ 8, -17], |
| 1320 | [ 18, -17], [ 28, -17], [ 39, -17], [-12, -15], [ 12, -15], |
| 1321 | [-21, -14], [ -1, -14], [ 1, -14], [-41, -13], [ -5, -13], |
| 1322 | [ 5, -13], [ 21, -13], [-31, -12], [-15, -11], [ -8, -11], |
| 1323 | [ 8, -11], [ 15, -11], [ -2, -10], [ 1, -10], [ 31, -10], |
| 1324 | [-23, -9], [-11, -9], [ -5, -9], [ 4, -9], [ 11, -9], |
| 1325 | [ 42, -9], [ 6, -8], [ 24, -8], [-18, -7], [ -7, -7], |
| 1326 | [ -3, -7], [ -1, -7], [ 2, -7], [ 18, -7], [-43, -6], |
| 1327 | [-13, -6], [ -4, -6], [ 4, -6], [ 8, -6], [-33, -5], |
| 1328 | [ -9, -5], [ -2, -5], [ 0, -5], [ 2, -5], [ 5, -5], |
| 1329 | [ 13, -5], [-25, -4], [ -6, -4], [ -3, -4], [ 3, -4], |
| 1330 | [ 9, -4], [-19, -3], [ -7, -3], [ -4, -3], [ -2, -3], |
| 1331 | [ -1, -3], [ 0, -3], [ 1, -3], [ 2, -3], [ 4, -3], |
| 1332 | [ 6, -3], [ 33, -3], [-14, -2], [-10, -2], [ -5, -2], |
| 1333 | [ -3, -2], [ -2, -2], [ -1, -2], [ 0, -2], [ 1, -2], |
| 1334 | [ 2, -2], [ 3, -2], [ 5, -2], [ 7, -2], [ 14, -2], |
| 1335 | [ 19, -2], [ 25, -2], [ 43, -2], [ -7, -1], [ -3, -1], |
| 1336 | [ -2, -1], [ -1, -1], [ 0, -1], [ 1, -1], [ 2, -1], |
| 1337 | [ 3, -1], [ 10, -1], [ -5, 0], [ -3, 0], [ -2, 0], |
| 1338 | [ -1, 0], [ 1, 0], [ 2, 0], [ 3, 0], [ 5, 0], |
| 1339 | [ 7, 0], [-10, 1], [ -7, 1], [ -3, 1], [ -2, 1], |
| 1340 | [ -1, 1], [ 0, 1], [ 1, 1], [ 2, 1], [ 3, 1], |
| 1341 | [-43, 2], [-25, 2], [-19, 2], [-14, 2], [ -5, 2], |
| 1342 | [ -3, 2], [ -2, 2], [ -1, 2], [ 0, 2], [ 1, 2], |
| 1343 | [ 2, 2], [ 3, 2], [ 5, 2], [ 7, 2], [ 10, 2], |
| 1344 | [ 14, 2], [-33, 3], [ -6, 3], [ -4, 3], [ -2, 3], |
| 1345 | [ -1, 3], [ 0, 3], [ 1, 3], [ 2, 3], [ 4, 3], |
| 1346 | [ 19, 3], [ -9, 4], [ -3, 4], [ 3, 4], [ 7, 4], |
| 1347 | [ 25, 4], [-13, 5], [ -5, 5], [ -2, 5], [ 0, 5], |
| 1348 | [ 2, 5], [ 5, 5], [ 9, 5], [ 33, 5], [ -8, 6], |
| 1349 | [ -4, 6], [ 4, 6], [ 13, 6], [ 43, 6], [-18, 7], |
| 1350 | [ -2, 7], [ 0, 7], [ 2, 7], [ 7, 7], [ 18, 7], |
| 1351 | [-24, 8], [ -6, 8], [-42, 9], [-11, 9], [ -4, 9], |
| 1352 | [ 5, 9], [ 11, 9], [ 23, 9], [-31, 10], [ -1, 10], |
| 1353 | [ 2, 10], [-15, 11], [ -8, 11], [ 8, 11], [ 15, 11], |
| 1354 | [ 31, 12], [-21, 13], [ -5, 13], [ 5, 13], [ 41, 13], |
| 1355 | [ -1, 14], [ 1, 14], [ 21, 14], [-12, 15], [ 12, 15], |
| 1356 | [-39, 17], [-28, 17], [-18, 17], [ -8, 17], [ 8, 17], |
| 1357 | [ 17, 18], [ -4, 19], [ 0, 19], [ 4, 19], [ 27, 19], |
| 1358 | [ 38, 20], [-13, 21], [ 12, 22], [-36, 23], [-24, 23], |
| 1359 | [ -8, 24], [ 7, 24], [ -3, 25], [ 1, 25], [ 22, 25], |
| 1360 | [ 34, 26], [-18, 28], [-32, 29], [ 16, 29], [-11, 31], |
| 1361 | [ 9, 32], [ 29, 32], [ -4, 33], [ 2, 33], [-26, 34], |
| 1362 | [ 23, 36], [-19, 39], [ 16, 40], [-13, 41], [ 9, 42], |
| 1363 | [ -6, 43], [ 1, 43], [ 0, 0], [ 0, 0], [ 0, 0], |
| 1364 | ], [ |
| 1365 | [ 0, 0], [ 1, 0], [ 2, 0], [ 3, 0], [ 5, 0], |
| 1366 | [ 8, 0], [ 13, 0], [ 21, 0], [ -1, 0], [ -2, 0], |
| 1367 | [ -3, 0], [ -5, 0], [ -8, 0], [-13, 0], [-17, 0], |
| 1368 | [-21, 0], [ 0, 1], [ 1, 1], [ 2, 1], [ 3, 1], |
| 1369 | [ 5, 1], [ 8, 1], [ 13, 1], [ 21, 1], [ -1, 1], |
| 1370 | [ -2, 1], [ -3, 1], [ -5, 1], [ -8, 1], [-13, 1], |
| 1371 | [-17, 1], [-21, 1], [ 0, 2], [ 1, 2], [ 2, 2], |
| 1372 | [ 3, 2], [ 5, 2], [ 8, 2], [ 13, 2], [ 21, 2], |
| 1373 | [ -1, 2], [ -2, 2], [ -3, 2], [ -5, 2], [ -8, 2], |
| 1374 | [-13, 2], [-17, 2], [-21, 2], [ 0, 3], [ 1, 3], |
| 1375 | [ 2, 3], [ 3, 3], [ 5, 3], [ 8, 3], [ 13, 3], |
| 1376 | [ 21, 3], [ -1, 3], [ -2, 3], [ -3, 3], [ -5, 3], |
| 1377 | [ -8, 3], [-13, 3], [-17, 3], [-21, 3], [ 0, 5], |
| 1378 | [ 1, 5], [ 2, 5], [ 3, 5], [ 5, 5], [ 8, 5], |
| 1379 | [ 13, 5], [ 21, 5], [ -1, 5], [ -2, 5], [ -3, 5], |
| 1380 | [ -5, 5], [ -8, 5], [-13, 5], [-17, 5], [-21, 5], |
| 1381 | [ 0, 8], [ 1, 8], [ 2, 8], [ 3, 8], [ 5, 8], |
| 1382 | [ 8, 8], [ 13, 8], [ 21, 8], [ -1, 8], [ -2, 8], |
| 1383 | [ -3, 8], [ -5, 8], [ -8, 8], [-13, 8], [-17, 8], |
| 1384 | [-21, 8], [ 0, 13], [ 1, 13], [ 2, 13], [ 3, 13], |
| 1385 | [ 5, 13], [ 8, 13], [ 13, 13], [ 21, 13], [ -1, 13], |
| 1386 | [ -2, 13], [ -3, 13], [ -5, 13], [ -8, 13], [-13, 13], |
| 1387 | [-17, 13], [-21, 13], [ 0, 21], [ 1, 21], [ 2, 21], |
| 1388 | [ 3, 21], [ 5, 21], [ 8, 21], [ 13, 21], [ 21, 21], |
| 1389 | [ -1, 21], [ -2, 21], [ -3, 21], [ -5, 21], [ -8, 21], |
| 1390 | [-13, 21], [-17, 21], [-21, 21], [ 0, -1], [ 1, -1], |
| 1391 | [ 2, -1], [ 3, -1], [ 5, -1], [ 8, -1], [ 13, -1], |
| 1392 | [ 21, -1], [ -1, -1], [ -2, -1], [ -3, -1], [ -5, -1], |
| 1393 | [ -8, -1], [-13, -1], [-17, -1], [-21, -1], [ 0, -2], |
| 1394 | [ 1, -2], [ 2, -2], [ 3, -2], [ 5, -2], [ 8, -2], |
| 1395 | [ 13, -2], [ 21, -2], [ -1, -2], [ -2, -2], [ -3, -2], |
| 1396 | [ -5, -2], [ -8, -2], [-13, -2], [-17, -2], [-21, -2], |
| 1397 | [ 0, -3], [ 1, -3], [ 2, -3], [ 3, -3], [ 5, -3], |
| 1398 | [ 8, -3], [ 13, -3], [ 21, -3], [ -1, -3], [ -2, -3], |
| 1399 | [ -3, -3], [ -5, -3], [ -8, -3], [-13, -3], [-17, -3], |
| 1400 | [-21, -3], [ 0, -5], [ 1, -5], [ 2, -5], [ 3, -5], |
| 1401 | [ 5, -5], [ 8, -5], [ 13, -5], [ 21, -5], [ -1, -5], |
| 1402 | [ -2, -5], [ -3, -5], [ -5, -5], [ -8, -5], [-13, -5], |
| 1403 | [-17, -5], [-21, -5], [ 0, -8], [ 1, -8], [ 2, -8], |
| 1404 | [ 3, -8], [ 5, -8], [ 8, -8], [ 13, -8], [ 21, -8], |
| 1405 | [ -1, -8], [ -2, -8], [ -3, -8], [ -5, -8], [ -8, -8], |
| 1406 | [-13, -8], [-17, -8], [-21, -8], [ 0, -13], [ 1, -13], |
| 1407 | [ 2, -13], [ 3, -13], [ 5, -13], [ 8, -13], [ 13, -13], |
| 1408 | [ 21, -13], [ -1, -13], [ -2, -13], [ -3, -13], [ -5, -13], |
| 1409 | [ -8, -13], [-13, -13], [-17, -13], [-21, -13], [ 0, -17], |
| 1410 | [ 1, -17], [ 2, -17], [ 3, -17], [ 5, -17], [ 8, -17], |
| 1411 | [ 13, -17], [ 21, -17], [ -1, -17], [ -2, -17], [ -3, -17], |
| 1412 | [ -5, -17], [ -8, -17], [-13, -17], [-17, -17], [-21, -17], |
| 1413 | [ 0, -21], [ 1, -21], [ 2, -21], [ 3, -21], [ 5, -21], |
| 1414 | [ 8, -21], [ 13, -21], [ 21, -21], [ -1, -21], [ -2, -21], |
| 1415 | [ -3, -21], [ -5, -21], [ -8, -21], [-13, -21], [-17, -21] |
| 1416 | ] |
| 1417 | ]; |