/// <summary> /// Run-length decode ( RLE blocks -> zigzaged image blocks -> inverse zigzag -> origin image block ) /// </summary> /// <param name="source">source data bits</param> /// <returns></returns> public List <Matrix <double> > Decode(IEnumerable <RLEBlock> source) { List <Matrix <double> > result = new List <Matrix <double> >(); int latestDc = 0; foreach (RLEBlock rleBlock in source) { List <double> array = new List <double>(); DCElement dc = rleBlock.DC; array.Add(dc.Diff + latestDc); latestDc = dc.Diff + latestDc; foreach (ACElement ac in rleBlock.ACs) { for (int i = 0; i < ac.Length; i++) { array.Add(0); } array.Add(ac.Value); } if (array.Count < 64) { int numOfZero = 64 - array.Count; for (int i = 0; i < numOfZero; i++) { array.Add(0); } } result.Add(ZigZagEncoder.IZigZag(array)); } return(result); }
/// <summary> /// Construct code word from RLE /// </summary> /// <param name="blocks"></param> /// <returns></returns> public static bool[] ConstructCodeWord(List <RLEBlock> blocks) { string codeword = string.Empty; foreach (RLEBlock block in blocks) { DCElement dc = block.DC; codeword += GetDCCodeWord(dc.Diff); foreach (ACElement ac in block.ACs) { codeword += GetACCodeWord(ac.Length, ac.Value); } codeword += "1010"; } return(Utility.StringToBoolArray(codeword)); }
/// <summary> /// Run-length encode , ( origin image blocks -> zigzaged image blocks -> RLE blocks ) /// </summary> /// <param name="source">image blocks</param> /// <returns></returns> public List <RLEBlock> Encode(List <Matrix <double> > source) { List <RLEBlock> blocks = new List <RLEBlock>(); int lastesrDC = 0; int run = 0; foreach (Matrix <double> matrix in source) { run = 0; List <double> list = ZigZagEncoder.ZigZag(matrix); List <ACElement> acs = new List <ACElement>(); int diff = (int)list[0] - lastesrDC; lastesrDC = (int)list[0]; DCElement dc = new DCElement(diff); List <double> listac = list.Skip(1).ToList(); foreach (double data in listac) { if (data == 0) { run++; } else { if (run >= 16) { int times = run / 16; run %= 16; for (int i = 0; i < times; i++) { acs.Add(new ACElement(15, 0)); } } acs.Add(new ACElement(run, (int)data)); run = 0; } } blocks.Add(new RLEBlock(dc, acs)); } return(blocks); }
/// <summary> /// Construct RLE from code words /// </summary> /// <param name="source"></param> /// <returns></returns> public static List <RLEBlock> ReconstructRleBlocks(string source) { List <RLEBlock> result = new List <RLEBlock>(); RLEBlock block = null; string temp = string.Empty; bool isDc = true; for (int i = 0; i < source.Length; i++) { // dc decode first if (isDc) { if (block == null) { block = new RLEBlock(); } temp += source[i]; string diff = string.Empty; if (DcCategoryHashTable.Contains(temp)) { int category = Convert.ToInt32(DcCategoryHashTable[temp]); int nextBits = category == 0 ? 1 : category; for (int j = 1; j <= nextBits; j++) { diff += source[i + j]; } i += nextBits; DCElement dc; if (category == 0 && diff == "0") { dc = new DCElement(0); } else { dc = new DCElement(FindDiffValue(category, diff)); } block.DC = dc; isDc = false; temp = string.Empty; } } // then ac else { temp += source[i]; if (AcCategoryHashTable.Contains(temp)) { string value = string.Empty; Tuple <int, int> runSize = (Tuple <int, int>)AcCategoryHashTable[temp]; if (runSize.Item1 == 0 && runSize.Item2 == 0) { isDc = true; result.Add(block); temp = string.Empty; block = null; continue; } int category = runSize.Item2; int nextBits = category == 0 ? 1 : category; for (int j = 1; j <= nextBits; j++) { value += source[i + j]; } i += nextBits; ACElement ac = new ACElement(runSize.Item1, FindDiffValue(runSize.Item2, value)); block.ACs.Add(ac); temp = string.Empty; } } } return(result); }
public RLEBlock(DCElement dc, List <ACElement> acs) { DC = dc; ACs = acs; }