void setDataFormat(PixeLINK.PixelFormat dataFormat, HistElt[] m_elts) { bool m_bSimpleMode = true; if (dataFormat == PixeLINK.PixelFormat.Yuv422) { // In YUV format, we do not allow the user to select different plot lines // to display, because that would involve lots of format converstions. if (m_bSimpleMode) { // Show RGB for (int i = 0; i < (int)formats.PIXEL_TYPES_TOTAL; i++) { m_elts[i].bShow = (i >= (int)formats.RGB_FIRST_CHANNEL && i <= (int)formats.RGB_LAST_CHANNEL); } } else { // Show YUV for (int i = 0; i < (int)formats.PIXEL_TYPES_TOTAL; i++) { m_elts[i].bShow = (i >= (int)formats.YUV_Y && i <= (int)formats.YUV_V); } } return; } //if (!m_bAutoFormatMode) // return; if (dataFormat == PixeLINK.PixelFormat.Mono8 || dataFormat == PixeLINK.PixelFormat.Mono16 || dataFormat == PixeLINK.PixelFormat.Mono12Packed || dataFormat == PixeLINK.PixelFormat.Mono12PackedMsfirst) { for (int i = 0; i < (int)formats.PIXEL_TYPES_TOTAL; i++) { m_elts[i].bShow = (i == (int)formats.ALL_PIXELS); } } else if (IsBayerFormat(dataFormat)) // Bayer format { if (m_bSimpleMode) { // Show RGB for (int i = 0; i < (int)formats.PIXEL_TYPES_TOTAL; i++) { m_elts[i].bShow = (i >= (int)formats.RGB_FIRST_CHANNEL && i <= (int)formats.RGB_LAST_CHANNEL); } } else { // Show 4 bayer channels for (int i = 0; i < (int)formats.PIXEL_TYPES_TOTAL; i++) { m_elts[i].bShow = (i >= (int)formats.BAYER_FIRST_CHANNEL && i <= (int)formats.BAYER_LAST_CHANNEL); } } } }
// Create another array of four double-pointers that point to the 4 bayer // data blocks, but this time put them in the order GRBG. void CreateGRBGarray(PixeLINK.PixelFormat dataFormat, List <countHolder> counts, List <countHolder> countsGRBG) { for (int i = (int)BayerChannel.GREEN1; i <= (int)BayerChannel.GREEN2; i++) { // std::pair<int, int> offsetYX = GetChannelOffset(i, uDataFormat); Tuple <int, int> offsetYX = GetChannelOffset(i, dataFormat); countsGRBG[i] = counts[2 * offsetYX.Item1 + offsetYX.Item2]; } }
Tuple <int, int> GetChannelOffset(int /*BayerChannel*/ channel, PixeLINK.PixelFormat dataFormat) { //// Return the row# and col# of the given channel, when the data is in the //// given format. // std::pair<int, int> channelCoords(channel / 2, channel % 2); Tuple <int, int> channelCoords = new Tuple <int, int>(channel / 2, channel % 2); //std::pair<int, int> offset = Green1Index(dataFormat); Tuple <int, int> offset = Green1Index(dataFormat); //return std::make_pair((channelCoords.first + offset.first) % 2, (channelCoords.second + offset.second) % 2); return(new Tuple <int, int>((channelCoords.Item1 + offset.Item1) % 2, (channelCoords.Item2 + offset.Item2) % 2)); }
Tuple <int, int> Green1Index(PixeLINK.PixelFormat dataFormat) { // Return (row#, col#) of Green1 (that's the green on the red row, and the blue column) switch (dataFormat) { // case PIXEL_FORMAT_BAYER8_GRBG: case PixeLINK.PixelFormat.Bayer8GRBG: // case PIXEL_FORMAT_BAYER16_GRBG: case PixeLINK.PixelFormat.Bayer16GRBG: // case PIXEL_FORMAT_BAYER12_GRBG_PACKED: // case PIXEL_FORMAT_BAYER12_GRBG_PACKED_MSFIRST: // return std::make_pair(0, 0); return(new Tuple <int, int>(0, 0)); // case PIXEL_FORMAT_BAYER8_RGGB: case PixeLINK.PixelFormat.Bayer8RGGB: // case PIXEL_FORMAT_BAYER16_RGGB: case PixeLINK.PixelFormat.Bayer16RGGB: // case PIXEL_FORMAT_BAYER12_RGGB_PACKED: case PixeLINK.PixelFormat.Bayer12RGGBPacked: // case PIXEL_FORMAT_BAYER12_RGGB_PACKED_MSFIRST: case PixeLINK.PixelFormat.Bayer12RGGBPackedMsfirst: // return std::make_pair(0, 1); return(new Tuple <int, int>(0, 1)); // case PIXEL_FORMAT_BAYER8_BGGR: case PixeLINK.PixelFormat.Bayer8BGGR: // case PIXEL_FORMAT_BAYER12_BGGR_PACKED: case PixeLINK.PixelFormat.Bayer12BGGRPacked: // case PIXEL_FORMAT_BAYER12_BGGR_PACKED_MSFIRST: case PixeLINK.PixelFormat.Bayer12BGGRPackedMsfirst: // return std::make_pair(1, 0); return(new Tuple <int, int>(1, 0)); // case PIXEL_FORMAT_BAYER8_GBRG: case PixeLINK.PixelFormat.Bayer8GBRG: // case PIXEL_FORMAT_BAYER16_GBRG: // case PIXEL_FORMAT_BAYER12_GBRG_PACKED: // case PIXEL_FORMAT_BAYER12_GBRG_PACKED_MSFIRST: // return std::make_pair(1, 1); return(new Tuple <int, int>(1, 1)); } return(new Tuple <int, int>(0, 0)); // Treat MONO as GRBG (the default for the PL-A682). }
bool IsBayerFormat(PixeLINK.PixelFormat fmt) { return(fmt == PixeLINK.PixelFormat.Bayer8BGGR || fmt == PixeLINK.PixelFormat.Bayer16GBRG || fmt == PixeLINK.PixelFormat.Bayer16GRBG || fmt == PixeLINK.PixelFormat.Bayer16RGGB || fmt == PixeLINK.PixelFormat.Bayer8BGGR || fmt == PixeLINK.PixelFormat.Bayer8GBRG || fmt == PixeLINK.PixelFormat.Bayer8GRBG || fmt == PixeLINK.PixelFormat.Bayer8RGGB || fmt == PixeLINK.PixelFormat.Bayer12RGGBPacked || fmt == PixeLINK.PixelFormat.Bayer12GBRGPacked || fmt == PixeLINK.PixelFormat.Bayer12GRBGPacked || fmt == PixeLINK.PixelFormat.Bayer12RGGBPacked || fmt == PixeLINK.PixelFormat.Bayer12BGGRPackedMsfirst || fmt == PixeLINK.PixelFormat.Bayer12GBRGPackedMsfirst || fmt == PixeLINK.PixelFormat.Bayer12GRBGPackedMsfirst || fmt == PixeLINK.PixelFormat.Bayer12RGGBPackedMsfirst ); }
public int MyCallbackFunction(int hCamera, System.IntPtr pBuf, PixeLINK.PixelFormat dataFormat, ref FrameDescriptor frameDesc, int userData) { lock (thisLock) { if (Application.Current == null) { return(0); } ((App)Application.Current).logger.MyLogFile("MyCallbackFunction ", string.Format("camera {0} threadid {1} ", hCamera, Thread.CurrentThread.ManagedThreadId)); // Calculate actual framerate. long curtime = (long)(frameDesc.FrameTime * 1000); long elapsedtime = curtime - m_startframetime; int elapsedframes = frameDesc.FrameNumber - m_startframe; Console.WriteLine("calc frame rate {0} {1}", elapsedtime, elapsedframes); if (elapsedtime >= 50 && elapsedframes >= 5) { // enough time and enough frames have elapsed to calculate a reasonably // accurate frame rate. m_rate = (double)(1000 * elapsedframes / elapsedtime); m_startframetime = curtime; m_startframe = frameDesc.FrameNumber; } else if (elapsedframes < 0 || elapsedtime < 0) { // Stream has been restarted. Reset our start values. m_startframetime = curtime; m_startframe = frameDesc.FrameNumber; } if ((elapsedtime < 50) || (elapsedframes < 0)) { // The rest of this function calculates the histogram data, and then // sends a message to update the GUI. Do not do this more than 20 times // per second - that would be a waste of processor power, since users // can't tell the difference between a GUI that is updating 20 times // per second and one that is updating 1000 times per second. // // The frame should also be ignored if the frame is older than // the most recent frame we've seen. (i.e. elapsedframes < 0) Console.WriteLine("skip frame"); return(0); } long numPixels = frameDesc.NumberOfPixels(); if (rawbits == null) { rawbits = new byte[numPixels]; } TransferBits transfer = new TransferBits(); transfer.bits = rawbits; // byte[] bits = new byte[40]; //copy the image bits from API to managed buffer try { System.Runtime.InteropServices.Marshal.Copy(pBuf, transfer.bits, 0, (int)numPixels); } catch { ((App)Application.Current).logger.MyLogFile("MyCallbackFunction ", "Exception in Marshal.Copy "); return(1); } //Buffer.BlockCopy(transfer.bits, 0, bits, 0, 40); //((App)Application.Current).logger.MyLogFile("pBuf ", string.Format(" thread {0} Bytes {1}", Thread.CurrentThread.ManagedThreadId, ByteArrayToString(bits))); transfer.dataFormat = dataFormat; transfer.frameDesc = frameDesc; transfer.hCamera = hCamera; //really should not need the worker thread but put this in to keep the camera red lite off ThreadPool.QueueUserWorkItem(Work1, transfer); return(1); } }