Ref<Result> PDF417Reader::decode(Ref<BinaryBitmap> image, DecodeHints hints) { Ref<DecoderResult> decoderResult; /* 2012-05-30 hfn C++ DecodeHintType does not yet know a type "PURE_BARCODE", */ /* therefore skip this for now, todo: may be add this type later */ /* if (!hints.isEmpty() && hints.containsKey(DecodeHintType.PURE_BARCODE)) { BitMatrix bits = extractPureBits(image.getBlackMatrix()); decoderResult = decoder.decode(bits); points = NO_POINTS; } else { */ Detector detector(image); Ref<DetectorResult> detectorResult = detector.detect(hints); /* 2012-09-17 hints ("try_harder") */ ArrayRef< Ref<ResultPoint> > points(detectorResult->getPoints()); if (!hints.isEmpty()) { Ref<ResultPointCallback> rpcb = hints.getResultPointCallback(); /* .get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); */ if (rpcb != NULL) { for (int i = 0; i < points->size(); i++) { rpcb->foundPossibleResultPoint(*points[i]); } } } decoderResult = decoder.decode(detectorResult->getBits(),hints); /* } */ Ref<Result> r(new Result(decoderResult->getText(), decoderResult->getRawBytes(), points, BarcodeFormat::PDF_417)); return r; }
/* * viewfinder_callback * * This callback is invoked when an image frame from the camera viewfinder becomes available. * The frame is analyzed to determine if a barcode can be matched. * Frames come in NV12 format which makes code analysis very fast. */ void viewfinder_callback(camera_handle_t handle,camera_buffer_t* buf,void* arg) { camera_frame_nv12_t* data = (camera_frame_nv12_t*)(&(buf->framedesc)); uint8_t* buff = buf->framebuf; int stride = data->stride; int width = data->width; int height = data->height; try { Ref<LuminanceSource> source(new GreyscaleLuminanceSource((unsigned char *)buff, stride, height, 0,0,width,height)); Ref<Binarizer> binarizer(new HybridBinarizer(source)); Ref<BinaryBitmap> bitmap(new BinaryBitmap(binarizer)); Ref<Result> result; // setup the code reader MultiFormatReader *reader = new MultiFormatReader(); DecodeHints *hints = new DecodeHints(); hints->addFormat(BarcodeFormat_QR_CODE); hints->addFormat(BarcodeFormat_EAN_8); hints->addFormat(BarcodeFormat_EAN_13); hints->addFormat(BarcodeFormat_UPC_A); hints->addFormat(BarcodeFormat_UPC_E); hints->addFormat(BarcodeFormat_DATA_MATRIX); hints->addFormat(BarcodeFormat_CODE_128); hints->addFormat(BarcodeFormat_CODE_39); hints->addFormat(BarcodeFormat_ITF); hints->addFormat(BarcodeFormat_AZTEC); // attempt to decode and retrieve a valid QR code from the image bitmap result = reader->decode(bitmap, *hints); std::string newBarcodeData = result->getText()->getText().data(); Json::FastWriter writer; Json::Value root; root["value"] = newBarcodeData; std::string event = "community.barcodescanner.codefound.native"; // notify caller that a valid QR code has been decoded if ( eventDispatcher != NULL){ eventDispatcher->NotifyEvent(event + " " + writer.write(root)); } #ifdef DEBUG fprintf(stderr, "This is the detected Barcode : %s\n", newBarcodeData.c_str()); #endif } catch (const std::exception& ex) { #ifdef DEBUG fprintf( stderr, "error occured : \%s \n", ex.what()); #endif } }
Ref<Result> PDF417Reader::decode(Ref<BinaryBitmap> image, DecodeHints hints) { Ref<DecoderResult> decoderResult; /* 2012-05-30 hfn C++ DecodeHintType does not yet know a type "PURE_BARCODE", */ /* therefore skip this for now, todo: may be add this type later */ /* if (!hints.isEmpty() && hints.containsKey(DecodeHintType.PURE_BARCODE)) { BitMatrix bits = extractPureBits(image.getBlackMatrix()); decoderResult = decoder.decode(bits); points = NO_POINTS; } else { */ Detector detector(image); Ref<DetectorResult> detectorResult = detector.detect(); #if (defined _WIN32 && defined DEBUG) { WCHAR sz[256]; wsprintf(sz,L"PDF417Reader::decode: detected, %d\n",detectorResult->getPoints()[0]); OutputDebugString(sz); } #endif ArrayRef< Ref<ResultPoint> > points(detectorResult->getPoints()); if (!hints.isEmpty()) { Ref<ResultPointCallback> rpcb = hints.getResultPointCallback(); /* .get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); */ if (rpcb != NULL) { for (int i = 0; i < (int)points->size(); i++) { rpcb->foundPossibleResultPoint(*(points[i])); } } } decoderResult = decoder_.decode(detectorResult->getBits()); /* } */ Ref<Result> r(new Result(decoderResult->getText(), decoderResult->getRawBytes(), points, BarcodeFormat::PDF_417)); #if (defined _WIN32 && defined(DEBUG)) { WCHAR sz[1024]; wsprintf(sz,L"PDF417Reader::decode: \"%S\"\n",decoderResult->getText().object_->getText().c_str()); OutputDebugString(sz); } #endif fprintf( stdout, "PDF417Reader::decode: \"%s\"\n", decoderResult->getText().object_->getText().c_str()); return r; }
Ref<Result> OneDReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) { try { return doDecode(image, hints); } catch (NotFoundException const& nfe) { // std::cerr << "trying harder" << std::endl; bool tryHarder = hints.getTryHarder(); if (tryHarder && image->isRotateSupported()) { // std::cerr << "v rotate" << std::endl; Ref<BinaryBitmap> rotatedImage(image->rotateCounterClockwise()); // std::cerr << "^ rotate" << std::endl; Ref<Result> result = doDecode(rotatedImage, hints); // Doesn't have java metadata stuff ArrayRef< Ref<ResultPoint> >& points (result->getResultPoints()); if (points && !points->empty()) { int height = rotatedImage->getHeight(); for (int i = 0; i < points->size(); i++) { points[i].reset(new OneDResultPoint(height - points[i]->getY() - 1, points[i]->getX())); } } // std::cerr << "tried harder" << std::endl; return result; } else { // std::cerr << "tried harder nfe" << std::endl; throw nfe; } } }
//! [0] BarcodeDecoderControl::BarcodeDecoderControl(Container *parent) : CustomControl(parent) , m_camera(new Camera(parent)) , m_cameraSettings(new CameraSettings(this)) , m_landscapePreviewFrames(false) , m_nbuffers(2) { setRoot(m_camera); connect(m_camera, SIGNAL(cameraOpened()), this, SLOT(onCameraOpened())); connect(m_camera, SIGNAL(viewfinderStarted()), this, SLOT(viewfinderStarted())); connect(m_camera, SIGNAL(viewfinderStopped()), this, SLOT(onViewfinderStopped())); //Prepare the camera m_camera->open(CameraUnit::Rear); //Configure camera settings m_camera->getSettings(m_cameraSettings); m_cameraSettings->setCameraMode(CameraMode::Photo); m_cameraSettings->setFocusMode(CameraFocusMode::ContinuousMacro); if (m_camera->applySettings(m_cameraSettings)) qDebug() << "settings applied successfully"; //Prepare the decoder m_reader = Ref<MultiFormatReader>(new MultiFormatReader()); DecodeHints *hints = new DecodeHints(); hints->addFormat(BarcodeFormat_QR_CODE); hints->addFormat(BarcodeFormat_EAN_8); hints->addFormat(BarcodeFormat_EAN_13); hints->addFormat(BarcodeFormat_UPC_A); hints->addFormat(BarcodeFormat_UPC_E); hints->addFormat(BarcodeFormat_DATA_MATRIX); hints->addFormat(BarcodeFormat_CODE_128); hints->addFormat(BarcodeFormat_CODE_39); hints->addFormat(BarcodeFormat_ITF); hints->addFormat(BarcodeFormat_AZTEC); m_reader.object_->setHints(*hints); }
MultiFormatUPCEANReader::MultiFormatUPCEANReader(DecodeHints hints) : readers() { if (hints.containsFormat(BarcodeFormat_EAN_13)) { readers.push_back(Ref<OneDReader>(new EAN13Reader())); } else if (hints.containsFormat(BarcodeFormat_UPC_A)) { readers.push_back(Ref<OneDReader>(new UPCAReader())); } if (hints.containsFormat(BarcodeFormat_EAN_8)) { readers.push_back(Ref<OneDReader>(new EAN8Reader())); } if (hints.containsFormat(BarcodeFormat_UPC_E)) { readers.push_back(Ref<OneDReader>(new UPCEReader())); } if (readers.size() == 0) { readers.push_back(Ref<OneDReader>(new EAN13Reader())); // UPC-A is covered by EAN-13 readers.push_back(Ref<OneDReader>(new EAN8Reader())); readers.push_back(Ref<OneDReader>(new UPCEReader())); } }
std::vector<Ref<DetectorResult> > MultiDetector::detectMulti(DecodeHints hints){ Ref<BitMatrix> image = getImage(); MultiFinderPatternFinder finder = MultiFinderPatternFinder(image, hints.getResultPointCallback()); std::vector<Ref<FinderPatternInfo> > info = finder.findMulti(hints); std::vector<Ref<DetectorResult> > result; for(unsigned int i = 0; i < info.size(); i++){ try{ result.push_back(processFinderPatternInfo(info[i])); } catch (ReaderException const& e){ (void)e; // ignore } } return result; }
MultiFormatOneDReader::MultiFormatOneDReader(DecodeHints hints) : readers() { if (hints.containsFormat(BarcodeFormat::EAN_13) || hints.containsFormat(BarcodeFormat::EAN_8) || hints.containsFormat(BarcodeFormat::UPC_A) || hints.containsFormat(BarcodeFormat::UPC_E)) { readers.push_back(Ref<OneDReader>(new MultiFormatUPCEANReader(hints))); } if (hints.containsFormat(BarcodeFormat::CODE_39)) { readers.push_back(Ref<OneDReader>(new Code39Reader())); } if (hints.containsFormat(BarcodeFormat::CODE_93)) { readers.push_back(Ref<OneDReader>(new Code93Reader())); } if (hints.containsFormat(BarcodeFormat::CODE_128)) { readers.push_back(Ref<OneDReader>(new Code128Reader())); } if (hints.containsFormat(BarcodeFormat::ITF)) { readers.push_back(Ref<OneDReader>(new ITFReader())); } if (hints.containsFormat(BarcodeFormat::CODABAR)) { readers.push_back(Ref<OneDReader>(new CodaBarReader())); } /* if (hints.containsFormat(BarcodeFormat::RSS_14)) { readers.push_back(Ref<OneDReader>(new RSS14Reader())); } */ /* if (hints.containsFormat(BarcodeFormat::RSS_EXPANDED)) { readers.push_back(Ref<OneDReader>(new RSS14ExpandedReader())); } */ if (readers.size() == 0) { readers.push_back(Ref<OneDReader>(new MultiFormatUPCEANReader(hints))); readers.push_back(Ref<OneDReader>(new Code39Reader())); readers.push_back(Ref<OneDReader>(new CodaBarReader())); readers.push_back(Ref<OneDReader>(new Code93Reader())); readers.push_back(Ref<OneDReader>(new Code128Reader())); readers.push_back(Ref<OneDReader>(new ITFReader())); // readers.push_back(Ref<OneDReader>(new RSS14Reader())); // readers.push_back(Ref<OneDReader>(new RSS14ExpandedReader())); } }
Ref<Result> OneDReader::doDecode(Ref<BinaryBitmap> image, DecodeHints hints) { int width = image->getWidth(); int height = image->getHeight(); Ref<BitArray> row(new BitArray(width)); int middle = height >> 1; bool tryHarder = hints.getTryHarder(); int rowStep = std::max(1, height >> (tryHarder ? 8 : 5)); using namespace std; // cerr << "rS " << rowStep << " " << height << " " << tryHarder << endl; int maxLines; if (tryHarder) { maxLines = height; // Look at the whole image, not just the center } else { maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image } for (int x = 0; x < maxLines; x++) { // Scanning from the middle out. Determine which row we're looking at next: int rowStepsAboveOrBelow = (x + 1) >> 1; bool isAbove = (x & 0x01) == 0; // i.e. is x even? int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow); if (false) { std::cerr << "rN " << rowNumber << " " << height << " " << middle << " " << rowStep << " " << isAbove << " " << rowStepsAboveOrBelow << std::endl; } if (rowNumber < 0 || rowNumber >= height) { // Oops, if we run off the top or bottom, stop break; } // Estimate black point for this row and load it: try { row = image->getBlackRow(rowNumber, row); } catch (NotFoundException const& ignored) { (void)ignored; continue; } // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to // handle decoding upside down barcodes. for (int attempt = 0; attempt < 2; attempt++) { if (attempt == 1) { row->reverse(); // reverse the row and continue } // Java hints stuff missing try { // Look for a barcode // std::cerr << "rn " << rowNumber << " " << typeid(*this).name() << std::endl; Ref<Result> result = decodeRow(rowNumber, row); // We found our barcode if (attempt == 1) { // But it was upside down, so note that // result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(180)); // And remember to flip the result points horizontally. ArrayRef< Ref<ResultPoint> > points(result->getResultPoints()); if (points) { points[0] = Ref<ResultPoint>(new OneDResultPoint(width - points[0]->getX() - 1, points[0]->getY())); points[1] = Ref<ResultPoint>(new OneDResultPoint(width - points[1]->getX() - 1, points[1]->getY())); } } return result; } catch (ReaderException const& re) { (void)re; continue; } } } throw NotFoundException(); }
Ref<FinderPatternInfo> FinderPatternFinder::find(DecodeHints const &hints) { bool tryHarder = hints.getTryHarder(); size_t maxI = image_->getHeight(); size_t maxJ = image_->getWidth(); // We are looking for black/white/black/white/black modules in // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far // As this is used often, we use an integer array instead of vector int stateCount[5]; bool done = false; // Let's assume that the maximum version QR Code we support takes up 1/4 // the height of the image, and then account for the center being 3 // modules in size. This gives the smallest number of pixels the center // could be, so skip this often. When trying harder, look for all // QR versions regardless of how dense they are. int iSkip = (3 * maxI) / (4 * MAX_MODULES); if (iSkip < MIN_SKIP || tryHarder) { iSkip = MIN_SKIP; } // This is slightly faster than using the Ref. Efficiency is important here BitMatrix &matrix = *image_; for (size_t i = iSkip - 1; i < maxI && !done; i += iSkip) { // Get a row of black/white values stateCount[0] = 0; stateCount[1] = 0; stateCount[2] = 0; stateCount[3] = 0; stateCount[4] = 0; int currentState = 0; for (size_t j = 0; j < maxJ; j++) { if (matrix.get(j, i)) { // Black pixel if ((currentState & 1) == 1) { // Counting white pixels currentState++; } stateCount[currentState]++; } else { // White pixel if ((currentState & 1) == 0) { // Counting black pixels if (currentState == 4) { // A winner? if (foundPatternCross(stateCount)) { // Yes bool confirmed = handlePossibleCenter(stateCount, i, j); if (confirmed) { // Start examining every other line. Checking each line turned out to be too // expensive and didn't improve performance. iSkip = 2; if (hasSkipped_) { done = haveMultiplyConfirmedCenters(); } else { int rowSkip = findRowSkip(); if (rowSkip > stateCount[2]) { // Skip rows between row of lower confirmed center // and top of presumed third confirmed center // but back up a bit to get a full chance of detecting // it, entire width of center of finder pattern // Skip by rowSkip, but back off by stateCount[2] (size // of last center of pattern we saw) to be conservative, // and also back off by iSkip which is about to be // re-added i += rowSkip - stateCount[2] - iSkip; j = maxJ - 1; } } } else { stateCount[0] = stateCount[2]; stateCount[1] = stateCount[3]; stateCount[2] = stateCount[4]; stateCount[3] = 1; stateCount[4] = 0; currentState = 3; continue; } // Clear state to start looking again currentState = 0; stateCount[0] = 0; stateCount[1] = 0; stateCount[2] = 0; stateCount[3] = 0; stateCount[4] = 0; } else { // No, shift counts back by two stateCount[0] = stateCount[2]; stateCount[1] = stateCount[3]; stateCount[2] = stateCount[4]; stateCount[3] = 1; stateCount[4] = 0; currentState = 3; } } else { stateCount[++currentState]++; } } else { // Counting white pixels stateCount[currentState]++; } } } if (foundPatternCross(stateCount)) { bool confirmed = handlePossibleCenter(stateCount, i, maxJ); if (confirmed) { iSkip = stateCount[0]; if (hasSkipped_) { // Found a third one done = haveMultiplyConfirmedCenters(); } } } } vector<Ref<FinderPattern> > patternInfo = selectBestPatterns(); patternInfo = orderBestPatterns(patternInfo); Ref<FinderPatternInfo> result(new FinderPatternInfo(patternInfo)); return result; }
Ref<DetectorResult> Detector::detect(DecodeHints const& hints) { callback_ = hints.getResultPointCallback(); FinderPatternFinder finder(image_, hints.getResultPointCallback()); Ref<FinderPatternInfo> info(finder.find(hints)); return processFinderPatternInfo(info); }
void MultiFormatReader::setHints(DecodeHints hints) { hints_ = hints; readers_.clear(); bool tryHarder = hints.getTryHarder(); bool addOneDReader = hints.containsFormat(BarcodeFormat::UPC_E) || hints.containsFormat(BarcodeFormat::UPC_A) || hints.containsFormat(BarcodeFormat::UPC_E) || hints.containsFormat(BarcodeFormat::EAN_13) || hints.containsFormat(BarcodeFormat::EAN_8) || hints.containsFormat(BarcodeFormat::CODABAR) || hints.containsFormat(BarcodeFormat::CODE_39) || hints.containsFormat(BarcodeFormat::CODE_93) || hints.containsFormat(BarcodeFormat::CODE_128) || hints.containsFormat(BarcodeFormat::ITF) || hints.containsFormat(BarcodeFormat::RSS_14) || hints.containsFormat(BarcodeFormat::RSS_EXPANDED); if (addOneDReader && !tryHarder) { readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints))); } if (hints.containsFormat(BarcodeFormat::QR_CODE)) { readers_.push_back(Ref<Reader>(new zxing::qrcode::QRCodeReader())); } if (hints.containsFormat(BarcodeFormat::DATA_MATRIX)) { readers_.push_back(Ref<Reader>(new zxing::datamatrix::DataMatrixReader())); } if (hints.containsFormat(BarcodeFormat::AZTEC)) { readers_.push_back(Ref<Reader>(new zxing::aztec::AztecReader())); } if (hints.containsFormat(BarcodeFormat::PDF_417)) { readers_.push_back(Ref<Reader>(new zxing::pdf417::PDF417Reader())); } /* if (formats.contains(BarcodeFormat.PDF_417)) { readers.add(new PDF417Reader()); } if (formats.contains(BarcodeFormat.MAXICODE)) { readers.add(new MaxiCodeReader()); } */ if (addOneDReader && tryHarder) { readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints))); } if (readers_.size() == 0) { if (!tryHarder) { readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints))); } readers_.push_back(Ref<Reader>(new zxing::qrcode::QRCodeReader())); readers_.push_back(Ref<Reader>(new zxing::datamatrix::DataMatrixReader())); readers_.push_back(Ref<Reader>(new zxing::aztec::AztecReader())); readers_.push_back(Ref<Reader>(new zxing::pdf417::PDF417Reader())); // readers.add(new PDF417Reader()); // readers.add(new MaxiCodeReader()); if (tryHarder) { readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints))); } } }
vector<Ref<FinderPatternInfo> > MultiFinderPatternFinder::findMulti(DecodeHints const& hints){ bool tryHarder = hints.getTryHarder(); Ref<BitMatrix> image = image_; // Protected member int maxI = image->getHeight(); int maxJ = image->getWidth(); // We are looking for black/white/black/white/black modules in // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the // image, and then account for the center being 3 modules in size. This gives the smallest // number of pixels the center could be, so skip this often. When trying harder, look for all // QR versions regardless of how dense they are. int iSkip = (int) (maxI / (MAX_MODULES * 4.0f) * 3); if (iSkip < MIN_SKIP || tryHarder) { iSkip = MIN_SKIP; } int stateCount[5]; for (int i = iSkip - 1; i < maxI; i += iSkip) { // Get a row of black/white values stateCount[0] = 0; stateCount[1] = 0; stateCount[2] = 0; stateCount[3] = 0; stateCount[4] = 0; int currentState = 0; for (int j = 0; j < maxJ; j++) { if (image->get(j, i)) { // Black pixel if ((currentState & 1) == 1) { // Counting white pixels currentState++; } stateCount[currentState]++; } else { // White pixel if ((currentState & 1) == 0) { // Counting black pixels if (currentState == 4) { // A winner? if (foundPatternCross(stateCount) && handlePossibleCenter(stateCount, i, j)) { // Yes // Clear state to start looking again currentState = 0; stateCount[0] = 0; stateCount[1] = 0; stateCount[2] = 0; stateCount[3] = 0; stateCount[4] = 0; } else { // No, shift counts back by two stateCount[0] = stateCount[2]; stateCount[1] = stateCount[3]; stateCount[2] = stateCount[4]; stateCount[3] = 1; stateCount[4] = 0; currentState = 3; } } else { stateCount[++currentState]++; } } else { // Counting white pixels stateCount[currentState]++; } } } // for j=... if (foundPatternCross(stateCount)) { handlePossibleCenter(stateCount, i, maxJ); } // end if foundPatternCross } // for i=iSkip-1 ... vector<vector<Ref<FinderPattern> > > patternInfo = selectBestPatterns(); vector<Ref<FinderPatternInfo> > result; for (unsigned int i = 0; i < patternInfo.size(); i++) { vector<Ref<FinderPattern> > pattern = patternInfo[i]; pattern = FinderPatternFinder::orderBestPatterns(pattern); result.push_back(Ref<FinderPatternInfo>(new FinderPatternInfo(pattern))); } return result; }
void TcZXing::setDecoder(DecoderFormatType hint) { DecodeHints newHints; if(hint & DecoderFormat_QR_CODE) newHints.addFormat((BarcodeFormat)BarcodeFormat_QR_CODE); if(hint & DecoderFormat_DATA_MATRIX) newHints.addFormat((BarcodeFormat)BarcodeFormat_DATA_MATRIX); if(hint & DecoderFormat_UPC_E) newHints.addFormat((BarcodeFormat)BarcodeFormat_UPC_E); if(hint & DecoderFormat_UPC_A) newHints.addFormat((BarcodeFormat)BarcodeFormat_UPC_A); if(hint & DecoderFormat_EAN_8) newHints.addFormat((BarcodeFormat)BarcodeFormat_EAN_8); if(hint & DecoderFormat_EAN_13) newHints.addFormat((BarcodeFormat)BarcodeFormat_EAN_13); if(hint & DecoderFormat_CODE_128) newHints.addFormat((BarcodeFormat)BarcodeFormat_CODE_128); if(hint & DecoderFormat_CODE_39) newHints.addFormat((BarcodeFormat)BarcodeFormat_CODE_39); if(hint & DecoderFormat_ITF) newHints.addFormat((BarcodeFormat)BarcodeFormat_ITF); if(hint & DecoderFormat_Aztec) newHints.addFormat((BarcodeFormat)BarcodeFormat_AZTEC); supportedFormats = newHints.getCurrentHint(); }