예제 #1
0
        private static void CalculateNextDrawCommand(uint colSpan, uint rowSpan, BtnProps btn, int res, int[] line)
        {
            Bitmap img = btn.screenImg;

            for (uint col = 0; col < line.Length; col++)
            {
                int x = (int)(col * colSpan);

                if (colSpan == 1 && rowSpan == 1)
                {
                    // nothing to average for a 1x1 square of color
                    line[col] = ImageMagic.ColorConvertColorToInt(img.GetPixel(x, (int)btn.rowIdx[res]));
                }
                else if (colSpan * rowSpan < 625_000) // arbitrary 10MB limit
                {
                    // calculate the median color
                    List <Tuple <Color, int> > colorSwatch = new List <Tuple <Color, int> >((int)(colSpan * rowSpan));
                    colorSwatch.OrderBy(t => t.Item2);
                    for (int i = 0; i < colSpan; i++)
                    {
                        for (int j = 0; j < rowSpan; j++)
                        {
                            int   y         = (int)(btn.rowIdx[res] * rowSpan);
                            Color color     = img.GetPixel(x + i, y + j);
                            int   intensity = color.R + color.G + color.B;
                            colorSwatch.Add(new Tuple <Color, int>(color, intensity));
                        }
                    }
                    Color c = colorSwatch[colorSwatch.Count / 2].Item1;
                    line[col] = ImageMagic.ColorConvertColorToInt(c);
                }
                else
                {
                    // calculate the average color
                    ulong[] uc = new ulong[4];
                    for (int i = 0; i < colSpan; i++)
                    {
                        for (int j = 0; j < rowSpan; j++)
                        {
                            int   y     = (int)(btn.rowIdx[res] * rowSpan);
                            Color color = img.GetPixel(x + i, y + j);
                            uc[0] += color.R;
                            uc[1] += color.G;
                            uc[2] += color.B;
                        }
                    }
                    uint pixelCnt = colSpan * rowSpan;
                    uint r        = (uint)uc[0] / pixelCnt;
                    uint g        = (uint)uc[1] / pixelCnt;
                    uint b        = (uint)uc[2] / pixelCnt;
                    line[col] = ImageMagic.ColorConvertRGBTo24(r, g, b);
                }
            }
        }
예제 #2
0
        public void SetDoUpdateImg(bool doUpdate)
        {
            this.doUpdateImg = doUpdate;

            if (doUpdate)
            {
                this.screenImg = new Bitmap(this.img, (int)screenWidth, (int)screenHeight);
                this.palette   = ImageMagic.CalculatePalette(this.img, 256);
                SetDoUpdatePalette(true);
                paletteWriteIdx = 0;
            }
        }
예제 #3
0
 /// <summary>
 /// Gets the mapped color, adding the given color as necessary.
 /// </summary>
 /// <returns>The index of the given color in the map.</returns>
 public byte GetPaletteColor(Color val)
 {
     return(GetPaletteColor(ImageMagic.ColorConvert24To16(val)));
 }
        public override bool SendImageRow(int[] line, uint startRow, uint rowSpan, BtnProps btn)
        {
            Stopwatch timer = new Stopwatch();

            timer.Start();
            int idx = 0;

            // check that WIDTH is a multiple of the line length
            uint colSpan = screenWidth / (uint)line.Length;

            if (line.Length * colSpan != screenWidth)
            {
                throw new ArgumentException($"The display width ({screenWidth}) must be a multiple of the line length ({line.Length})");
            }

            // send packetized data
            if (startRow == 0)
            {
                byte[] restart = new byte[62];                // buffer to be sent
                idx            = BitBashing.UIntToDecimalBytes(ref restart, 0, 2, 0);
                restart[idx++] = Convert.ToByte(':');
                restart[idx++] = Convert.ToByte('R');         // "Reset Draw" command
                restart[idx++] = Convert.ToByte('L');
                if (waitingForAck)
                {
                    WaitForAck(1000);
                }
                if (!CheckedWrite(restart, 0, idx))
                {
                    return(false);
                }
                waitingForAck = true;
            }

            // send colSpan and rowSpan
            byte[] spans = new byte[62];                      // buffer to be sent
            idx          = BitBashing.SIntToDecimalBytes(ref spans, 0, 5, 0);
            spans[idx++] = Convert.ToByte(':');
            spans[idx++] = Convert.ToByte('S');               // "Span Size" command
            idx         += BitBashing.UIntToHexBytes(ref spans, idx, colSpan, 2, 2);
            idx         += BitBashing.UIntToHexBytes(ref spans, idx, rowSpan, 2, 2);
            if (waitingForAck)
            {
                WaitForAck(1000);
            }
            if (!CheckedWrite(spans, 0, idx))
            {
                return(false);
            }
            waitingForAck = true;

            // determine the necessity of a palette and send the palette
            bool usePalette = btn.palette != null && colSpan < 16 && rowSpan < 16;

            if (usePalette && startRow == 0 && btn.doUpdatePalette)
            {
                SendColorPalette(btn.palette);
                btn.SetDoUpdatePalette(false);
            }

            // send packetized line color data
            byte[] linePart = new byte[62];                   // buffer to be sent
            int    linePartLen;                               // packetized line message length
            int    bytesPerPixel = (usePalette) ? 1 : 2;

            linePartLen = (int)(56 / bytesPerPixel);
            char command = (usePalette) ? 'l' : 'L';

            for (int i = 0; i < line.Length; i += linePartLen)
            {
                int sendCnt = Math.Min(linePartLen, line.Length - i);

                // prepare the message header
                int pixelCnt = (usePalette) ? sendCnt : sendCnt * bytesPerPixel;
                idx             = BitBashing.SIntToDecimalBytes(ref linePart, 0, pixelCnt + 1, 0);
                linePart[idx++] = Convert.ToByte(':');
                linePart[idx++] = Convert.ToByte(command);    // "Line Part" or "line (palette) Part" command

                // add the color values
                for (int j = 0; j < sendCnt; j++)
                {
                    int    col     = idx + j * bytesPerPixel;
                    ushort color16 = ImageMagic.ColorConvert24To16(line[i + j]);
                    if (usePalette)
                    {
                        linePart[col] = btn.palette.GetPaletteColor(color16);
                    }
                    else
                    {
                        linePart[col + 1] = BitConverter.GetBytes(color16)[0];
                        linePart[col + 0] = BitConverter.GetBytes(color16)[1];
                    }
                }

                // send the message
                if (waitingForAck)
                {
                    WaitForAck(1000);
                }
                if (!CheckedWrite(linePart, 0, pixelCnt + idx))
                {
                    return(false);
                }
                waitingForAck = true;
            }

            //Console.WriteLine("c#: " + timer.ElapsedMilliseconds);

            return(true);
        }