File indexing completed on 2024-04-14 03:42:38
0001 /* 0002 SPDX-FileCopyrightText: 2022 Jasem Mutlaq <mutlaqja@ikarustech.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "indicamerachip.h" 0008 #include "indicamera.h" 0009 0010 #include "Options.h" 0011 0012 #include "indi_debug.h" 0013 0014 namespace ISD 0015 { 0016 0017 CameraChip::CameraChip(ISD::Camera *camera, ChipType type): m_Camera(camera), m_Type(type) {} 0018 0019 FITSView *CameraChip::getImageView(FITSMode imageType) 0020 { 0021 switch (imageType) 0022 { 0023 case FITS_NORMAL: 0024 return normalImage; 0025 0026 case FITS_FOCUS: 0027 return focusImage; 0028 0029 case FITS_GUIDE: 0030 return guideImage; 0031 0032 case FITS_CALIBRATE: 0033 return calibrationImage; 0034 0035 case FITS_ALIGN: 0036 return alignImage; 0037 0038 default: 0039 break; 0040 } 0041 0042 return nullptr; 0043 } 0044 0045 void CameraChip::setImageView(FITSView *image, FITSMode imageType) 0046 { 0047 switch (imageType) 0048 { 0049 case FITS_NORMAL: 0050 normalImage = image; 0051 break; 0052 0053 case FITS_FOCUS: 0054 focusImage = image; 0055 break; 0056 0057 case FITS_GUIDE: 0058 guideImage = image; 0059 break; 0060 0061 case FITS_CALIBRATE: 0062 calibrationImage = image; 0063 break; 0064 0065 case FITS_ALIGN: 0066 alignImage = image; 0067 break; 0068 0069 default: 0070 break; 0071 } 0072 0073 if (image) 0074 imageData = image->imageData(); 0075 } 0076 0077 bool CameraChip::getFrameMinMax(int *minX, int *maxX, int *minY, int *maxY, int *minW, int *maxW, int *minH, int *maxH) 0078 { 0079 INumberVectorProperty *frameProp = nullptr; 0080 0081 switch (m_Type) 0082 { 0083 case PRIMARY_CCD: 0084 frameProp = m_Camera->getNumber("CCD_FRAME"); 0085 break; 0086 0087 case GUIDE_CCD: 0088 frameProp = m_Camera->getNumber("GUIDER_FRAME"); 0089 break; 0090 } 0091 0092 if (frameProp == nullptr) 0093 return false; 0094 0095 INumber *arg = IUFindNumber(frameProp, "X"); 0096 0097 if (arg == nullptr) 0098 return false; 0099 0100 if (minX) 0101 *minX = arg->min; 0102 if (maxX) 0103 *maxX = arg->max; 0104 0105 arg = IUFindNumber(frameProp, "Y"); 0106 0107 if (arg == nullptr) 0108 return false; 0109 0110 if (minY) 0111 *minY = arg->min; 0112 if (maxY) 0113 *maxY = arg->max; 0114 0115 arg = IUFindNumber(frameProp, "WIDTH"); 0116 0117 if (arg == nullptr) 0118 return false; 0119 0120 if (minW) 0121 *minW = arg->min; 0122 if (maxW) 0123 *maxW = arg->max; 0124 0125 arg = IUFindNumber(frameProp, "HEIGHT"); 0126 0127 if (arg == nullptr) 0128 return false; 0129 0130 if (minH) 0131 *minH = arg->min; 0132 if (maxH) 0133 *maxH = arg->max; 0134 0135 return true; 0136 } 0137 0138 bool CameraChip::setImageInfo(uint16_t width, uint16_t height, double pixelX, double pixelY, uint8_t bitdepth) 0139 { 0140 INumberVectorProperty *ccdInfoProp = nullptr; 0141 0142 switch (m_Type) 0143 { 0144 case PRIMARY_CCD: 0145 ccdInfoProp = m_Camera->getNumber("CCD_INFO"); 0146 break; 0147 0148 case GUIDE_CCD: 0149 ccdInfoProp = m_Camera->getNumber("GUIDER_INFO"); 0150 break; 0151 } 0152 0153 if (ccdInfoProp == nullptr) 0154 return false; 0155 0156 ccdInfoProp->np[0].value = width; 0157 ccdInfoProp->np[1].value = height; 0158 ccdInfoProp->np[2].value = std::hypotf(pixelX, pixelY); 0159 ccdInfoProp->np[3].value = pixelX; 0160 ccdInfoProp->np[4].value = pixelY; 0161 ccdInfoProp->np[5].value = bitdepth; 0162 0163 m_Camera->sendNewProperty(ccdInfoProp); 0164 0165 return true; 0166 } 0167 0168 bool CameraChip::getImageInfo(uint16_t &width, uint16_t &height, double &pixelX, double &pixelY, uint8_t &bitdepth) 0169 { 0170 INumberVectorProperty *ccdInfoProp = nullptr; 0171 0172 switch (m_Type) 0173 { 0174 case PRIMARY_CCD: 0175 ccdInfoProp = m_Camera->getNumber("CCD_INFO"); 0176 break; 0177 0178 case GUIDE_CCD: 0179 ccdInfoProp = m_Camera->getNumber("GUIDER_INFO"); 0180 break; 0181 } 0182 0183 if (ccdInfoProp == nullptr) 0184 return false; 0185 0186 width = ccdInfoProp->np[0].value; 0187 height = ccdInfoProp->np[1].value; 0188 pixelX = ccdInfoProp->np[2].value; 0189 pixelY = ccdInfoProp->np[3].value; 0190 bitdepth = ccdInfoProp->np[5].value; 0191 0192 return true; 0193 } 0194 0195 bool CameraChip::getBayerInfo(uint16_t &offsetX, uint16_t &offsetY, QString &pattern) 0196 { 0197 ITextVectorProperty * bayerTP = m_Camera->getText("CCD_CFA"); 0198 if (!bayerTP) 0199 return false; 0200 0201 offsetX = QString(bayerTP->tp[0].text).toInt(); 0202 offsetY = QString(bayerTP->tp[1].text).toInt(); 0203 pattern = QString(bayerTP->tp[2].text); 0204 0205 return true; 0206 } 0207 0208 bool CameraChip::getFrame(int *x, int *y, int *w, int *h) 0209 { 0210 INumberVectorProperty *frameProp = nullptr; 0211 0212 switch (m_Type) 0213 { 0214 case PRIMARY_CCD: 0215 frameProp = m_Camera->getNumber("CCD_FRAME"); 0216 break; 0217 0218 case GUIDE_CCD: 0219 frameProp = m_Camera->getNumber("GUIDER_FRAME"); 0220 break; 0221 } 0222 0223 if (frameProp == nullptr) 0224 return false; 0225 0226 INumber *arg = IUFindNumber(frameProp, "X"); 0227 0228 if (arg == nullptr) 0229 return false; 0230 0231 *x = arg->value; 0232 0233 arg = IUFindNumber(frameProp, "Y"); 0234 if (arg == nullptr) 0235 return false; 0236 0237 *y = arg->value; 0238 0239 arg = IUFindNumber(frameProp, "WIDTH"); 0240 if (arg == nullptr) 0241 return false; 0242 0243 *w = arg->value; 0244 0245 arg = IUFindNumber(frameProp, "HEIGHT"); 0246 if (arg == nullptr) 0247 return false; 0248 0249 *h = arg->value; 0250 0251 return true; 0252 } 0253 0254 bool CameraChip::resetFrame() 0255 { 0256 INumberVectorProperty *frameProp = nullptr; 0257 0258 switch (m_Type) 0259 { 0260 case PRIMARY_CCD: 0261 frameProp = m_Camera->getNumber("CCD_FRAME"); 0262 break; 0263 0264 case GUIDE_CCD: 0265 frameProp = m_Camera->getNumber("GUIDER_FRAME"); 0266 break; 0267 } 0268 0269 if (frameProp == nullptr) 0270 return false; 0271 0272 INumber *xarg = IUFindNumber(frameProp, "X"); 0273 INumber *yarg = IUFindNumber(frameProp, "Y"); 0274 INumber *warg = IUFindNumber(frameProp, "WIDTH"); 0275 INumber *harg = IUFindNumber(frameProp, "HEIGHT"); 0276 0277 if (xarg && yarg && warg && harg) 0278 { 0279 if (!std::fabs(xarg->value - xarg->min) && 0280 !std::fabs(yarg->value - yarg->min) && 0281 !std::fabs(warg->value - warg->max) && 0282 !std::fabs(harg->value - harg->max)) 0283 return false; 0284 0285 xarg->value = xarg->min; 0286 yarg->value = yarg->min; 0287 warg->value = warg->max; 0288 harg->value = harg->max; 0289 0290 m_Camera->sendNewProperty(frameProp); 0291 return true; 0292 } 0293 0294 return false; 0295 } 0296 0297 bool CameraChip::setFrame(int x, int y, int w, int h, bool force) 0298 { 0299 INumberVectorProperty *frameProp = nullptr; 0300 0301 switch (m_Type) 0302 { 0303 case PRIMARY_CCD: 0304 frameProp = m_Camera->getNumber("CCD_FRAME"); 0305 break; 0306 0307 case GUIDE_CCD: 0308 frameProp = m_Camera->getNumber("GUIDER_FRAME"); 0309 break; 0310 } 0311 0312 if (frameProp == nullptr) 0313 return false; 0314 0315 INumber *xarg = IUFindNumber(frameProp, "X"); 0316 INumber *yarg = IUFindNumber(frameProp, "Y"); 0317 INumber *warg = IUFindNumber(frameProp, "WIDTH"); 0318 INumber *harg = IUFindNumber(frameProp, "HEIGHT"); 0319 0320 if (xarg && yarg && warg && harg) 0321 { 0322 if (!force && 0323 !std::fabs(xarg->value - x) && 0324 !std::fabs(yarg->value - y) && 0325 !std::fabs(warg->value - w) && 0326 !std::fabs(harg->value - h)) 0327 return true; 0328 0329 xarg->value = x; 0330 yarg->value = y; 0331 warg->value = w; 0332 harg->value = h; 0333 0334 m_Camera->sendNewProperty(frameProp); 0335 return true; 0336 } 0337 0338 return false; 0339 } 0340 0341 bool CameraChip::capture(double exposure) 0342 { 0343 //qCDebug(KSTARS_INDI) << "IndiCCD: capture()" << (type==PRIMARY_CCD?"CCD":"Guide"); 0344 INumberVectorProperty *expProp = nullptr; 0345 0346 switch (m_Type) 0347 { 0348 case PRIMARY_CCD: 0349 expProp = m_Camera->getNumber("CCD_EXPOSURE"); 0350 break; 0351 0352 case GUIDE_CCD: 0353 expProp = m_Camera->getNumber("GUIDER_EXPOSURE"); 0354 break; 0355 } 0356 0357 if (expProp == nullptr) 0358 return false; 0359 0360 // If we have exposure presets, let's limit the exposure value 0361 // to the preset values if it falls within their range of max/min 0362 if (Options::forceDSLRPresets()) 0363 { 0364 QMap<QString, double> exposurePresets = m_Camera->getExposurePresets(); 0365 if (!exposurePresets.isEmpty()) 0366 { 0367 double min, max; 0368 QPair<double, double> minmax = m_Camera->getExposurePresetsMinMax(); 0369 min = minmax.first; 0370 max = minmax.second; 0371 if (exposure > min && exposure < max) 0372 { 0373 double diff = 1e6; 0374 double closestMatch = exposure; 0375 for (const auto &oneValue : exposurePresets.values()) 0376 { 0377 double newDiff = std::fabs(exposure - oneValue); 0378 if (newDiff < diff) 0379 { 0380 closestMatch = oneValue; 0381 diff = newDiff; 0382 } 0383 } 0384 0385 qCDebug(KSTARS_INDI) << "Requested exposure" << exposure << "closes match is" << closestMatch; 0386 exposure = closestMatch; 0387 } 0388 } 0389 } 0390 0391 // clone the INumberVectorProperty, to avoid modifications to the same 0392 // property from two threads 0393 INumber n; 0394 strcpy(n.name, expProp->np[0].name); 0395 n.value = exposure; 0396 0397 std::unique_ptr<INumberVectorProperty> newExpProp(new INumberVectorProperty()); 0398 strncpy(newExpProp->device, expProp->device, MAXINDIDEVICE); 0399 strncpy(newExpProp->name, expProp->name, MAXINDINAME); 0400 strncpy(newExpProp->label, expProp->label, MAXINDILABEL); 0401 newExpProp->np = &n; 0402 newExpProp->nnp = 1; 0403 0404 m_Camera->sendNewProperty(newExpProp.get()); 0405 0406 return true; 0407 } 0408 0409 bool CameraChip::abortExposure() 0410 { 0411 if (!m_Camera) return false; 0412 ISwitchVectorProperty *abortProp = nullptr; 0413 0414 switch (m_Type) 0415 { 0416 case PRIMARY_CCD: 0417 abortProp = m_Camera->getSwitch("CCD_ABORT_EXPOSURE"); 0418 break; 0419 0420 case GUIDE_CCD: 0421 abortProp = m_Camera->getSwitch("GUIDER_ABORT_EXPOSURE"); 0422 break; 0423 } 0424 0425 if (abortProp == nullptr) 0426 return false; 0427 0428 ISwitch *abort = IUFindSwitch(abortProp, "ABORT"); 0429 0430 if (abort == nullptr) 0431 return false; 0432 0433 abort->s = ISS_ON; 0434 0435 m_Camera->sendNewProperty(abortProp); 0436 0437 return true; 0438 } 0439 bool CameraChip::canBin() const 0440 { 0441 return CanBin && m_Camera->getEncodingFormat() != QLatin1String("Native"); 0442 } 0443 0444 void CameraChip::setCanBin(bool value) 0445 { 0446 CanBin = value; 0447 } 0448 0449 bool CameraChip::canSubframe() const 0450 { 0451 return CanSubframe && m_Camera->getEncodingFormat() != QLatin1String("Native"); 0452 } 0453 0454 void CameraChip::setCanSubframe(bool value) 0455 { 0456 CanSubframe = value; 0457 } 0458 bool CameraChip::canAbort() const 0459 { 0460 return CanAbort; 0461 } 0462 0463 void CameraChip::setCanAbort(bool value) 0464 { 0465 CanAbort = value; 0466 } 0467 0468 const QSharedPointer<FITSData> &CameraChip::getImageData() const 0469 { 0470 return imageData; 0471 } 0472 0473 int CameraChip::getISOIndex() const 0474 { 0475 auto isoProp = m_Camera->getSwitch("CCD_ISO"); 0476 0477 if (!isoProp) 0478 return -1; 0479 0480 return isoProp->findOnSwitchIndex(); 0481 } 0482 0483 bool CameraChip::getISOValue(QString &value) const 0484 { 0485 auto index = getISOIndex(); 0486 auto list = getISOList(); 0487 if (!list.isEmpty() && index >= 0 && index < list.count()) 0488 { 0489 value = list[index]; 0490 return true; 0491 } 0492 0493 return false; 0494 } 0495 0496 bool CameraChip::setISOIndex(int value) 0497 { 0498 auto isoProp = m_Camera->getSwitch("CCD_ISO"); 0499 0500 if (!isoProp) 0501 return false; 0502 0503 isoProp->reset(); 0504 isoProp->at(value)->setState(ISS_ON); 0505 0506 m_Camera->sendNewProperty(isoProp); 0507 0508 return true; 0509 } 0510 0511 QStringList CameraChip::getISOList() const 0512 { 0513 QStringList isoList; 0514 0515 auto isoProp = m_Camera->getSwitch("CCD_ISO"); 0516 0517 if (!isoProp) 0518 return isoList; 0519 0520 for (const auto &it : *isoProp) 0521 isoList << it.getLabel(); 0522 0523 return isoList; 0524 } 0525 0526 bool CameraChip::isCapturing() 0527 { 0528 if (!m_Camera) return false; 0529 INumberVectorProperty *expProp = nullptr; 0530 0531 switch (m_Type) 0532 { 0533 case PRIMARY_CCD: 0534 expProp = m_Camera->getNumber("CCD_EXPOSURE"); 0535 break; 0536 0537 case GUIDE_CCD: 0538 expProp = m_Camera->getNumber("GUIDER_EXPOSURE"); 0539 break; 0540 } 0541 0542 if (expProp == nullptr) 0543 return false; 0544 0545 return (expProp->s == IPS_BUSY); 0546 } 0547 0548 bool CameraChip::setFrameType(const QString &name) 0549 { 0550 CCDFrameType fType = FRAME_LIGHT; 0551 0552 if (name == "FRAME_LIGHT" || name == "Light") 0553 fType = FRAME_LIGHT; 0554 else if (name == "FRAME_DARK" || name == "Dark") 0555 fType = FRAME_DARK; 0556 else if (name == "FRAME_BIAS" || name == "Bias") 0557 fType = FRAME_BIAS; 0558 else if (name == "FRAME_FLAT" || name == "Flat") 0559 fType = FRAME_FLAT; 0560 else 0561 { 0562 qCWarning(KSTARS_INDI) << name << " frame type is unknown." ; 0563 return false; 0564 } 0565 0566 return setFrameType(fType); 0567 } 0568 0569 bool CameraChip::setFrameType(CCDFrameType fType) 0570 { 0571 ISwitchVectorProperty *frameProp = nullptr; 0572 0573 if (m_Type == PRIMARY_CCD) 0574 frameProp = m_Camera->getSwitch("CCD_FRAME_TYPE"); 0575 else 0576 frameProp = m_Camera->getSwitch("GUIDER_FRAME_TYPE"); 0577 if (frameProp == nullptr) 0578 return false; 0579 0580 ISwitch *ccdFrame = nullptr; 0581 0582 if (fType == FRAME_LIGHT) 0583 ccdFrame = IUFindSwitch(frameProp, "FRAME_LIGHT"); 0584 else if (fType == FRAME_DARK) 0585 ccdFrame = IUFindSwitch(frameProp, "FRAME_DARK"); 0586 else if (fType == FRAME_BIAS) 0587 ccdFrame = IUFindSwitch(frameProp, "FRAME_BIAS"); 0588 else if (fType == FRAME_FLAT) 0589 ccdFrame = IUFindSwitch(frameProp, "FRAME_FLAT"); 0590 0591 if (ccdFrame == nullptr) 0592 return false; 0593 0594 if (ccdFrame->s == ISS_ON) 0595 return true; 0596 0597 if (fType != FRAME_LIGHT) 0598 captureMode = FITS_CALIBRATE; 0599 0600 IUResetSwitch(frameProp); 0601 ccdFrame->s = ISS_ON; 0602 0603 m_Camera->sendNewProperty(frameProp); 0604 0605 return true; 0606 } 0607 0608 CCDFrameType CameraChip::getFrameType() 0609 { 0610 CCDFrameType fType = FRAME_LIGHT; 0611 ISwitchVectorProperty *frameProp = nullptr; 0612 0613 if (m_Type == PRIMARY_CCD) 0614 frameProp = m_Camera->getSwitch("CCD_FRAME_TYPE"); 0615 else 0616 frameProp = m_Camera->getSwitch("GUIDER_FRAME_TYPE"); 0617 0618 if (frameProp == nullptr) 0619 return fType; 0620 0621 ISwitch *ccdFrame = nullptr; 0622 0623 ccdFrame = IUFindOnSwitch(frameProp); 0624 0625 if (ccdFrame == nullptr) 0626 { 0627 qCWarning(KSTARS_INDI) << "ISD:CCD Cannot find active frame in CCD!"; 0628 return fType; 0629 } 0630 0631 if (!strcmp(ccdFrame->name, "FRAME_LIGHT")) 0632 fType = FRAME_LIGHT; 0633 else if (!strcmp(ccdFrame->name, "FRAME_DARK")) 0634 fType = FRAME_DARK; 0635 else if (!strcmp(ccdFrame->name, "FRAME_FLAT")) 0636 fType = FRAME_FLAT; 0637 else if (!strcmp(ccdFrame->name, "FRAME_BIAS")) 0638 fType = FRAME_BIAS; 0639 0640 return fType; 0641 } 0642 0643 bool CameraChip::setBinning(CCDBinType binType) 0644 { 0645 switch (binType) 0646 { 0647 case SINGLE_BIN: 0648 return setBinning(1, 1); 0649 case DOUBLE_BIN: 0650 return setBinning(2, 2); 0651 case TRIPLE_BIN: 0652 return setBinning(3, 3); 0653 case QUADRAPLE_BIN: 0654 return setBinning(4, 4); 0655 } 0656 0657 return false; 0658 } 0659 0660 CCDBinType CameraChip::getBinning() 0661 { 0662 CCDBinType binType = SINGLE_BIN; 0663 INumberVectorProperty *binProp = nullptr; 0664 0665 switch (m_Type) 0666 { 0667 case PRIMARY_CCD: 0668 binProp = m_Camera->getNumber("CCD_BINNING"); 0669 break; 0670 0671 case GUIDE_CCD: 0672 binProp = m_Camera->getNumber("GUIDER_BINNING"); 0673 break; 0674 } 0675 0676 if (binProp == nullptr) 0677 return binType; 0678 0679 INumber *horBin = nullptr, *verBin = nullptr; 0680 0681 horBin = IUFindNumber(binProp, "HOR_BIN"); 0682 verBin = IUFindNumber(binProp, "VER_BIN"); 0683 0684 if (!horBin || !verBin) 0685 return binType; 0686 0687 switch (static_cast<int>(horBin->value)) 0688 { 0689 case 2: 0690 binType = DOUBLE_BIN; 0691 break; 0692 0693 case 3: 0694 binType = TRIPLE_BIN; 0695 break; 0696 0697 case 4: 0698 binType = QUADRAPLE_BIN; 0699 break; 0700 0701 default: 0702 break; 0703 } 0704 0705 return binType; 0706 } 0707 0708 bool CameraChip::getBinning(int *bin_x, int *bin_y) 0709 { 0710 INumberVectorProperty *binProp = nullptr; 0711 *bin_x = *bin_y = 1; 0712 0713 switch (m_Type) 0714 { 0715 case PRIMARY_CCD: 0716 binProp = m_Camera->getNumber("CCD_BINNING"); 0717 break; 0718 0719 case GUIDE_CCD: 0720 binProp = m_Camera->getNumber("GUIDER_BINNING"); 0721 break; 0722 } 0723 0724 if (binProp == nullptr) 0725 return false; 0726 0727 INumber *horBin = nullptr, *verBin = nullptr; 0728 0729 horBin = IUFindNumber(binProp, "HOR_BIN"); 0730 verBin = IUFindNumber(binProp, "VER_BIN"); 0731 0732 if (!horBin || !verBin) 0733 return false; 0734 0735 *bin_x = horBin->value; 0736 *bin_y = verBin->value; 0737 0738 return true; 0739 } 0740 0741 bool CameraChip::getMaxBin(int *max_xbin, int *max_ybin) 0742 { 0743 if (!max_xbin || !max_ybin) 0744 return false; 0745 0746 INumberVectorProperty *binProp = nullptr; 0747 0748 *max_xbin = *max_ybin = 1; 0749 0750 switch (m_Type) 0751 { 0752 case PRIMARY_CCD: 0753 binProp = m_Camera->getNumber("CCD_BINNING"); 0754 break; 0755 0756 case GUIDE_CCD: 0757 binProp = m_Camera->getNumber("GUIDER_BINNING"); 0758 break; 0759 } 0760 0761 if (binProp == nullptr) 0762 return false; 0763 0764 INumber *horBin = nullptr, *verBin = nullptr; 0765 0766 horBin = IUFindNumber(binProp, "HOR_BIN"); 0767 verBin = IUFindNumber(binProp, "VER_BIN"); 0768 0769 if (!horBin || !verBin) 0770 return false; 0771 0772 *max_xbin = horBin->max; 0773 *max_ybin = verBin->max; 0774 0775 return true; 0776 } 0777 0778 bool CameraChip::setBinning(int bin_x, int bin_y) 0779 { 0780 INumberVectorProperty *binProp = nullptr; 0781 0782 switch (m_Type) 0783 { 0784 case PRIMARY_CCD: 0785 binProp = m_Camera->getNumber("CCD_BINNING"); 0786 break; 0787 0788 case GUIDE_CCD: 0789 binProp = m_Camera->getNumber("GUIDER_BINNING"); 0790 break; 0791 } 0792 0793 if (binProp == nullptr) 0794 return false; 0795 0796 INumber *horBin = IUFindNumber(binProp, "HOR_BIN"); 0797 INumber *verBin = IUFindNumber(binProp, "VER_BIN"); 0798 0799 if (!horBin || !verBin) 0800 return false; 0801 0802 if (!std::fabs(horBin->value - bin_x) && !std::fabs(verBin->value - bin_y)) 0803 return true; 0804 0805 if (bin_x > horBin->max || bin_y > verBin->max) 0806 return false; 0807 0808 horBin->value = bin_x; 0809 verBin->value = bin_y; 0810 0811 m_Camera->sendNewProperty(binProp); 0812 0813 return true; 0814 } 0815 0816 }