Ejemplo n.º 1
0
        public bool CheckAndSplitMask(Bitmap mask, ColorMath math)
        {
            //array of with array for each line.
            //each line has entrys with the color and the start position of that color in that line
            ColPos[][] C_Arr = new ColPos[Scanlines][];

            BitmapData data = mask.LockBits(new Rectangle(new Point(0, 0), mask.Size), ImageLockMode.ReadWrite, mask.PixelFormat);

            byte[] bytes = new byte[data.Height * data.Stride];
            System.Runtime.InteropServices.Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);

            for (int y = 0; y < mask.Height; y++)
            {
                Color         ColorToCheck = BitmapEffects.GetPixel(data, bytes, 0, y);         //mask.GetPixel(0, y);
                List <ColPos> CList        = new List <ColPos>();
                CList.Add(new ColPos(ColorToCheck, 0));

                for (int x = 1; x < mask.Width; x++)
                {
                    Color c = BitmapEffects.GetPixel(data, bytes, x, y);
                    if (ColorToCheck == c)                     //mask.GetPixel(x, y))
                    {
                        continue;
                    }

                    ColorToCheck = c;                     //mask.GetPixel(x, y);
                    CList.Add(new ColPos(ColorToCheck, x));
                }
                C_Arr[y] = CList.ToArray();
            }

            mask.UnlockBits(data);

            //if more then two black/white transitions appear in (any) line
            bool black3 = C_Arr.Any((CA => CA.Count(c => c.Color.Name == "ff000000") > 2));
            bool white3 = C_Arr.Any((CA => CA.Count(c => c.Color.Name == "ffffffff") > 2));

            //3 transitions in both won't work eg. black-white-black-white-black-white
            if (black3 && white3)
            {
                return(false);
            }

            int[] BlackLines;
            int[] WhiteLines;

            //get all the lines with 3 black transitions.
            //can't be more then 3 because that would result in more then 3 white trans. in the same line.
            IEnumerable <ColPos[]> Puff = C_Arr.Where((CA => CA.Count(c => c.Color.Name == "ff000000") > 2));

            //an array of indeces to those lines.
            BlackLines = new int[Puff.Count()];
            int i = 0;

            foreach (ColPos[] cp in Puff)
            {
                BlackLines[i] = Array.IndexOf(C_Arr, cp);
                i++;
            }

            //same for white.
            Puff       = C_Arr.Where((CA => CA.Count(c => c.Color.Name == "ffffffff") > 2));
            WhiteLines = new int[Puff.Count()];
            i          = 0;
            foreach (ColPos[] cp in Puff)
            {
                WhiteLines[i] = Array.IndexOf(C_Arr, cp);
                i++;
            }

            Bitmap w1 = BitmapEffects.FromColor(Color.White, 256, 224);
            Bitmap w2 = BitmapEffects.FromColor(Color.White, 256, 224);

            BitmapData w1Data = w1.LockBits(new Rectangle(0, 0, w1.Width, w1.Height), ImageLockMode.ReadWrite, w1.PixelFormat);
            BitmapData w2Data = w2.LockBits(new Rectangle(0, 0, w2.Width, w2.Height), ImageLockMode.ReadWrite, w2.PixelFormat);

            byte[] w1Bytes = new byte[w1Data.Height * w1Data.Stride];
            byte[] w2Bytes = new byte[w2Data.Height * w2Data.Stride];
            System.Runtime.InteropServices.Marshal.Copy(w1Data.Scan0, w1Bytes, 0, w1Bytes.Length);
            System.Runtime.InteropServices.Marshal.Copy(w2Data.Scan0, w2Bytes, 0, w2Bytes.Length);


            Table = new HDMATable(".windowTable");
            HDMATableEntry entry     = null;
            HDMATableEntry lastEntry = null;

            //if any line in this image requires 3 black and 2 white, one window (bm1) has to be inverted.
            bool WindowInverted = C_Arr.Any(cp => (cp.Count(c => c.Color.Name == "ff000000") == 3 &&
                                                   cp.Count(c => c.Color.Name == "ffffffff") == 2));

            for (int y = 0; y < Scanlines; y++)
            {
                entry = new HDMATableEntry(TableValueType.db, (byte)(1 + y - Table.TotalScanlines),
                                           0xFF, 0x00, 0xFF, 0x00);

                int countBlack = C_Arr[y].Count(cp => cp.Color.Name == "ff000000");
                int countWhite = C_Arr[y].Count(cp => cp.Color.Name == "ffffffff");

                Func <int, int, int, bool> BlackFromTill = (window, from, till) =>
                {
                    if (till == 0x100)
                    {
                        till = 0xFF;
                    }

                    if (window == 1)
                    {
                        for (int x = from; x < till; x++)
                        {
                            BitmapEffects.SetPixel(w1Data, ref w1Bytes, x, y, Color.Black);
                        }
                        entry.Values[0] = (byte)from;
                        entry.Values[1] = (byte)till;
                        return(true);
                    }
                    else if (window == 2)
                    {
                        for (int x = from; x < till; x++)
                        {
                            BitmapEffects.SetPixel(w2Data, ref w2Bytes, x, y, Color.Black);
                        }
                        entry.Values[2] = (byte)from;
                        entry.Values[3] = (byte)till;
                        return(true);
                    }
                    return(false);
                };

                if (countBlack == 1 && countWhite == 0)
                {
                    // whole line black.
                    // if window get's inverted, line can be left unchanged.
                    if (!WindowInverted)
                    {
                        BlackFromTill(1, 0, w1.Width);                          // if not, whole line black
                    }
                }
                else if (countBlack == 2 && countWhite == 1)
                {
                    //outer black, inner white (black-white-black)

                    if (WindowInverted)                                               //if window 1 is inverted it can be done using one window.
                    {
                        BlackFromTill(1, C_Arr[y][1].Position, C_Arr[y][2].Position); //The part white in the mask will be black in w1
                    }
                    else                                                              //window 1 not inveted:
                    {
                        BlackFromTill(1, C_Arr[y][0].Position, C_Arr[y][1].Position); // first black part of mask in window 1,
                        BlackFromTill(2, C_Arr[y][2].Position, w2.Width);             // and the second in window 2.
                    }
                }
                else if (countBlack == 3 && countWhite == 2)
                {
                    //black-white-black-white-black
                    //1 window inverted, the other not (not possible otherwise).
                    //meaning window 1 will be inverted.

                    BlackFromTill(1, C_Arr[y][1].Position, C_Arr[y][4].Position);                       // windows 1 will be black from the beginning of the first white
                    BlackFromTill(2, C_Arr[y][2].Position, C_Arr[y][3].Position);                       // till the end of the second. Windows 2 is the middle black part.
                }

                //else if (countBlack == 3 && countWhite == 3)
                //... IMPOSSIBRU <.<

                else if (countBlack == 2 && countWhite == 3)
                {
                    //white-black-white-black-white
                    //both windows have to be uninverted. (or playing with XOR setting)

                    BlackFromTill(1, C_Arr[y][1].Position, C_Arr[y][2].Position);                       // window 1 black for first black part of mask
                    BlackFromTill(2, C_Arr[y][3].Position, C_Arr[y][4].Position);                       // windows 2 black for second part.
                }
                else if (countBlack == 1 && countWhite == 2)
                {
                    //outer white inner black (white-black-white)

                    if (WindowInverted)                                               //if windows 1 is inverted, we have to use window 2 and set window 1 black on the whole line
                    {
                        BlackFromTill(1, 0, w1.Width);                                // window 1 completly black
                        BlackFromTill(2, C_Arr[y][1].Position, C_Arr[y][2].Position); // window 2 black where mask is black.
                    }
                    else
                    {
                        BlackFromTill(1, C_Arr[y][1].Position, C_Arr[y][2].Position);                           // if not inverted, simply use window 1.
                    }
                }
                else if (countBlack == 0 && countWhite == 1)
                {
                    //whole line visible
                    if (WindowInverted)
                    {
                        BlackFromTill(1, 0, w1.Width);                                          // if window 1 inverted, whole line black
                    }
                }
                else if (countBlack == 2 && countWhite == 2)
                {
                    //problem: unknown if black-white-black-white or white-black-white-black
                    #region 2/2
                    if (C_Arr[y][0].Color.Name == "ff000000")                             //if fisrt part black then B-W-B-W
                    {
                        if (WindowInverted)                                               //inverted:
                        {
                            BlackFromTill(1, C_Arr[y][1].Position, w1.Width);             // the -W-B-W area will be black, so inverted makes the first bar black
                            BlackFromTill(2, C_Arr[y][2].Position, C_Arr[y][3].Position); // window 2 simply makes second bar black
                        }
                        else                                                              //not inverted
                        {
                            BlackFromTill(1, C_Arr[y][0].Position, C_Arr[y][1].Position); // first bar in window 1
                            BlackFromTill(2, C_Arr[y][2].Position, C_Arr[y][3].Position); // guess what
                        }
                    }
                    else                                                                  // first bar not black, thus W-B-W-B
                    {
                        if (WindowInverted)                                               //inverted:
                        {
                            BlackFromTill(1, C_Arr[y][0].Position, C_Arr[y][3].Position); // the W-B-W- area will be black, inverting makes the last bar black.
                            BlackFromTill(2, C_Arr[y][1].Position, C_Arr[y][2].Position); // window 2 will be black where the first bar is.
                        }
                        else                                                              //not inverted
                        {
                            BlackFromTill(1, C_Arr[y][1].Position, C_Arr[y][2].Position); // first bar in window 2
                            BlackFromTill(2, C_Arr[y][3].Position, w2.Width);             // ...
                        }
                    }
                    #endregion
                }
                else if (countBlack == 1 && countWhite == 1)
                {
                    //problem: unknown if black-white or white-black
                    if (C_Arr[y][0].Color.Name == "ff000000")                             //first bar is black thus B-W
                    {
                        if (WindowInverted)                                               //inverted:
                        {
                            BlackFromTill(1, C_Arr[y][1].Position, w1.Width);             //set second bar (white) to black due to inverting
                        }
                        else                                                              //not inverted
                        {
                            BlackFromTill(1, C_Arr[y][0].Position, C_Arr[y][1].Position); //first bar (black) in window one to black
                        }
                    }
                    else                                                                  //first bar not black thus W-B
                    {
                        if (WindowInverted)                                               //inverted:
                        {
                            BlackFromTill(1, C_Arr[y][0].Position, C_Arr[y][1].Position); // set white part black;
                        }
                        else                                                              //not inverted
                        {
                            BlackFromTill(1, C_Arr[y][1].Position, w1.Width);             //set second bar black.
                        }
                    }
                }


                if ((lastEntry != null && !entry.Values.SequenceEqual(lastEntry.Values)) || entry.Scanlines == 0x81)
                {
                    Table.Add(lastEntry);
                    entry.Scanlines = 1;
                }
                lastEntry = (HDMATableEntry)entry.Clone();
            }                              //end of for-loop

            Table.Add(lastEntry);          //the last last entry
            Table.Add(HDMATableEntry.End); //the actual end.

            System.Runtime.InteropServices.Marshal.Copy(w1Bytes, 0, w1Data.Scan0, w1Bytes.Length);
            System.Runtime.InteropServices.Marshal.Copy(w2Bytes, 0, w2Data.Scan0, w2Bytes.Length);
            w1.UnlockBits(w1Data);
            w2.UnlockBits(w2Data);

            math.WindowingMask1 = w1;
            math.WindowingMask2 = w2;

            math.Window1Inverted = WindowInverted ? (WindowingLayers)0x3F : 0;

            return(true);
        }