bool Camera_SSAGClass::Capture(int duration, usImage& img, int options, const wxRect& subframe) { // Only does full frames unsigned short *dptr; int xsize = FullSize.GetWidth(); int ysize = FullSize.GetHeight(); bool firstimg = true; //qglogfile->AddLine(wxString::Format("Capturing dur %d",duration)); //qglogfile->Write(); _SSAG_ProgramCamera(0, 0, 1280, 1024, (GuideCameraGain * 63 / 100)); if (img.Init(FullSize)) { DisconnectWithAlert(CAPT_FAIL_MEMORY); return true; } CameraWatchdog watchdog(duration, GetTimeoutMs()); _SSAG_ThreadedExposure(duration, NULL); //qglogfile->AddLine("Exposure programmed"); //qglogfile->Write(); if (duration > 100) { if (WorkerThread::MilliSleep(duration - 100, WorkerThread::INT_ANY) && (WorkerThread::TerminateRequested() || StopExposure())) { return true; } } while (_SSAG_isExposing()) { wxMilliSleep(50); if (WorkerThread::InterruptRequested() && (WorkerThread::TerminateRequested() || StopExposure())) { return true; } if (watchdog.Expired()) { DisconnectWithAlert(CAPT_FAIL_TIMEOUT); return true; } } //qglogfile->AddLine("Exposure done"); //qglogfile->Write(); dptr = img.ImageData; _SSAG_GETBUFFER(dptr, img.NPixels * 2); if (options & CAPTURE_SUBTRACT_DARK) SubtractDark(img); //qglogfile->AddLine("Image loaded"); //qglogfile->Write(); return false; }
bool Camera_WDMClass::CaptureOneFrame(usImage& img, int options, const wxRect& subframe) { bool bError = false; try { if (BeginCapture(img, CAPTURE_ONE_FRAME)) { throw ERROR_INFO("BeingCapture() failed"); } EndCapture(); if (options & CAPTURE_SUBTRACT_DARK) { SubtractDark(img); } } catch (wxString Msg) { POSSIBLY_UNUSED(Msg); bError = true; } return bError; }
bool Camera_WDMClass::Capture(int duration, usImage& img, int options, const wxRect& subframe) { bool bError = false; try { if (BeginCapture(img, CAPTURE_STACK_FRAMES)) { throw ERROR_INFO("BeingCapture() failed"); } // accumulate for the requested duration WorkerThread::MilliSleep(duration, WorkerThread::INT_ANY); EndCapture(); pFrame->StatusMsg(wxString::Format("%d frames", m_nFrames)); if (options & CAPTURE_SUBTRACT_DARK) { SubtractDark(img); } } catch (wxString Msg) { POSSIBLY_UNUSED(Msg); bError = true; } return bError; }
bool Camera_SSPIAGClass::Capture(int duration, usImage& img, int options, const wxRect& subframe) { // Only does full frames still static int last_dur = 0; static int last_gain = 60; unsigned char *bptr; unsigned short *dptr; int x,y; int xsize = FullSize.GetWidth(); int ysize = FullSize.GetHeight(); // bool firstimg = true; if (img.Init(FullSize)) { DisconnectWithAlert(CAPT_FAIL_MEMORY); return true; } if (duration != last_dur) { Q5V_SetLongExpTime(duration); last_dur = duration; } else if (GuideCameraGain != last_gain) { Q5V_SetQHY5VGlobalGain(GuideCameraGain * 63 / 100); last_gain = GuideCameraGain; // Q5V_GetFullSizeImage(RawBuffer); } bptr = RawBuffer; Q5V_GetFullSizeImage(bptr); // Load and crop from the 800 x 525 image that came in dptr = img.ImageData; for (y=0; y<ysize; y++) { bptr = RawBuffer + 800*(y+4) + 47; for (x=0; x<xsize; x++, bptr++, dptr++) { // CAN SPEED THIS UP *dptr=(unsigned short) *bptr; } } if (options & CAPTURE_SUBTRACT_DARK) SubtractDark(img); // Do quick L recon to remove bayer array if (options & CAPTURE_RECON) QuickLRecon(img); return false; }
bool Camera_OpticstarPL130Class::Capture(int duration, usImage& img, int options, const wxRect& subframe) { bool still_going = true; int mode = 3 * (int) Color; if (img.Init(FullSize)) { DisconnectWithAlert(CAPT_FAIL_MEMORY); return true; } if (OSPL130_Capture(mode,duration)) { pFrame->Alert(_("Cannot start exposure")); return true; } if (duration > 100) { wxMilliSleep(duration - 100); // wait until near end of exposure, nicely wxGetApp().Yield(); // if (Abort) { // MeadeCam->AbortImage(); // return true; // } } while (still_going) { // wait for image to finish and d/l wxMilliSleep(20); OSPL130_IsExposing(&still_going); wxGetApp().Yield(); } // Download OSPL130_GetRawImage(0,0,FullSize.GetWidth(),FullSize.GetHeight(), (void *) img.ImageData); unsigned short *dataptr; dataptr = img.ImageData; // byte swap if (options & CAPTURE_SUBTRACT_DARK) SubtractDark(img); if (Color && (options & CAPTURE_RECON)) QuickLRecon(img); return false; }
bool Camera_Altair::Capture(int duration, usImage& img, int options, const wxRect& subframe) { if (img.Init(FullSize)) { DisconnectWithAlert(CAPT_FAIL_MEMORY); return true; } wxRect frame; wxPoint subframePos; // position of subframe within frame //bool useSubframe = UseSubframes; //if (subframe.width <= 0 || subframe.height <= 0) // useSubframe = false; //if (useSubframe) //{ // // ensure transfer size is a multiple of 1024 // // moving the sub-frame or resizing it is somewhat costly (stopCapture / startCapture) // frame.SetLeft(round_down(subframe.GetLeft(), 32)); // frame.SetRight(round_up(subframe.GetRight() + 1, 32) - 1); // frame.SetTop(round_down(subframe.GetTop(), 32)); // frame.SetBottom(round_up(subframe.GetBottom() + 1, 32) - 1); // subframePos = subframe.GetLeftTop() - frame.GetLeftTop(); //} //else //{ frame = wxRect(FullSize); // } long exposureUS = duration * 1000; unsigned int cur_exp; if (Altair_get_ExpoTime(m_handle, &cur_exp) == 0 && cur_exp != exposureUS) { Debug.AddLine("Altair: set CONTROL_EXPOSURE %d", exposureUS); Altair_put_ExpoTime(m_handle, exposureUS); } long new_gain = cam_gain(m_minGain, m_maxGain, GuideCameraGain); unsigned short cur_gain; if (Altair_get_ExpoAGain(m_handle, &cur_gain) == 0 && new_gain != cur_gain) { Debug.AddLine("Altair: set CONTROL_GAIN %d%% %d", GuideCameraGain, new_gain); Altair_put_ExpoAGain(m_handle, new_gain); } /* bool size_change = frame.GetSize() != m_frame.GetSize(); bool pos_change = frame.GetLeftTop() != m_frame.GetLeftTop(); if (size_change || pos_change) { m_frame = frame; Debug.AddLine("Altair: frame (%d,%d)+(%d,%d)", m_frame.x, m_frame.y, m_frame.width, m_frame.height); } if (size_change) { StopCapture(); ASI_ERROR_CODE status = ASISetROIFormat(m_handle, frame.GetWidth(), frame.GetHeight(), 1, ASI_IMG_Y8); if (status != ASI_SUCCESS) Debug.AddLine("Altair: setImageFormat(%d,%d) => %d", frame.GetWidth(), frame.GetHeight(), status); } if (pos_change) { ASI_ERROR_CODE status = ASISetStartPos(m_handle, frame.GetLeft(), frame.GetTop()); if (status != ASI_SUCCESS) Debug.AddLine("Altair: setStartPos(%d,%d) => %d", frame.GetLeft(), frame.GetTop(), status); }*/ // the camera and/or driver will buffer frames and return the oldest frame, // which could be quite stale. read out all buffered frames so the frame we // get is current //flush_buffered_image(m_handle, img); if (!m_capturing) { Debug.AddLine("Altair: startcapture"); m_frameReady = false; Altair_StartPullModeWithCallback(m_handle, CameraCallback, this); m_capturing = true; } int frameSize = frame.GetWidth() * frame.GetHeight(); int poll = wxMin(duration, 100); CameraWatchdog watchdog(duration, duration + GetTimeoutMs() + 10000); // total timeout is 2 * duration + 15s (typically) if (WorkerThread::MilliSleep(duration, WorkerThread::INT_ANY) && (WorkerThread::TerminateRequested() || StopCapture())) { return true; } while (true) { if (m_frameReady) { m_frameReady = false; unsigned int width, height; if (SUCCEEDED(Altair_PullImage(m_handle, m_buffer, 8, &width, &height))) break; } WorkerThread::MilliSleep(poll, WorkerThread::INT_ANY); if (WorkerThread::InterruptRequested()) { StopCapture(); return true; } if (watchdog.Expired()) { Debug.AddLine("Altair: getimagedata failed"); StopCapture(); DisconnectWithAlert(CAPT_FAIL_TIMEOUT); return true; } } //if (useSubframe) //{ // img.Subframe = subframe; // // Clear out the image // img.Clear(); // for (int y = 0; y < subframe.height; y++) // { // const unsigned char *src = m_buffer + (y + subframePos.y) * frame.width + subframePos.x; // unsigned short *dst = img.ImageData + (y + subframe.y) * FullSize.GetWidth() + subframe.x; // for (int x = 0; x < subframe.width; x++) // *dst++ = *src++; // } //} //else { for (int i = 0; i < img.NPixels; i++) img.ImageData[i] = m_buffer[i]; } if (options & CAPTURE_SUBTRACT_DARK) SubtractDark(img); return false; }
bool Camera_QHY::Capture(int duration, usImage& img, int options, const wxRect& subframe) { bool useSubframe = UseSubframes && !subframe.IsEmpty(); if (Binning != m_curBin) { FullSize = wxSize(m_maxSize.GetX() / Binning, m_maxSize.GetY() / Binning); m_curBin = Binning; useSubframe = false; // subframe may be out of bounds now } if (img.Init(FullSize)) { DisconnectWithAlert(CAPT_FAIL_MEMORY); return true; } wxRect frame = useSubframe ? subframe : wxRect(FullSize); if (useSubframe) img.Clear(); wxRect roi; if (useSubframe) { // Use a larger ROI around the subframe to avoid changing the ROI as the centroid // wobbles around. Changing the ROI introduces a lag of several seconds. // This also satifies the constraint that ROI width and height must be multiples of 4. enum { PAD = 1 << 5 }; roi.SetLeft(round_down(subframe.GetLeft(), PAD)); roi.SetRight(round_up(subframe.GetRight() + 1, PAD) - 1); roi.SetTop(round_down(subframe.GetTop(), PAD)); roi.SetBottom(round_up(subframe.GetBottom() + 1, PAD) - 1); } else { roi = frame; } uint32_t ret = QHYCCD_ERROR; // lzr from QHY says this needs to be set for every exposure ret = SetQHYCCDBinMode(m_camhandle, Binning, Binning); if (ret != QHYCCD_SUCCESS) { Debug.Write(wxString::Format("SetQHYCCDBinMode failed! ret = %d\n", (int)ret)); } if (m_roi != roi) { // when roi changes, must call this ret = CancelQHYCCDExposingAndReadout(m_camhandle); if (ret == QHYCCD_SUCCESS) { Debug.Write("CancelQHYCCDExposingAndReadout success\n"); } else { Debug.Write("CancelQHYCCDExposingAndReadout failed\n"); } ret = SetQHYCCDResolution(m_camhandle, roi.GetLeft(), roi.GetTop(), roi.GetWidth(), roi.GetHeight()); if (ret == QHYCCD_SUCCESS) { m_roi = roi; } else { Debug.Write(wxString::Format("SetQHYCCDResolution(%d,%d,%d,%d) failed! ret = %d\n", roi.GetLeft(), roi.GetTop(), roi.GetWidth(), roi.GetHeight(), (int)ret)); } } if (duration != m_curExposure) { ret = SetQHYCCDParam(m_camhandle, CONTROL_EXPOSURE, duration * 1000.0); // QHY duration is usec if (ret == QHYCCD_SUCCESS) { m_curExposure = duration; } else { Debug.Write(wxString::Format("QHY set exposure ret %d\n", (int)ret)); pFrame->Alert(_("Failed to set camera exposure")); } } if (GuideCameraGain != m_curGain) { double gain = m_gainMin + GuideCameraGain * (m_gainMax - m_gainMin) / 100.0; gain = floor(gain / m_gainStep) * m_gainStep; Debug.Write(wxString::Format("QHY set gain %g (%g..%g incr %g)\n", gain, m_gainMin, m_gainMax, m_gainStep)); ret = SetQHYCCDParam(m_camhandle, CONTROL_GAIN, gain); if (ret == QHYCCD_SUCCESS) { m_curGain = GuideCameraGain; } else { Debug.Write(wxString::Format("QHY set gain ret %d\n", (int)ret)); pFrame->Alert(_("Failed to set camera gain")); } } ret = ExpQHYCCDSingleFrame(m_camhandle); if (ret == QHYCCD_ERROR) { Debug.Write(wxString::Format("QHY exp single frame ret %d\n", (int)ret)); DisconnectWithAlert(_("QHY exposure failed"), NO_RECONNECT); return true; } if (ret == QHYCCD_SUCCESS) { Debug.Write(wxString::Format("QHY: 200ms delay needed\n")); WorkerThread::MilliSleep(200); } if (ret == QHYCCD_READ_DIRECTLY) { //Debug.Write("QHYCCD_READ_DIRECTLY\n"); } uint32_t w, h, bpp, channels; ret = GetQHYCCDSingleFrame(m_camhandle, &w, &h, &bpp, &channels, RawBuffer); if (ret != QHYCCD_SUCCESS || (bpp != 8 && bpp != 16)) { Debug.Write(wxString::Format("QHY get single frame ret %d bpp %u\n", ret, bpp)); // users report that reconnecting the camera after this failure allows // them to resume guiding so we'll try to reconnect automatically DisconnectWithAlert(_("QHY get frame failed"), RECONNECT); return true; } if (useSubframe) { img.Subframe = frame; int xofs = subframe.GetLeft() - roi.GetLeft(); int yofs = subframe.GetTop() - roi.GetTop(); int dxr = w - frame.width - xofs; if (bpp == 8) { const unsigned char *src = RawBuffer + yofs * w; unsigned short *dst = img.ImageData + frame.GetTop() * FullSize.GetWidth() + frame.GetLeft(); for (int y = 0; y < frame.height; y++) { unsigned short *d = dst; src += xofs; for (int x = 0; x < frame.width; x++) *d++ = (unsigned short) *src++; src += dxr; dst += FullSize.GetWidth(); } } else // bpp == 16 { const unsigned short *src = (const unsigned short *) RawBuffer + yofs * w; unsigned short *dst = img.ImageData + frame.GetTop() * FullSize.GetWidth() + frame.GetLeft(); for (int y = 0; y < frame.height; y++) { src += xofs; memcpy(dst, src, frame.width * sizeof(unsigned short)); src += frame.width + dxr; dst += FullSize.GetWidth(); } } } else { if (bpp == 8) { const unsigned char *src = RawBuffer; unsigned short *dst = img.ImageData; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { *dst++ = (unsigned short) *src++; } } } else // bpp == 16 { memcpy(img.ImageData, RawBuffer, w * h * sizeof(unsigned short)); } } if (options & CAPTURE_SUBTRACT_DARK) SubtractDark(img); if (Color && Binning == 1 && (options & CAPTURE_RECON)) QuickLRecon(img); return false; }
bool Camera_DSIClass::Capture(int duration, usImage& img, int options, const wxRect& subframe) { MeadeCam->SetGain((unsigned int) (GuideCameraGain * 63 / 100)); MeadeCam->SetExposureTime(duration); if (img.Init(MeadeCam->GetWidth(), MeadeCam->GetHeight())) { DisconnectWithAlert(CAPT_FAIL_MEMORY); return true; } bool retval = MeadeCam->GetImage(img.ImageData, true); if (!retval) return true; // The AbortImage method does not appear to work with the DSI camera. If abort is called and the thread is terminated, the // pending image is still downloaded and PHD2 will crash #if AbortActuallyWorks CameraWatchdog watchdog(duration, GetTimeoutMs()); // wait for image to finish and d/l while (!MeadeCam->ImageReady) { wxMilliSleep(20); if (WorkerThread::InterruptRequested()) { MeadeCam->AbortImage(); return true; } if (watchdog.Expired()) { MeadeCam->AbortImage(); DisconnectWithAlert(CAPT_FAIL_TIMEOUT); return true; } } #else // handle the pending image download, regardless // We also need to prevent the thread from being killed when phd2 is closed WorkerThreadKillGuard _guard; if (duration > 100) { wxMilliSleep(duration - 100); // wait until near end of exposure, nicely } bool still_going = true; while (still_going) { // wait for image to finish and d/l wxMilliSleep(20); still_going = !(MeadeCam->ImageReady); } #endif // end of waiting for the image if (options & CAPTURE_SUBTRACT_DARK) SubtractDark(img); if (options & CAPTURE_RECON) { if (MeadeCam->IsColor) QuickLRecon(img); if (MeadeCam->IsDsiII) SquarePixels(img, 8.6, 8.3); else if (!MeadeCam->IsDsiIII) // Original DSI SquarePixels(img, 9.6, 7.5); } return false; }
bool Camera_INDIClass::Capture(int duration, usImage& img, int options, const wxRect& subframeArg) { if (Connected) { bool takeSubframe = UseSubframes; wxRect subframe(subframeArg); // we can set the exposure time directly in the camera if (expose_prop) { if (Binning != m_curBinning) { FullSize = wxSize(m_maxSize.x / Binning, m_maxSize.y / Binning); binning_x->value = Binning; binning_y->value = Binning; sendNewNumber(binning_prop); m_curBinning = Binning; } if (subframe.width <= 0 || subframe.height <= 0) { takeSubframe = false; } // Program the size if (!takeSubframe) { subframe = wxRect(0, 0, FullSize.GetWidth(), FullSize.GetHeight()); } if (subframe != m_roi) { frame_x->value = subframe.x*Binning; frame_y->value = subframe.y*Binning; frame_width->value = subframe.width*Binning; frame_height->value = subframe.height*Binning; sendNewNumber(frame_prop); m_roi = subframe; } //printf("Exposing for %d(ms)\n", duration); // set the exposure time, this immediately start the exposure expose_prop->np->value = (double)duration/1000; sendNewNumber(expose_prop); modal = true; // will be reset when the image blob is received unsigned long loopwait = duration > 100 ? 10 : 1; CameraWatchdog watchdog(duration, GetTimeoutMs()); while (modal) { wxMilliSleep(loopwait); if (WorkerThread::TerminateRequested()) return true; if (watchdog.Expired()) { DisconnectWithAlert(CAPT_FAIL_TIMEOUT); return true; } } } // for video camera without exposure time setting else if (video_prop) { takeSubframe = false; //printf("Enabling video capture\n"); ISwitch *v_on = IUFindSwitch(video_prop,"ON"); ISwitch *v_off = IUFindSwitch(video_prop,"OFF"); v_on->s = ISS_ON; v_off->s = ISS_OFF; // start capture, every video frame is received as a blob sendNewSwitch(video_prop); // wait the required time wxMilliSleep(duration); // TODO : add the frames received during exposure //printf("Stop video capture\n"); v_on->s = ISS_OFF; v_off->s = ISS_ON; sendNewSwitch(video_prop); } else { return true; } //printf("Exposure end\n"); if (strcmp(cam_bp->format, ".fits") == 0) { //printf("Processing fits file\n"); // for CCD camera if ( ! ReadFITS(img,takeSubframe,subframe) ) { if (options & CAPTURE_SUBTRACT_DARK) { //printf("Subtracting dark\n"); SubtractDark(img); } if (options & CAPTURE_RECON) { if (PixSizeX != PixSizeY) SquarePixels(img, PixSizeX, PixSizeY); } return false; } else { return true; } } else if (strcmp(cam_bp->format, ".stream") == 0) { //printf("Processing stream file\n"); // for video camera return ReadStream(img); } else { pFrame->Alert(_("Unknown image format: ") + wxString::FromAscii(cam_bp->format)); return true; } } else { // in case the camera is not connected return true; } // we must never go here return true; }
bool Camera_ASCOMLateClass::Capture(int duration, usImage& img, int options, const wxRect& subframeArg) { bool retval = false; bool takeSubframe = UseSubframes; wxRect subframe(subframeArg); if (subframe.width <= 0 || subframe.height <= 0) { takeSubframe = false; } bool binning_changed = false; if (Binning != m_curBin) { FullSize = wxSize(m_maxSize.x / Binning, m_maxSize.y / Binning); binning_changed = true; } // Program the size if (!takeSubframe) { subframe = wxRect(0, 0, FullSize.GetWidth(), FullSize.GetHeight()); } if (img.Init(FullSize)) { pFrame->Alert(_("Cannot allocate memory to download image from camera")); return true; } GITObjRef cam(m_gitEntry); EXCEPINFO excep; if (binning_changed) { if (ASCOM_SetBin(cam.IDisp(), Binning, &excep)) { pFrame->Alert(_("The ASCOM camera failed to set binning. See the debug log for more information.")); return true; } m_curBin = Binning; } if (subframe != m_roi) { ASCOM_SetROI(cam.IDisp(), subframe, &excep); m_roi = subframe; } bool takeDark = HasShutter && ShutterClosed; // Start the exposure if (ASCOM_StartExposure(cam.IDisp(), (double)duration / 1000.0, takeDark, &excep)) { Debug.AddLine(ExcepMsg("ASCOM_StartExposure failed", excep)); pFrame->Alert(ExcepMsg(_("ASCOM error -- Cannot start exposure with given parameters"), excep)); return true; } CameraWatchdog watchdog(duration, GetTimeoutMs()); if (duration > 100) { // wait until near end of exposure if (WorkerThread::MilliSleep(duration - 100, WorkerThread::INT_ANY) && (WorkerThread::TerminateRequested() || AbortExposure())) { return true; } } while (true) // wait for image to finish and d/l { wxMilliSleep(20); bool ready; EXCEPINFO excep; if (ASCOM_ImageReady(cam.IDisp(), &ready, &excep)) { Debug.AddLine(ExcepMsg("ASCOM_ImageReady failed", excep)); pFrame->Alert(ExcepMsg(_("Exception thrown polling camera"), excep)); return true; } if (ready) break; if (WorkerThread::InterruptRequested() && (WorkerThread::TerminateRequested() || AbortExposure())) { return true; } if (watchdog.Expired()) { DisconnectWithAlert(CAPT_FAIL_TIMEOUT); return true; } } // Get the image if (ASCOM_Image(cam.IDisp(), img, takeSubframe, subframe, &excep)) { Debug.AddLine(ExcepMsg(_T("ASCOM_Image failed"), excep)); pFrame->Alert(ExcepMsg(_("Error reading image"), excep)); return true; } if (options & CAPTURE_SUBTRACT_DARK) SubtractDark(img); if (Color && Binning == 1 && (options & CAPTURE_RECON)) QuickLRecon(img); return false; }