/// <summary> /// Encode a bitmap with Run-length format /// </summary> /// <param name="resBmp">The bitmap to be encoded in residual layer.</param> public static CLEARCODEC_RESIDUAL_DATA Encode(Bitmap resBmp) { CLEARCODEC_RESIDUAL_DATA resData = new CLEARCODEC_RESIDUAL_DATA(); List <CLEARCODEC_RGB_RUN_SEGMENT> resRLSegList = new List <CLEARCODEC_RGB_RUN_SEGMENT>(); Color compColor = resBmp.GetPixel(0, 0); uint count = 0; for (ushort y = 0; y < resBmp.Height; y++) { for (ushort x = 0; x < resBmp.Width; x++) { Color pixelColor = resBmp.GetPixel(x, y); if (compColor.Equals(pixelColor)) { count++; } else { // add old compared color with repeate count into list addPixelToRLSegList(resRLSegList, compColor, count); // reset to new compare color and count. compColor = pixelColor; count = 1; } } } // add the last color RL seg here addPixelToRLSegList(resRLSegList, compColor, count); resData.resRLSegArr = resRLSegList.ToArray(); return(resData); }
/// <summary> /// It decode byte stream into CLEARCODEC_RESIDUAL_DATA structure /// </summary> /// <param name = "residualSegs"> the structure that decode result save to </param> /// <return> true if decode success, otherwise return false </return> public bool Decode(ref CLEARCODEC_RESIDUAL_DATA residualSegs) { if (decodeData == null) return false; List<CLEARCODEC_RGB_RUN_SEGMENT> segList = new List<CLEARCODEC_RGB_RUN_SEGMENT>(); while (offset < decodeData.Count()) { CLEARCODEC_RGB_RUN_SEGMENT runSeg = new CLEARCODEC_RGB_RUN_SEGMENT(); if (!DecodeByte(ref runSeg.buleValue)) return false; if (!DecodeByte(ref runSeg.greenValue)) return false; if (!DecodeByte(ref runSeg.redValue)) return false; // decode rlfactor if (!DecodeRulLengthFactor(ref runSeg.rlFactor)) return false; segList.Add(runSeg); } residualSegs.resRLSegArr = segList.ToArray(); return true; }
/// <summary> /// It decode byte stream into CLEARCODEC_RESIDUAL_DATA structure /// </summary> /// <param name = "residualSegs"> the structure that decode result save to </param> /// <return> true if decode success, otherwise return false </return> public bool Decode(ref CLEARCODEC_RESIDUAL_DATA residualSegs) { if (decodeData == null) { return(false); } List <CLEARCODEC_RGB_RUN_SEGMENT> segList = new List <CLEARCODEC_RGB_RUN_SEGMENT>(); while (offset < decodeData.Count()) { CLEARCODEC_RGB_RUN_SEGMENT runSeg = new CLEARCODEC_RGB_RUN_SEGMENT(); if (!DecodeByte(ref runSeg.buleValue)) { return(false); } if (!DecodeByte(ref runSeg.greenValue)) { return(false); } if (!DecodeByte(ref runSeg.redValue)) { return(false); } // decode rlfactor if (!DecodeRulLengthFactor(ref runSeg.rlFactor)) { return(false); } segList.Add(runSeg); } residualSegs.resRLSegArr = segList.ToArray(); return(true); }
/// <summary> /// Convert encoded residual layer structure into byte stream. /// </summary> /// <param name = "resData">The structure data to be converted into byte stream.</param> public byte[] ToBytes(CLEARCODEC_RESIDUAL_DATA resData) { if (resData.resRLSegArr == null) return null; List<byte> bufList = new List<byte>(); for (int i = 0; i < resData.resRLSegArr.Count(); i++) { CLEARCODEC_RGB_RUN_SEGMENT seg = resData.resRLSegArr[i]; bufList.AddRange(TypeMarshal.ToBytes<byte>(seg.buleValue)); bufList.AddRange(TypeMarshal.ToBytes<byte>(seg.greenValue)); bufList.AddRange(TypeMarshal.ToBytes<byte>(seg.redValue)); if (ccTestType == RdpegfxNegativeTypes.ClearCodec_Residual_ZeroRunLengthFactor) { bufList.AddRange(TypeMarshal.ToBytes<byte>(0x00)); break; } if (seg.rlFactor < 255) // RLF1 exists, RLF2 & 3 doesn't exit. { bufList.AddRange(TypeMarshal.ToBytes<byte>((byte)seg.rlFactor)); } else if (seg.rlFactor < 65535) // RLF1 is 0xff, RLF2 exists, RLF3 doesn't exit. { if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Residual_RedundantRunLengthFactor2) { bufList.AddRange(TypeMarshal.ToBytes<byte>(0xff)); } else { bufList.AddRange(TypeMarshal.ToBytes<byte>(0xf0)); } if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Residual_AbsentRunLengthFactor2) { bufList.AddRange(TypeMarshal.ToBytes<ushort>((ushort)seg.rlFactor)); } } else // RLF1 is 0xff, RLF2 is 0xffff, RLF3 exists. { if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Residual_RedundantRunLengthFactor2) { bufList.AddRange(TypeMarshal.ToBytes<byte>(0xff)); } else { bufList.AddRange(TypeMarshal.ToBytes<byte>(0xf0)); } if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Residual_RedundantRunLengthFactor3) { bufList.AddRange(TypeMarshal.ToBytes<ushort>(0xffff)); } else { bufList.AddRange(TypeMarshal.ToBytes<ushort>(0xf0f0)); // Change RLF3 highest byte to avoid RLF3 is parsed into a color(3 bytes) plus RLF1=0 // when RLF1 is zero, all the left area will be filled by the color, no error triggers. seg.rlFactor |= 0xf0000000; } if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Residual_AbsentRunLengthFactor3) { bufList.AddRange(TypeMarshal.ToBytes<uint>((uint)seg.rlFactor)); } } } return bufList.ToArray(); }
/// <summary> /// Encode a bitmap with Run-length format /// </summary> /// <param name="resBmp">The bitmap to be encoded in residual layer.</param> public static CLEARCODEC_RESIDUAL_DATA Encode(Bitmap resBmp) { CLEARCODEC_RESIDUAL_DATA resData = new CLEARCODEC_RESIDUAL_DATA(); List<CLEARCODEC_RGB_RUN_SEGMENT> resRLSegList = new List<CLEARCODEC_RGB_RUN_SEGMENT>(); Color compColor = resBmp.GetPixel(0, 0); uint count = 0; for (ushort y = 0; y < resBmp.Height; y++) { for (ushort x = 0; x < resBmp.Width; x++) { Color pixelColor = resBmp.GetPixel(x, y); if (compColor.Equals(pixelColor)) { count++; } else { // add old compared color with repeate count into list addPixelToRLSegList(resRLSegList, compColor, count); // reset to new compare color and count. compColor = pixelColor; count = 1; } } } // add the last color RL seg here addPixelToRLSegList(resRLSegList, compColor, count); resData.resRLSegArr = resRLSegList.ToArray(); return resData; }
/// <summary> /// Encode the residual, band, and subcodec layer images into a bytestream. /// </summary> public byte[] EncodeCompositePayload() { List <byte> buf = new List <byte>(); if (resBmp != null) { CLEARCODEC_RESIDUAL_DATA resData = ClearCodecResidualEncoder.Encode(resBmp); compPayload.residualData = ToBytes(resData); if (compPayload.residualData == null) { return(null); } compPayload.residualByteCount = (uint)compPayload.residualData.Count(); } else { compPayload.residualByteCount = 0; compPayload.residualData = null; } if (bandDict.Count() != 0) // Band image are loaded before. { ClearCodecBandEncoder bandencoder = ClearCodecBandEncoder.GetInstance(); if ((this.flags & ClearCodec_BitmapStream.CLEARCODEC_FLAG_CACHE_RESET) != 0) { bandencoder.ResetVBarStorage(); } CLEARCODEC_BAND_DATA bandsData = bandencoder.Encode(bandDict); compPayload.bandData = ToBytes(bandsData); if (compPayload.bandData == null) { return(null); } compPayload.bandByteCount = (uint)compPayload.bandData.Count(); } else { compPayload.bandByteCount = 0; compPayload.bandData = null; } if (subcodecDict.Count() != 0) // Subcodec image are loaded before. { CLEARCODEC_SUBCODEC_DATA subcodecs = ClearCodecSubCodecEncoder.Encode(subcodecDict); compPayload.subcodecData = ToBytes(subcodecs); if (compPayload.subcodecData == null) { return(null); } compPayload.subcodecByteCount = (uint)compPayload.subcodecData.Count(); } else { compPayload.subcodecByteCount = 0; compPayload.subcodecData = null; } buf.AddRange(TypeMarshal.ToBytes <uint>(compPayload.residualByteCount)); buf.AddRange(TypeMarshal.ToBytes <uint>(compPayload.bandByteCount)); buf.AddRange(TypeMarshal.ToBytes <uint>(compPayload.subcodecByteCount)); if (compPayload.residualByteCount > 0) { buf.AddRange(compPayload.residualData); } if (compPayload.bandByteCount > 0) { buf.AddRange(compPayload.bandData); } if (compPayload.subcodecByteCount > 0) { buf.AddRange(compPayload.subcodecData); } return(buf.ToArray()); }
/// <summary> /// Convert encoded residual layer structure into byte stream. /// </summary> /// <param name = "resData">The structure data to be converted into byte stream.</param> public byte[] ToBytes(CLEARCODEC_RESIDUAL_DATA resData) { if (resData.resRLSegArr == null) { return(null); } List <byte> bufList = new List <byte>(); for (int i = 0; i < resData.resRLSegArr.Count(); i++) { CLEARCODEC_RGB_RUN_SEGMENT seg = resData.resRLSegArr[i]; bufList.AddRange(TypeMarshal.ToBytes <byte>(seg.buleValue)); bufList.AddRange(TypeMarshal.ToBytes <byte>(seg.greenValue)); bufList.AddRange(TypeMarshal.ToBytes <byte>(seg.redValue)); if (ccTestType == RdpegfxNegativeTypes.ClearCodec_Residual_ZeroRunLengthFactor) { bufList.AddRange(TypeMarshal.ToBytes <byte>(0x00)); break; } if (seg.rlFactor < 255) // RLF1 exists, RLF2 & 3 doesn't exit. { bufList.AddRange(TypeMarshal.ToBytes <byte>((byte)seg.rlFactor)); } else if (seg.rlFactor < 65535) // RLF1 is 0xff, RLF2 exists, RLF3 doesn't exit. { if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Residual_RedundantRunLengthFactor2) { bufList.AddRange(TypeMarshal.ToBytes <byte>(0xff)); } else { bufList.AddRange(TypeMarshal.ToBytes <byte>(0xf0)); } if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Residual_AbsentRunLengthFactor2) { bufList.AddRange(TypeMarshal.ToBytes <ushort>((ushort)seg.rlFactor)); } } else // RLF1 is 0xff, RLF2 is 0xffff, RLF3 exists. { if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Residual_RedundantRunLengthFactor2) { bufList.AddRange(TypeMarshal.ToBytes <byte>(0xff)); } else { bufList.AddRange(TypeMarshal.ToBytes <byte>(0xf0)); } if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Residual_RedundantRunLengthFactor3) { bufList.AddRange(TypeMarshal.ToBytes <ushort>(0xffff)); } else { bufList.AddRange(TypeMarshal.ToBytes <ushort>(0xf0f0)); // Change RLF3 highest byte to avoid RLF3 is parsed into a color(3 bytes) plus RLF1=0 // when RLF1 is zero, all the left area will be filled by the color, no error triggers. seg.rlFactor |= 0xf0000000; } if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Residual_AbsentRunLengthFactor3) { bufList.AddRange(TypeMarshal.ToBytes <uint>((uint)seg.rlFactor)); } } } return(bufList.ToArray()); }