示例#1
0
        /// <summary>
        /// It decode byte stream into CLEARCODEC_VBAR structure
        /// </summary>
        /// <param name = "bandVBar"> The structure that decode result save to. </param>
        public bool DecodeBandVBar(ref CLEARCODEC_VBAR bandVBar)
        {
            ushort vBarStat = 0;

            if (!DecodeUShort(ref vBarStat))
            {
                return(false);
            }

            if ((vBarStat & 0x8000) != 0)  // VBAR_CACHE_HIT structure
            {
                bandVBar.type = VBAR_TYPE.VBAR_CACHE_HIT;
                bandVBar.vbarCacheHit.vBarIndex_x = vBarStat;
            }
            else if ((vBarStat & 0xc000) != 0)  // SHORT_VBAR_CACHE_HIT structure
            {
                bandVBar.type = VBAR_TYPE.SHORT_VBAR_CACHE_HIT;
                bandVBar.shortVbarCacheHit.shortVBarIndex_x = vBarStat;
                if (!DecodeByte(ref bandVBar.shortVbarCacheHit.shortVBarYOn))
                {
                    return(false);
                }
            }
            else  // Must be SHORT_VBAR_CACHE_MISS structure.
            {
                bandVBar.type = VBAR_TYPE.SHORT_VBAR_CACHE_MISS;
                bandVBar.shortVbarCacheMiss.shortVBarYOnOff_x = vBarStat;
                byte pixelCount = (byte)(bandVBar.shortVbarCacheMiss.shortVBarYOff - bandVBar.shortVbarCacheMiss.shortVBarYOn);

                // Decode shortVBarPixels.
                List <Color_RGB> shortVBarPixelList = new List <Color_RGB>();
                for (int i = 0; i < pixelCount; i++)
                {
                    Color_RGB rgb = new Color_RGB();
                    if (!DecodeByte(ref rgb.B))
                    {
                        return(false);
                    }
                    if (!DecodeByte(ref rgb.G))
                    {
                        return(false);
                    }
                    if (!DecodeByte(ref rgb.R))
                    {
                        return(false);
                    }
                    shortVBarPixelList.Add(rgb);
                }

                bandVBar.shortVbarCacheMiss.shortVBarPixels = shortVBarPixelList.ToArray();
            }
            return(true);
        }
        /// <summary>
        /// Convert encoded band layer structure into byte stream.
        /// </summary>
        /// <param name = "bandData">The structure data to be converted into byte stream.</param>
        public byte[] ToBytes(CLEARCODEC_BAND bandData)
        {
            List <byte> bufList = new List <byte>();

            bufList.AddRange(TypeMarshal.ToBytes <ushort>(bandData.xStart));
            bufList.AddRange(TypeMarshal.ToBytes <ushort>(bandData.xEnd));
            bufList.AddRange(TypeMarshal.ToBytes <ushort>(bandData.yStart));
            bufList.AddRange(TypeMarshal.ToBytes <ushort>(bandData.yEnd));

            bufList.AddRange(TypeMarshal.ToBytes <byte>(bandData.blueBkg));
            bufList.AddRange(TypeMarshal.ToBytes <byte>(bandData.greenBkg));
            bufList.AddRange(TypeMarshal.ToBytes <byte>(bandData.redBkg));

            for (int i = 0; i < bandData.vBars.Count(); i++)
            {
                if (bandData.vBars[i].type == VBAR_TYPE.VBAR_CACHE_HIT)  // 1 bit check.
                {
                    VBAR_CACHE_HIT vbarCacheHit = bandData.vBars[i].vbarCacheHit;
                    bufList.AddRange(ToBytes(vbarCacheHit));

                    if (ccTestType == RdpegfxNegativeTypes.ClearCodec_Band_VBarCacheHit_ShortVBarPixelsExist)
                    {
                        // Add an additional pixel into encoded data.
                        Color_RGB pixel = new Color_RGB();
                        bufList.AddRange(TypeMarshal.ToBytes <byte>(pixel.B));
                        bufList.AddRange(TypeMarshal.ToBytes <byte>(pixel.G));
                        bufList.AddRange(TypeMarshal.ToBytes <byte>(pixel.R));
                    }
                }
                else if (bandData.vBars[i].type == VBAR_TYPE.SHORT_VBAR_CACHE_HIT)  // 2 bits check.
                {
                    SHORT_VBAR_CACHE_HIT svbarCacheHit = bandData.vBars[i].shortVbarCacheHit;
                    bufList.AddRange(ToBytes(svbarCacheHit));

                    if (ccTestType == RdpegfxNegativeTypes.ClearCodec_Band_ShortVBarCacheHit_ShortVBarPixelsExist)
                    {
                        // add an additional pixel into encoded data
                        Color_RGB pixel = new Color_RGB();
                        bufList.AddRange(TypeMarshal.ToBytes <byte>(pixel.B));
                        bufList.AddRange(TypeMarshal.ToBytes <byte>(pixel.G));
                        bufList.AddRange(TypeMarshal.ToBytes <byte>(pixel.R));
                    }
                }
                else if (bandData.vBars[i].type == VBAR_TYPE.SHORT_VBAR_CACHE_MISS)  // 2 bits check.
                {
                    SHORT_VBAR_CACHE_MISS svbarCacheMiss = bandData.vBars[i].shortVbarCacheMiss;
                    bufList.AddRange(ToBytes(svbarCacheMiss));
                }
            }
            return(bufList.ToArray());
        }
 /// <summary>
 /// It decode rawDataCount bytes data into RLEX_RGB_TRIPLET structure array
 /// </summary>
 /// <param name = "rawDataCount"> the number of bytes to be decoeded as raw bitmap </param>
 /// <param name = "bmpPixels"> the structure array that decode result save to </param>
 /// <return> > true if decode success, otherwise return false </return>
 public bool DecodeRawData(uint rawDataCount, ref RLEX_RGB_TRIPLET[] bmpPixels)
 {
     List<RLEX_RGB_TRIPLET> pixelList = new List<RLEX_RGB_TRIPLET>();
     while (rawDataCount > 0)
     {
         RLEX_RGB_TRIPLET pixel = new RLEX_RGB_TRIPLET();
         if (!DecodeByte(ref pixel.B)) return false;
         if (!DecodeByte(ref pixel.G)) return false;
         if (!DecodeByte(ref pixel.R)) return false;
         rawDataCount -= 3;
         pixelList.Add(pixel);
     }
     if (rawDataCount < 0) return false;
     bmpPixels = pixelList.ToArray();
     return true;
 }
        /// <summary>
        /// Convert SHORT_VBAR_CACHE_MISS structure into byte stream.
        /// </summary>
        /// <param name = "cacheMiss"> the structure data to be converted into byte stream </param>
        public byte[] ToBytes(SHORT_VBAR_CACHE_MISS cacheMiss)
        {
            List <byte> bufList = new List <byte>();

            bufList.AddRange(TypeMarshal.ToBytes <ushort>(cacheMiss.shortVBarYOnOff_x));

            if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Band_ShortVBarCacheMiss_IncorrectPixelNumber)
            {
                if (cacheMiss.shortVBarPixels != null)
                {
                    for (int i = 0; i < cacheMiss.shortVBarPixels.Count(); i++)
                    {
                        Color_RGB pixel = cacheMiss.shortVBarPixels[i];
                        bufList.AddRange(TypeMarshal.ToBytes <byte>(pixel.B));
                        bufList.AddRange(TypeMarshal.ToBytes <byte>(pixel.G));
                        bufList.AddRange(TypeMarshal.ToBytes <byte>(pixel.R));
                    }
                }
            }

            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 
        /// </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 RawEncode(Bitmap subcodecBmp, ref RLEX_RGB_TRIPLET[] bmpPixels)
        {
            if (subcodecBmp == null) return false;

            List<RLEX_RGB_TRIPLET> pixelList = new List<RLEX_RGB_TRIPLET>();

            for (int y = 0; y < subcodecBmp.Height; y++)
            {
                for (int x = 0; x < subcodecBmp.Width; x++)
                {
                    Color pixelColor = subcodecBmp.GetPixel(x, y);
                    RLEX_RGB_TRIPLET rgbPlette = Convert2RGB(pixelColor);
                    pixelList.Add(rgbPlette);
                }
            }
            bmpPixels = pixelList.ToArray();
            return true ;
        }
 /// <summary>
 /// convert a color into RLEX_RGB_TRIPLET structure
 /// </summary>
 /// <param name="pixelColor">The color to be converted.</param>
 public static RLEX_RGB_TRIPLET Convert2RGB(Color pixelColor)
 {
     RLEX_RGB_TRIPLET rgbPlette = new RLEX_RGB_TRIPLET();
     rgbPlette.B = pixelColor.B;
     rgbPlette.G = pixelColor.G;
     rgbPlette.R = pixelColor.R;
     return rgbPlette;
 }
        /// <summary>
        /// It decode byte stream into CLEARCODEC_VBAR structure
        /// </summary>
        /// <param name = "bandVBar"> The structure that decode result save to. </param>
        public bool DecodeBandVBar(ref CLEARCODEC_VBAR bandVBar)
        {
            ushort vBarStat = 0;
            if (!DecodeUShort(ref vBarStat)) return false;

            if ((vBarStat & 0x8000) != 0)  // VBAR_CACHE_HIT structure
            {
                bandVBar.type = VBAR_TYPE.VBAR_CACHE_HIT;
                bandVBar.vbarCacheHit.vBarIndex_x = vBarStat;
            }
            else if ((vBarStat & 0xc000) != 0)  // SHORT_VBAR_CACHE_HIT structure
            {
                bandVBar.type = VBAR_TYPE.SHORT_VBAR_CACHE_HIT;
                bandVBar.shortVbarCacheHit.shortVBarIndex_x = vBarStat;
                if (!DecodeByte(ref bandVBar.shortVbarCacheHit.shortVBarYOn)) return false;
            }
            else  // Must be SHORT_VBAR_CACHE_MISS structure.
            {
                bandVBar.type = VBAR_TYPE.SHORT_VBAR_CACHE_MISS;
                bandVBar.shortVbarCacheMiss.shortVBarYOnOff_x = vBarStat;
                byte pixelCount = (byte)(bandVBar.shortVbarCacheMiss.shortVBarYOff - bandVBar.shortVbarCacheMiss.shortVBarYOn);

                // Decode shortVBarPixels.
                List<Color_RGB> shortVBarPixelList = new List<Color_RGB>();
                for (int i = 0; i < pixelCount; i++)
                {
                    Color_RGB rgb = new Color_RGB();
                    if (!DecodeByte(ref rgb.B)) return false;
                    if (!DecodeByte(ref rgb.G)) return false;
                    if (!DecodeByte(ref rgb.R)) return false;
                    shortVBarPixelList.Add(rgb);
                }

                bandVBar.shortVbarCacheMiss.shortVBarPixels = shortVBarPixelList.ToArray();
            }
            return true;
        }
        /// <summary>
        /// Encode a band bitmap into byte stream
        /// </summary>
        /// <param name="bandBmp">The bitmap to be encoded in band layer.</param>
        /// <param name="bandRect">The band position relative to bitmap left-top edge.</param>
        public CLEARCODEC_BAND EncodeBand(Bitmap bandBmp, ClearCodec_RECT16 bandRect)
        {
            CLEARCODEC_BAND bandData = new CLEARCODEC_BAND();

            Color bgColor = bandBmp.GetPixel(0, 0);

            bandData.xStart = bandRect.left;
            bandData.xEnd   = (ushort)(bandRect.right - 1);
            bandData.yStart = bandRect.top;
            bandData.yEnd   = (ushort)(bandRect.bottom - 1);

            bandData.blueBkg  = bgColor.B;
            bandData.greenBkg = bgColor.G;
            bandData.redBkg   = bgColor.R;

            List <CLEARCODEC_VBAR> vBarList = new List <CLEARCODEC_VBAR>();

            // use short vbar cache miss method
            for (ushort x = 0; x < bandBmp.Width; x++)
            {
                byte shortVBarYOn  = 0; // relative to top of V-Bar, won't excceed 52
                byte shortVBarYOff = 0; // relative to top of V-Bar, won't excceed 52

                // find shortVBarYOn from top
                byte y;  // bandBmp.Height can't exceed 52 pixels
                for (y = 0; y < bandBmp.Height; y++)
                {
                    Color pixelColor = bandBmp.GetPixel(x, y);
                    if (!bgColor.Equals(pixelColor))
                    {
                        shortVBarYOn = (byte)y;
                        break;
                    }
                }

                // the whole vbar use bgColor
                if (y == (ushort)bandBmp.Height)
                {
                    shortVBarYOn  = (byte)y;
                    shortVBarYOff = (byte)y;
                }

                // find shortVBarYOff from bottem, which is the first position for left bgcolor
                for (y = (byte)(bandBmp.Height - 1); y > shortVBarYOn; y--)
                {
                    Color pixelColor = bandBmp.GetPixel(x, y);
                    if (!bgColor.Equals(pixelColor))
                    {
                        shortVBarYOff = (byte)(y + 1);
                        break;
                    }
                }

                // only one point in shortVBar is different from bgColor
                if (y == shortVBarYOn)
                {
                    shortVBarYOff = (byte)(shortVBarYOn + 1);
                }

                // construct short Vbar Pixels

                List <Color_RGB> shortVBarPixelList = new List <Color_RGB>();
                for (y = shortVBarYOn; y < shortVBarYOff; y++)
                {
                    Color     pixelColor = bandBmp.GetPixel(x, y);
                    Color_RGB svbarColor = new Color_RGB();
                    svbarColor.B = pixelColor.B;
                    svbarColor.G = pixelColor.G;
                    svbarColor.R = pixelColor.R;

                    shortVBarPixelList.Add(svbarColor);
                }

                // construct vbar pixels
                List <Color_RGB> vBarPixelList = new List <Color_RGB>();
                for (int k = 0; k < bandBmp.Height; k++)
                {
                    Color     pixelColor = bandBmp.GetPixel(x, k);
                    Color_RGB vbarColor  = new Color_RGB();
                    vbarColor.B = pixelColor.B;
                    vbarColor.G = pixelColor.G;
                    vbarColor.R = pixelColor.R;
                    vBarPixelList.Add(vbarColor);
                }

                // check if vbar or short vbar cache matched
                ushort vbarIdx = GetVbarIndex(vBarPixelList);
                if (vbarIdx != 0xffff)
                {
                    // use cache index
                    CLEARCODEC_VBAR vBar = new CLEARCODEC_VBAR();
                    vBar.type                   = VBAR_TYPE.VBAR_CACHE_HIT;
                    vBar.vbarCacheHit.x         = 0x1;
                    vBar.vbarCacheHit.vBarIndex = vbarIdx;

                    vBarList.Add(vBar);

                    continue;
                }
                else
                {
                    vBarDict.Add(vBarPixelList, vBarCursor);
                    vBarCursor = (ushort)((vBarCursor + 1) % CLEARCODEC_CONST.CLEARCODEC_BAND_MAX_VBAR_CACHE_SLOT);
                }

                // cechk short vbar cache
                ushort shortvbarIdx = GetShortVbarIndex(shortVBarPixelList);
                if (shortvbarIdx != 0xffff)
                {
                    // use short vbar cache index
                    CLEARCODEC_VBAR svBar = new CLEARCODEC_VBAR();
                    svBar.type = VBAR_TYPE.SHORT_VBAR_CACHE_HIT;
                    svBar.shortVbarCacheHit.x = 0x1;
                    svBar.shortVbarCacheHit.shortVBarIndex = shortvbarIdx;
                    svBar.shortVbarCacheHit.shortVBarYOn   = shortVBarYOn;

                    vBarList.Add(svBar);
                    continue;
                }
                else
                {
                    // add short vbar into cache dictionary and send the short vbar vbar in SHORT_VBAR_CACHE_MISS structure later.
                    shortvBarDict.Add(shortVBarPixelList, shortvBarCursor);
                    shortvBarCursor = (ushort)((shortvBarCursor + 1) % CLEARCODEC_CONST.CLEARCODEC_BAND_MAX_SHORT_VBAR_CACHE_SLOT);
                }


                // get to here mean no vbar or short vbar cache hit
                CLEARCODEC_VBAR vBarUncache = new CLEARCODEC_VBAR();
                vBarUncache.type = VBAR_TYPE.SHORT_VBAR_CACHE_MISS;
                vBarUncache.shortVbarCacheMiss.x = 0x0;

                // pack data into vBar.shortVbarCacheMiss
                vBarUncache.shortVbarCacheMiss.shortVBarYOn  = shortVBarYOn;
                vBarUncache.shortVbarCacheMiss.shortVBarYOff = shortVBarYOff;
                if (shortVBarYOff > shortVBarYOn)
                {
                    vBarUncache.shortVbarCacheMiss.shortVBarPixels = shortVBarPixelList.ToArray();
                }

                vBarList.Add(vBarUncache);
            }

            bandData.vBars = vBarList.ToArray();

            return(bandData);
        }
        /// <summary>
        /// Convert RLEX_RGB_TRIPLET structure array into byte stream.
        /// </summary>
        /// <param name="bmpPixels">The encoded RLEX_RGB_TRIPLET structure Array.</param>
        public byte[] ToBytes(RLEX_RGB_TRIPLET[] bmpPixels)
        {
            List<byte> bufList = new List<byte>();
            if (bmpPixels == null) return null;

            for (int i = 0; i < bmpPixels.Count(); i++)
            {
                bufList.AddRange(TypeMarshal.ToBytes<byte>(bmpPixels[i].B));
                bufList.AddRange(TypeMarshal.ToBytes<byte>(bmpPixels[i].G));
                bufList.AddRange(TypeMarshal.ToBytes<byte>(bmpPixels[i].R));
            }

            return bufList.ToArray();
        }
        /// <summary>
        /// Convert encoded band layer structure into byte stream.
        /// </summary>
        /// <param name = "bandData">The structure data to be converted into byte stream.</param>
        public byte[] ToBytes(CLEARCODEC_BAND bandData)
        {
            List<byte> bufList = new List<byte>();

            bufList.AddRange(TypeMarshal.ToBytes<ushort>(bandData.xStart));
            bufList.AddRange(TypeMarshal.ToBytes<ushort>(bandData.xEnd));
            bufList.AddRange(TypeMarshal.ToBytes<ushort>(bandData.yStart));
            bufList.AddRange(TypeMarshal.ToBytes<ushort>(bandData.yEnd));

            bufList.AddRange(TypeMarshal.ToBytes<byte>(bandData.blueBkg));
            bufList.AddRange(TypeMarshal.ToBytes<byte>(bandData.greenBkg));
            bufList.AddRange(TypeMarshal.ToBytes<byte>(bandData.redBkg));

            for (int i = 0; i < bandData.vBars.Count(); i++)
            {
                if (bandData.vBars[i].type == VBAR_TYPE.VBAR_CACHE_HIT)  // 1 bit check.
                {
                    VBAR_CACHE_HIT vbarCacheHit = bandData.vBars[i].vbarCacheHit;
                    bufList.AddRange(ToBytes(vbarCacheHit));

                    if (ccTestType == RdpegfxNegativeTypes.ClearCodec_Band_VBarCacheHit_ShortVBarPixelsExist)
                    {
                        // Add an additional pixel into encoded data.
                        Color_RGB pixel = new Color_RGB();
                        bufList.AddRange(TypeMarshal.ToBytes<byte>(pixel.B));
                        bufList.AddRange(TypeMarshal.ToBytes<byte>(pixel.G));
                        bufList.AddRange(TypeMarshal.ToBytes<byte>(pixel.R));
                    }
                }
                else if (bandData.vBars[i].type == VBAR_TYPE.SHORT_VBAR_CACHE_HIT)  // 2 bits check.
                {
                    SHORT_VBAR_CACHE_HIT svbarCacheHit = bandData.vBars[i].shortVbarCacheHit;
                    bufList.AddRange(ToBytes(svbarCacheHit));

                    if (ccTestType == RdpegfxNegativeTypes.ClearCodec_Band_ShortVBarCacheHit_ShortVBarPixelsExist)
                    {
                        // add an additional pixel into encoded data
                        Color_RGB pixel = new Color_RGB();
                        bufList.AddRange(TypeMarshal.ToBytes<byte>(pixel.B));
                        bufList.AddRange(TypeMarshal.ToBytes<byte>(pixel.G));
                        bufList.AddRange(TypeMarshal.ToBytes<byte>(pixel.R));
                    }
                }
                else if (bandData.vBars[i].type == VBAR_TYPE.SHORT_VBAR_CACHE_MISS)  // 2 bits check.
                {
                    SHORT_VBAR_CACHE_MISS svbarCacheMiss = bandData.vBars[i].shortVbarCacheMiss;
                    bufList.AddRange(ToBytes(svbarCacheMiss));
                }
            }
            return bufList.ToArray();
        }
        /// <summary>
        /// Encode a band bitmap into byte stream
        /// </summary>
        /// <param name="bandBmp">The bitmap to be encoded in band layer.</param>
        /// <param name="bandRect">The band position relative to bitmap left-top edge.</param>
        public CLEARCODEC_BAND EncodeBand(Bitmap bandBmp, ClearCodec_RECT16 bandRect)
        {
            CLEARCODEC_BAND bandData = new CLEARCODEC_BAND();

            Color bgColor = bandBmp.GetPixel(0, 0);

            bandData.xStart = bandRect.left;
            bandData.xEnd = (ushort)(bandRect.right-1);
            bandData.yStart = bandRect.top;
            bandData.yEnd = (ushort)(bandRect.bottom-1);

            bandData.blueBkg = bgColor.B;
            bandData.greenBkg = bgColor.G;
            bandData.redBkg = bgColor.R;

            List<CLEARCODEC_VBAR> vBarList = new List<CLEARCODEC_VBAR>();

            // use short vbar cache miss method
            for (ushort x = 0; x < bandBmp.Width; x++)
            {
                byte shortVBarYOn = 0;  // relative to top of V-Bar, won't excceed 52
                byte shortVBarYOff = 0; // relative to top of V-Bar, won't excceed 52

                // find shortVBarYOn from top
                byte y;  // bandBmp.Height can't exceed 52 pixels
                for ( y = 0; y < bandBmp.Height; y++)
                {
                    Color pixelColor = bandBmp.GetPixel(x, y);
                    if (!bgColor.Equals(pixelColor))
                    {
                        shortVBarYOn = (byte)y;
                        break;
                    }
                }

                // the whole vbar use bgColor
                if (y == (ushort)bandBmp.Height)
                {
                    shortVBarYOn = (byte)y;
                    shortVBarYOff = (byte)y;
                }

                // find shortVBarYOff from bottem, which is the first position for left bgcolor
                for (y = (byte)(bandBmp.Height - 1); y > shortVBarYOn; y--)
                {
                    Color pixelColor = bandBmp.GetPixel(x, y);
                    if (!bgColor.Equals(pixelColor))
                    {
                        shortVBarYOff = (byte)(y + 1);
                        break;
                    }
                }

                // only one point in shortVBar is different from bgColor
                if (y == shortVBarYOn)
                {
                    shortVBarYOff = (byte)(shortVBarYOn + 1);
                }

                // construct short Vbar Pixels

                List<Color_RGB> shortVBarPixelList = new List<Color_RGB>();
                for (y = shortVBarYOn; y < shortVBarYOff; y++)
                {
                    Color pixelColor = bandBmp.GetPixel(x, y);
                    Color_RGB svbarColor = new Color_RGB();
                    svbarColor.B = pixelColor.B;
                    svbarColor.G = pixelColor.G;
                    svbarColor.R = pixelColor.R;

                    shortVBarPixelList.Add(svbarColor);
                }

                // construct vbar pixels
                List<Color_RGB> vBarPixelList = new List<Color_RGB>();
                for (int k = 0; k < bandBmp.Height; k++)
                {
                    Color pixelColor = bandBmp.GetPixel(x, k);
                    Color_RGB vbarColor = new Color_RGB();
                    vbarColor.B = pixelColor.B;
                    vbarColor.G = pixelColor.G;
                    vbarColor.R = pixelColor.R;
                    vBarPixelList.Add(vbarColor);
                }

                // check if vbar or short vbar cache matched
                ushort vbarIdx = GetVbarIndex(vBarPixelList);
                if (vbarIdx != 0xffff)
                {
                    // use cache index
                    CLEARCODEC_VBAR vBar = new CLEARCODEC_VBAR();
                    vBar.type = VBAR_TYPE.VBAR_CACHE_HIT;
                    vBar.vbarCacheHit.x = 0x1;
                    vBar.vbarCacheHit.vBarIndex = vbarIdx;

                    vBarList.Add(vBar);

                    continue;
                }
                else
                {
                    vBarDict.Add(vBarPixelList, vBarCursor);
                    vBarCursor = (ushort)((vBarCursor + 1) % CLEARCODEC_CONST.CLEARCODEC_BAND_MAX_VBAR_CACHE_SLOT);
                }

                // cechk short vbar cache
                ushort shortvbarIdx = GetShortVbarIndex(shortVBarPixelList);
                if (shortvbarIdx != 0xffff)
                {
                    // use short vbar cache index
                    CLEARCODEC_VBAR svBar = new CLEARCODEC_VBAR();
                    svBar.type = VBAR_TYPE.SHORT_VBAR_CACHE_HIT;
                    svBar.shortVbarCacheHit.x = 0x1;
                    svBar.shortVbarCacheHit.shortVBarIndex = shortvbarIdx;
                    svBar.shortVbarCacheHit.shortVBarYOn = shortVBarYOn;

                    vBarList.Add(svBar);
                    continue;
                }
                else
                {
                    // add short vbar into cache dictionary and send the short vbar vbar in SHORT_VBAR_CACHE_MISS structure later.
                    shortvBarDict.Add(shortVBarPixelList, shortvBarCursor);
                    shortvBarCursor = (ushort)((shortvBarCursor + 1) % CLEARCODEC_CONST.CLEARCODEC_BAND_MAX_SHORT_VBAR_CACHE_SLOT);
                }

                // get to here mean no vbar or short vbar cache hit
                CLEARCODEC_VBAR vBarUncache = new CLEARCODEC_VBAR();
                vBarUncache.type = VBAR_TYPE.SHORT_VBAR_CACHE_MISS;
                vBarUncache.shortVbarCacheMiss.x = 0x0;

                // pack data into vBar.shortVbarCacheMiss
                vBarUncache.shortVbarCacheMiss.shortVBarYOn = shortVBarYOn;
                vBarUncache.shortVbarCacheMiss.shortVBarYOff = shortVBarYOff;
                if (shortVBarYOff > shortVBarYOn )
                {
                    vBarUncache.shortVbarCacheMiss.shortVBarPixels = shortVBarPixelList.ToArray();
                }

                vBarList.Add(vBarUncache);
            }

            bandData.vBars = vBarList.ToArray();

            return bandData;
        }