/// <summary> /// Convert CLEARCODEC_SUBCODEC_RLEX structure into byte stream. /// </summary> /// <param name="rlex">The encoded CLEARCODEC_SUBCODEC_RLEX structure.</param> public byte[] ToBytes(CLEARCODEC_SUBCODEC_RLEX rlex) { List <byte> bufList = new List <byte>(); if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Band_Subcodec_IncorrectPaletteCount) { bufList.AddRange(TypeMarshal.ToBytes <byte>(rlex.paletteCount)); } else { bufList.AddRange(TypeMarshal.ToBytes <byte>((byte)(rlex.paletteCount + 1))); } for (int i = 0; i < rlex.paletteEntries.Count(); i++) { bufList.AddRange(TypeMarshal.ToBytes <byte>(rlex.paletteEntries[i].B)); bufList.AddRange(TypeMarshal.ToBytes <byte>(rlex.paletteEntries[i].G)); bufList.AddRange(TypeMarshal.ToBytes <byte>(rlex.paletteEntries[i].R)); } // Blow encode rlex segment. // Calculate bit number for stopIndex. byte bitNum = 0; byte count = (byte)(rlex.paletteCount - 1); while (count > 0) { bitNum++; count >>= 1; } for (int i = 0; i < rlex.segments.Count(); i++) { byte stopIdx_suiteDepth = (byte)(rlex.segments[i].stopIndex | (rlex.segments[i].suiteDepth << bitNum)); bufList.AddRange(TypeMarshal.ToBytes <byte>(stopIdx_suiteDepth)); if (rlex.segments[i].runLengthFactor < 0xff) { bufList.AddRange(TypeMarshal.ToBytes <byte>((byte)rlex.segments[i].runLengthFactor)); } else if (rlex.segments[i].runLengthFactor < 0xffff) { bufList.AddRange(TypeMarshal.ToBytes <byte>((byte)0xff)); bufList.AddRange(TypeMarshal.ToBytes <ushort>((ushort)rlex.segments[i].runLengthFactor)); } else { bufList.AddRange(TypeMarshal.ToBytes <byte>((byte)0xff)); bufList.AddRange(TypeMarshal.ToBytes <ushort>((ushort)0xffff)); bufList.AddRange(TypeMarshal.ToBytes <uint>((uint)rlex.segments[i].runLengthFactor)); } } return(bufList.ToArray()); }
/// <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; }
/// <summary> /// Convert CLEARCODEC_SUBCODEC_RLEX structure into byte stream. /// </summary> /// <param name="rlex">The encoded CLEARCODEC_SUBCODEC_RLEX structure.</param> public byte[] ToBytes(CLEARCODEC_SUBCODEC_RLEX rlex) { List<byte> bufList = new List<byte>(); if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Band_Subcodec_IncorrectPaletteCount) { bufList.AddRange(TypeMarshal.ToBytes<byte>(rlex.paletteCount)); } else { bufList.AddRange(TypeMarshal.ToBytes<byte>((byte)(rlex.paletteCount + 1))); } for (int i = 0; i < rlex.paletteEntries.Count(); i++) { bufList.AddRange(TypeMarshal.ToBytes<byte>(rlex.paletteEntries[i].B)); bufList.AddRange(TypeMarshal.ToBytes<byte>(rlex.paletteEntries[i].G)); bufList.AddRange(TypeMarshal.ToBytes<byte>(rlex.paletteEntries[i].R)); } // Blow encode rlex segment. // Calculate bit number for stopIndex. byte bitNum = 0; byte count = (byte)(rlex.paletteCount - 1); while (count > 0) { bitNum++; count >>= 1; } for (int i = 0; i < rlex.segments.Count(); i++) { byte stopIdx_suiteDepth = (byte)(rlex.segments[i].stopIndex | (rlex.segments[i].suiteDepth << bitNum)); bufList.AddRange(TypeMarshal.ToBytes<byte>(stopIdx_suiteDepth)); if (rlex.segments[i].runLengthFactor < 0xff) { bufList.AddRange(TypeMarshal.ToBytes<byte>((byte)rlex.segments[i].runLengthFactor)); } else if (rlex.segments[i].runLengthFactor < 0xffff) { bufList.AddRange(TypeMarshal.ToBytes<byte>((byte)0xff)); bufList.AddRange(TypeMarshal.ToBytes<ushort>((ushort)rlex.segments[i].runLengthFactor)); } else { bufList.AddRange(TypeMarshal.ToBytes<byte>((byte)0xff)); bufList.AddRange(TypeMarshal.ToBytes<ushort>((ushort)0xffff)); bufList.AddRange(TypeMarshal.ToBytes<uint>((uint)rlex.segments[i].runLengthFactor)); } } return bufList.ToArray(); }
/// <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); }