/// <summary> /// Initializes a new instance of the MainViewModel class. /// </summary> public MainViewModel() { SelectedFrame = VideoFrame.Default; SetFree(); for (int i = 1; i <= 60; i++) { FrameRates.Add(i); } SelectedFrameRate = FrameRates[2]; if (IsInDesignMode) { IEnumerable <string> images = Directory.EnumerateFiles(@"C:\tmp\gpvid\frames", "thumb*.jpg"); foreach (string image in images) { Frames.Add(new VideoFrame() { FullPath = image, ThumbnailPath = image }); } for (int i = 0; i < 10; i++) { Frames[i].IsDuplicate = true; } for (int i = 0; i < 20; i++) { if (i % 2 == 0) { Frames[i].HasFace = true; } } for (int i = 0; i < 30; i++) { if (i % 3 == 0) { Frames[i].Show = false; } } } }
public void Save(Stream outputStream) { // Make sure we have frames if (!_frames.Any()) { throw new InvalidDataException("Frames must be supplied."); } // Make sure they all have value, height and width if (_frames.Any(f => f == null || f.Height == 0 || f.Width == 0)) { throw new InvalidDataException("Bitmap frames cannot be zero (height or width)."); } // Add frames to the encoder var gifEncoder = new GifBitmapEncoder(); _frames.ForEach(frame => gifEncoder.Frames.Add( BitmapFrame.Create( Imaging.CreateBitmapSourceFromHBitmap(frame.GetHbitmap(), IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()) ) ) ); byte[] bytes; using (var ms = new MemoryStream()) { gifEncoder.Save(ms); bytes = ms.ToArray(); } // Locate the right location where to insert the metadata in the binary // This will be just before the first label &H0021F9 (Graphic Control Extension) int metadataPtr = 0; bool located = false; do { metadataPtr++; if (bytes[metadataPtr] == 0 && bytes[metadataPtr + 1] == 0x21 && bytes[metadataPtr + 2] == 0xf9) { located = true; } } while (!located); // SET METADATA Repeat // This add an Application Extension Netscape2.0 if (Repeat) { byte[] temp = new byte[bytes.Length - 1 + 20]; // label: &H21, &HFF + one byte: length(&HB) + NETSCAPE2.0 + one byte: Datalength(&H3) + {1, 0, 0} + Block terminator, 1 byte, &H00 byte[] appExtension = { 0x21, 0xff, 0xb, 0x4e, 0x45, 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2e, 0x30, 0x3, 0x1, 0x0, 0x0, 0x0 }; Array.Copy(bytes, temp, metadataPtr); Array.Copy(appExtension, 0, temp, metadataPtr + 1, 19); Array.Copy(bytes, metadataPtr + 1, temp, metadataPtr + 20, bytes.Length - metadataPtr - 1); bytes = temp; } // SET METADATA Comments // This add a Comment Extension for each string if (Metadata.Any()) { foreach (string comment in Metadata) { if (!string.IsNullOrEmpty(comment)) { string theComment = null; if (comment.Length > 254) { theComment = comment.Substring(0, 254); } else { theComment = comment; } var commentBytes = UTF7Encoding.UTF7.GetBytes(theComment); var commentData = new byte[] { 0x21, 0xfe, (byte)commentBytes.Length }.Concat(commentBytes).Concat(new byte[] { 0x0 }).ToArray(); var temp = new byte[bytes.Length - 1 + commentData.Length + 1]; Array.Copy(bytes, temp, metadataPtr); Array.Copy(commentData, 0, temp, metadataPtr + 1, commentData.Length); Array.Copy(bytes, metadataPtr + 1, temp, metadataPtr + commentData.Length + 1, bytes.Length - metadataPtr - 1); bytes = temp; } } } // SET METADATA frameRate // Sets the third and fourth byte of each Graphic Control Extension (5 bytes from each label 0x0021F9) // word, little endian, the hundredths of second to show this frame if (FrameRates == null) { FrameRates = new List <int>(); } if (FrameRates.Count < _frames.Count) { FrameRates.AddRange(Enumerable.Repeat <int>(FrameRate, _frames.Count - FrameRates.Count)); } int frameId = 0; for (int x = 0; x <= bytes.Length - 1; x++) { if (bytes[x] == 0 && bytes[x + 1] == 0x21 && bytes[x + 2] == 0xf9 && bytes[x + 3] == 4) { var fr = BitConverter.GetBytes(FrameRates[frameId++] / 10); bytes[x + 5] = fr[0]; bytes[x + 6] = fr[1]; } } outputStream.Write(bytes, 0, bytes.Length); }
void InitilizeOLED() { _rwPin.Write(false); Thread.Sleep(100); _resetPin.Write(false); Thread.Sleep(10); _resetPin.Write(true); Thread.Sleep(10); /* Soft reset */ SendCommand(SEPS114A_SOFT_RESET, 0x00); /* Standby ON/OFF*/ SendCommand(SEPS114A_STANDBY_ON_OFF, 0x01); // Standby on Thread.Sleep(5); // Wait for 5ms (1ms Delay Minimum) SendCommand(SEPS114A_STANDBY_ON_OFF, 0x00); // Standby off Thread.Sleep(5); // 1ms Delay Minimum (1ms Delay Minimum) /* Display OFF */ SendCommand(SEPS114A_DISPLAY_ON_OFF, 0x00); /* Set Oscillator operation */ SendCommand(SEPS114A_ANALOG_CONTROL, 0x00); // using external resistor and internal OSC /* Set frame rate */ SendCommand(SEPS114A_OSC_ADJUST, (byte)FrameRates.OCS_95Hz); // frame rate : 95Hz --- was 0x03 for 95 hz, now 0x0A for 130hz , 0x0F for 140 /* Set active display area of panel */ SendCommand(SEPS114A_DISPLAY_X1, 0x00); SendCommand(SEPS114A_DISPLAY_X2, 0x5F); SendCommand(SEPS114A_DISPLAY_Y1, 0x00); SendCommand(SEPS114A_DISPLAY_Y2, 0x5F); /* Select the RGB data format and set the initial state of RGB interface port */ SendCommand(SEPS114A_RGB_IF, 0x00); // RGB 8bit interface was 0x00 for 8-bit /* Set RGB polarity */ SendCommand(SEPS114A_RGB_POL, 0x00); // was 0x00 /* Set display mode control */ SendCommand(SEPS114A_DISPLAY_MODE_CONTROL, 0x80); // SWAP:BGR, Reduce current : Normal, DC[1:0] : Normal was 0x80 /* Set MCU Interface */ SendCommand(SEPS114A_CPU_IF, 0x00); // MPU External interface mode, 8bits /* Set Memory Read/Write mode */ SendCommand(SEPS114A_MEMORY_WRITE_READ, 0x00); /* Set row scan direction */ SendCommand(SEPS114A_ROW_SCAN_DIRECTION, 0x00); // Column : 0 --> Max, Row : 0 --> Max --- was 0x00 /* Set row scan mode */ SendCommand(SEPS114A_ROW_SCAN_MODE, 0x00); // Alternate scan mode --- was 0x00 /* Set column current */ SendCommand(SEPS114A_COLUMN_CURRENT_R, 0x6E); SendCommand(SEPS114A_COLUMN_CURRENT_G, 0x4F); SendCommand(SEPS114A_COLUMN_CURRENT_B, 0x77); /* Set row overlap */ SendCommand(SEPS114A_ROW_OVERLAP, 0x00); // Band gap only /* Set discharge time */ SendCommand(SEPS114A_DISCHARGE_TIME, 0x01); // Discharge time : normal discharge /* Set peak pulse delay */ SendCommand(SEPS114A_PEAK_PULSE_DELAY, 0x00); /* Set peak pulse width */ SendCommand(SEPS114A_PEAK_PULSE_WIDTH_R, 0x02); SendCommand(SEPS114A_PEAK_PULSE_WIDTH_G, 0x02); SendCommand(SEPS114A_PEAK_PULSE_WIDTH_B, 0x02); /* Set pre-charge current */ SendCommand(SEPS114A_PRECHARGE_CURRENT_R, 0x14); SendCommand(SEPS114A_PRECHARGE_CURRENT_G, 0x50); SendCommand(SEPS114A_PRECHARGE_CURRENT_B, 0x19); /* Set row scan on/off */ SendCommand(SEPS114A_ROW_SCAN_ON_OFF, 0x00); // Normal row scan /* Set scan off level */ SendCommand(SEPS114A_SCAN_OFF_LEVEL, 0x04); // VCC_C*0.75 /* Set memory access point */ SendCommand(SEPS114A_DISPLAYSTART_X, 0x00); SendCommand(SEPS114A_DISPLAYSTART_Y, 0x00); /* Clear the display */ if (!OledClearAll()) { throw new DeviceInitialisationException("Not enough memory to complete initialization."); } /* Display ON */ SendCommand(SEPS114A_DISPLAY_ON_OFF, 0x01); _powerMode = PowerModes.On; _frameRate = FrameRates.OCS_95Hz; }