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); } } }
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; } }
/// <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); }