// -------------------------------------------------------------- #region PUBLIC FUNCTIONS // -------------------------------------------------------------- /// <summary> /// Load the frame image /// </summary> /// <param name="_ImageData">Byte array to read</param> /// <param name="_ImageDataOffset">Data offset</param> /// <param name="m_Colours">Colors table to use</param> public void LoadFrameImage(byte[] _ImageData, long _ImageDataOffset, List <ColourEntry> m_Colours) { // create the VD image data array (in case we want to save the image in VD later) m_VDImageData = new string[m_width, m_height]; // create the basic image m_image = new DirectBitmap(m_width, m_height); // get the current byte index int currByte = (int)((long)DataOffset - _ImageDataOffset); // starting x and y coordinates for drawing pixels int curx = 0; int cury = 0; // are we still within the image boundries? while (cury < m_height) { // get the next byte byte curr = _ImageData[currByte++]; // are we positioned before the header? if (curr < (byte)128) { // move to the correct starting point for ( ; curr > (byte)0; curr--) { NextCoordinate(ref curx, ref cury, m_width, m_height); } } else // correct position { // get the next byte byte next = _ImageData[currByte++]; // calculate the factors int factor1 = (int)next / 16; int factor2 = (int)next % 16; // is the factor greater than 0? if (factor1 > 0) { // combine the colors Color color = CombineColors(m_Colours[(int)_ImageData[currByte++]].Pixel, m_image.GetPixel(curx, cury), factor1); // color the pixel m_image.SetPixel(curx, cury, color); // flag that this pixel is used (for VD save) m_VDImageData[curx, cury] = "1"; // get the next coordinate in the image NextCoordinate(ref curx, ref cury, m_width, m_height); } // scan the other bytes for (byte i = (byte)((uint)curr - 128U); i > (byte)0; i--) { // get the pixel color Color pixel = m_Colours[(int)_ImageData[currByte++]].Pixel; // set the color to the image m_image.SetPixel(curx, cury, pixel); // flag that this pixel is used (for VD save) m_VDImageData[curx, cury] = "1"; // move to the next coordinate in the image NextCoordinate(ref curx, ref cury, m_width, m_height); } // is the second factor greater than 0? if (factor2 > 0) { // combine the colors Color color = CombineColors(m_Colours[(int)_ImageData[currByte++]].Pixel, m_image.GetPixel(curx, cury), factor2); // color the pixel m_image.SetPixel(curx, cury, color); // flag that this pixel is used (for VD save) m_VDImageData[curx, cury] = "1"; // get the next coordinate in the image NextCoordinate(ref curx, ref cury, m_width, m_height); } } } }
/// <summary> /// Floodfill gray pixels in an image /// </summary> /// <param name="bmp">Image to parse</param> /// <param name="pt">Starting point (must be gray)</param> /// <param name="levels">Hue colors table</param> /// <param name="handled">List of all the pixels already done</param> private static void FloodFillGrayPixels(DirectBitmap bmp, Point pt, List <Color> levels, ref List <Point> handled) { // create a points queue Queue <Point> q = new Queue <Point>(); // add the current point to the queue q.Enqueue(pt); // keep going until the queue is empty while (q.Count > 0) { // get the first point Point n = q.Dequeue(); // get the color for the current pixel Color currColor = bmp.GetPixel(n.X, n.Y); // if the pixel is not gray or is already been handled, we can get out (we also skil black and transparent colors) if (!(currColor.R == currColor.G && currColor.R == currColor.B) || ColorMatch(currColor, Color.Black) || ColorMatch(currColor, Color.FromArgb(0, 0, 0, 0)) || handled.Contains(pt)) { return; } // get the next point Point w = n, e = new Point(n.X + 1, n.Y); // keep going until the colors are within the threshold or we reach the beginning of the line while ((w.X >= 0) && IsPixelGrayScale(bmp.GetPixel(w.X, w.Y))) { // replace the pixel color bmp.SetPixel(w.X, w.Y, levels[bmp.GetPixel(w.X, w.Y).B]); // add the pixel to the list of the handled ones if (!handled.Contains(w)) { handled.Add(w); } // if the previous pixel is grayscale, we put that in the queue if ((w.Y > 0) && IsPixelGrayScale(bmp.GetPixel(w.X, w.Y - 1))) { q.Enqueue(new Point(w.X, w.Y - 1)); } // if the next pixel is grayscale, we put that in the queue if ((w.Y < bmp.Height - 1) && IsPixelGrayScale(bmp.GetPixel(w.X, w.Y + 1))) { q.Enqueue(new Point(w.X, w.Y + 1)); } // move backwards in the line w.X--; } // keep going until the colors are within the threshold or we reach the end of the line while ((e.X <= bmp.Width - 1) && IsPixelGrayScale(bmp.GetPixel(e.X, e.Y))) { // replace the pixel color bmp.SetPixel(e.X, e.Y, levels[bmp.GetPixel(e.X, e.Y).B]); // add the pixel to the list of the handled ones if (!handled.Contains(e)) { handled.Add(e); } // check the pixel on the previous line, if it matches, we add it to the queue if ((e.Y > 0) && IsPixelGrayScale(bmp.GetPixel(e.X, e.Y - 1))) { q.Enqueue(new Point(e.X, e.Y - 1)); } // check the pixel in the next line, if it matches, we add it to the queue if ((e.Y < bmp.Height - 1) && IsPixelGrayScale(bmp.GetPixel(e.X, e.Y + 1))) { q.Enqueue(new Point(e.X, e.Y + 1)); } // move forward along the line e.X++; } } }