/// <summary> /// It decode byte stream into CLEARCODEC_SUBCODEC_RLEX_SEGMENT structure /// </summary> /// <param name = "stopIdxBitNum"> the bit number of stopIndex field </param> /// <param name = "relSeg"> the structure that decode result save to </param> /// <return> > 0 if decode success, otherwise return 0 </return> public byte DecodeRlexSeg(byte stopIdxBitNum, ref CLEARCODEC_SUBCODEC_RLEX_SEGMENT relSeg) { byte stopIdx_suiteDepth = 0; byte decodedCount = 0; if (!DecodeByte(ref stopIdx_suiteDepth)) { return(0); } decodedCount++; byte stopIdxMask = (byte)((1 << stopIdxBitNum) - 1); relSeg.stopIndex = (byte)(stopIdx_suiteDepth & stopIdxMask); relSeg.suiteDepth = (byte)(stopIdx_suiteDepth >> stopIdxBitNum); if (!DecodeRulLengthFactor(ref relSeg.runLengthFactor)) { return(0); } if (relSeg.runLengthFactor < 0xff) { decodedCount++; } else if (relSeg.runLengthFactor < 0xffff) { decodedCount += 3; } else { decodedCount += 7; } return(decodedCount); }
/// <summary> /// It decode rlexByteCount bytes data into CLEARCODEC_SUBCODEC_RLEX structure /// </summary> /// <param name = "rlexByteCount"> the number of bytes to be decoded into CLEARCODEC_SUBCODEC_RLEX structure </param> /// <param name = "rlex"> the structure that decode result save to </param> /// <return> true if decode success, otherwise return false </return> public bool DecodeRlexData(uint rlexByteCount, ref CLEARCODEC_SUBCODEC_RLEX rlex) { if (!DecodeByte(ref rlex.paletteCount)) return false; rlexByteCount--; // calculate bitNum of stopIndex in rlex segment byte bitNum = 0; byte count = rlex.paletteCount; // calculate bit number for stopIndex while (count > 0) { bitNum++; count >>= 1; } // decode pletteEntries List<RLEX_RGB_TRIPLET> pletList = new List<RLEX_RGB_TRIPLET>(); for (int i = 0; i < rlex.paletteCount; i++) { RLEX_RGB_TRIPLET plet = new RLEX_RGB_TRIPLET(); if (!DecodeByte(ref plet.B)) return false; if (!DecodeByte(ref plet.G)) return false; if (!DecodeByte(ref plet.R)) return false; rlexByteCount -= 3; pletList.Add(plet); } rlex.paletteEntries = pletList.ToArray(); // decode rlex segments List<CLEARCODEC_SUBCODEC_RLEX_SEGMENT> segList = new List<CLEARCODEC_SUBCODEC_RLEX_SEGMENT>(); while (rlexByteCount > 0) { CLEARCODEC_SUBCODEC_RLEX_SEGMENT rlex_seg = new CLEARCODEC_SUBCODEC_RLEX_SEGMENT(); byte decodedBytes = DecodeRlexSeg(bitNum, ref rlex_seg); if (decodedBytes == 0) return false; rlexByteCount -= decodedBytes; segList.Add(rlex_seg); } if (rlexByteCount < 0) return false; rlex.segments = segList.ToArray(); return true; }
/// <summary> /// It decode byte stream into CLEARCODEC_SUBCODEC_RLEX_SEGMENT structure /// </summary> /// <param name = "stopIdxBitNum"> the bit number of stopIndex field </param> /// <param name = "relSeg"> the structure that decode result save to </param> /// <return> > 0 if decode success, otherwise return 0 </return> public byte DecodeRlexSeg(byte stopIdxBitNum, ref CLEARCODEC_SUBCODEC_RLEX_SEGMENT relSeg) { byte stopIdx_suiteDepth = 0; byte decodedCount = 0; if (!DecodeByte(ref stopIdx_suiteDepth)) return 0; decodedCount++; byte stopIdxMask = (byte)((1 << stopIdxBitNum) - 1); relSeg.stopIndex = (byte)(stopIdx_suiteDepth & stopIdxMask); relSeg.suiteDepth = (byte)(stopIdx_suiteDepth >> stopIdxBitNum); if (!DecodeRulLengthFactor(ref relSeg.runLengthFactor)) return 0; if (relSeg.runLengthFactor < 0xff) decodedCount++; else if (relSeg.runLengthFactor < 0xffff) decodedCount += 3; else decodedCount += 7; return decodedCount; }
/// <summary> /// Encode a bitmap with RLEX method /// </summary> /// <param name="subcodeBmp">The bitmap to be encoded in subcodec layer.</param> /// <return> > 0 if encode success, otherwise return 0 </return> public static bool RlexEncode(Bitmap subcodecBmp, ref CLEARCODEC_SUBCODEC_RLEX rlex) { if (subcodecBmp == null) return false; Dictionary<RLEX_RGB_TRIPLET, byte> pletteDict = GetTripletDict(subcodecBmp); // if the bitmap color number is bigger than 255, RLEX subcodec encoding can't be applied. if (pletteDict.Count() > 0xff) return false; rlex.paletteCount = (byte)pletteDict.Count(); rlex.paletteEntries = new RLEX_RGB_TRIPLET[rlex.paletteCount]; int index=0; foreach (KeyValuePair<RLEX_RGB_TRIPLET, byte> triPlette in pletteDict) { rlex.paletteEntries[index] = triPlette.Key; index++; } List<CLEARCODEC_SUBCODEC_RLEX_SEGMENT> rlexSegList = new List<CLEARCODEC_SUBCODEC_RLEX_SEGMENT>(); CLEARCODEC_SUBCODEC_RLEX_SEGMENT rlex_seg = new CLEARCODEC_SUBCODEC_RLEX_SEGMENT(); rlex_seg.suiteDepth = 0; // we always set suite depth is 0 due to only 1 color in a suite rlex_seg.stopIndex = ColorToPletIdx(subcodecBmp.GetPixel(0, 0), pletteDict); rlex_seg.runLengthFactor = 0; // the first pixel in blow loop is at (0, 0), rlfactor is init as 0 here. for (int y = 0; y < subcodecBmp.Height; y++) { for (int x = 0; x < subcodecBmp.Width; x++) { if (x == 0 && y == 0) continue; // skip the pixel (0, 0) Color pixelColor = subcodecBmp.GetPixel(x, y); byte pletIdx = ColorToPletIdx(pixelColor, pletteDict); if (rlex_seg.stopIndex == pletIdx) // same color as previous one { rlex_seg.runLengthFactor++; } else { // add old structure into list rlexSegList.Add(rlex_seg); // create a new structure for the pixel rlex_seg = new CLEARCODEC_SUBCODEC_RLEX_SEGMENT(); rlex_seg.suiteDepth = 0; rlex_seg.stopIndex = pletIdx; rlex_seg.runLengthFactor = 0; } } } // add the final structure into list rlexSegList.Add(rlex_seg); rlex.segments = rlexSegList.ToArray(); return true; }
/// <summary> /// It decode rlexByteCount bytes data into CLEARCODEC_SUBCODEC_RLEX structure /// </summary> /// <param name = "rlexByteCount"> the number of bytes to be decoded into CLEARCODEC_SUBCODEC_RLEX structure </param> /// <param name = "rlex"> the structure that decode result save to </param> /// <return> true if decode success, otherwise return false </return> public bool DecodeRlexData(uint rlexByteCount, ref CLEARCODEC_SUBCODEC_RLEX rlex) { if (!DecodeByte(ref rlex.paletteCount)) { return(false); } rlexByteCount--; // calculate bitNum of stopIndex in rlex segment byte bitNum = 0; byte count = rlex.paletteCount; // calculate bit number for stopIndex while (count > 0) { bitNum++; count >>= 1; } // decode pletteEntries List <RLEX_RGB_TRIPLET> pletList = new List <RLEX_RGB_TRIPLET>(); for (int i = 0; i < rlex.paletteCount; i++) { RLEX_RGB_TRIPLET plet = new RLEX_RGB_TRIPLET(); if (!DecodeByte(ref plet.B)) { return(false); } if (!DecodeByte(ref plet.G)) { return(false); } if (!DecodeByte(ref plet.R)) { return(false); } rlexByteCount -= 3; pletList.Add(plet); } rlex.paletteEntries = pletList.ToArray(); // decode rlex segments List <CLEARCODEC_SUBCODEC_RLEX_SEGMENT> segList = new List <CLEARCODEC_SUBCODEC_RLEX_SEGMENT>(); while (rlexByteCount > 0) { CLEARCODEC_SUBCODEC_RLEX_SEGMENT rlex_seg = new CLEARCODEC_SUBCODEC_RLEX_SEGMENT(); byte decodedBytes = DecodeRlexSeg(bitNum, ref rlex_seg); if (decodedBytes == 0) { return(false); } rlexByteCount -= decodedBytes; segList.Add(rlex_seg); } if (rlexByteCount < 0) { return(false); } rlex.segments = segList.ToArray(); return(true); }
/// <summary> /// Encode a bitmap with RLEX method /// </summary> /// <param name="subcodeBmp">The bitmap to be encoded in subcodec layer.</param> /// <return> > 0 if encode success, otherwise return 0 </return> public static bool RlexEncode(Bitmap subcodecBmp, ref CLEARCODEC_SUBCODEC_RLEX rlex) { if (subcodecBmp == null) { return(false); } Dictionary <RLEX_RGB_TRIPLET, byte> pletteDict = GetTripletDict(subcodecBmp); // if the bitmap color number is bigger than 255, RLEX subcodec encoding can't be applied. if (pletteDict.Count() > 0xff) { return(false); } rlex.paletteCount = (byte)pletteDict.Count(); rlex.paletteEntries = new RLEX_RGB_TRIPLET[rlex.paletteCount]; int index = 0; foreach (KeyValuePair <RLEX_RGB_TRIPLET, byte> triPlette in pletteDict) { rlex.paletteEntries[index] = triPlette.Key; index++; } List <CLEARCODEC_SUBCODEC_RLEX_SEGMENT> rlexSegList = new List <CLEARCODEC_SUBCODEC_RLEX_SEGMENT>(); CLEARCODEC_SUBCODEC_RLEX_SEGMENT rlex_seg = new CLEARCODEC_SUBCODEC_RLEX_SEGMENT(); rlex_seg.suiteDepth = 0; // we always set suite depth is 0 due to only 1 color in a suite rlex_seg.stopIndex = ColorToPletIdx(subcodecBmp.GetPixel(0, 0), pletteDict); rlex_seg.runLengthFactor = 0; // the first pixel in blow loop is at (0, 0), rlfactor is init as 0 here. for (int y = 0; y < subcodecBmp.Height; y++) { for (int x = 0; x < subcodecBmp.Width; x++) { if (x == 0 && y == 0) { continue; // skip the pixel (0, 0) } Color pixelColor = subcodecBmp.GetPixel(x, y); byte pletIdx = ColorToPletIdx(pixelColor, pletteDict); if (rlex_seg.stopIndex == pletIdx) // same color as previous one { rlex_seg.runLengthFactor++; } else { // add old structure into list rlexSegList.Add(rlex_seg); // create a new structure for the pixel rlex_seg = new CLEARCODEC_SUBCODEC_RLEX_SEGMENT(); rlex_seg.suiteDepth = 0; rlex_seg.stopIndex = pletIdx; rlex_seg.runLengthFactor = 0; } } } // add the final structure into list rlexSegList.Add(rlex_seg); rlex.segments = rlexSegList.ToArray(); return(true); }