diff --git a/AUTHORS b/AUTHORS index e2f33f5af..b30e0c33d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -30,6 +30,7 @@ Mateusz JÄ™drasik Matthew Schulkind (Google) Matt York (LifeMarks) Mohamad Fairol +Nikolaos Ftylitakis Paul Hackenberger Randy Shen (Acer) Rasmus Schrøder Sørensen diff --git a/symbian/QQrDecoder/CameraImageWrapper.cpp b/symbian/QQrDecoder/CameraImageWrapper.cpp new file mode 100644 index 000000000..e8ac50f2c --- /dev/null +++ b/symbian/QQrDecoder/CameraImageWrapper.cpp @@ -0,0 +1,77 @@ +#include "CameraImageWrapper.h" +#include +#include +#include + +CameraImageWrapper::CameraImageWrapper() : LuminanceSource() +{ +} + +CameraImageWrapper::CameraImageWrapper(CameraImageWrapper& otherInstance) : LuminanceSource() +{ + image = otherInstance.getOriginalImage().copy(); +} + +CameraImageWrapper::~CameraImageWrapper() +{ +} + +int CameraImageWrapper::getWidth() +{ + return image.width(); +} + +int CameraImageWrapper::getHeight() +{ + return image.height(); +} + +unsigned char CameraImageWrapper::getPixel(int x, int y) +{ + QRgb pixel = image.pixel(x,y); + + return qGray(pixel);//((qRed(pixel) + qGreen(pixel) + qBlue(pixel)) / 3); +} + +void CameraImageWrapper::setImage(QString fileName, char* format) +{ + image.load(fileName); + + if(image.width() > QApplication::desktop()->width()) + image = image.scaled(QApplication::desktop()->width(), image.height(), Qt::IgnoreAspectRatio); + + if(image.height() > QApplication::desktop()->height()) + image = image.scaled(image.width(), QApplication::desktop()->height(), Qt::IgnoreAspectRatio); +} + +void CameraImageWrapper::setImage(QImage newImage) +{ + image = newImage.copy(); + + if(image.width() > 640) + image = image.scaled(640, image.height(), Qt::KeepAspectRatio); +} + +QImage CameraImageWrapper::grayScaleImage(QImage::Format f) +{ + QImage tmp(image.width(), image.height(), f); + for(int i=0; i +#include +#include + +using namespace zxing; + +class CameraImageWrapper : public LuminanceSource +{ +public: + CameraImageWrapper(); + CameraImageWrapper(CameraImageWrapper& otherInstance); + ~CameraImageWrapper(); + + int getWidth(); + int getHeight(); + + unsigned char getPixel(int x, int y); + + void setImage(QString fileName, char* format); + void setImage(QImage newImage); + QImage grayScaleImage(QImage::Format f); + QImage getOriginalImage(); + +private: + QImage image; +}; + +#endif //CAMERAIMAGE_H diff --git a/symbian/QQrDecoder/Nokia_Licence.txt b/symbian/QQrDecoder/Nokia_Licence.txt new file mode 100644 index 000000000..758a74555 --- /dev/null +++ b/symbian/QQrDecoder/Nokia_Licence.txt @@ -0,0 +1,31 @@ +Copyright © 2009 Nokia Corporation. All rights reserved. +Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. +Java and all Java-based marks are trademarks or registered trademarks of +Sun Microsystems, Inc. Other product and company names mentioned herein may be +trademarks or trade names of their respective owners. + + +Subject to the conditions below, you may, without charge: + +· Use, copy, modify and/or merge copies of this software and + associated documentation files (the “Software”) + +· Publish, distribute, sub-license and/or sell new software + derived from or incorporating the Software. + + + +This file, unmodified, shall be included with all copies or substantial portions +of the Software that are distributed in source code form. + +The Software cannot constitute the primary value of any new software derived +from or incorporating the Software. + +Any person dealing with the Software shall not misrepresent the source of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/symbian/QQrDecoder/QCameraControllerWidget.cpp b/symbian/QQrDecoder/QCameraControllerWidget.cpp new file mode 100644 index 000000000..12f22c5b4 --- /dev/null +++ b/symbian/QQrDecoder/QCameraControllerWidget.cpp @@ -0,0 +1,322 @@ +#include "QCameraControllerWidget.h" +#include + +QCameraControllerWidget::QCameraControllerWidget(QWidget* parent) : QWidget(parent), +iCameraWrapper(NULL), iBackBuffer(NULL), iBackBufferDevice(NULL), iBackBufferContext(NULL) +{ + timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(sendBackbufferToDecode())); + timer->start(500); +} + +QCameraControllerWidget::~QCameraControllerWidget() +{ + if (iCameraWrapper) + { + iCameraWrapper->ReleaseAndPowerOff(); + } + + delete iCameraWrapper; + + if(timer) + { + delete timer; + timer = NULL; + } + + ReleaseBackBuffer(); +} + +void QCameraControllerWidget::CaptureImage() +{ + if (iCameraWrapper && iCameraWrapper->State() == CCameraEngine::EEngineViewFinding) + { + emit logMessage("Capturing picture"); + iCameraWrapper->StopViewFinder(); + TRAPD(err,iCameraWrapper->CaptureL()); + if (err) + { + emit logMessage("Camera capture error"); + } + } +} + +void QCameraControllerWidget::paintEvent(QPaintEvent* event) +{ + if(iBackBuffer) + { + QPainter paint(this); + paint.drawPixmap(0,0,QPixmap::fromSymbianCFbsBitmap(iBackBuffer)); + } +} + +void QCameraControllerWidget::resizeEvent(QResizeEvent* event) +{ + static int savedWidth = 0; + static int savedHeight = 0; + + if(!savedWidth || !savedHeight) + { + InitializeCamera(); + savedWidth = geometry().width(); + savedHeight = geometry().height(); + } +} + +void QCameraControllerWidget::InitializeCamera() +{ + // Create camera wrapper class here because + // whole camera wrapper and all handles have to reset + // while orientatio of the application changes. + if (iCameraWrapper) + { + // Power off camera if it is on + iCameraWrapper->StopViewFinder(); + iCameraWrapper->ReleaseAndPowerOff(); + delete iCameraWrapper; iCameraWrapper = NULL; + } + TInt camErr(KErrNotSupported); + if(CCameraEngine::CamerasAvailable() > 0) + { + TRAP(camErr, iCameraWrapper = CCameraEngine::NewL(0,0,this)); + } + + // iViewFinderSize is picture size for viewfinder. + // iCaptureSize is picture size for capturing picture. + // We want fill whole screen + if (geometry().width() > geometry().height()) + { + iViewFinderSize = TSize(geometry().width(),geometry().width()); + iCaptureSize = TSize(geometry().width(),geometry().width()); // Captured picture size + } + else + { + iViewFinderSize = TSize(geometry().height(), geometry().height()); + iCaptureSize = TSize(geometry().height(),geometry().height()); // Captured picture size + } + + // Create back buffer where recieved camera pictures are copied + ReleaseBackBuffer(); + CreateBackBufferL(); + + // Power on camera, start viewfinder when MceoCameraReady() received + if(camErr == KErrNone) + { + iCameraWrapper->ReserveAndPowerOn(); + emit logMessage("Camera power on"); + } + else + { + emit logMessage("no camera found"); + } +} + +void QCameraControllerWidget::CreateBackBufferL() +{ + // create back buffer bitmap + iBackBuffer = q_check_ptr(new CFbsBitmap); + + try{ + TSize size; + size.iHeight = this->geometry().height(); + size.iWidth = this->geometry().width(); + QT_TRAP_THROWING( iBackBuffer->Create(size,EColor64K)); + } + catch(std::exception& e) + { + + } + + // create back buffer graphics context + iBackBufferDevice = CFbsBitmapDevice::NewL(iBackBuffer); + User::LeaveIfError(iBackBufferDevice->CreateContext(iBackBufferContext)); + iBackBufferContext->SetPenStyle(CGraphicsContext::ESolidPen); + + iBackBufferContext->SetBrushColor(KRgbBlack); + iBackBufferContext->Clear(); +} + +void QCameraControllerWidget::ReleaseBackBuffer() +{ + if (iBackBufferContext) + { + delete iBackBufferContext; + iBackBufferContext = NULL; + } + if (iBackBufferDevice) + { + delete iBackBufferDevice; + iBackBufferDevice = NULL; + } + if (iBackBuffer) + { + delete iBackBuffer; + iBackBuffer = NULL; + } +} + +void QCameraControllerWidget::MceoCameraReady() +{ + if (iCameraWrapper->State() == CCameraEngine::EEngineIdle) + { + // Prepare camera + TSize imageSize; + imageSize.iHeight = 480; + imageSize.iWidth = 640; + + CCamera::TFormat format = CCamera::EFormatFbsBitmapColor64K; + + TRAPD(err,iCameraWrapper->PrepareL(imageSize, format)); + if (err) + { + emit logMessage("Camera prepare error"); + return; + } + + // Start viewfinder. Viewfinder pictures starts coming into MceoViewFinderFrameReady(); + + TSize finderSize; + finderSize.iHeight = this->geometry().height(); + finderSize.iWidth = this->geometry().width(); + TRAPD(err2,iCameraWrapper->StartViewFinderL(finderSize)); + if (err2) + { + emit logMessage("Camera start viewfinder error"); + return; + } + + emit logMessage("Camera viewfinder started"); + } +} + +void QCameraControllerWidget::MceoFocusComplete() +{ + // CameraEngine state is EEngineIdle + emit logMessage("Focused"); + + // Capture picture after it has focused + iCameraWrapper->StopViewFinder(); + TRAPD(err,iCameraWrapper->CaptureL()); + if (err) + { + emit logMessage("Camera capture error"); + } +} + +void QCameraControllerWidget::MceoCapturedDataReady( TDesC8* aData ) +{ + +} + +void QCameraControllerWidget::MceoCapturedBitmapReady( CFbsBitmap* aBitmap ) +{ + if (iBackBufferContext) + { + emit logMessage("Succesfull capture"); + + QPixmap pix(QPixmap::fromSymbianCFbsBitmap(aBitmap)); + emit imageCaptured(pix.toImage()); + + TSize finderSize; + finderSize.iHeight = this->geometry().height(); + finderSize.iWidth = this->geometry().width(); + TRAPD(err2,iCameraWrapper->StartViewFinderL(finderSize)); + if (err2) + { + emit logMessage("Camera start viewfinder error"); + return; + } + } + if (iCameraWrapper) + iCameraWrapper->ReleaseImageBuffer(); +} + +void QCameraControllerWidget::MceoViewFinderFrameReady( CFbsBitmap& aFrame ) +{ + if (iBackBufferContext) + { + TSize bmpSizeInPixels = aFrame.SizeInPixels(); + TInt xDelta = 0; + TInt yDelta = 0; + TPoint pos( xDelta, yDelta ); + + // Copy received viewfinder picture to back buffer + iBackBufferContext->BitBlt( pos, &aFrame, TRect( TPoint( 0, 0 ), bmpSizeInPixels )); + + // Update backbuffer into screen + update(); + } + if (iCameraWrapper) + iCameraWrapper->ReleaseViewFinderBuffer(); +} + +void QCameraControllerWidget::MceoHandleError( TCameraEngineError aErrorType, TInt aError ) +{ + // NOTE: CameraEngine state seems to go into CCameraEngine::EEngineIdle state + + if (aErrorType == EErrReserve) + { + return; //-18 comes on application startup, but everything works ok + } + + switch (aErrorType) + { + case EErrReserve: + { + emit logMessage("Camera reserved error"); + break; + } + case EErrPowerOn: + { + emit logMessage("Camera power on error"); + break; + } + case EErrViewFinderReady: + { + emit logMessage("Camera viewfinder error"); + break; + } + case EErrImageReady: + { + emit logMessage("Camera image ready error"); + break; + } + case EErrAutoFocusInit: + case EErrAutoFocusMode: + case EErrAutoFocusArea: + case EErrAutoFocusRange: + case EErrAutoFocusType: + case EErrOptimisedFocusComplete: + { + //emit logMessage("Try focusing again"); + break; + } + default: + { + emit logMessage("Unknown error"); + break; + } + }; + + // Try handle error + //CancelCapturedPicture(EFalse); + // iAppUi->UseOptionsExitCbaL(); +} + +void QCameraControllerWidget::MceoHandleOtherEvent( const TECAMEvent& /*aEvent*/ ) +{ +} + +//Timer slot +void QCameraControllerWidget::sendBackbufferToDecode() +{ + if(!iBackBuffer) + return; + + QPixmap pix(QPixmap::fromSymbianCFbsBitmap(iBackBuffer)); + emit imageCaptured(pix.toImage()); + + if(timer) + timer->start(500); +} + diff --git a/symbian/QQrDecoder/QCameraControllerWidget.h b/symbian/QQrDecoder/QCameraControllerWidget.h new file mode 100644 index 000000000..ae0e38d0d --- /dev/null +++ b/symbian/QQrDecoder/QCameraControllerWidget.h @@ -0,0 +1,67 @@ +#ifndef QCAMERACONTROLLER_H +#define QCAMERACONTROLLER_H + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +class QCameraControllerWidget : public QWidget, public MCameraEngineObserver +{ + Q_OBJECT + +public: + QCameraControllerWidget(QWidget* parent); + ~QCameraControllerWidget(); + +protected: + void paintEvent(QPaintEvent* event); + void resizeEvent(QResizeEvent* event); + +private: // From MCameraEngineObserver + void CreateBackBufferL(); + void ReleaseBackBuffer(); + + void MceoCameraReady(); + void MceoFocusComplete(); + void MceoCapturedDataReady( TDesC8* aData ); + void MceoCapturedBitmapReady( CFbsBitmap* aBitmap ); + void MceoViewFinderFrameReady( CFbsBitmap& aFrame ); + void MceoHandleError( TCameraEngineError aErrorType, TInt aError ); + void MceoHandleOtherEvent( const TECAMEvent& /*aEvent*/ ); + void InitializeCamera(); + +//////////////////////// +public slots: + void CaptureImage(); + +private slots: + void sendBackbufferToDecode(); + +signals: + void logMessage(QString str); + void imageCaptured(QImage cImage); + +private: + // CameraWrapper class + CCameraEngine* iCameraWrapper; + + CFbsBitmap* iBackBuffer; + CFbsBitmapDevice* iBackBufferDevice; + CFbsBitGc* iBackBufferContext; + + TSize iViewFinderSize; + TSize iCaptureSize; + + //Timer + QTimer* timer; +}; + +#endif //QCAMERACONTROLLER_H diff --git a/symbian/QQrDecoder/QQrDecoder.cpp b/symbian/QQrDecoder/QQrDecoder.cpp new file mode 100644 index 000000000..a20ad1fa4 --- /dev/null +++ b/symbian/QQrDecoder/QQrDecoder.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** + ** + ** Trolltech hereby grants a license to use the Qt/Eclipse Integration + ** plug-in (the software contained herein), in binary form, solely for the + ** purpose of creating code to be used with Trolltech's Qt software. + ** + ** Qt Designer is licensed under the terms of the GNU General Public + ** License versions 2.0 and 3.0 ("GPL License"). Trolltech offers users the + ** right to use certain no GPL licensed software under the terms of its GPL + ** Exception version 1.2 (http://trolltech.com/products/qt/gplexception). + ** + ** THIS SOFTWARE IS PROVIDED BY TROLLTECH AND ITS CONTRIBUTORS (IF ANY) "AS + ** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + ** PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + ** OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + ** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** Since we now have the GPL exception I think that the "special exception + ** is no longer needed. The license text proposed above (other than the + ** special exception portion of it) is the BSD license and we have added + ** the BSD license as a permissible license under the exception. + ** + ****************************************************************************/ + +#include "QQrDecoder.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace zxing; +using namespace zxing::qrcode; + +QQrDecoder::QQrDecoder(QWidget *parent): QMainWindow(parent) +{ + ui.setupUi(this); + connect(ui.startDecode, SIGNAL(clicked()), this, SLOT(findAndDecode())); + connect(ui.cameraWidget, SIGNAL(imageCaptured(QImage)), this, SLOT(decodeImage(QImage))); + connect(ui.cameraWidget, SIGNAL(logMessage(QString)), ui.resultLabel, SLOT(setText(QString))); +} + +QQrDecoder::~QQrDecoder() +{ +} + +void QQrDecoder::InitializeSymbianCamera() +{ + +} + +void QQrDecoder::findAndDecode() +{ + ui.cameraWidget->CaptureImage(); +} + +void QQrDecoder::decodeImage(QImage originalImage) +{ + QRCodeReader decoder; + + image.setImage(originalImage); + + Ref res; + + try{ + Ref imageRef(new CameraImageWrapper(image)); + GlobalHistogramBinarizer* binz = new GlobalHistogramBinarizer(imageRef); + + Ref bz (binz); + BinaryBitmap* bb = new BinaryBitmap(bz); + + Ref ref(bb); + + res = decoder.decode(ref); + + QString string = QString(res->getText()->getText().c_str()); + ui.resultLabel->setText(string); + } + catch(zxing::Exception& e) + { + ui.resultLabel->setText("Error"); + } +} + +void QQrDecoder::reloadFormatedPicture(int x) +{ +} + diff --git a/symbian/QQrDecoder/QQrDecoder.h b/symbian/QQrDecoder/QQrDecoder.h new file mode 100644 index 000000000..ecdfff228 --- /dev/null +++ b/symbian/QQrDecoder/QQrDecoder.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Trolltech hereby grants a license to use the Qt/Eclipse Integration +** plug-in (the software contained herein), in binary form, solely for the +** purpose of creating code to be used with Trolltech's Qt software. +** +** Qt Designer is licensed under the terms of the GNU General Public +** License versions 2.0 and 3.0 ("GPL License"). Trolltech offers users the +** right to use certain no GPL licensed software under the terms of its GPL +** Exception version 1.2 (http://trolltech.com/products/qt/gplexception). +** +** THIS SOFTWARE IS PROVIDED BY TROLLTECH AND ITS CONTRIBUTORS (IF ANY) "AS +** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +** PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +** OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** Since we now have the GPL exception I think that the "special exception +** is no longer needed. The license text proposed above (other than the +** special exception portion of it) is the BSD license and we have added +** the BSD license as a permissible license under the exception. +** +****************************************************************************/ + +#ifndef QQRDECODER_H +#define QQRDECODER_H + +#include +#include +#include "ui_QQrDecoder.h" + +#include "CameraImageWrapper.h" + +class QQrDecoder : public QMainWindow +{ + Q_OBJECT + +public: + QQrDecoder(QWidget *parent = 0); + ~QQrDecoder(); + +private: + void InitializeSymbianCamera(); + +protected slots: + void findAndDecode(); + void decodeImage(QImage originalImage); + void reloadFormatedPicture(int x); + +private: + Ui::QQrDecoder ui; + CameraImageWrapper image; + QPixmap px; +}; + +#endif // QQRDECODER_H diff --git a/symbian/QQrDecoder/QQrDecoder.pro b/symbian/QQrDecoder/QQrDecoder.pro new file mode 100644 index 000000000..8db037323 --- /dev/null +++ b/symbian/QQrDecoder/QQrDecoder.pro @@ -0,0 +1,159 @@ +TEMPLATE = app +TARGET = QQrDecoder +QT += core \ + gui +HEADERS += CameraImageWrapper.h \ + zxing/BarcodeFormat.h \ + zxing/Binarizer.h \ + zxing/BinaryBitmap.h \ + zxing/Exception.h \ + zxing/LuminanceSource.h \ + zxing/MultiFormatReader.h \ + zxing/Reader.h \ + zxing/ReaderException.h \ + zxing/Result.h \ + zxing/ResultPoint.h \ + zxing/common/Array.h \ + zxing/common/BitArray.h \ + zxing/common/BitMatrix.h \ + zxing/common/BitSource.h \ + zxing/common/Counted.h \ + zxing/common/DecoderResult.h \ + zxing/common/DetectorResult.h \ + zxing/common/EdgeDetector.h \ + zxing/common/GlobalHistogramBinarizer.h \ + zxing/common/GridSampler.h \ + zxing/common/IllegalArgumentException.h \ + zxing/common/LocalBlockBinarizer.h \ + zxing/common/PerspectiveTransform.h \ + zxing/common/Point.h \ + zxing/common/Str.h \ + zxing/common/reedsolomon/GF256.h \ + zxing/common/reedsolomon/GF256Poly.h \ + zxing/common/reedsolomon/ReedSolomonDecoder.h \ + zxing/common/reedsolomon/ReedSolomonException.h \ + zxing/oned/Code128Reader.h \ + zxing/oned/Code39Reader.h \ + zxing/oned/EAN13Reader.h \ + zxing/oned/EAN8Reader.h \ + zxing/oned/ITFReader.h \ + zxing/oned/MultiFormatOneDReader.h \ + zxing/oned/MultiFormatUPCEANReader.h \ + zxing/oned/OneDReader.h \ + zxing/oned/OneDResultPoint.h \ + zxing/oned/UPCAReader.h \ + zxing/oned/UPCEANReader.h \ + zxing/oned/UPCEReader.h \ + zxing/qrcode/ErrorCorrectionLevel.h \ + zxing/qrcode/FormatInformation.h \ + zxing/qrcode/QRCodeReader.h \ + zxing/qrcode/Version.h \ + zxing/qrcode/decoder/BitMatrixParser.h \ + zxing/qrcode/decoder/DataBlock.h \ + zxing/qrcode/decoder/DataMask.h \ + zxing/qrcode/decoder/DecodedBitStreamParser.h \ + zxing/qrcode/decoder/Decoder.h \ + zxing/qrcode/decoder/Mode.h \ + zxing/qrcode/detector/AlignmentPattern.h \ + zxing/qrcode/detector/AlignmentPatternFinder.h \ + zxing/qrcode/detector/Detector.h \ + zxing/qrcode/detector/FinderPattern.h \ + zxing/qrcode/detector/FinderPatternFinder.h \ + zxing/qrcode/detector/FinderPatternInfo.h \ + zxing/qrcode/detector/QREdgeDetector.h \ + QQrDecoder.loc \ + QQrDecoder.h +SOURCES += CameraImageWrapper.cpp \ + zxing/BarcodeFormat.cpp \ + zxing/Binarizer.cpp \ + zxing/BinaryBitmap.cpp \ + zxing/Exception.cpp \ + zxing/LuminanceSource.cpp \ + zxing/MultiFormatReader.cpp \ + zxing/Reader.cpp \ + zxing/ReaderException.cpp \ + zxing/Result.cpp \ + zxing/ResultPoint.cpp \ + zxing/common/Array.cpp \ + zxing/common/BitArray.cpp \ + zxing/common/BitMatrix.cpp \ + zxing/common/BitSource.cpp \ + zxing/common/Counted.cpp \ + zxing/common/DecoderResult.cpp \ + zxing/common/DetectorResult.cpp \ + zxing/common/EdgeDetector.cpp \ + zxing/common/GlobalHistogramBinarizer.cpp \ + zxing/common/GridSampler.cpp \ + zxing/common/IllegalArgumentException.cpp \ + zxing/common/LocalBlockBinarizer.cpp \ + zxing/common/PerspectiveTransform.cpp \ + zxing/common/Str.cpp \ + zxing/common/reedsolomon/GF256.cpp \ + zxing/common/reedsolomon/GF256Poly.cpp \ + zxing/common/reedsolomon/ReedSolomonDecoder.cpp \ + zxing/common/reedsolomon/ReedSolomonException.cpp \ + zxing/oned/Code128Reader.cpp \ + zxing/oned/Code39Reader.cpp \ + zxing/oned/EAN13Reader.cpp \ + zxing/oned/EAN8Reader.cpp \ + zxing/oned/ITFReader.cpp \ + zxing/oned/MultiFormatOneDReader.cpp \ + zxing/oned/MultiFormatUPCEANReader.cpp \ + zxing/oned/OneDReader.cpp \ + zxing/oned/OneDResultPoint.cpp \ + zxing/oned/UPCAReader.cpp \ + zxing/oned/UPCEANReader.cpp \ + zxing/oned/UPCEReader.cpp \ + zxing/qrcode/ErrorCorrectionLevel.cpp \ + zxing/qrcode/FormatInformation.cpp \ + zxing/qrcode/QRCodeReader.cpp \ + zxing/qrcode/Version.cpp \ + zxing/qrcode/decoder/BitMatrixParser.cpp \ + zxing/qrcode/decoder/DataBlock.cpp \ + zxing/qrcode/decoder/DataMask.cpp \ + zxing/qrcode/decoder/DecodedBitStreamParser.cpp \ + zxing/qrcode/decoder/Decoder.cpp \ + zxing/qrcode/decoder/Mode.cpp \ + zxing/qrcode/detector/AlignmentPattern.cpp \ + zxing/qrcode/detector/AlignmentPatternFinder.cpp \ + zxing/qrcode/detector/Detector.cpp \ + zxing/qrcode/detector/FinderPattern.cpp \ + zxing/qrcode/detector/FinderPatternFinder.cpp \ + zxing/qrcode/detector/FinderPatternInfo.cpp \ + zxing/qrcode/detector/QREdgeDetector.cpp \ + QQrDecoder.rss \ + QQrDecoder_reg.rss \ + main.cpp \ + QQrDecoder.cpp +FORMS += QQrDecoder.ui +RESOURCES += +symbian { + TARGET.UID3 = 0xEF2CE79D + HEADERS += QCameraControllerWidget.h + SOURCES += QCameraControllerWidget.cpp + LIBS += -leuser \ + -lapparc \ + -lcone \ + -leikcore \ + -lavkon \ + -lcommonengine \ + -lefsrv \ + -lestor \ + -laknnotify \ + -lfbscli \ + -lbitgdi \ + -leikcoctl \ + -lbafl \ # BafUtils + -lecam \ # Camera + -lcamerawrapper + TARGET.CAPABILITY = UserEnvironment + + customrules.pkg_prerules = \ + ";CameraWrapper" \ + "@\"$(EPOCROOT)Epoc32\InstallToDevice\CameraWrapper\sis\camerawrapper.sisx\", (0x2001ec5f)" \ + " " + + DEPLOYMENT += customrules +} + +ICON = QQrDecoder.svg diff --git a/symbian/QQrDecoder/QQrDecoder.svg b/symbian/QQrDecoder/QQrDecoder.svg new file mode 100644 index 000000000..3bd9d64ae --- /dev/null +++ b/symbian/QQrDecoder/QQrDecoder.svg @@ -0,0 +1,91 @@ + + + + + + diff --git a/symbian/QQrDecoder/QQrDecoder.ui b/symbian/QQrDecoder/QQrDecoder.ui new file mode 100644 index 000000000..c691a66a9 --- /dev/null +++ b/symbian/QQrDecoder/QQrDecoder.ui @@ -0,0 +1,54 @@ + + + QQrDecoder + + + + 0 + 0 + 340 + 640 + + + + QQrDecoder + + + + + + + Capture And Decode + + + + + + + + 0 + 0 + + + + No result + + + + + + + + + + + + QCameraControllerWidget + QWidget +
qcameracontrollerwidget.h
+ 1 +
+
+ + +
diff --git a/symbian/QQrDecoder/QQrDecoder_template.sisx b/symbian/QQrDecoder/QQrDecoder_template.sisx new file mode 100644 index 000000000..dbf497dd2 Binary files /dev/null and b/symbian/QQrDecoder/QQrDecoder_template.sisx differ diff --git a/symbian/QQrDecoder/ZXing_Licence.txt b/symbian/QQrDecoder/ZXing_Licence.txt new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/symbian/QQrDecoder/ZXing_Licence.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/symbian/QQrDecoder/camerawrapper/epoc32/InstallToDevice/CameraWrapper/sis/camerawrapper.sisx b/symbian/QQrDecoder/camerawrapper/epoc32/InstallToDevice/CameraWrapper/sis/camerawrapper.sisx new file mode 100644 index 000000000..8a4fab2e2 Binary files /dev/null and b/symbian/QQrDecoder/camerawrapper/epoc32/InstallToDevice/CameraWrapper/sis/camerawrapper.sisx differ diff --git a/symbian/QQrDecoder/camerawrapper/epoc32/include/cameraengine.h b/symbian/QQrDecoder/camerawrapper/epoc32/include/cameraengine.h new file mode 100644 index 000000000..d802fb377 --- /dev/null +++ b/symbian/QQrDecoder/camerawrapper/epoc32/include/cameraengine.h @@ -0,0 +1,241 @@ +/* +* ============================================================================ +* Name : cameraengine.h +* Part of : CameraWrapper +* Description : Camera engine class declaration +* Version : %version: 2 % +* +* Copyright (c) 2009 Nokia Corporation. +* This material, including documentation and any related +* computer programs, is protected by copyright controlled by +* Nokia Corporation. +* ============================================================================== +*/ + +#ifndef CCAMERAENGINE_H +#define CCAMERAENGINE_H + +// INCLUDES +#include +#include + +// FORWARD DECLARATIONS +class CCameraEnginePrivate; +class MCameraEngineObserver; +class CCameraAdvancedSettings; + +NONSHARABLE_CLASS( CCameraEngine ) : public CBase + { +public: + + enum TCameraEngineState + { + EEngineNotReady, + EEngineIdle, + EEngineViewFinding, + EEngineCapturing, + EEngineFocusing + }; + + IMPORT_C static CCameraEngine* NewL( TInt aCameraHandle, + TInt aPriority, + MCameraEngineObserver* aObserver ); + IMPORT_C ~CCameraEngine(); + +public: + + /** + * Returns the current state (TCameraEngineState) + * of the camera engine. + */ + IMPORT_C TCameraEngineState State() const; + + /** + * Returns true if the camera has been reserved and + * powered on. + */ + IMPORT_C TBool IsCameraReady() const; + + /** + * Returns true if the camera supports AutoFocus. + */ + IMPORT_C TBool IsAutoFocusSupported() const; + + /** + * Captures an image. When complete, observer will receive + * MceoCapturedDataReady() or MceoCapturedBitmapReady() callback, + * depending on which image format was used in PrepareL(). + * @leave May leave with KErrNotReady if camera is not + * reserved or prepared for capture. + */ + IMPORT_C void CaptureL(); + + /** + * Reserves and powers on the camera. When complete, + * observer will receive MceoCameraReady() callback + * + */ + IMPORT_C void ReserveAndPowerOn(); + + /** + * Releases and powers off the camera + * + */ + IMPORT_C void ReleaseAndPowerOff(); + + /** + * Prepares for image capture. + * @param aCaptureSize requested capture size. On return, + * contains the selected size (closest match) + * @param aFormat Image format to use. Default is JPEG with + * EXIF information as provided by the camera module + * @leave KErrNotSupported, KErrNoMemory, KErrNotReady + */ + IMPORT_C void PrepareL( TSize& aCaptureSize, + CCamera::TFormat aFormat = CCamera::EFormatExif ); + + /** + * Starts the viewfinder. Observer will receive + * MceoViewFinderFrameReady() callbacks periodically. + * @param aSize requested viewfinder size. On return, + * contains the selected size. + * + * @leave KErrNotSupported is viewfinding with bitmaps is not + * supported, KErrNotReady + */ + IMPORT_C void StartViewFinderL( TSize& aSize ); + + /** + * Stops the viewfinder if active. + */ + IMPORT_C void StopViewFinder(); + + /** + * Releases memory for the last received viewfinder frame. + * Client must call this in response to MceoViewFinderFrameReady() + * callback, after drawing the viewfinder frame is complete. + */ + IMPORT_C void ReleaseViewFinderBuffer(); + + /** + * Releases memory for the last captured image. + * Client must call this in response to MceoCapturedDataReady() + * or MceoCapturedBitmapReady()callback, after processing the + * data/bitmap is complete. + */ + IMPORT_C void ReleaseImageBuffer(); + + /** + * Starts focusing. Does nothing if AutoFocus is not supported. + * When complete, observer will receive MceoFocusComplete() + * callback. + * @leave KErrInUse, KErrNotReady + */ + IMPORT_C void StartFocusL(); + + /** + * Cancels the ongoing focusing operation. + */ + IMPORT_C void FocusCancel(); + + /** + * Gets a bitfield of supported focus ranges. + * @param aSupportedRanges a bitfield of either TAutoFocusRange + * (S60 3.0/3.1 devices) or TFocusRange (S60 3.2 and onwards) values + */ + IMPORT_C void SupportedFocusRanges( TInt& aSupportedRanges ) const; + + /** + * Sets the focus range + * @param aFocusRange one of the values returned by + * SupportedFocusRanges(). + */ + IMPORT_C void SetFocusRange( TInt aFocusRange ); + + /** + * Returns a pointer to CCamera object used by the engine. + * Allows getting access to additional functionality + * from CCamera - do not use for functionality already provided + * by CCameraEngine methods. + */ + IMPORT_C CCamera* Camera(); + + /** + * Returns a pointer to CCameraAdvancedSettings object used by + * the engine. May be NULL if adv. settings is not available. + * Allows getting access to additional functionality + * from CCameraAdvancedSettings - do not use for functionality already + * provided by CCameraEngine methods. + */ + IMPORT_C CCamera::CCameraAdvancedSettings* AdvancedSettings(); + + /** + * Static function that returns the number of cameras on the device. + */ + IMPORT_C static TInt CamerasAvailable(); + + /** + * Maximum digital zoom value. 0 if digital zoom is not supported + */ + IMPORT_C TInt MaxDigitalZoom(); + + /** + * Current digital zoom value + */ + IMPORT_C TInt DigitalZoom(); + + /** + * Adjust digital zoom. set aTele to ETrue to increase zoom (tele) + * or EFalse to decrease zoom (wide) + * @return Returns the new zoom level or KErrNotSupported + */ + IMPORT_C TInt AdjustDigitalZoom( TBool aTele ); + + /** + * Returns a bitfield of supported exposure modes + * See CCamera::TExposure + */ + IMPORT_C TInt SupportedExposureModes(); + + /** + * Returns the current exposure mode + * See CCamera::TExposure + */ + IMPORT_C TInt Exposure(); + + /** + * Set camera exposure mode + * See CCamera::TExposure + * @param aExposure One of the modes from SupportedExposureModes + * @return KErrNone or KErrNotSupported + */ + IMPORT_C TInt SetExposure( TInt aExposure ); + + /** + * Returns a bitfield of supported flash modes + * See CCamera::TFlash + */ + IMPORT_C TInt SupportedFlashModes(); + + /** + * Returns the current flash mode + * See CCamera::TFlash + */ + IMPORT_C TInt Flash(); + + /** + * Set camera flash mode + * See CCamera::TFlash + * @param aFlash One of the modes from SupportedFlashModes + * @return KErrNone or KErrNotSupported + */ + IMPORT_C TInt SetFlash( TInt aFlash ); + +protected: + CCameraEngine(); + +private: + CCameraEnginePrivate* iPimpl; + }; + +#endif //CCAMERAENGINE_H diff --git a/symbian/QQrDecoder/camerawrapper/epoc32/include/cameraengineobserver.h b/symbian/QQrDecoder/camerawrapper/epoc32/include/cameraengineobserver.h new file mode 100644 index 000000000..832dfc1c1 --- /dev/null +++ b/symbian/QQrDecoder/camerawrapper/epoc32/include/cameraengineobserver.h @@ -0,0 +1,92 @@ +/* +* ============================================================================ +* Name : cameraengineobserver.h +* Part of : CameraWrapper +* Description : Observer interface for camera engine (wrapper DLL) +* Version : %version: 1 % +* +* Copyright (c) 2009 Nokia Corporation. +* This material, including documentation and any related +* computer programs, is protected by copyright controlled by +* Nokia Corporation. +* ============================================================================== +*/ + +#ifndef __CCAMERAENGINEOBSERVER_H__ +#define __CCAMERAENGINEOBSERVER_H__ + +// FORWARD DECLARATIONS +class CFbsBitmap; +class TECAMEvent; + +enum TCameraEngineError + { + EErrReserve, + EErrPowerOn, + EErrViewFinderReady, + EErrImageReady, + EErrAutoFocusInit, + EErrAutoFocusMode, + EErrAutoFocusArea, + EErrAutoFocusRange, + EErrAutoFocusType, + EErrOptimisedFocusComplete, + }; + + +class MCameraEngineObserver + { +public: + + /** + * Camera is ready to use for capturing images. + */ + virtual void MceoCameraReady() = 0; + + /** + * Camera AF lens has attained optimal focus + */ + virtual void MceoFocusComplete() = 0; + + /** + * Captured data is ready - call CCameraEngine::ReleaseImageBuffer() + * after processing/saving the data (typically, JPG-encoded image) + * @param aData Pointer to a descriptor containing a frame of camera data. + */ + virtual void MceoCapturedDataReady( TDesC8* aData ) = 0; + + /** + * Captured bitmap is ready. + * after processing/saving the image, call + * CCameraEngine::ReleaseImageBuffer() to free the bitmap. + * @param aBitmap Pointer to an FBS bitmap containing a captured image. + */ + virtual void MceoCapturedBitmapReady( CFbsBitmap* aBitmap ) = 0; + + /** + * A new viewfinder frame is ready. + * after displaying the frame, call + * CCameraEngine::ReleaseViewFinderBuffer() + * to free the bitmap. + * @param aFrame Pointer to an FBS bitmap containing a viewfinder frame. + */ + virtual void MceoViewFinderFrameReady( CFbsBitmap& aFrame ) = 0; + + /** + * Notifies clients about errors in camera engine + * @param aErrorType type of error (see TCameraEngineError) + * @param aError Symbian system-wide error code + */ + virtual void MceoHandleError( TCameraEngineError aErrorType, TInt aError ) = 0; + + /** + * Notifies client about other events not recognized by camera engine. + * The default implementation is empty. + * @param aEvent camera event (see MCameraObserver2::HandleEvent()) + */ + virtual void MceoHandleOtherEvent( const TECAMEvent& /*aEvent*/ ) {} + }; + +#endif // __CCAMERAENGINEOBSERVER_H__ + +// eof diff --git a/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/lib/camerawrapper.dso b/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/lib/camerawrapper.dso new file mode 100644 index 000000000..cc6203161 Binary files /dev/null and b/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/lib/camerawrapper.dso differ diff --git a/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/lib/camerawrapper.lib b/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/lib/camerawrapper.lib new file mode 100644 index 000000000..9e972bda9 Binary files /dev/null and b/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/lib/camerawrapper.lib differ diff --git a/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/lib/camerawrapper{000a0000}.dso b/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/lib/camerawrapper{000a0000}.dso new file mode 100644 index 000000000..cc6203161 Binary files /dev/null and b/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/lib/camerawrapper{000a0000}.dso differ diff --git a/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/lib/camerawrapper{000a0000}.lib b/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/lib/camerawrapper{000a0000}.lib new file mode 100644 index 000000000..9e972bda9 Binary files /dev/null and b/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/lib/camerawrapper{000a0000}.lib differ diff --git a/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/urel/camerawrapper.dll b/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/urel/camerawrapper.dll new file mode 100644 index 000000000..04e2b18a6 Binary files /dev/null and b/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/urel/camerawrapper.dll differ diff --git a/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/urel/camerawrapper.dll.map b/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/urel/camerawrapper.dll.map new file mode 100644 index 000000000..0aa9800ee --- /dev/null +++ b/symbian/QQrDecoder/camerawrapper/epoc32/release/armv5/urel/camerawrapper.dll.map @@ -0,0 +1,431 @@ +ARM Linker, RVCT2.2 [Build 616] + +================================================================================ + +Image Symbol Table + + Local Symbols + + Symbol Name Value Ov Type Size Object(Section) + + [Anonymous Symbol] 0x00000000 Number 0 FBSCLI{000a0000}-130.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 drtaeabi{000a0000}-184.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 FBSCLI{000a0000}-25.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-2123.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 scppnwdl{000a0000}-3.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 FBSCLI{000a0000}-30.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-2125.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-2061.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 FBSCLI{000a0000}-31.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-593.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-208.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 ecamadvsettings{000a0000}-120.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-649.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-2082.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 ecamadvsettings{000a0000}-125.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-654.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 ecamadvsettings{000a0000}-64.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 ecamadvsettings{000a0000}-26.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-669.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 drtaeabi{000a0000}-158.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 ecamadvsettings{000a0000}-28.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 ecam{000a0000}-2.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 drtaeabi{000a0000}-180.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 ecamadvsettings{000a0000}-41.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 ecam{000a0000}-3.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 drtaeabi{000a0000}-183.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 ecamadvsettings{000a0000}-42.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-1356.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-205.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-1657.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-1601.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-2060.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-1659.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-1311.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-1308.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-1838.o ABSOLUTE + [Anonymous Symbol] 0x00000000 Number 0 euser{000a0000}-1169.o ABSOLUTE + ..\..\..\..\..\..\EPOC32\BUILD\src\common\generic\COMMS-INFRAS\Flogger\GROUP\FLOGGER\ARMV5\VtblExports.s 0x00000000 Number 0 VtblExports.o ABSOLUTE + ..\src\Ccamautofocus.cpp 0x00000000 Number 0 CCamAutoFocus.o ABSOLUTE + ..\src\Ccamautofocusimpl.cpp 0x00000000 Number 0 CCamAutoFocusImpl.o ABSOLUTE + \EPOC32\BUILD\src\cedar\generic\BASE\E32\EDLL\ARMV5\UREL\uc_dll_.cpp 0x00000000 Number 0 uc_dll_.o ABSOLUTE + \EPOC32\BUILD\src\cedar\generic\BASE\E32\EUSER\ARMV5\VtblExports.s 0x00000000 Number 0 VtblExports.o ABSOLUTE + \EPOC32\BUILD\src\cedar\generic\BASE\E32\compsupp\DRTAEABI\ARMV5\VtblExports.s 0x00000000 Number 0 VtblExports.o ABSOLUTE + \EPOC32\BUILD\src\common\generic\GRAPHICS\Fbserv\GROUP\FBSCLI\ARMV5\VtblExports.s 0x00000000 Number 0 VtblExports.o ABSOLUTE + \EPOC32\BUILD\src\common\generic\MULTIMEDIA\ECAM\GROUP\ECAMADVSETTINGS\ARMV5\VtblExports.s 0x00000000 Number 0 VtblExports.o ABSOLUTE + \EPOC32\BUILD\src\common\generic\MULTIMEDIA\ECAM\GROUP\ECAM\ARMV5\VtblExports.s 0x00000000 Number 0 VtblExports.o ABSOLUTE + \S60\S60_3rd_FP1\EPOC32\BUILD\S60\proj\CameraWrapper\group\CAMERAWRAPPER\ARMV5\camerawrapper{000a0000}.s 0x00000000 Number 0 camerawrapper{000a0000}.exp ABSOLUTE + \S60\proj\CameraWrapper\src\cameraengine.cpp 0x00000000 Number 0 camerawrapper.in ABSOLUTE + \S60\proj\CameraWrapper\src\cameraengineprivate.cpp 0x00000000 Number 0 camerawrapper.in ABSOLUTE + \\EPOC32\\BUILD\\src\\cedar\\generic\\BASE\\E32\\EDLL\\ARMV5\\UREL\\uc_dll_.cpp 0x00000000 Number 0 uc_dll_.o ABSOLUTE + \\src\\cedar\\generic\\BASE\\E32\\compsupp\\RVCT2_2\\ucppinit_aeabi.cpp 0x00000000 Number 0 ucppinit_aeabi.o ABSOLUTE + \src\cedar\generic\BASE\E32\EUSER\epoc\arm\uc_dll.cpp 0x00000000 Number 0 uc_dll.o ABSOLUTE + \src\cedar\generic\BASE\E32\compsupp\RVCT2_2\ucppinit_aeabi.cpp 0x00000000 Number 0 ucppinit_aeabi.o ABSOLUTE + .emb_text 0x00008000 Section 40 uc_dll_.o(.emb_text) + .emb_text 0x00008028 Section 72 ucppinit_aeabi.o(.emb_text) + skip 0x0000803c ARM Code 0 ucppinit_aeabi.o(.emb_text) + loop 0x0000804c ARM Code 0 ucppinit_aeabi.o(.emb_text) + fpinit 0x00008064 Data 0 ucppinit_aeabi.o(.emb_text) + base 0x00008068 Data 0 ucppinit_aeabi.o(.emb_text) + limit 0x0000806c Data 0 ucppinit_aeabi.o(.emb_text) + .text 0x00008070 Section 348 camerawrapper.in(.text) + .text 0x000081cc Section 2104 camerawrapper.in(.text) + .text 0x00008a04 Section 40 uc_dll.o(.text) + .text 0x00008a2c Section 188 CCamAutoFocus.o(.text) + .text 0x00008ae8 Section 304 CCamAutoFocusImpl.o(.text) + .text.clean 0x00008c18 Section 10 camerawrapper.in(.text.clean) + .text.clean 0x00008c22 Section 76 camerawrapper.in(.text.clean) + .text.clean 0x00008c6e Section 10 CCamAutoFocus.o(.text.clean) + .text.clean 0x00008c78 Section 10 CCamAutoFocusImpl.o(.text.clean) + ExportTable 0x00008c84 Section 140 camerawrapper{000a0000}.exp(ExportTable) + StubCode 0x00008d10 Section 8 euser{000a0000}-1169.o(StubCode) + theImportedSymbol 0x00008d14 Data 0 euser{000a0000}-1169.o(StubCode) + StubCode 0x00008d18 Section 8 euser{000a0000}-1308.o(StubCode) + theImportedSymbol 0x00008d1c Data 0 euser{000a0000}-1308.o(StubCode) + StubCode 0x00008d20 Section 8 euser{000a0000}-1311.o(StubCode) + theImportedSymbol 0x00008d24 Data 0 euser{000a0000}-1311.o(StubCode) + StubCode 0x00008d28 Section 8 euser{000a0000}-1356.o(StubCode) + theImportedSymbol 0x00008d2c Data 0 euser{000a0000}-1356.o(StubCode) + StubCode 0x00008d30 Section 8 euser{000a0000}-1601.o(StubCode) + theImportedSymbol 0x00008d34 Data 0 euser{000a0000}-1601.o(StubCode) + StubCode 0x00008d38 Section 8 euser{000a0000}-1657.o(StubCode) + theImportedSymbol 0x00008d3c Data 0 euser{000a0000}-1657.o(StubCode) + StubCode 0x00008d40 Section 8 euser{000a0000}-1659.o(StubCode) + theImportedSymbol 0x00008d44 Data 0 euser{000a0000}-1659.o(StubCode) + StubCode 0x00008d48 Section 8 euser{000a0000}-1838.o(StubCode) + theImportedSymbol 0x00008d4c Data 0 euser{000a0000}-1838.o(StubCode) + StubCode 0x00008d50 Section 8 euser{000a0000}-205.o(StubCode) + theImportedSymbol 0x00008d54 Data 0 euser{000a0000}-205.o(StubCode) + StubCode 0x00008d58 Section 8 euser{000a0000}-2060.o(StubCode) + theImportedSymbol 0x00008d5c Data 0 euser{000a0000}-2060.o(StubCode) + StubCode 0x00008d60 Section 8 euser{000a0000}-2061.o(StubCode) + theImportedSymbol 0x00008d64 Data 0 euser{000a0000}-2061.o(StubCode) + StubCode 0x00008d68 Section 8 euser{000a0000}-208.o(StubCode) + theImportedSymbol 0x00008d6c Data 0 euser{000a0000}-208.o(StubCode) + StubCode 0x00008d70 Section 8 euser{000a0000}-2082.o(StubCode) + theImportedSymbol 0x00008d74 Data 0 euser{000a0000}-2082.o(StubCode) + StubCode 0x00008d78 Section 8 euser{000a0000}-2123.o(StubCode) + theImportedSymbol 0x00008d7c Data 0 euser{000a0000}-2123.o(StubCode) + StubCode 0x00008d80 Section 8 euser{000a0000}-2125.o(StubCode) + theImportedSymbol 0x00008d84 Data 0 euser{000a0000}-2125.o(StubCode) + StubCode 0x00008d88 Section 8 euser{000a0000}-593.o(StubCode) + theImportedSymbol 0x00008d8c Data 0 euser{000a0000}-593.o(StubCode) + StubCode 0x00008d90 Section 8 euser{000a0000}-649.o(StubCode) + theImportedSymbol 0x00008d94 Data 0 euser{000a0000}-649.o(StubCode) + StubCode 0x00008d98 Section 8 euser{000a0000}-654.o(StubCode) + theImportedSymbol 0x00008d9c Data 0 euser{000a0000}-654.o(StubCode) + StubCode 0x00008da0 Section 8 euser{000a0000}-669.o(StubCode) + theImportedSymbol 0x00008da4 Data 0 euser{000a0000}-669.o(StubCode) + StubCode 0x00008da8 Section 8 ecam{000a0000}-2.o(StubCode) + theImportedSymbol 0x00008dac Data 0 ecam{000a0000}-2.o(StubCode) + StubCode 0x00008db0 Section 8 ecam{000a0000}-3.o(StubCode) + theImportedSymbol 0x00008db4 Data 0 ecam{000a0000}-3.o(StubCode) + StubCode 0x00008db8 Section 8 FBSCLI{000a0000}-130.o(StubCode) + theImportedSymbol 0x00008dbc Data 0 FBSCLI{000a0000}-130.o(StubCode) + StubCode 0x00008dc0 Section 8 FBSCLI{000a0000}-25.o(StubCode) + theImportedSymbol 0x00008dc4 Data 0 FBSCLI{000a0000}-25.o(StubCode) + StubCode 0x00008dc8 Section 8 FBSCLI{000a0000}-30.o(StubCode) + theImportedSymbol 0x00008dcc Data 0 FBSCLI{000a0000}-30.o(StubCode) + StubCode 0x00008dd0 Section 8 FBSCLI{000a0000}-31.o(StubCode) + theImportedSymbol 0x00008dd4 Data 0 FBSCLI{000a0000}-31.o(StubCode) + StubCode 0x00008dd8 Section 8 ecamadvsettings{000a0000}-120.o(StubCode) + theImportedSymbol 0x00008ddc Data 0 ecamadvsettings{000a0000}-120.o(StubCode) + StubCode 0x00008de0 Section 8 ecamadvsettings{000a0000}-125.o(StubCode) + theImportedSymbol 0x00008de4 Data 0 ecamadvsettings{000a0000}-125.o(StubCode) + StubCode 0x00008de8 Section 8 ecamadvsettings{000a0000}-26.o(StubCode) + theImportedSymbol 0x00008dec Data 0 ecamadvsettings{000a0000}-26.o(StubCode) + StubCode 0x00008df0 Section 8 ecamadvsettings{000a0000}-28.o(StubCode) + theImportedSymbol 0x00008df4 Data 0 ecamadvsettings{000a0000}-28.o(StubCode) + StubCode 0x00008df8 Section 8 ecamadvsettings{000a0000}-41.o(StubCode) + theImportedSymbol 0x00008dfc Data 0 ecamadvsettings{000a0000}-41.o(StubCode) + StubCode 0x00008e00 Section 8 ecamadvsettings{000a0000}-42.o(StubCode) + theImportedSymbol 0x00008e04 Data 0 ecamadvsettings{000a0000}-42.o(StubCode) + StubCode 0x00008e08 Section 8 ecamadvsettings{000a0000}-64.o(StubCode) + theImportedSymbol 0x00008e0c Data 0 ecamadvsettings{000a0000}-64.o(StubCode) + StubCode 0x00008e10 Section 8 drtaeabi{000a0000}-158.o(StubCode) + theImportedSymbol 0x00008e14 Data 0 drtaeabi{000a0000}-158.o(StubCode) + StubCode 0x00008e18 Section 8 drtaeabi{000a0000}-180.o(StubCode) + theImportedSymbol 0x00008e1c Data 0 drtaeabi{000a0000}-180.o(StubCode) + StubCode 0x00008e20 Section 8 drtaeabi{000a0000}-183.o(StubCode) + theImportedSymbol 0x00008e24 Data 0 drtaeabi{000a0000}-183.o(StubCode) + StubCode 0x00008e28 Section 8 drtaeabi{000a0000}-184.o(StubCode) + theImportedSymbol 0x00008e2c Data 0 drtaeabi{000a0000}-184.o(StubCode) + StubCode 0x00008e30 Section 8 scppnwdl{000a0000}-3.o(StubCode) + theImportedSymbol 0x00008e34 Data 0 scppnwdl{000a0000}-3.o(StubCode) + i._ZN20CCameraEnginePrivate16FrameBufferReadyEP12MFrameBufferi 0x00008e38 Section 2 camerawrapper.in(i._ZN20CCameraEnginePrivate16FrameBufferReadyEP12MFrameBufferi) + i._ZN20CCameraEnginePrivate16VideoBufferReadyER13MCameraBufferi 0x00008e3a Section 2 camerawrapper.in(i._ZN20CCameraEnginePrivate16VideoBufferReadyER13MCameraBufferi) + i._ZThn4_N20CCameraEnginePrivate16FrameBufferReadyEP12MFrameBufferi 0x00008e3c Section 2 camerawrapper.in(i._ZThn4_N20CCameraEnginePrivate16FrameBufferReadyEP12MFrameBufferi) + i._ZThn8_N20CCameraEnginePrivate16VideoBufferReadyER13MCameraBufferi 0x00008e3e Section 2 camerawrapper.in(i._ZThn8_N20CCameraEnginePrivate16VideoBufferReadyER13MCameraBufferi) + .extab._ZN13CCameraEngineD1Ev 0x00008e40 Data 0 camerawrapper.in(.ARM.extab) + .extab._ZN20CCameraEnginePrivate10ConstructLEv 0x00008e50 Data 0 camerawrapper.in(.ARM.extab) + .extab._ZN20CCameraEnginePrivateC1EiiP21MCameraEngineObserver 0x00008eb8 Data 0 camerawrapper.in(.ARM.extab) + .extab._ZN20CCameraEnginePrivateD1Ev 0x00008ec8 Data 0 camerawrapper.in(.ARM.extab) + .extab._ZN20CCameraEnginePrivate13SetFocusRangeEi 0x00008ed8 Data 0 camerawrapper.in(.ARM.extab) + .extab._ZN20CCameraEnginePrivate17AdjustDigitalZoomEi 0x00008f00 Data 0 camerawrapper.in(.ARM.extab) + .extab._ZN20CCameraEnginePrivate11SetExposureEi 0x00008f28 Data 0 camerawrapper.in(.ARM.extab) + .extab._ZN20CCameraEnginePrivate8SetFlashEi 0x00008f50 Data 0 camerawrapper.in(.ARM.extab) + .extab._ZN20CCameraEnginePrivate16ImageBufferReadyER13MCameraBufferi 0x00008f78 Data 0 camerawrapper.in(.ARM.extab) + .extab._ZN20CCameraEnginePrivate15PowerOnCompleteEi 0x00008fc0 Data 0 camerawrapper.in(.ARM.extab) + .extab._ZN13CCamAutoFocusD1Ev 0x00008fe8 Data 0 CCamAutoFocus.o(.ARM.extab) + .extab._ZN17CCamAutoFocusImplD1Ev 0x00008ff8 Data 0 CCamAutoFocusImpl.o(.ARM.extab) + .constdata$1 0x00009008 Data 0 camerawrapper.in(.constdata) + KUidECamEventReserveComplete 0x00009008 Data 4 camerawrapper.in(.constdata) + .constdata 0x00009008 Section 16 camerawrapper.in(.constdata) + KUidECamEventPowerOnComplete 0x0000900c Data 4 camerawrapper.in(.constdata) + KNullDesC 0x00009010 Data 8 camerawrapper.in(.constdata) + .constdata$1 0x00009018 Data 0 CCamAutoFocusImpl.o(.constdata) + KCameraAutoFocusUid 0x00009018 Data 4 CCamAutoFocusImpl.o(.constdata) + .constdata 0x00009018 Section 4 CCamAutoFocusImpl.o(.constdata) + .constdata__ZTI13CCamAutoFocus 0x0000901c Section 12 CCamAutoFocus.o(.constdata__ZTI13CCamAutoFocus) + .constdata__ZTI13CCameraEngine 0x00009028 Section 12 camerawrapper.in(.constdata__ZTI13CCameraEngine) + .constdata__ZTI15MCameraObserver 0x00009034 Section 8 camerawrapper.in(.constdata__ZTI15MCameraObserver) + .constdata__ZTI16MCameraObserver2 0x0000903c Section 8 camerawrapper.in(.constdata__ZTI16MCameraObserver2) + .constdata__ZTI17CCamAutoFocusImpl 0x00009044 Section 32 CCamAutoFocusImpl.o(.constdata__ZTI17CCamAutoFocusImpl) + .constdata__ZTI20CCameraEnginePrivate 0x00009064 Section 48 camerawrapper.in(.constdata__ZTI20CCameraEnginePrivate) + .constdata__ZTI21MCamAutoFocusObserver 0x00009094 Section 8 camerawrapper.in(.constdata__ZTI21MCamAutoFocusObserver) + .constdata__ZTI24MCameraAutoFocusObserver 0x0000909c Section 8 CCamAutoFocusImpl.o(.constdata__ZTI24MCameraAutoFocusObserver) + .constdata__ZTS13CCamAutoFocus 0x000090a4 Section 16 CCamAutoFocus.o(.constdata__ZTS13CCamAutoFocus) + .constdata__ZTS13CCameraEngine 0x000090b4 Section 16 camerawrapper.in(.constdata__ZTS13CCameraEngine) + .constdata__ZTS15MCameraObserver 0x000090c4 Section 18 camerawrapper.in(.constdata__ZTS15MCameraObserver) + .constdata__ZTS16MCameraObserver2 0x000090d6 Section 19 camerawrapper.in(.constdata__ZTS16MCameraObserver2) + .constdata__ZTS17CCamAutoFocusImpl 0x000090e9 Section 20 CCamAutoFocusImpl.o(.constdata__ZTS17CCamAutoFocusImpl) + .constdata__ZTS20CCameraEnginePrivate 0x000090fd Section 23 camerawrapper.in(.constdata__ZTS20CCameraEnginePrivate) + .constdata__ZTS21MCamAutoFocusObserver 0x00009114 Section 24 camerawrapper.in(.constdata__ZTS21MCamAutoFocusObserver) + .constdata__ZTS24MCameraAutoFocusObserver 0x0000912c Section 27 CCamAutoFocusImpl.o(.constdata__ZTS24MCameraAutoFocusObserver) + .constdata__ZTV13CCamAutoFocus 0x00009148 Section 20 CCamAutoFocus.o(.constdata__ZTV13CCamAutoFocus) + .constdata__ZTV13CCameraEngine 0x0000915c Section 20 camerawrapper.in(.constdata__ZTV13CCameraEngine) + .constdata__ZTV17CCamAutoFocusImpl 0x00009170 Section 44 CCamAutoFocusImpl.o(.constdata__ZTV17CCamAutoFocusImpl) + .constdata__ZTV20CCameraEnginePrivate 0x0000919c Section 132 camerawrapper.in(.constdata__ZTV20CCameraEnginePrivate) + .ARM.exidx 0x00009220 Section 8 ucppinit_aeabi.o(.ARM.exidx) + + Global Symbols + + Symbol Name Value Ov Type Size Object(Section) + + BuildAttributes$$THUMB_ISAv2$ARM_ISAv5$M$PE$A:L22$X:L11$S22$IEEE1$IW$USESV6$~STKCKD$USESV7$~SHL$OSPACE$IEEEJ$EBA8$UX$REQ8$PRES8$EABIv2 0x00000000 Number 0 anon$$obj.o ABSOLUTE + #FBSCLI{000a0000}[10003a15].DLL#<\DLL>19 - Undefined Reference + #FBSCLI{000a0000}[10003a15].DLL#<\DLL>1e - Undefined Reference + #FBSCLI{000a0000}[10003a15].DLL#<\DLL>1f - Undefined Reference + #FBSCLI{000a0000}[10003a15].DLL#<\DLL>82 - Undefined Reference + #drtaeabi{000a0000}.dll#<\DLL>9e - Undefined Reference + #drtaeabi{000a0000}.dll#<\DLL>b4 - Undefined Reference + #drtaeabi{000a0000}.dll#<\DLL>b7 - Undefined Reference + #drtaeabi{000a0000}.dll#<\DLL>b8 - Undefined Reference + #ecamadvsettings{000a0000}[1020e76b].dll#<\DLL>1a - Undefined Reference + #ecamadvsettings{000a0000}[1020e76b].dll#<\DLL>1c - Undefined Reference + #ecamadvsettings{000a0000}[1020e76b].dll#<\DLL>29 - Undefined Reference + #ecamadvsettings{000a0000}[1020e76b].dll#<\DLL>2a - Undefined Reference + #ecamadvsettings{000a0000}[1020e76b].dll#<\DLL>40 - Undefined Reference + #ecamadvsettings{000a0000}[1020e76b].dll#<\DLL>78 - Undefined Reference + #ecamadvsettings{000a0000}[1020e76b].dll#<\DLL>7d - Undefined Reference + #ecam{000a0000}[101fb4c3].dll#<\DLL>2 - Undefined Reference + #ecam{000a0000}[101fb4c3].dll#<\DLL>3 - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>251 - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>289 - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>28e - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>29d - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>491 - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>51c - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>51f - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>54c - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>641 - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>679 - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>67b - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>72e - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>80c - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>80d - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>822 - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>84b - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>84d - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>cd - Undefined Reference + #euser{000a0000}[100039e5].dll#<\DLL>d0 - Undefined Reference + #scppnwdl{000a0000}.dll#<\DLL>3 - Undefined Reference + SHT$$INIT_ARRAY$$Base - Undefined Weak Reference + SHT$$INIT_ARRAY$$Limit - Undefined Weak Reference + typeinfo for XLeaveException - Undefined Reference + typeinfo for CBase - Undefined Reference + vtable for __cxxabiv1::__class_type_info - Undefined Reference + vtable for __cxxabiv1::__si_class_type_info - Undefined Reference + vtable for __cxxabiv1::__vmi_class_type_info - Undefined Reference + _fp_init - Undefined Weak Reference + run_static_dtors - Undefined Weak Reference + Image$$ER_RO$$Base 0x00008000 Number 0 anon$$obj.o(linker$$defined$$symbols) + _E32Dll 0x00008000 ARM Code 40 uc_dll_.o(.emb_text) + Symbian$$CPP$$Exception$$Descriptor 0x00008014 Data 0 uc_dll_.o(.emb_text) + __cpp_initialize__aeabi_ 0x00008028 ARM Code 72 ucppinit_aeabi.o(.emb_text) + CCameraEngine::CCameraEngine() 0x00008071 Thumb Code 6 camerawrapper.in(.text) + CCameraEngine::CCameraEngine__sub_object() 0x00008071 Thumb Code 0 camerawrapper.in(.text) + std::nothrow 0x00008071 Thumb Code 0 ucppinit_aeabi.o(.emb_text) + CCameraEngine::NewL(int, int, MCameraEngineObserver*) 0x00008077 Thumb Code 44 camerawrapper.in(.text) + CCameraEngine::~CCameraEngine() 0x000080a3 Thumb Code 28 camerawrapper.in(.text) + CCameraEngine::~CCameraEngine__sub_object() 0x000080a3 Thumb Code 0 camerawrapper.in(.text) + CCameraEngine::~CCameraEngine__deallocating() 0x000080bf Thumb Code 16 camerawrapper.in(.text) + CCameraEngine::State() const 0x000080cf Thumb Code 6 camerawrapper.in(.text) + CCameraEngine::IsCameraReady() const 0x000080d5 Thumb Code 6 camerawrapper.in(.text) + CCameraEngine::IsAutoFocusSupported() const 0x000080db Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::CaptureL() 0x000080e5 Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::ReserveAndPowerOn() 0x000080ef Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::ReleaseAndPowerOff() 0x000080f9 Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::PrepareL(TSize&, CCamera::TFormat) 0x00008103 Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::StartViewFinderL(TSize&) 0x0000810d Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::StopViewFinder() 0x00008117 Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::ReleaseViewFinderBuffer() 0x00008121 Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::ReleaseImageBuffer() 0x0000812b Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::StartFocusL() 0x00008135 Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::FocusCancel() 0x0000813f Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::SupportedFocusRanges(int&) const 0x00008149 Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::SetFocusRange(int) 0x00008153 Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::Camera() 0x0000815d Thumb Code 6 camerawrapper.in(.text) + CCameraEngine::AdvancedSettings() 0x00008163 Thumb Code 8 camerawrapper.in(.text) + CCameraEngine::CamerasAvailable() 0x0000816b Thumb Code 8 camerawrapper.in(.text) + CCameraEngine::MaxDigitalZoom() 0x00008173 Thumb Code 6 camerawrapper.in(.text) + CCameraEngine::DigitalZoom() 0x00008179 Thumb Code 8 camerawrapper.in(.text) + CCameraEngine::AdjustDigitalZoom(int) 0x00008181 Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::SupportedExposureModes() 0x0000818b Thumb Code 6 camerawrapper.in(.text) + CCameraEngine::Exposure() 0x00008191 Thumb Code 14 camerawrapper.in(.text) + CCameraEngine::SetExposure(int) 0x0000819f Thumb Code 10 camerawrapper.in(.text) + CCameraEngine::SupportedFlashModes() 0x000081a9 Thumb Code 6 camerawrapper.in(.text) + CCameraEngine::Flash() 0x000081af Thumb Code 14 camerawrapper.in(.text) + CCameraEngine::SetFlash(int) 0x000081bd Thumb Code 10 camerawrapper.in(.text) + CCameraEnginePrivate::ConstructL() 0x000081cd Thumb Code 268 camerawrapper.in(.text) + CCameraEnginePrivate::CCameraEnginePrivate(int, int, MCameraEngineObserver*) 0x000082d9 Thumb Code 48 camerawrapper.in(.text) + CCameraEnginePrivate::CCameraEnginePrivate__sub_object(int, int, MCameraEngineObserver*) 0x000082d9 Thumb Code 0 camerawrapper.in(.text) + CCameraEnginePrivate::NewL(int, int, MCameraEngineObserver*) 0x00008309 Thumb Code 44 camerawrapper.in(.text) + CCameraEnginePrivate::ReleaseImageBuffer() 0x00008335 Thumb Code 40 camerawrapper.in(.text) + CCameraEnginePrivate::ReleaseViewFinderBuffer() 0x0000835d Thumb Code 22 camerawrapper.in(.text) + CCameraEnginePrivate::StopViewFinder() 0x00008373 Thumb Code 30 camerawrapper.in(.text) + CCameraEnginePrivate::~CCameraEnginePrivate() 0x00008391 Thumb Code 98 camerawrapper.in(.text) + CCameraEnginePrivate::~CCameraEnginePrivate__sub_object() 0x00008391 Thumb Code 0 camerawrapper.in(.text) + CCameraEnginePrivate::~CCameraEnginePrivate__deallocating() 0x000083f3 Thumb Code 16 camerawrapper.in(.text) + CCameraEnginePrivate::IsAutoFocusSupported() const 0x00008403 Thumb Code 34 camerawrapper.in(.text) + CCameraEnginePrivate::CaptureL() 0x00008425 Thumb Code 34 camerawrapper.in(.text) + CCameraEnginePrivate::ReserveAndPowerOn() 0x00008447 Thumb Code 8 camerawrapper.in(.text) + CCameraEnginePrivate::FocusCancel() 0x0000844f Thumb Code 38 camerawrapper.in(.text) + CCameraEnginePrivate::ReleaseAndPowerOff() 0x00008475 Thumb Code 44 camerawrapper.in(.text) + CCameraEnginePrivate::PrepareL(TSize&, CCamera::TFormat) 0x000084a1 Thumb Code 118 camerawrapper.in(.text) + CCameraEnginePrivate::StartViewFinderL(TSize&) 0x00008517 Thumb Code 62 camerawrapper.in(.text) + CCameraEnginePrivate::StartFocusL() 0x00008555 Thumb Code 88 camerawrapper.in(.text) + CCameraEnginePrivate::SupportedFocusRanges(int&) const 0x000085ad Thumb Code 36 camerawrapper.in(.text) + CCameraEnginePrivate::SetFocusRange(int) 0x000085d1 Thumb Code 98 camerawrapper.in(.text) + CCameraEnginePrivate::AdjustDigitalZoom(int) 0x00008633 Thumb Code 110 camerawrapper.in(.text) + CCameraEnginePrivate::SetExposure(int) 0x000086a1 Thumb Code 62 camerawrapper.in(.text) + CCameraEnginePrivate::SetFlash(int) 0x000086df Thumb Code 62 camerawrapper.in(.text) + CCameraEnginePrivate::HandleEvent(const TECAMEvent&) 0x0000871d Thumb Code 196 camerawrapper.in(.text) + thunk{-8} to CCameraEnginePrivate::HandleEvent(const TECAMEvent&) 0x000087e1 Thumb Code 4 camerawrapper.in(.text) + CCameraEnginePrivate::ViewFinderReady(MCameraBuffer&, int) 0x000087e5 Thumb Code 46 camerawrapper.in(.text) + thunk{-8} to CCameraEnginePrivate::ViewFinderReady(MCameraBuffer&, int) 0x00008813 Thumb Code 4 camerawrapper.in(.text) + CCameraEnginePrivate::HandleImageReady(CFbsBitmap*, TDesC8*, int) 0x00008817 Thumb Code 60 camerawrapper.in(.text) + CCameraEnginePrivate::ImageBufferReady(MCameraBuffer&, int) 0x00008853 Thumb Code 126 camerawrapper.in(.text) + thunk{-8} to CCameraEnginePrivate::ImageBufferReady(MCameraBuffer&, int) 0x000088d1 Thumb Code 4 camerawrapper.in(.text) + CCameraEnginePrivate::ReserveComplete(int) 0x000088d5 Thumb Code 24 camerawrapper.in(.text) + thunk{-4} to CCameraEnginePrivate::ReserveComplete(int) 0x000088ed Thumb Code 4 camerawrapper.in(.text) + CCameraEnginePrivate::PowerOnComplete(int) 0x000088f1 Thumb Code 142 camerawrapper.in(.text) + thunk{-4} to CCameraEnginePrivate::PowerOnComplete(int) 0x0000897f Thumb Code 4 camerawrapper.in(.text) + CCameraEnginePrivate::ViewFinderFrameReady(CFbsBitmap&) 0x00008983 Thumb Code 8 camerawrapper.in(.text) + thunk{-4} to CCameraEnginePrivate::ViewFinderFrameReady(CFbsBitmap&) 0x0000898b Thumb Code 4 camerawrapper.in(.text) + CCameraEnginePrivate::ImageReady(CFbsBitmap*, HBufC8*, int) 0x0000898f Thumb Code 48 camerawrapper.in(.text) + thunk{-4} to CCameraEnginePrivate::ImageReady(CFbsBitmap*, HBufC8*, int) 0x000089bf Thumb Code 4 camerawrapper.in(.text) + CCameraEnginePrivate::InitComplete(int) 0x000089c3 Thumb Code 18 camerawrapper.in(.text) + thunk{-12} to CCameraEnginePrivate::InitComplete(int) 0x000089d5 Thumb Code 4 camerawrapper.in(.text) + CCameraEnginePrivate::OptimisedFocusComplete(int) 0x000089d9 Thumb Code 26 camerawrapper.in(.text) + thunk{-12} to CCameraEnginePrivate::OptimisedFocusComplete(int) 0x000089f3 Thumb Code 4 camerawrapper.in(.text) + _E32Dll_Body 0x00008a05 Thumb Code 34 uc_dll.o(.text) + CCamAutoFocus::ConstructL(CCamera*) 0x00008a2d Thumb Code 26 CCamAutoFocus.o(.text) + CCamAutoFocus::CCamAutoFocus() 0x00008a47 Thumb Code 6 CCamAutoFocus.o(.text) + CCamAutoFocus::CCamAutoFocus__sub_object() 0x00008a47 Thumb Code 0 CCamAutoFocus.o(.text) + CCamAutoFocus::NewL(CCamera*) 0x00008a4d Thumb Code 36 CCamAutoFocus.o(.text) + CCamAutoFocus::~CCamAutoFocus() 0x00008a71 Thumb Code 28 CCamAutoFocus.o(.text) + CCamAutoFocus::~CCamAutoFocus__sub_object() 0x00008a71 Thumb Code 0 CCamAutoFocus.o(.text) + CCamAutoFocus::~CCamAutoFocus__deallocating() 0x00008a8d Thumb Code 16 CCamAutoFocus.o(.text) + CCamAutoFocus::InitL(MCamAutoFocusObserver&) 0x00008a9d Thumb Code 10 CCamAutoFocus.o(.text) + CCamAutoFocus::AttemptOptimisedFocusL() 0x00008aa7 Thumb Code 10 CCamAutoFocus.o(.text) + CCamAutoFocus::SetFocusRangeL(CCamAutoFocus::TAutoFocusRange) 0x00008ab1 Thumb Code 10 CCamAutoFocus.o(.text) + CCamAutoFocus::FocusRange(CCamAutoFocus::TAutoFocusRange&) 0x00008abb Thumb Code 10 CCamAutoFocus.o(.text) + CCamAutoFocus::Cancel() 0x00008ac5 Thumb Code 10 CCamAutoFocus.o(.text) + CCamAutoFocus::ResetToIdleL() 0x00008acf Thumb Code 10 CCamAutoFocus.o(.text) + CCamAutoFocus::Close() 0x00008ad9 Thumb Code 10 CCamAutoFocus.o(.text) + CCamAutoFocusImpl::CCamAutoFocusImpl(CCamera*) 0x00008ae9 Thumb Code 22 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::CCamAutoFocusImpl__sub_object(CCamera*) 0x00008ae9 Thumb Code 0 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::ConstructL() 0x00008aff Thumb Code 2 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::Close() 0x00008b01 Thumb Code 22 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::~CCamAutoFocusImpl() 0x00008b17 Thumb Code 26 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::~CCamAutoFocusImpl__sub_object() 0x00008b17 Thumb Code 0 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::~CCamAutoFocusImpl__deallocating() 0x00008b31 Thumb Code 16 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::InitL(MCamAutoFocusObserver&) 0x00008b41 Thumb Code 60 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::AttemptOptimisedFocusL() 0x00008b7d Thumb Code 28 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::SetFocusRangeL(int) 0x00008b99 Thumb Code 34 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::FocusRange(int&) 0x00008bbb Thumb Code 6 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::Cancel() 0x00008bc1 Thumb Code 14 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::ResetToIdleL() 0x00008bcf Thumb Code 28 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::InitComplete(int) 0x00008beb Thumb Code 14 CCamAutoFocusImpl.o(.text) + thunk{-4} to CCamAutoFocusImpl::InitComplete(int) 0x00008bf9 Thumb Code 4 CCamAutoFocusImpl.o(.text) + CCamAutoFocusImpl::OptimisedFocusComplete(int) 0x00008bfd Thumb Code 14 CCamAutoFocusImpl.o(.text) + thunk{-4} to CCamAutoFocusImpl::OptimisedFocusComplete(int) 0x00008c0b Thumb Code 4 CCamAutoFocusImpl.o(.text) + __DLL_Export_Table__ 0x00008c84 ARM Code 0 camerawrapper{000a0000}.exp(ExportTable) + DLL##ExportTableSize 0x00008c88 Data 0 camerawrapper{000a0000}.exp(ExportTable) + DLL##ExportTable 0x00008c8c Data 0 camerawrapper{000a0000}.exp(ExportTable) + TPtrC16::TPtrC16(const unsigned short*) 0x00008d10 ARM Code 0 euser{000a0000}-1169.o(StubCode) + RLibrary::Load(const TDesC16&, const TDesC16&) 0x00008d18 ARM Code 0 euser{000a0000}-1308.o(StubCode) + RLibrary::Close() 0x00008d20 ARM Code 0 euser{000a0000}-1311.o(StubCode) + TVersion::TVersion() 0x00008d28 ARM Code 0 euser{000a0000}-1356.o(StubCode) + TUid::operator ==(const TUid&) const 0x00008d30 ARM Code 0 euser{000a0000}-1601.o(StubCode) + TSize::operator ==(const TSize&) const 0x00008d38 ARM Code 0 euser{000a0000}-1657.o(StubCode) + TSize::operator -(const TSize&) const 0x00008d40 ARM Code 0 euser{000a0000}-1659.o(StubCode) + RLibrary::Lookup(int) const 0x00008d48 ARM Code 0 euser{000a0000}-1838.o(StubCode) + CleanupStack::Pop() 0x00008d50 ARM Code 0 euser{000a0000}-205.o(StubCode) + User::MarkCleanupStack() 0x00008d58 ARM Code 0 euser{000a0000}-2060.o(StubCode) + User::UnMarkCleanupStack(TTrapHandler*) 0x00008d60 ARM Code 0 euser{000a0000}-2061.o(StubCode) + CleanupStack::PushL(CBase*) 0x00008d68 ARM Code 0 euser{000a0000}-208.o(StubCode) + XLeaveException::GetReason() const 0x00008d70 ARM Code 0 euser{000a0000}-2082.o(StubCode) + CBase::Extension_(unsigned, void*&, void*) 0x00008d78 ARM Code 0 euser{000a0000}-2123.o(StubCode) + CBase::~CBase() 0x00008d80 ARM Code 0 euser{000a0000}-2125.o(StubCode) + User::LeaveIfError(int) 0x00008d88 ARM Code 0 euser{000a0000}-593.o(StubCode) + User::Leave(int) 0x00008d90 ARM Code 0 euser{000a0000}-649.o(StubCode) + User::AllocZL(int) 0x00008d98 ARM Code 0 euser{000a0000}-654.o(StubCode) + User::Invariant() 0x00008da0 ARM Code 0 euser{000a0000}-669.o(StubCode) + CCamera::CamerasAvailable() 0x00008da8 ARM Code 0 ecam{000a0000}-2.o(StubCode) + CCamera::NewL(MCameraObserver&, int) 0x00008db0 ARM Code 0 ecam{000a0000}-3.o(StubCode) + CFbsBitmap::Handle() const 0x00008db8 ARM Code 0 FBSCLI{000a0000}-130.o(StubCode) + CFbsBitmap::Reset() 0x00008dc0 ARM Code 0 FBSCLI{000a0000}-25.o(StubCode) + CFbsBitmap::Duplicate(int) 0x00008dc8 ARM Code 0 FBSCLI{000a0000}-30.o(StubCode) + CFbsBitmap::CFbsBitmap() 0x00008dd0 ARM Code 0 FBSCLI{000a0000}-31.o(StubCode) + CCamera::CCameraAdvancedSettings::SupportedFocusModes() const 0x00008dd8 ARM Code 0 ecamadvsettings{000a0000}-120.o(StubCode) + CCamera::CCameraAdvancedSettings::SupportedFocusRanges() const 0x00008de0 ARM Code 0 ecamadvsettings{000a0000}-125.o(StubCode) + CCamera::CCameraAdvancedSettings::SetFocusMode(CCamera::CCameraAdvancedSettings::TFocusMode) 0x00008de8 ARM Code 0 ecamadvsettings{000a0000}-26.o(StubCode) + CCamera::CCameraAdvancedSettings::SetFocusRange(CCamera::CCameraAdvancedSettings::TFocusRange) 0x00008df0 ARM Code 0 ecamadvsettings{000a0000}-28.o(StubCode) + CCamera::CCameraAdvancedSettings::SetAutoFocusArea(CCamera::CCameraAdvancedSettings::TAutoFocusArea) 0x00008df8 ARM Code 0 ecamadvsettings{000a0000}-41.o(StubCode) + CCamera::CCameraAdvancedSettings::SetAutoFocusType(CCamera::CCameraAdvancedSettings::TAutoFocusType) 0x00008e00 ARM Code 0 ecamadvsettings{000a0000}-42.o(StubCode) + CCamera::CCameraAdvancedSettings::NewL(CCamera&) 0x00008e08 ARM Code 0 ecamadvsettings{000a0000}-64.o(StubCode) + __aeabi_unwind_cpp_pr0 0x00008e10 ARM Code 0 drtaeabi{000a0000}-158.o(StubCode) + __cxa_begin_catch 0x00008e18 ARM Code 0 drtaeabi{000a0000}-180.o(StubCode) + __cxa_end_catch 0x00008e20 ARM Code 0 drtaeabi{000a0000}-183.o(StubCode) + __cxa_end_cleanup 0x00008e28 ARM Code 0 drtaeabi{000a0000}-184.o(StubCode) + operator delete (void*) 0x00008e30 ARM Code 0 scppnwdl{000a0000}-3.o(StubCode) + CCameraEnginePrivate::FrameBufferReady(MFrameBuffer*, int) 0x00008e39 Thumb Code 2 camerawrapper.in(i._ZN20CCameraEnginePrivate16FrameBufferReadyEP12MFrameBufferi) + CCameraEnginePrivate::VideoBufferReady(MCameraBuffer&, int) 0x00008e3b Thumb Code 2 camerawrapper.in(i._ZN20CCameraEnginePrivate16VideoBufferReadyER13MCameraBufferi) + thunk{-4} to CCameraEnginePrivate::FrameBufferReady(MFrameBuffer*, int) 0x00008e3d Thumb Code 2 camerawrapper.in(i._ZThn4_N20CCameraEnginePrivate16FrameBufferReadyEP12MFrameBufferi) + thunk{-8} to CCameraEnginePrivate::VideoBufferReady(MCameraBuffer&, int) 0x00008e3f Thumb Code 2 camerawrapper.in(i._ZThn8_N20CCameraEnginePrivate16VideoBufferReadyER13MCameraBufferi) + typeinfo for CCamAutoFocus 0x0000901c Data 12 CCamAutoFocus.o(.constdata__ZTI13CCamAutoFocus) + typeinfo for CCameraEngine 0x00009028 Data 12 camerawrapper.in(.constdata__ZTI13CCameraEngine) + typeinfo for MCameraObserver 0x00009034 Data 8 camerawrapper.in(.constdata__ZTI15MCameraObserver) + typeinfo for MCameraObserver2 0x0000903c Data 8 camerawrapper.in(.constdata__ZTI16MCameraObserver2) + typeinfo for CCamAutoFocusImpl 0x00009044 Data 32 CCamAutoFocusImpl.o(.constdata__ZTI17CCamAutoFocusImpl) + typeinfo for CCameraEnginePrivate 0x00009064 Data 48 camerawrapper.in(.constdata__ZTI20CCameraEnginePrivate) + typeinfo for MCamAutoFocusObserver 0x00009094 Data 8 camerawrapper.in(.constdata__ZTI21MCamAutoFocusObserver) + typeinfo for MCameraAutoFocusObserver 0x0000909c Data 8 CCamAutoFocusImpl.o(.constdata__ZTI24MCameraAutoFocusObserver) + typeinfo name for CCamAutoFocus 0x000090a4 Data 16 CCamAutoFocus.o(.constdata__ZTS13CCamAutoFocus) + typeinfo name for CCameraEngine 0x000090b4 Data 16 camerawrapper.in(.constdata__ZTS13CCameraEngine) + typeinfo name for MCameraObserver 0x000090c4 Data 18 camerawrapper.in(.constdata__ZTS15MCameraObserver) + typeinfo name for MCameraObserver2 0x000090d6 Data 19 camerawrapper.in(.constdata__ZTS16MCameraObserver2) + typeinfo name for CCamAutoFocusImpl 0x000090e9 Data 20 CCamAutoFocusImpl.o(.constdata__ZTS17CCamAutoFocusImpl) + typeinfo name for CCameraEnginePrivate 0x000090fd Data 23 camerawrapper.in(.constdata__ZTS20CCameraEnginePrivate) + typeinfo name for MCamAutoFocusObserver 0x00009114 Data 24 camerawrapper.in(.constdata__ZTS21MCamAutoFocusObserver) + typeinfo name for MCameraAutoFocusObserver 0x0000912c Data 27 CCamAutoFocusImpl.o(.constdata__ZTS24MCameraAutoFocusObserver) + vtable for CCamAutoFocus 0x00009148 Data 20 CCamAutoFocus.o(.constdata__ZTV13CCamAutoFocus) + vtable for CCameraEngine 0x0000915c Data 20 camerawrapper.in(.constdata__ZTV13CCameraEngine) + vtable for CCamAutoFocusImpl 0x00009170 Data 44 CCamAutoFocusImpl.o(.constdata__ZTV17CCamAutoFocusImpl) + vtable for CCameraEnginePrivate 0x0000919c Data 132 camerawrapper.in(.constdata__ZTV20CCameraEnginePrivate) + .ARM.exidx$$Base 0x00009220 Number 0 ucppinit_aeabi.o(.ARM.exidx) + .ARM.exidx$$Limit 0x00009338 Number 0 camerawrapper.in(.ARM.exidx) + Image$$ER_RO$$Limit 0x00009338 Number 0 anon$$obj.o(linker$$defined$$symbols) + diff --git a/symbian/QQrDecoder/camerawrapper/epoc32/release/winscw/udeb/CamAutoFocus.dll b/symbian/QQrDecoder/camerawrapper/epoc32/release/winscw/udeb/CamAutoFocus.dll new file mode 100644 index 000000000..da16da62e Binary files /dev/null and b/symbian/QQrDecoder/camerawrapper/epoc32/release/winscw/udeb/CamAutoFocus.dll differ diff --git a/symbian/QQrDecoder/camerawrapper/epoc32/release/winscw/udeb/camerawrapper.dll b/symbian/QQrDecoder/camerawrapper/epoc32/release/winscw/udeb/camerawrapper.dll new file mode 100644 index 000000000..d352fa8a6 Binary files /dev/null and b/symbian/QQrDecoder/camerawrapper/epoc32/release/winscw/udeb/camerawrapper.dll differ diff --git a/symbian/QQrDecoder/camerawrapper/epoc32/release/winscw/udeb/camerawrapper.lib b/symbian/QQrDecoder/camerawrapper/epoc32/release/winscw/udeb/camerawrapper.lib new file mode 100644 index 000000000..272d0aa5d Binary files /dev/null and b/symbian/QQrDecoder/camerawrapper/epoc32/release/winscw/udeb/camerawrapper.lib differ diff --git a/symbian/QQrDecoder/main.cpp b/symbian/QQrDecoder/main.cpp new file mode 100644 index 000000000..a7589121c --- /dev/null +++ b/symbian/QQrDecoder/main.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Trolltech hereby grants a license to use the Qt/Eclipse Integration +** plug-in (the software contained herein), in binary form, solely for the +** purpose of creating code to be used with Trolltech's Qt software. +** +** Qt Designer is licensed under the terms of the GNU General Public +** License versions 2.0 and 3.0 ("GPL License"). Trolltech offers users the +** right to use certain no GPL licensed software under the terms of its GPL +** Exception version 1.2 (http://trolltech.com/products/qt/gplexception). +** +** THIS SOFTWARE IS PROVIDED BY TROLLTECH AND ITS CONTRIBUTORS (IF ANY) "AS +** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +** PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +** OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** Since we now have the GPL exception I think that the "special exception +** is no longer needed. The license text proposed above (other than the +** special exception portion of it) is the BSD license and we have added +** the BSD license as a permissible license under the exception. +** +****************************************************************************/ + +#include "QQrDecoder.h" + +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QQrDecoder w; + w.showMaximized(); + return a.exec(); +} diff --git a/symbian/QQrDecoder/zxing/BarcodeFormat.cpp b/symbian/QQrDecoder/zxing/BarcodeFormat.cpp new file mode 100644 index 000000000..b31afccf1 --- /dev/null +++ b/symbian/QQrDecoder/zxing/BarcodeFormat.cpp @@ -0,0 +1,22 @@ +/* + * BarcodeFormat.cpp + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + diff --git a/symbian/QQrDecoder/zxing/BarcodeFormat.h b/symbian/QQrDecoder/zxing/BarcodeFormat.h new file mode 100644 index 000000000..943831dad --- /dev/null +++ b/symbian/QQrDecoder/zxing/BarcodeFormat.h @@ -0,0 +1,42 @@ +#ifndef __BARCODE_FORMAT_H__ +#define __BARCODE_FORMAT_H__ + +/* + * BarcodeFormat.h + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Modified by Lukasz Warchol on 02/02/2010 + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace zxing { + + typedef enum BarcodeFormat { + BarcodeFormat_None = 0, + BarcodeFormat_QR_CODE, + BarcodeFormat_DATA_MATRIX, + BarcodeFormat_UPC_E, + BarcodeFormat_UPC_A, + BarcodeFormat_EAN_8, + BarcodeFormat_EAN_13, + BarcodeFormat_CODE_128, + BarcodeFormat_CODE_39, + BarcodeFormat_ITF + } BarcodeFormat; + +} + +#endif // __BARCODE_FORMAT_H__ diff --git a/symbian/QQrDecoder/zxing/Binarizer.cpp b/symbian/QQrDecoder/zxing/Binarizer.cpp new file mode 100644 index 000000000..5f6e746bc --- /dev/null +++ b/symbian/QQrDecoder/zxing/Binarizer.cpp @@ -0,0 +1,48 @@ +/* + * Binarizer.cpp + * zxing + * + * Created by Ralf Kistner on 16/10/2009. + * Copyright 2008 ZXing authors All rights reserved. + * Modified by Lukasz Warchol on 02/02/2010. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { + + Binarizer::Binarizer(Ref source) : source_(source) { + } + + Binarizer::~Binarizer() { + } + + Ref Binarizer::getBlackRow(int y, Ref row){ + if (array_ == NULL) + array_ = estimateBlackRow(y, row); + return array_; + } + + Ref Binarizer::getBlackMatrix() { + if (matrix_ == NULL) + matrix_ = estimateBlackMatrix(); + return matrix_; + } + + Ref Binarizer::getSource() { + return source_; + } + +} diff --git a/symbian/QQrDecoder/zxing/Binarizer.h b/symbian/QQrDecoder/zxing/Binarizer.h new file mode 100644 index 000000000..ea1240c0b --- /dev/null +++ b/symbian/QQrDecoder/zxing/Binarizer.h @@ -0,0 +1,51 @@ +/* + * Binarizer.h + * zxing + * + * Created by Ralf Kistner on 16/10/2009. + * Copyright 2008 ZXing authors All rights reserved. + * Modified by Lukasz Warchol on 02/02/2010. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BINARIZER_H_ +#define BINARIZER_H_ + +#include +#include +#include +#include + +namespace zxing { + + class Binarizer : public Counted { + private: + Ref source_; + Ref matrix_; + Ref array_; + + public: + Binarizer(Ref source); + virtual ~Binarizer(); + + virtual Ref estimateBlackRow(int y, Ref row)=0; + Ref getBlackRow(int y, Ref row); + + virtual Ref estimateBlackMatrix() = 0; + Ref getBlackMatrix(); + Ref getSource(); + }; + +} +#endif /* BINARIZER_H_ */ diff --git a/symbian/QQrDecoder/zxing/BinaryBitmap.cpp b/symbian/QQrDecoder/zxing/BinaryBitmap.cpp new file mode 100644 index 000000000..1e692a9f5 --- /dev/null +++ b/symbian/QQrDecoder/zxing/BinaryBitmap.cpp @@ -0,0 +1,57 @@ +/* + * BinaryBitmap.cpp + * zxing + * + * Created by Ralf Kistner on 19/10/2009. + * Copyright 2008 ZXing authors All rights reserved. + * Modified by Lukasz Warchol on 02/02/2010. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { + + BinaryBitmap::BinaryBitmap(Ref binarizer) : bits_(NULL), binarizer_(binarizer) { + + } + + BinaryBitmap::~BinaryBitmap() { + } + + Ref BinaryBitmap::getBlackRow(int y, Ref row) { + if (array_bits_ == NULL) { + array_bits_ = binarizer_->getBlackRow(y, row); + } + return array_bits_; + } + + Ref BinaryBitmap::getBlackMatrix() { + if (bits_ == NULL) { + bits_ = binarizer_->getBlackMatrix(); + } + return bits_; + } + int BinaryBitmap::getWidth() { + return getSource()->getWidth(); + } + int BinaryBitmap::getHeight() { + return getSource()->getHeight(); + } + + Ref BinaryBitmap::getSource() { + return binarizer_->getSource(); + } + +} diff --git a/symbian/QQrDecoder/zxing/BinaryBitmap.h b/symbian/QQrDecoder/zxing/BinaryBitmap.h new file mode 100644 index 000000000..ecd9a8549 --- /dev/null +++ b/symbian/QQrDecoder/zxing/BinaryBitmap.h @@ -0,0 +1,51 @@ +/* + * BinaryBitmap.h + * zxing + * + * Created by Ralf Kistner on 19/10/2009. + * Copyright 2008 ZXing authors All rights reserved. + * Modified by Lukasz Warchol on 02/02/2010. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef BINARYBITMAP_H_ +#define BINARYBITMAP_H_ + +#include +#include +#include +#include + +namespace zxing { + + class BinaryBitmap : public Counted { + private: + Ref bits_; + Ref array_bits_; + Ref binarizer_; + + public: + BinaryBitmap(Ref binarizer); + virtual ~BinaryBitmap(); + + Ref getBlackRow(int y, Ref row); + Ref getBlackMatrix(); + Ref getSource(); + + int getWidth(); + int getHeight(); + }; + +} + +#endif /* BINARYBITMAP_H_ */ diff --git a/symbian/QQrDecoder/zxing/Exception.cpp b/symbian/QQrDecoder/zxing/Exception.cpp new file mode 100644 index 000000000..47143c964 --- /dev/null +++ b/symbian/QQrDecoder/zxing/Exception.cpp @@ -0,0 +1,25 @@ +/* + * Exception.cpp + * ZXing + * + * Created by Christian Brunschen on 03/06/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + */ + +#include + +namespace zxing { + +Exception::Exception(const char *msg) : + message(msg) { +} + +const char* Exception::what() const throw() { + return message; +} + +Exception::~Exception() throw() { +} + +} diff --git a/symbian/QQrDecoder/zxing/Exception.h b/symbian/QQrDecoder/zxing/Exception.h new file mode 100644 index 000000000..7502c5cb6 --- /dev/null +++ b/symbian/QQrDecoder/zxing/Exception.h @@ -0,0 +1,40 @@ +#ifndef __EXCEPTION_H__ +#define __EXCEPTION_H__ + +/* + * Exception.h + * ZXing + * + * Created by Christian Brunschen on 03/06/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace zxing { + +class Exception : public std::exception { +private: + const char * message; + +public: + Exception(const char *msg); + virtual const char* what() const throw(); + virtual ~Exception() throw(); +}; + +} +#endif // __EXCEPTION_H__ diff --git a/symbian/QQrDecoder/zxing/LuminanceSource.cpp b/symbian/QQrDecoder/zxing/LuminanceSource.cpp new file mode 100644 index 000000000..6c8ef1e6e --- /dev/null +++ b/symbian/QQrDecoder/zxing/LuminanceSource.cpp @@ -0,0 +1,43 @@ +/* + * LuminanceSource.cpp + * zxing + * + * Created by Ralf Kistner on 16/10/2009. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { + +LuminanceSource::LuminanceSource() { +} + +LuminanceSource::~LuminanceSource() { +} + +unsigned char* LuminanceSource::copyMatrix() { + int width = getWidth(); + int height = getHeight(); + unsigned char* matrix = new unsigned char[width*height]; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + matrix[y*width+x] = getPixel(x, y); + } + } + return matrix; +} + +} diff --git a/symbian/QQrDecoder/zxing/LuminanceSource.h b/symbian/QQrDecoder/zxing/LuminanceSource.h new file mode 100644 index 000000000..e23621ef9 --- /dev/null +++ b/symbian/QQrDecoder/zxing/LuminanceSource.h @@ -0,0 +1,42 @@ +/* + * LuminanceSource.h + * zxing + * + * Created by Ralf Kistner on 16/10/2009. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LUMINANCESOURCE_H_ +#define LUMINANCESOURCE_H_ + +#include + +namespace zxing { + +class LuminanceSource : public Counted { +public: + LuminanceSource(); + virtual ~LuminanceSource(); + + virtual int getWidth() = 0; + virtual int getHeight() = 0; + + virtual unsigned char getPixel(int x, int y) = 0; + virtual unsigned char* copyMatrix(); +}; + +} + +#endif /* LUMINANCESOURCE_H_ */ diff --git a/symbian/QQrDecoder/zxing/MultiFormatReader.cpp b/symbian/QQrDecoder/zxing/MultiFormatReader.cpp new file mode 100644 index 000000000..2270ebeca --- /dev/null +++ b/symbian/QQrDecoder/zxing/MultiFormatReader.cpp @@ -0,0 +1,54 @@ +/* + * MultiFormatBarcodeReader.cpp + * ZXing + * + * Created by Lukasz Warchol on 10-01-26. + * Modified by Luiz Silva on 09/02/2010. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MultiFormatReader.h" +#include +//#include +#include +#include +#include + +namespace zxing { + MultiFormatReader::MultiFormatReader(){ + readers = new std::vector(); + + readers->push_back(new zxing::qrcode::QRCodeReader()); +// readers->push_back(new zxing::datamatrix::DataMatrixReader()); + readers->push_back(new zxing::oned::MultiFormatUPCEANReader()); + readers->push_back(new zxing::oned::MultiFormatOneDReader()); + } + + Ref MultiFormatReader::decode(Ref image){ + int size = readers->size(); + for (int i = 0; i < size; i++) { + Reader* reader = (*readers)[i]; + try { + return reader->decode(image); + } catch (ReaderException re) { + // continue + } + } + throw ReaderException("No code detected"); + } + MultiFormatReader::~MultiFormatReader(){ + delete readers; + } +} diff --git a/symbian/QQrDecoder/zxing/MultiFormatReader.h b/symbian/QQrDecoder/zxing/MultiFormatReader.h new file mode 100644 index 000000000..ff51c01c2 --- /dev/null +++ b/symbian/QQrDecoder/zxing/MultiFormatReader.h @@ -0,0 +1,38 @@ +/* + * MultiFormatBarcodeReader.h + * ZXing + * + * Created by Lukasz Warchol on 10-01-26. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include + +namespace zxing { + class MultiFormatReader : public Reader { + + private: + std::vector* readers; + public: + MultiFormatReader(); + + Ref decode(Ref image); + + ~MultiFormatReader(); + }; +} diff --git a/symbian/QQrDecoder/zxing/Reader.cpp b/symbian/QQrDecoder/zxing/Reader.cpp new file mode 100644 index 000000000..1e1fdc39b --- /dev/null +++ b/symbian/QQrDecoder/zxing/Reader.cpp @@ -0,0 +1,27 @@ +/* + * Reader.cpp + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { + +Reader::~Reader() { } + +} diff --git a/symbian/QQrDecoder/zxing/Reader.h b/symbian/QQrDecoder/zxing/Reader.h new file mode 100644 index 000000000..3de270f95 --- /dev/null +++ b/symbian/QQrDecoder/zxing/Reader.h @@ -0,0 +1,38 @@ +#ifndef __READER_H__ +#define __READER_H__ + +/* + * Reader.h + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace zxing { + +class Reader { +public: + virtual Ref decode(Ref image) = 0; + virtual ~Reader(); +}; + +} + +#endif // __READER_H__ diff --git a/symbian/QQrDecoder/zxing/ReaderException.cpp b/symbian/QQrDecoder/zxing/ReaderException.cpp new file mode 100644 index 000000000..7d2bc9d98 --- /dev/null +++ b/symbian/QQrDecoder/zxing/ReaderException.cpp @@ -0,0 +1,32 @@ +/* + * ReaderException.cpp + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { + +ReaderException::ReaderException(const char *msg) : + Exception(msg) { +} + +ReaderException::~ReaderException() throw() { +} + +} diff --git a/symbian/QQrDecoder/zxing/ReaderException.h b/symbian/QQrDecoder/zxing/ReaderException.h new file mode 100644 index 000000000..1a31ae8e9 --- /dev/null +++ b/symbian/QQrDecoder/zxing/ReaderException.h @@ -0,0 +1,35 @@ +#ifndef __READER_EXCEPTION_H__ +#define __READER_EXCEPTION_H__ + +/* + * ReaderException.h + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { + +class ReaderException : public Exception { +public: + ReaderException(const char *msg); + ~ReaderException() throw(); +}; + +} +#endif // __READER_EXCEPTION_H__ diff --git a/symbian/QQrDecoder/zxing/Result.cpp b/symbian/QQrDecoder/zxing/Result.cpp new file mode 100644 index 000000000..f87ef8844 --- /dev/null +++ b/symbian/QQrDecoder/zxing/Result.cpp @@ -0,0 +1,59 @@ +/* + * Result.cpp + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { +using namespace std; + +Result::Result(Ref text, ArrayRef rawBytes, std::vector > resultPoints, + BarcodeFormat format) : + text_(text), rawBytes_(rawBytes), resultPoints_(resultPoints), format_(format) { +} + +Result::~Result() { +} + +Ref Result::getText() { + return text_; +} + +ArrayRef Result::getRawBytes() { + return rawBytes_; +} + +std::vector > Result::getResultPoints() { + return resultPoints_; +} + +BarcodeFormat Result::getBarcodeFormat() { + return format_; +} + +ostream& operator<<(ostream &out, Result& result) { + if (result.text_ != 0) { + out << result.text_->getText(); + } else { + out << "[" << result.rawBytes_->size() << " bytes]"; + } + return out; +} + +} diff --git a/symbian/QQrDecoder/zxing/Result.h b/symbian/QQrDecoder/zxing/Result.h new file mode 100644 index 000000000..710d8d5a6 --- /dev/null +++ b/symbian/QQrDecoder/zxing/Result.h @@ -0,0 +1,54 @@ +#ifndef __RESULT_H__ +#define __RESULT_H__ + +/* + * Result.h + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace zxing { + +class Result : public Counted { +private: + Ref text_; + ArrayRef rawBytes_; + std::vector > resultPoints_; + BarcodeFormat format_; + +public: + Result(Ref text, ArrayRef rawBytes, std::vector > resultPoints, + BarcodeFormat format); + ~Result(); + Ref getText(); + ArrayRef getRawBytes(); + std::vector > getResultPoints(); + BarcodeFormat getBarcodeFormat(); + + friend std::ostream& operator<<(std::ostream &out, Result& result); +}; + +} +#endif // __RESULT_H__ diff --git a/symbian/QQrDecoder/zxing/ResultPoint.cpp b/symbian/QQrDecoder/zxing/ResultPoint.cpp new file mode 100644 index 000000000..464956873 --- /dev/null +++ b/symbian/QQrDecoder/zxing/ResultPoint.cpp @@ -0,0 +1,22 @@ +/* + * ResultPoint.cpp + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + diff --git a/symbian/QQrDecoder/zxing/ResultPoint.h b/symbian/QQrDecoder/zxing/ResultPoint.h new file mode 100644 index 000000000..6118cc0dc --- /dev/null +++ b/symbian/QQrDecoder/zxing/ResultPoint.h @@ -0,0 +1,36 @@ +#ifndef __RESULT_POINT_H__ +#define __RESULT_POINT_H__ + +/* + * ResultPoint.h + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { + +class ResultPoint : public Counted { +public: + virtual float getX() = 0; + virtual float getY() = 0; +}; + +} + +#endif // __RESULT_POINT_H__ diff --git a/symbian/QQrDecoder/zxing/common/Array.cpp b/symbian/QQrDecoder/zxing/common/Array.cpp new file mode 100644 index 000000000..aa1834a27 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/Array.cpp @@ -0,0 +1,22 @@ +/* + * Array.cpp + * zxing + * + * Created by Christian Brunschen on 07/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + diff --git a/symbian/QQrDecoder/zxing/common/Array.h b/symbian/QQrDecoder/zxing/common/Array.h new file mode 100644 index 000000000..39b178607 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/Array.h @@ -0,0 +1,209 @@ +#ifndef __ARRAY_H__ +#define __ARRAY_H__ + +/* + * Array.h + * zxing + * + * Created by Christian Brunschen on 07/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#ifdef DEBUG_COUNTING +#include +#include +#endif + +#include + + +namespace zxing { + +template class Array : public Counted { +protected: +public: + std::valarray values_; + Array(size_t n) : + Counted(), values_(T(), n) { + } + Array(T *ts, size_t n) : + Counted(), values_(ts, n) { + } + Array(T v, size_t n) : + Counted(), values_(v, n) { + } + Array(std::valarray &v) : + Counted(), values_(v) { + } + Array(Array &other) : + Counted(), values_(other.values_) { + } + Array(Array *other) : + Counted(), values_(other->values_) { + } + virtual ~Array() { + } + Array& operator=(const Array &other) { +#ifdef DEBUG_COUNTING + cout << "assigning values from Array " << &other << " to this Array " << this << ", "; +#endif + values_ = other.values_; +#ifdef DEBUG_COUNTING + cout << "new size = " << values_.size() << "\n"; +#endif + return *this; + } + Array& operator=(const std::valarray &array) { +#ifdef DEBUG_COUNTING + cout << "assigning values from Array " << &array << " to this Array " << this << ", "; +#endif + values_ = array; +#ifdef DEBUG_COUNTING + cout << "new size = " << values_.size() << "\n"; +#endif + return *this; + } + T operator[](size_t i) const { + return values_[i]; + } + T& operator[](size_t i) { + return values_[i]; + } + size_t size() const { + return values_.size(); + } + std::valarray values() const { + return values_; + } + std::valarray& values() { + return values_; + } +}; + +template class ArrayRef { +private: +public: + Array *array_; + ArrayRef() : + array_(0) { +#ifdef DEBUG_COUNTING + cout << "instantiating empty ArrayRef " << this << "\n"; +#endif + } + ArrayRef(size_t n) : + array_(0) { +#ifdef DEBUG_COUNTING + cout << "instantiating ArrayRef " << this << "with size " << n << "\n"; +#endif + reset(new Array (n)); + } + ArrayRef(T *ts, size_t n) : + array_(0) { +#ifdef DEBUG_COUNTING + cout << "instantiating ArrayRef " << this << "with " << n << " elements at " << (void *)ts << "\n"; +#endif + reset(new Array (ts, n)); + } + ArrayRef(Array *a) : + array_(0) { +#ifdef DEBUG_COUNTING + cout << "instantiating ArrayRef " << this << " from pointer:\n"; +#endif + reset(a); + } + ArrayRef(const Array &a) : + array_(0) { +#ifdef DEBUG_COUNTING + cout << "instantiating ArrayRef " << this << " from reference to Array " << (void *)&a << ":\n"; +#endif + reset(const_cast *>(&a)); + } + ArrayRef(const ArrayRef &other) : + array_(0) { +#ifdef DEBUG_COUNTING + cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n"; +#endif + reset(other.array_); + } + + template + ArrayRef(const ArrayRef &other) : + array_(0) { +#ifdef DEBUG_COUNTING + cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n"; +#endif + reset(static_cast *>(other.array_)); + } + + ~ArrayRef() { +#ifdef DEBUG_COUNTING + cout << "destroying ArrayRef " << this << " with " << (array_ ? typeid(*array_).name() : "NULL") << " " + << array_ << "\n"; +#endif + if (array_) { + array_->release(); + } + array_ = 0; + } + + T operator[](size_t i) const { + return (*array_)[i]; + } + T& operator[](size_t i) { + return (*array_)[i]; + } + size_t size() const { + return array_->size(); + } + + void reset(Array *a) { +#ifdef DEBUG_COUNTING + cout << "resetting ArrayRef " << this << " from " << (array_ ? typeid(*array_).name() : "NULL") << " " + << array_ << " to " << (a ? typeid(*a).name() : "NULL") << " " << a << "\n"; +#endif + if (a) { + a->retain(); + } + if (array_) { + array_->release(); + } + array_ = a; + } + void reset(const ArrayRef &other) { + reset(other.array_); + } + ArrayRef& operator=(const ArrayRef &other) { + reset(other); + return *this; + } + ArrayRef& operator=(Array *a) { + reset(a); + return *this; + } + + Array& operator*() { + return *array_; + } + Array* operator->() { + return array_; + } +}; + +} // namespace zxing + +#endif // __ARRAY_H__ diff --git a/symbian/QQrDecoder/zxing/common/BitArray.cpp b/symbian/QQrDecoder/zxing/common/BitArray.cpp new file mode 100644 index 000000000..26e686930 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/BitArray.cpp @@ -0,0 +1,118 @@ +/* + * BitArray.cpp + * zxing + * + * Created by Christian Brunschen on 09/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +using namespace std; + +namespace zxing { +static unsigned int logDigits(unsigned digits) { + unsigned log = 0; + unsigned val = 1; + while (val < digits) { + log++; + val <<= 1; + } + return log; +} +const unsigned int BitArray::bitsPerWord_ = numeric_limits::digits; +const unsigned int BitArray::logBits_ = logDigits(bitsPerWord_); +const unsigned int BitArray::bitsMask_ = (1 << logBits_) - 1; +size_t BitArray::wordsForBits(size_t bits) { + int arraySize = bits >> logBits_; + if (bits - (arraySize << logBits_) != 0) { + arraySize++; + } + return arraySize; +} +BitArray::BitArray() { + cout << "hey! don't use this BitArrayConstructor!\n"; +} + +BitArray::BitArray(size_t size) : + size_(size), bits_((const unsigned int)0, wordsForBits(size)) { +} +BitArray::~BitArray() { +} +size_t BitArray::getSize() { + return size_; +} +bool BitArray::get(size_t i) { + return (bits_[i >> logBits_] & (1 << (i & bitsMask_))) != 0; +} +void BitArray::set(size_t i) { + bits_[i >> logBits_] |= 1 << (i & bitsMask_); +} +void BitArray::setBulk(size_t i, unsigned int newBits) { + bits_[i >> logBits_] = newBits; +} +void BitArray::clear() { + size_t max = bits_.size(); + for (size_t i = 0; i < max; i++) { + bits_[i] = 0; + } +} +bool BitArray::isRange(size_t start, size_t end, bool value) { + if (end < start) { + throw IllegalArgumentException("end must be after start"); + } + if (end == start) { + return true; + } + // treat the 'end' as inclusive, rather than exclusive + end--; + size_t firstWord = start >> logBits_; + size_t lastWord = end >> logBits_; + for (size_t i = firstWord; i <= lastWord; i++) { + size_t firstBit = i > firstWord ? 0 : start & bitsMask_; + size_t lastBit = i < lastWord ? logBits_ : end & bitsMask_; + unsigned int mask; + if (firstBit == 0 && lastBit == logBits_) { + mask = numeric_limits::max(); + } else { + mask = 0; + for (size_t j = firstBit; j <= lastBit; j++) { + mask |= 1 << j; + } + } + if (value) { + if ((bits_[i] & mask) != mask) { + return false; + } + } else { + if ((bits_[i] & mask) != 0) { + return false; + } + } + } + return true; +} +valarray& BitArray::getBitArray() { + return bits_; +} +void BitArray::reverse() { + unsigned int allBits = numeric_limits::max(); + size_t max = bits_.size(); + for (size_t i = 0; i < max; i++) { + bits_[i] = bits_[i] ^ allBits; + } +} +} diff --git a/symbian/QQrDecoder/zxing/common/BitArray.h b/symbian/QQrDecoder/zxing/common/BitArray.h new file mode 100644 index 000000000..1e8828e96 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/BitArray.h @@ -0,0 +1,57 @@ +#ifndef __BIT_ARRAY_H__ +#define __BIT_ARRAY_H__ + +/* + * BitArray.h + * zxing + * + * Created by Christian Brunschen on 09/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +namespace zxing { + +class BitArray : public Counted { +private: + size_t size_; + std::valarray bits_; + static const unsigned int bitsPerWord_; + static const unsigned int logBits_; + static const unsigned int bitsMask_; + static size_t wordsForBits(size_t bits); + explicit BitArray(); + +public: + BitArray(size_t size); + ~BitArray(); + size_t getSize(); + bool get(size_t i); + void set(size_t i); + void setBulk(size_t i, unsigned int newBits); + void clear(); + bool isRange(size_t start, size_t end, bool value); + std::valarray& getBitArray(); + void reverse(); +}; + +} + +#endif // __BIT_ARRAY_H__ diff --git a/symbian/QQrDecoder/zxing/common/BitMatrix.cpp b/symbian/QQrDecoder/zxing/common/BitMatrix.cpp new file mode 100644 index 000000000..9256c4097 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/BitMatrix.cpp @@ -0,0 +1,148 @@ +/* + * BitMatrix.cpp + * zxing + * + * Created by Christian Brunschen on 12/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include + +namespace zxing { +using namespace std; + +unsigned int logDigits(unsigned digits) { + unsigned log = 0; + unsigned val = 1; + while (val < digits) { + log++; + val <<= 1; + } + return log; +} + + +const unsigned int bitsPerWord = std::numeric_limits::digits; +const unsigned int logBits = logDigits(bitsPerWord); +const unsigned int bitsMask = (1 << logBits) - 1; + +static size_t wordsForSize(size_t width, size_t height) { + size_t bits = width * height; + int arraySize = bits >> logBits; + if (bits - (arraySize << logBits) != 0) { + arraySize++; + } + return arraySize; +} + +BitMatrix::BitMatrix(size_t dimension) : + width_(dimension), height_(dimension), bits_(NULL) { + + words_ = wordsForSize(width_, height_); + bits_ = new unsigned int[words_]; + clear(); +} + +BitMatrix::BitMatrix(size_t width, size_t height) : + width_(width), height_(height), bits_(NULL) { + + words_ = wordsForSize(width_, height_); + bits_ = new unsigned int[words_]; + clear(); +} + +BitMatrix::~BitMatrix() { + delete[] bits_; +} + + +bool BitMatrix::get(size_t x, size_t y) const { + size_t offset = x + width_ * y; + return ((bits_[offset >> logBits] >> (offset & bitsMask)) & 0x01) != 0; +} + +void BitMatrix::set(size_t x, size_t y) { + size_t offset = x + width_ * y; + bits_[offset >> logBits] |= 1 << (offset & bitsMask); +} + +void BitMatrix::flip(size_t x, size_t y) { + size_t offset = x + width_ * y; + bits_[offset >> logBits] ^= 1 << (offset & bitsMask); +} + +void BitMatrix::clear() { + std::memset(bits_, 0, sizeof(unsigned int) * words_); +} + +void BitMatrix::setRegion(size_t left, size_t top, size_t width, size_t height) { + if (top < 0 || left < 0) { + throw IllegalArgumentException("topI and leftJ must be nonnegative"); + } + if (height < 1 || width < 1) { + throw IllegalArgumentException("height and width must be at least 1"); + } + size_t right = left + width; + size_t bottom = top + height; + if (right > width_ || bottom > height_) { + throw IllegalArgumentException("top + height and left + width must be <= matrix dimension"); + } + for (size_t y = top; y < bottom; y++) { + int yOffset = width_ * y; + for (size_t x = left; x < right; x++) { + size_t offset = x + yOffset; + bits_[offset >> logBits] |= 1 << (offset & bitsMask); + } + } +} + +size_t BitMatrix::getWidth() const { + return width_; +} + +size_t BitMatrix::getHeight() const { + return height_; +} + +size_t BitMatrix::getDimension() const { + return width_; +} + +unsigned int* BitMatrix::getBits() { + return bits_; +} + +ostream& operator<<(ostream &out, BitMatrix &bm) { + for (size_t y = 0; y < bm.height_; y++) { + for (size_t x = 0; x < bm.width_; x++) { + out << (bm.get(x, y) ? "X " : " "); + } + out << "\n"; + } + return out; +} +const char *BitMatrix::description() { + ostringstream out; + out << *this; + return out.str().c_str(); +} + +} diff --git a/symbian/QQrDecoder/zxing/common/BitMatrix.h b/symbian/QQrDecoder/zxing/common/BitMatrix.h new file mode 100644 index 000000000..e8f8f847e --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/BitMatrix.h @@ -0,0 +1,61 @@ +#ifndef __BIT_MATRIX_H__ +#define __BIT_MATRIX_H__ + +/* + * BitMatrix.h + * zxing + * + * Created by Christian Brunschen on 12/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace zxing { + +class BitMatrix : public Counted { +private: + size_t width_; + size_t height_; + size_t words_; + unsigned int* bits_; + +public: + BitMatrix(size_t dimension); + BitMatrix(size_t width, size_t height); + + ~BitMatrix(); + // Inlining this does not really improve performance. + bool get(size_t x, size_t y) const; + void set(size_t x, size_t y); + void flip(size_t x, size_t y); + void clear(); + void setRegion(size_t left, size_t top, size_t width, size_t height); + + size_t getDimension() const; + size_t getWidth() const; + size_t getHeight() const; + + unsigned int* getBits(); + + friend std::ostream& operator<<(std::ostream &out, BitMatrix &bm); + const char *description(); +}; + +} + +#endif // __BIT_MATRIX_H__ diff --git a/symbian/QQrDecoder/zxing/common/BitSource.cpp b/symbian/QQrDecoder/zxing/common/BitSource.cpp new file mode 100644 index 000000000..4b53b4da7 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/BitSource.cpp @@ -0,0 +1,75 @@ +/* + * BitSource.cpp + * zxing + * + * Created by Christian Brunschen on 09/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace zxing { + +int BitSource::readBits(int numBits) { + if (numBits < 0 || numBits > 32) { + throw IllegalArgumentException("cannot read <1 or >32 bits"); + } else if (numBits > available()) { + throw IllegalArgumentException("reading more bits than are available"); + } + + int result = 0; + + + // First, read remainder from current byte + if (bitOffset_ > 0) { + int bitsLeft = 8 - bitOffset_; + int toRead = numBits < bitsLeft ? numBits : bitsLeft; + int bitsToNotRead = bitsLeft - toRead; + int mask = (0xFF >> (8 - toRead)) << bitsToNotRead; + result = (bytes_[byteOffset_] & mask) >> bitsToNotRead; + numBits -= toRead; + bitOffset_ += toRead; + if (bitOffset_ == 8) { + bitOffset_ = 0; + byteOffset_++; + } + } + + // Next read whole bytes + if (numBits > 0) { + while (numBits >= 8) { + result = (result << 8) | (bytes_[byteOffset_] & 0xFF); + byteOffset_++; + numBits -= 8; + } + + + // Finally read a partial byte + if (numBits > 0) { + int bitsToNotRead = 8 - numBits; + int mask = (0xFF >> bitsToNotRead) << bitsToNotRead; + result = (result << numBits) | ((bytes_[byteOffset_] & mask) >> bitsToNotRead); + bitOffset_ += numBits; + } + } + + return result; +} + +int BitSource::available() { + return 8 * (bytes_.size() - byteOffset_) - bitOffset_; +} +} diff --git a/symbian/QQrDecoder/zxing/common/BitSource.h b/symbian/QQrDecoder/zxing/common/BitSource.h new file mode 100644 index 000000000..78201738f --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/BitSource.h @@ -0,0 +1,68 @@ +#ifndef __BIT_SOURCE_H__ +#define __BIT_SOURCE_H__ + +/* + * BitSource.h + * zxing + * + * Created by Christian Brunschen on 09/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { +/** + *

This provides an easy abstraction to read bits at a time from a sequence of bytes, where the + * number of bits read is not often a multiple of 8.

+ * + *

This class is not thread-safe.

+ * + * @author srowen@google.com (Sean Owen) + * @author christian.brunschen@gmail.com (Christian Brunschen) + */ +class BitSource : public Counted { + typedef unsigned char byte; +private: + ArrayRef bytes_; + int byteOffset_; + int bitOffset_; +public: + /** + * @param bytes bytes from which this will read bits. Bits will be read from the first byte first. + * Bits are read within a byte from most-significant to least-significant bit. + */ + BitSource(ArrayRef &bytes) : + bytes_(bytes), byteOffset_(0), bitOffset_(0) { + } + + + /** + * @param numBits number of bits to read + * @return int representing the bits read. The bits will appear as the least-significant + * bits of the int + * @throws IllegalArgumentException if numBits isn't in [1,32] + */ + int readBits(int numBits); + + /** + * @return number of bits that can be read successfully + */ + int available(); +}; + +} + +#endif // __BIT_SOURCE_H__ diff --git a/symbian/QQrDecoder/zxing/common/Counted.cpp b/symbian/QQrDecoder/zxing/common/Counted.cpp new file mode 100644 index 000000000..fb2a99b06 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/Counted.cpp @@ -0,0 +1,32 @@ +/* + * Counted.cpp + * zxing + * + * Created by Christian Brunschen on 07/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { + +using namespace std; + +template +ostream& operator<<(ostream &out, Ref& ref) { + out << "Ref(" << (ref.object_ ? (*ref.object_) : "NULL") << ")"; + return out; +} +} diff --git a/symbian/QQrDecoder/zxing/common/Counted.h b/symbian/QQrDecoder/zxing/common/Counted.h new file mode 100644 index 000000000..c2723996b --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/Counted.h @@ -0,0 +1,204 @@ +#ifndef __COUNTED_H__ +#define __COUNTED_H__ + +/* + * Counted.h + * zxing + * + * Created by Christian Brunschen on 07/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define DEBUG_COUNTING +//using namespace std; + +#include + + +#ifdef DEBUG_COUNTING +#include +using namespace std; +#endif + +namespace zxing { + +/* base class for reference-counted objects */ +class Counted { +private: + unsigned int count_; +public: + Counted() : + count_(0) { +#ifdef DEBUG_COUNTING + cout << "instantiating " << typeid(*this).name() << " " << this << + " @ " << count_ << "\n"; +#endif + } + virtual ~Counted() { + } + virtual Counted *retain() { +#ifdef DEBUG_COUNTING + cout << "retaining " << typeid(*this).name() << " " << this << + " @ " << count_; +#endif + count_++; +#ifdef DEBUG_COUNTING + cout << "->" << count_ << "\n"; +#endif + return this; + } + virtual void release() { +#ifdef DEBUG_COUNTING + cout << "releasing " << typeid(*this).name() << " " << this << + " @ " << count_; +#endif + if (count_ == 0 || count_ == 54321) { +#ifdef DEBUG_COUNTING + cout << "\nOverreleasing already-deleted object " << this << "!!!\n"; +#endif + throw 4711; + } + count_--; +#ifdef DEBUG_COUNTING + cout << "->" << count_ << "\n"; +#endif + if (count_ == 0) { +#ifdef DEBUG_COUNTING + cout << "deleting " << typeid(*this).name() << " " << this << "\n"; +#endif + count_ = 0xDEADF001; + delete this; + } + } + + + /* return the current count for denugging purposes or similar */ + int count() const { + return count_; + } +}; + +/* counting reference to reference-counted objects */ +template class Ref { +private: +public: + T *object_; + explicit Ref(T *o = 0) : + object_(0) { +#ifdef DEBUG_COUNTING + cout << "instantiating Ref " << this << " from pointer" << o << "\n"; +#endif + reset(o); + } + + explicit Ref(const T &o) : + object_(0) { +#ifdef DEBUG_COUNTING + cout << "instantiating Ref " << this << " from reference\n"; +#endif + reset(const_cast(&o)); + } + + Ref(const Ref &other) : + object_(0) { +#ifdef DEBUG_COUNTING + cout << "instantiating Ref " << this << " from Ref " << &other << "\n"; +#endif + reset(other.object_); + } + + template + Ref(const Ref &other) : + object_(0) { +#ifdef DEBUG_COUNTING + cout << "instantiating Ref " << this << " from reference\n"; +#endif + reset(other.object_); + } + + ~Ref() { +#ifdef DEBUG_COUNTING + cout << "destroying Ref " << this << " with " << + (object_ ? typeid(*object_).name() : "NULL") << " " << object_ << "\n"; +#endif + if (object_) { + object_->release(); + } + } + + void reset(T *o) { +#ifdef DEBUG_COUNTING + cout << "resetting Ref " << this << " from " << + (object_ ? typeid(*object_).name() : "NULL") << " " << object_ << + " to " << (o ? typeid(*o).name() : "NULL") << " " << o << "\n"; +#endif + if (o) { + o->retain(); + } + if (object_ != 0) { + object_->release(); + } + object_ = o; + } + Ref& operator=(const Ref &other) { + reset(other.object_); + return *this; + } + template + Ref& operator=(const Ref &other) { + reset(other.object_); + return *this; + } + Ref& operator=(T* o) { + reset(o); + return *this; + } + template + Ref& operator=(Y* o) { + reset(o); + return *this; + } + + T& operator*() { + return *object_; + } + T* operator->() { + return object_; + } + operator T*() { + return object_; + } + + bool operator==(const int x) { + return x == 0 ? object_ == 0 : false; + } + bool operator==(const Ref &other) const { + return object_ == other.object_ || *object_ == *(other.object_); + } + template + bool operator==(const Ref &other) const { + return object_ == other.object_ || *object_ == *(other.object_); + } + + bool operator!=(const int x) { + return x == 0 ? object_ != 0 : true; + } + + template + friend std::ostream& operator<<(std::ostream &out, Ref& ref); +}; +} + +#endif // __COUNTED_H__ diff --git a/symbian/QQrDecoder/zxing/common/DecoderResult.cpp b/symbian/QQrDecoder/zxing/common/DecoderResult.cpp new file mode 100644 index 000000000..86b11f810 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/DecoderResult.cpp @@ -0,0 +1,37 @@ +/* + * DecoderResult.cpp + * zxing + * + * Created by Christian Brunschen on 20/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { + +DecoderResult::DecoderResult(ArrayRef rawBytes, Ref text) : + rawBytes_(rawBytes), text_(text) { +} + +ArrayRef DecoderResult::getRawBytes() { + return rawBytes_; +} + +Ref DecoderResult::getText() { + return text_; +} + +} diff --git a/symbian/QQrDecoder/zxing/common/DecoderResult.h b/symbian/QQrDecoder/zxing/common/DecoderResult.h new file mode 100644 index 000000000..1e3e42b2a --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/DecoderResult.h @@ -0,0 +1,44 @@ +#ifndef __DECODER_RESULT_H__ +#define __DECODER_RESULT_H__ + +/* + * DecoderResult.h + * zxing + * + * Created by Christian Brunschen on 20/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +namespace zxing { + +class DecoderResult : public Counted { +private: + ArrayRef rawBytes_; + Ref text_; + +public: + DecoderResult(ArrayRef rawBytes, Ref text); + ArrayRef getRawBytes(); + Ref getText(); +}; + +} + +#endif // __DECODER_RESULT_H__ diff --git a/symbian/QQrDecoder/zxing/common/DetectorResult.cpp b/symbian/QQrDecoder/zxing/common/DetectorResult.cpp new file mode 100644 index 000000000..a314cfe79 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/DetectorResult.cpp @@ -0,0 +1,41 @@ +/* + * DetectorResult.cpp + * zxing + * + * Created by Christian Brunschen on 14/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { + +DetectorResult::DetectorResult(Ref bits, std::vector > points, Ref transform) : + bits_(bits), points_(points), transform_(transform) { +} + +Ref DetectorResult::getBits() { + return bits_; +} + +std::vector > DetectorResult::getPoints() { + return points_; +} + +Ref DetectorResult::getTransform() { + return transform_; +} + +} diff --git a/symbian/QQrDecoder/zxing/common/DetectorResult.h b/symbian/QQrDecoder/zxing/common/DetectorResult.h new file mode 100644 index 000000000..ba8f9a821 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/DetectorResult.h @@ -0,0 +1,47 @@ +#ifndef __DETECTOR_RESULT_H__ +#define __DETECTOR_RESULT_H__ + +/* + * DetectorResult.h + * zxing + * + * Created by Christian Brunschen on 14/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +namespace zxing { + +class DetectorResult : public Counted { +private: + Ref bits_; + std::vector > points_; + Ref transform_; + +public: + DetectorResult(Ref bits, std::vector > points, Ref transform); + Ref getBits(); + std::vector > getPoints(); + Ref getTransform(); +}; +} + +#endif // __DETECTOR_RESULT_H__ diff --git a/symbian/QQrDecoder/zxing/common/EdgeDetector.cpp b/symbian/QQrDecoder/zxing/common/EdgeDetector.cpp new file mode 100644 index 000000000..3f0b403cc --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/EdgeDetector.cpp @@ -0,0 +1,190 @@ +/* + * EdgeDetector.cpp + * zxing + * + * Created by Ralf Kistner on 7/12/2009. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +using namespace std; + +namespace zxing { +namespace EdgeDetector { + +void findEdgePoints(std::vector& points, const BitMatrix& image, Point start, Point end, bool invert, int skip, float deviation) { + float xdist = end.x - start.x; + float ydist = end.y - start.y; + float length = sqrt(xdist * xdist + ydist * ydist); + + + int var; + + if (abs(xdist) > abs(ydist)) { + // Horizontal + if (xdist < 0) + skip = -skip; + + var = int(abs(deviation * length / xdist)); + + float dy = ydist / xdist * skip; + bool left = (skip < 0) ^ invert; + int x = int(start.x); + + int steps = int(xdist / skip); + for (int i = 0; i < steps; i++) { + x += skip; + if (x < 0 || x >= (int)image.getWidth()) + continue; // In case we start off the edge + int my = int(start.y + dy * i); + int ey = min(my + var + 1, (int)image.getHeight() - 1); + int sy = max(my - var, 0); + for (int y = sy + 1; y < ey; y++) { + if (left) { + if (image.get(x, y) && !image.get(x, y + 1)) { + points.push_back(Point(x, y + 0.5f)); + } + } else { + if (!image.get(x, y) && image.get(x, y + 1)) { + points.push_back(Point(x, y + 0.5f)); + } + } + } + } + } else { + // Vertical + if (ydist < 0) + skip = -skip; + + var = int(abs(deviation * length / ydist)); + + float dx = xdist / ydist * skip; + bool down = (skip > 0) ^ invert; + int y = int(start.y); + + int steps = int(ydist / skip); + for (int i = 0; i < steps; i++) { + y += skip; + if (y < 0 || y >= (int)image.getHeight()) + continue; // In case we start off the edge + int mx = int(start.x + dx * i); + int ex = min(mx + var + 1, (int)image.getWidth() - 1); + int sx = max(mx - var, 0); + for (int x = sx + 1; x < ex; x++) { + if (down) { + if (image.get(x, y) && !image.get(x + 1, y)) { + points.push_back(Point(x + 0.5f, y)); + } + + } else { + if (!image.get(x, y) && image.get(x + 1, y)) { + points.push_back(Point(x + 0.5f, y)); + } + } + + } + } + + } +} + +Line findLine(const BitMatrix& image, Line estimate, bool invert, int deviation, float threshold, int skip) { + float t = threshold * threshold; + + Point start = estimate.start; + Point end = estimate.end; + + vector edges; + edges.clear(); + findEdgePoints(edges, image, start, end, invert, skip, deviation); + + int n = edges.size(); + + float xdist = end.x - start.x; + float ydist = end.y - start.y; + + bool horizontal = abs(xdist) > abs(ydist); + + float max = 0; + Line bestLine(start, end); // prepopulate with the given line, in case we can't find any line for some reason + + for (int i = -deviation; i < deviation; i++) { + float x1, y1; + if (horizontal) { + y1 = start.y + i; + x1 = start.x - i * ydist / xdist; + } else { + y1 = start.y - i * xdist / ydist; + x1 = start.x + i; + } + + for (int j = -deviation; j < deviation; j++) { + float x2, y2; + if (horizontal) { + y2 = end.y + j; + x2 = end.x - j * ydist / xdist; + } else { + y2 = end.y - j * xdist / ydist; + x2 = end.x + j; + } + + float dx = x1 - x2; + float dy = y1 - y2; + float length = sqrt(dx * dx + dy * dy); + + float score = 0; + + for(int k = 0; k < n; k++) { + const Point& edge = edges[k]; + float dist = ((x1 - edge.x) * dy - (y1 - edge.y) * dx) / length; + // Similar to least squares method + float s = t - dist * dist; + if (s > 0) + score += s; + } + + if (score > max) { + max = score; + bestLine.start = Point(x1, y1); + bestLine.end = Point(x2, y2); + } + } + } + + return bestLine; +} + +Point intersection(Line a, Line b) { + float dxa = a.start.x - a.end.x; + float dxb = b.start.x - b.end.x; + float dya = a.start.y - a.end.y; + float dyb = b.start.y - b.end.y; + + float p = a.start.x * a.end.y - a.start.y * a.end.x; + float q = b.start.x * b.end.y - b.start.y * b.end.x; + float denom = dxa * dyb - dya * dxb; + if(denom == 0) // Lines don't intersect + return Point(INFINITY, INFINITY); + + float x = (p * dxb - dxa * q) / denom; + float y = (p * dyb - dya * q) / denom; + + return Point(x, y); +} + +} // namespace EdgeDetector +} // namespace zxing diff --git a/symbian/QQrDecoder/zxing/common/EdgeDetector.h b/symbian/QQrDecoder/zxing/common/EdgeDetector.h new file mode 100644 index 000000000..3698c1c8b --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/EdgeDetector.h @@ -0,0 +1,38 @@ +/* + * EdgeDetector.h + * zxing + * + * Created by Ralf Kistner on 7/12/2009. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef EDGEDETECTOR_H_ +#define EDGEDETECTOR_H_ + +#include +#include +#include + +namespace zxing { +namespace EdgeDetector { + +void findEdgePoints(std::vector& points, const BitMatrix& image, Point start, Point end, bool invert, int skip, float deviation); +Line findLine(const BitMatrix& image, Line estimate, bool invert, int deviation, float threshold, int skip); + +Point intersection(Line a, Line b); + +} +} +#endif /* EDGEDETECTOR_H_ */ diff --git a/symbian/QQrDecoder/zxing/common/GlobalHistogramBinarizer.cpp b/symbian/QQrDecoder/zxing/common/GlobalHistogramBinarizer.cpp new file mode 100644 index 000000000..8767dbd34 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/GlobalHistogramBinarizer.cpp @@ -0,0 +1,177 @@ +/* + * GlobalHistogramBinarizer.cpp + * zxing + * + * Created by Ralf Kistner on 16/10/2009. + * Copyright 2008 ZXing authors All rights reserved. + * Modified by Lukasz Warchol on 02/02/2010. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +namespace zxing { + using namespace std; + + const int LUMINANCE_BITS = 5; + const int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS; + const int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS; + + GlobalHistogramBinarizer::GlobalHistogramBinarizer(Ref source) : + Binarizer(source) { + + } + + GlobalHistogramBinarizer::~GlobalHistogramBinarizer() { + } + + + Ref GlobalHistogramBinarizer::estimateBlackRow(int y, Ref row){ + valarray histogram(0, LUMINANCE_BUCKETS); + LuminanceSource& source = *getSource(); + int width = source.getWidth(); + if (row == NULL || row->getSize() < width) { + row = new BitArray(width); + } else { + row->clear(); + } + + for (int x = 0; x < width; x++) { + unsigned char pixel = source.getPixel(x, y); + histogram[pixel >> LUMINANCE_SHIFT]++; + } + int blackPoint = estimate(histogram) << LUMINANCE_SHIFT; + + + Ref array_ref(new BitArray(width)); + BitArray& array = *array_ref; + + int left = source.getPixel(0, y); + int center = source.getPixel(1, y); + for (int x = 1; x < width - 1; x++) { + int right = source.getPixel(x+1, y); + // A simple -1 4 -1 box filter with a weight of 2. + int luminance = ((center << 2) - left - right) >> 1; + if (luminance < blackPoint) { + array.set(x); + } + left = center; + center = right; + } + + return array_ref; + } + + Ref GlobalHistogramBinarizer::estimateBlackMatrix() { + // Faster than working with the reference + LuminanceSource& source = *getSource(); + int width = source.getWidth(); + int height = source.getHeight(); + valarray histogram(0, LUMINANCE_BUCKETS); + + + // Quickly calculates the histogram by sampling four rows from the image. This proved to be + // more robust on the blackbox tests than sampling a diagonal as we used to do. + for (int y = 1; y < 5; y++) { + int row = height * y / 5; + int right = (width << 2) / 5; + int sdf; + for (int x = width / 5; x < right; x++) { + unsigned char pixel = source.getPixel(x, row); + histogram[pixel >> LUMINANCE_SHIFT]++; + sdf = histogram[pixel >> LUMINANCE_SHIFT]; + } + } + + int blackPoint = estimate(histogram) << LUMINANCE_SHIFT; + + Ref matrix_ref(new BitMatrix(width, height)); + BitMatrix& matrix = *matrix_ref; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + if (source.getPixel(x, y) <= blackPoint) + matrix.set(x, y); + } + } + return matrix_ref; + } + + int GlobalHistogramBinarizer::estimate(valarray &histogram) { + int numBuckets = histogram.size(); + int maxBucketCount = 0; + + + // Find tallest peak in histogram + int firstPeak = 0; + int firstPeakSize = 0; + for (int i = 0; i < numBuckets; i++) { + if (histogram[i] > firstPeakSize) { + firstPeak = i; + firstPeakSize = histogram[i]; + } + if (histogram[i] > maxBucketCount) { + maxBucketCount = histogram[i]; + } + } + + // Find second-tallest peak -- well, another peak that is tall and not + // so close to the first one + int secondPeak = 0; + int secondPeakScore = 0; + for (int i = 0; i < numBuckets; i++) { + int distanceToBiggest = i - firstPeak; + // Encourage more distant second peaks by multiplying by square of distance + int score = histogram[i] * distanceToBiggest * distanceToBiggest; + if (score > secondPeakScore) { + secondPeak = i; + secondPeakScore = score; + } + } + + // Put firstPeak first + if (firstPeak > secondPeak) { + int temp = firstPeak; + firstPeak = secondPeak; + secondPeak = temp; + } + + // Kind of arbitrary; if the two peaks are very close, then we figure there is so little + // dynamic range in the image, that discriminating black and white is too error-prone. + // Decoding the image/line is either pointless, or may in some cases lead to a false positive + // for 1D formats, which are relatively lenient. + // We arbitrarily say "close" is "<= 1/16 of the total histogram buckets apart" + if (secondPeak - firstPeak <= numBuckets >> 4) { + throw IllegalArgumentException("Too little dynamic range in luminance"); + } + + // Find a valley between them that is low and closer to the white peak + int bestValley = secondPeak - 1; + int bestValleyScore = -1; + for (int i = secondPeak - 1; i > firstPeak; i--) { + int fromFirst = i - firstPeak; + // Favor a "valley" that is not too close to either peak -- especially not the black peak -- + // and that has a low value of course + int score = fromFirst * fromFirst * (secondPeak - i) * (maxBucketCount - histogram[i]); + if (score > bestValleyScore) { + bestValley = i; + bestValleyScore = score; + } + } + + return bestValley; + } + +} diff --git a/symbian/QQrDecoder/zxing/common/GlobalHistogramBinarizer.h b/symbian/QQrDecoder/zxing/common/GlobalHistogramBinarizer.h new file mode 100644 index 000000000..6735c5b9f --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/GlobalHistogramBinarizer.h @@ -0,0 +1,44 @@ +/* + * GlobalHistogramBinarizer.h + * zxing + * + * Created by Ralf Kistner on 16/10/2009. + * Copyright 2008 ZXing authors All rights reserved. + * Modified by Lukasz Warchol on 02/02/2010. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GLOBALHISTOGRAMBINARIZER_H_ +#define GLOBALHISTOGRAMBINARIZER_H_ + +#include +#include +#include +#include + +namespace zxing { + + class GlobalHistogramBinarizer : public Binarizer { + public: + GlobalHistogramBinarizer(Ref source); + virtual ~GlobalHistogramBinarizer(); + + virtual Ref estimateBlackRow(int y, Ref row); + virtual Ref estimateBlackMatrix(); + static int estimate(std::valarray &histogram); + }; + +} + +#endif /* GLOBALHISTOGRAMBINARIZER_H_ */ diff --git a/symbian/QQrDecoder/zxing/common/GridSampler.cpp b/symbian/QQrDecoder/zxing/common/GridSampler.cpp new file mode 100644 index 000000000..06bb602c1 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/GridSampler.cpp @@ -0,0 +1,101 @@ +/* + * GridSampler.cpp + * zxing + * + * Created by Christian Brunschen on 18/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +namespace zxing { +using namespace std; + +GridSampler GridSampler::gridSampler; + +GridSampler::GridSampler() { +} + +Ref GridSampler::sampleGrid(Ref image, int dimension, Ref transform) { + Ref bits(new BitMatrix(dimension)); + valarray points((const float)0.0f, dimension << 1); + for (int y = 0; y < dimension; y++) { + int max = points.size(); + float yValue = (float)y + 0.5f; + for (int x = 0; x < max; x += 2) { + points[x] = (float)(x >> 1) + 0.5f; + points[x + 1] = yValue; + } + transform->transformPoints(points); + checkAndNudgePoints(image, points); + for (int x = 0; x < max; x += 2) { + if (image->get((int)points[x], (int)points[x + 1])) { + bits->set(x >> 1, y); + } + } + } + return bits; +} + +Ref GridSampler::sampleGrid(Ref image, int dimension, float p1ToX, float p1ToY, float p2ToX, + float p2ToY, float p3ToX, float p3ToY, float p4ToX, float p4ToY, float p1FromX, float p1FromY, float p2FromX, + float p2FromY, float p3FromX, float p3FromY, float p4FromX, float p4FromY) { + Ref transform(PerspectiveTransform::quadrilateralToQuadrilateral(p1ToX, p1ToY, p2ToX, p2ToY, + p3ToX, p3ToY, p4ToX, p4ToY, p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY)); + + return sampleGrid(image, dimension, transform); + +} + +void GridSampler::checkAndNudgePoints(Ref image, valarray &points) { + int width = image->getWidth(); + int height = image->getHeight(); + + + // The Java code assumes that if the start and end points are in bounds, the rest will also be. + // However, in some unusual cases points in the middle may also be out of bounds. + // Since we can't rely on an ArrayIndexOutOfBoundsException like Java, we check every point. + + for (size_t offset = 0; offset < points.size(); offset += 2) { + int x = (int)points[offset]; + int y = (int)points[offset + 1]; + if (x < -1 || x > width || y < -1 || y > height) { + ostringstream s; + s << "Transformed point out of bounds at " << x << "," << y; + throw ReaderException(s.str().c_str()); + } + + if (x == -1) { + points[offset] = 0.0f; + } else if (x == width) { + points[offset] = width - 1; + } + if (y == -1) { + points[offset + 1] = 0.0f; + } else if (y == height) { + points[offset + 1] = height - 1; + } + } + +} + +GridSampler &GridSampler::getInstance() { + return gridSampler; +} +} diff --git a/symbian/QQrDecoder/zxing/common/GridSampler.h b/symbian/QQrDecoder/zxing/common/GridSampler.h new file mode 100644 index 000000000..3dd577dcb --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/GridSampler.h @@ -0,0 +1,44 @@ +#ifndef __GRID_SAMPLER_H__ +#define __GRID_SAMPLER_H__ + +/* + * GridSampler.h + * zxing + * + * Created by Christian Brunschen on 18/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace zxing { +class GridSampler { +private: + static GridSampler gridSampler; + GridSampler(); + +public: + Ref sampleGrid(Ref image, int dimension, Ref transform); + Ref sampleGrid(Ref image, int dimension, float p1ToX, float p1ToY, float p2ToX, float p2ToY, + float p3ToX, float p3ToY, float p4ToX, float p4ToY, float p1FromX, float p1FromY, float p2FromX, + float p2FromY, float p3FromX, float p3FromY, float p4FromX, float p4FromY); + static void checkAndNudgePoints(Ref image, std::valarray &points); + static GridSampler &getInstance(); +}; +} + +#endif // __GRID_SAMPLER_H__ diff --git a/symbian/QQrDecoder/zxing/common/IllegalArgumentException.cpp b/symbian/QQrDecoder/zxing/common/IllegalArgumentException.cpp new file mode 100644 index 000000000..49068ca5d --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/IllegalArgumentException.cpp @@ -0,0 +1,31 @@ +/* + * IllegalArgumentException.cpp + * zxing + * + * Created by Christian Brunschen on 06/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { + +IllegalArgumentException::IllegalArgumentException(const char *msg) : + Exception(msg) { +} +IllegalArgumentException::~IllegalArgumentException() throw() { + +} +} diff --git a/symbian/QQrDecoder/zxing/common/IllegalArgumentException.h b/symbian/QQrDecoder/zxing/common/IllegalArgumentException.h new file mode 100644 index 000000000..5def73636 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/IllegalArgumentException.h @@ -0,0 +1,34 @@ +#ifndef __ILLEGAL_ARGUMENT_EXCEPTION_H__ +#define __ILLEGAL_ARGUMENT_EXCEPTION_H__ + +/* + * IllegalArgumentException.h + * zxing + * + * Created by Christian Brunschen on 06/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { +class IllegalArgumentException : public zxing::Exception { +public: + IllegalArgumentException(const char *msg); + ~IllegalArgumentException() throw(); +}; +} + +#endif // __ILLEGAL_ARGUMENT_EXCEPTION_H__ diff --git a/symbian/QQrDecoder/zxing/common/LocalBlockBinarizer.cpp b/symbian/QQrDecoder/zxing/common/LocalBlockBinarizer.cpp new file mode 100644 index 000000000..135902a6d --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/LocalBlockBinarizer.cpp @@ -0,0 +1,196 @@ +/* + * LocalBlockBinarizer.cpp + * zxing + * + * Created by Ralf Kistner on 17/10/2009. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { + +const int GLOBAL = 0; +const int THRESHOLD = 1; + +LocalBlockBinarizer::LocalBlockBinarizer(Ref source) : + Binarizer(source) { + +} + +LocalBlockBinarizer::~LocalBlockBinarizer() { +} + +Ref LocalBlockBinarizer::estimateBlackRow(int y, Ref row) { + //TODO: implement + return Ref(); +} + +// Calculates the final BitMatrix once for all requests. This could be called once from the +// constructor instead, but there are some advantages to doing it lazily, such as making +// profiling easier, and not doing heavy lifting when callers don't expect it. +Ref LocalBlockBinarizer::estimateBlackMatrix() { + Ref source = getSource(); + unsigned char* luminances = source->copyMatrix(); + int width = source->getWidth(); + int height = source->getHeight(); + // Sharpening does not really help for 2d barcodes + // sharpenRow(luminances, width, height); + + int subWidth = width >> 3; + int subHeight = height >> 3; + + unsigned char* averages = new unsigned char[subWidth * subHeight]; + unsigned char* types = new unsigned char[subWidth * subHeight]; + + calculateBlackPoints(luminances, averages, types, subWidth, subHeight, width); + + Ref matrix(new BitMatrix(width, height)); + calculateThresholdForBlock(luminances, subWidth, subHeight, width, averages, types, *matrix); + + delete[] averages; + delete[] types; + delete[] luminances; + + return matrix; +} + +// For each 8x8 block in the image, calculate the average black point using a 5x5 grid +// of the blocks around it. Also handles the corner cases, but will ignore up to 7 pixels +// on the right edge and 7 pixels at the bottom of the image if the overall dimensions are not +// multiples of eight. In practice, leaving those pixels white does not seem to be a problem. +void LocalBlockBinarizer::calculateThresholdForBlock(const unsigned char* luminances, int subWidth, int subHeight, + int stride, const unsigned char* averages, const unsigned char* types, BitMatrix& matrix) { + // Calculate global average + int global = 0; + for (int y = 0; y < subHeight; y++) { + for (int x = 0; x < subWidth; x++) { + global += averages[y * subWidth + x]; + } + } + + global /= subWidth * subHeight; + + + for (int y = 0; y < subHeight; y++) { + for (int x = 0; x < subWidth; x++) { + int left = (x > 0) ? x : 1; + left = (left < subWidth - 1) ? left : subWidth - 2; + int top = (y > 0) ? y : 1; + top = (top < subHeight - 1) ? top : subHeight - 2; + int sum = 0; + int contrast = 0; + for (int z = -1; z <= 1; z++) { +// sum += averages[(top + z) * subWidth + left - 2]; + sum += averages[(top + z) * subWidth + left - 1]; + sum += averages[(top + z) * subWidth + left]; + sum += averages[(top + z) * subWidth + left + 1]; +// sum += averages[(top + z) * subWidth + left + 2]; + +// type += types[(top + z) * subWidth + left - 2]; + contrast += types[(top + z) * subWidth + left - 1]; + contrast += types[(top + z) * subWidth + left]; + contrast += types[(top + z) * subWidth + left + 1]; +// type += types[(top + z) * subWidth + left + 2]; + } + int average = sum / 9; + + + if (contrast > 2) + threshold8x8Block(luminances, x << 3, y << 3, average, stride, matrix); +// else if(average < global) // Black +// matrix.setRegion(x << 3, y << 3, 8, 8); + // If white, we don't need to do anything - the block is already cleared. + } + } +} + +// Applies a single threshold to an 8x8 block of pixels. +void LocalBlockBinarizer::threshold8x8Block(const unsigned char* luminances, int xoffset, int yoffset, int threshold, + int stride, BitMatrix& matrix) { + for (int y = 0; y < 8; y++) { + int offset = (yoffset + y) * stride + xoffset; + for (int x = 0; x < 8; x++) { + int pixel = luminances[offset + x]; + if (pixel < threshold) { + matrix.set(xoffset + x, yoffset + y); + } + } + } +} + +// Calculates a single black point for each 8x8 block of pixels and saves it away. +void LocalBlockBinarizer::calculateBlackPoints(const unsigned char* luminances, unsigned char* averages, + unsigned char* types, int subWidth, int subHeight, int stride) { + for (int y = 0; y < subHeight; y++) { + for (int x = 0; x < subWidth; x++) { + int sum = 0; + int min = 255; + int max = 0; + for (int yy = 0; yy < 8; yy++) { + int offset = ((y << 3) + yy) * stride + (x << 3); + const unsigned char* lumo = luminances + offset; + for (int xx = 0; xx < 8; xx++) { + int pixel = lumo[xx]; + sum += pixel; + if (pixel < min) { + min = pixel; + } + if (pixel > max) { + max = pixel; + } + } + } + + // If the contrast is inadequate, we treat the block as white. + // An arbitrary value is chosen here. Higher values mean less noise, but may also reduce + // the ability to recognise some barcodes. + int average = sum >> 6; + int type; + + if (max - min > 30) + type = THRESHOLD; + else + type = GLOBAL; + // int average = (max - min > 24) ? (sum >> 6) : (min-1); + averages[y * subWidth + x] = average; + types[y * subWidth + x] = type; + } + } +} + +// Applies a simple -1 4 -1 box filter with a weight of 2 to each row. +void LocalBlockBinarizer::sharpenRow(unsigned char* luminances, int width, int height) { + for (int y = 0; y < height; y++) { + int offset = y * width; + int left = luminances[offset]; + int center = luminances[offset + 1]; + for (int x = 1; x < width - 1; x++) { + unsigned char right = luminances[offset + x + 1]; + int pixel = ((center << 2) - left - right) >> 1; + // Must clamp values to 0..255 so they will fit in a byte. + if (pixel > 255) { + pixel = 255; + } else if (pixel < 0) { + pixel = 0; + } + luminances[offset + x] = (unsigned char)pixel; + left = center; + center = right; + } + } +} + +} diff --git a/symbian/QQrDecoder/zxing/common/LocalBlockBinarizer.h b/symbian/QQrDecoder/zxing/common/LocalBlockBinarizer.h new file mode 100644 index 000000000..bae80bc75 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/LocalBlockBinarizer.h @@ -0,0 +1,47 @@ +/* + * LocalBlockBinarizer.h + * zxing + * + * Created by Ralf Kistner on 17/10/2009. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LOCALBLOCKBINARIZER_H_ +#define LOCALBLOCKBINARIZER_H_ + +#include +#include + +namespace zxing { +class LocalBlockBinarizer : public Binarizer { +public: + LocalBlockBinarizer(Ref source); + virtual ~LocalBlockBinarizer(); + + virtual Ref estimateBlackMatrix(); + Ref estimateBlackRow(int y, Ref row); + +private: + + void calculateThresholdForBlock(const unsigned char* luminances, int subWidth, int subHeight, + int stride, const unsigned char* averages, const unsigned char* types, BitMatrix& matrix); + void sharpenRow(unsigned char* luminances, int width, int height); + void calculateBlackPoints(const unsigned char* luminances, unsigned char* averages, unsigned char* types, int subWidth, int subHeight, int stride); + void threshold8x8Block(const unsigned char* luminances, int xoffset, int yoffset, int threshold, + int stride, BitMatrix& matrix); +}; +} + +#endif /* LOCALBLOCKBINARIZER_H_ */ diff --git a/symbian/QQrDecoder/zxing/common/PerspectiveTransform.cpp b/symbian/QQrDecoder/zxing/common/PerspectiveTransform.cpp new file mode 100644 index 000000000..44d9ddcb0 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/PerspectiveTransform.cpp @@ -0,0 +1,121 @@ +/* + * PerspectiveTransform.cpp + * zxing + * + * Created by Christian Brunschen on 12/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { +using namespace std; + +PerspectiveTransform::PerspectiveTransform(float a11, float a21, float a31, float a12, float a22, float a32, float a13, + float a23, float a33) { + this->a11 = a11; + this->a12 = a12; + this->a13 = a13; + this->a21 = a21; + this->a22 = a22; + this->a23 = a23; + this->a31 = a31; + this->a32 = a32; + this->a33 = a33; +} + +Ref PerspectiveTransform::quadrilateralToQuadrilateral(float x0, float y0, float x1, float y1, + float x2, float y2, float x3, float y3, float x0p, float y0p, float x1p, float y1p, float x2p, float y2p, + float x3p, float y3p) { + Ref qToS = PerspectiveTransform::quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3); + Ref sToQ = + PerspectiveTransform::squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p); + return sToQ->times(qToS); +} + +Ref PerspectiveTransform::squareToQuadrilateral(float x0, float y0, float x1, float y1, float x2, + float y2, float x3, float y3) { + float dy2 = y3 - y2; + float dy3 = y0 - y1 + y2 - y3; + if (dy2 == 0.0f && dy3 == 0.0f) { + Ref result(new PerspectiveTransform(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0f, + 0.0f, 1.0f)); + return result; + } else { + float dx1 = x1 - x2; + float dx2 = x3 - x2; + float dx3 = x0 - x1 + x2 - x3; + float dy1 = y1 - y2; + float denominator = dx1 * dy2 - dx2 * dy1; + float a13 = (dx3 * dy2 - dx2 * dy3) / denominator; + float a23 = (dx1 * dy3 - dx3 * dy1) / denominator; + Ref result(new PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0 + + a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0f)); + return result; + } +} + +Ref PerspectiveTransform::quadrilateralToSquare(float x0, float y0, float x1, float y1, float x2, + float y2, float x3, float y3) { + // Here, the adjoint serves as the inverse: + return squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3)->buildAdjoint(); +} + +Ref PerspectiveTransform::buildAdjoint() { + // Adjoint is the transpose of the cofactor matrix: + Ref result(new PerspectiveTransform(a22 * a33 - a23 * a32, a23 * a31 - a21 * a33, a21 * a32 + - a22 * a31, a13 * a32 - a12 * a33, a11 * a33 - a13 * a31, a12 * a31 - a11 * a32, a12 * a23 - a13 * a22, + a13 * a21 - a11 * a23, a11 * a22 - a12 * a21)); + return result; +} + +Ref PerspectiveTransform::times(Ref other) { + Ref result(new PerspectiveTransform(a11 * other->a11 + a21 * other->a12 + a31 * other->a13, + a11 * other->a21 + a21 * other->a22 + a31 * other->a23, a11 * other->a31 + a21 * other->a32 + a31 + * other->a33, a12 * other->a11 + a22 * other->a12 + a32 * other->a13, a12 * other->a21 + a22 + * other->a22 + a32 * other->a23, a12 * other->a31 + a22 * other->a32 + a32 * other->a33, a13 + * other->a11 + a23 * other->a12 + a33 * other->a13, a13 * other->a21 + a23 * other->a22 + a33 + * other->a23, a13 * other->a31 + a23 * other->a32 + a33 * other->a33)); + return result; +} + +void PerspectiveTransform::transformPoints(valarray &points) { + int max = points.size(); + float a11 = this->a11; + float a12 = this->a12; + float a13 = this->a13; + float a21 = this->a21; + float a22 = this->a22; + float a23 = this->a23; + float a31 = this->a31; + float a32 = this->a32; + float a33 = this->a33; + for (int i = 0; i < max; i += 2) { + float x = points[i]; + float y = points[i + 1]; + float denominator = a13 * x + a23 * y + a33; + points[i] = (a11 * x + a21 * y + a31) / denominator; + points[i + 1] = (a12 * x + a22 * y + a32) / denominator; + } +} + +ostream& operator<<(ostream& out, PerspectiveTransform &pt) { + out << pt.a11 << ", " << pt.a12 << ", " << pt.a13 << ", \n"; + out << pt.a21 << ", " << pt.a22 << ", " << pt.a23 << ", \n"; + out << pt.a31 << ", " << pt.a32 << ", " << pt.a33 << "\n"; + return out; +} + +} diff --git a/symbian/QQrDecoder/zxing/common/PerspectiveTransform.h b/symbian/QQrDecoder/zxing/common/PerspectiveTransform.h new file mode 100644 index 000000000..581f92880 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/PerspectiveTransform.h @@ -0,0 +1,50 @@ +#ifndef __PERSPECTIVE_TANSFORM_H__ +#define __PERSPECTIVE_TANSFORM_H__ + +/* + * PerspectiveTransform.h + * zxing + * + * Created by Christian Brunschen on 12/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace zxing { +class PerspectiveTransform : public Counted { +private: + float a11, a12, a13, a21, a22, a23, a31, a32, a33; + PerspectiveTransform(float a11, float a21, float a31, float a12, float a22, float a32, float a13, float a23, + float a33); + +public: + static Ref + quadrilateralToQuadrilateral(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, + float x0p, float y0p, float x1p, float y1p, float x2p, float y2p, float x3p, float y3p); + static Ref squareToQuadrilateral(float x0, float y0, float x1, float y1, float x2, float y2, + float x3, float y3); + static Ref quadrilateralToSquare(float x0, float y0, float x1, float y1, float x2, float y2, + float x3, float y3); + Ref buildAdjoint(); + Ref times(Ref other); + void transformPoints(std::valarray &points); + + friend std::ostream& operator<<(std::ostream& out, PerspectiveTransform &pt); +}; +} + +#endif // __PERSPECTIVE_TANSFORM_H__ diff --git a/symbian/QQrDecoder/zxing/common/Point.h b/symbian/QQrDecoder/zxing/common/Point.h new file mode 100644 index 000000000..a391042fe --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/Point.h @@ -0,0 +1,47 @@ +/* + * Point.h + * zxing + * + * Created by Ralf Kistner on 7/12/2009. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ZXING_POINT_H_ +#define ZXING_POINT_H_ + +namespace zxing { +class PointI { +public: + int x; + int y; +}; + +class Point { +public: + Point(float x_, float y_) : x(x_), y(y_) {}; + + float x; + float y; +}; + +class Line { +public: + Line(Point start_, Point end_) : start(start_), end(end_) {}; + + Point start; + Point end; +}; +} +#endif // POINT_H_ diff --git a/symbian/QQrDecoder/zxing/common/Str.cpp b/symbian/QQrDecoder/zxing/common/Str.cpp new file mode 100644 index 000000000..e2122dc3a --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/Str.cpp @@ -0,0 +1,38 @@ +/* + * String.cpp + * zxing + * + * Created by Christian Brunschen on 20/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { +using namespace std; + +String::String(const std::string &text) : + text_(text) { +} +std::string& String::getText() { + return text_; +} + +ostream &operator<<(ostream &out, const String &s) { + out << s.text_; + return out; +} + +} diff --git a/symbian/QQrDecoder/zxing/common/Str.h b/symbian/QQrDecoder/zxing/common/Str.h new file mode 100644 index 000000000..255a05531 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/Str.h @@ -0,0 +1,41 @@ +#ifndef __COMMON__STRING_H__ +#define __COMMON__STRING_H__ + +/* + * String.h + * zxing + * + * Created by Christian Brunschen on 20/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace zxing { + +class String : public Counted { +private: + std::string text_; +public: + String(const std::string &text); + std::string &getText(); + friend std::ostream &operator<<(std::ostream &out, const String &s); +}; + +} + +#endif // __COMMON__STRING_H__ diff --git a/symbian/QQrDecoder/zxing/common/reedsolomon/GF256.cpp b/symbian/QQrDecoder/zxing/common/reedsolomon/GF256.cpp new file mode 100644 index 000000000..8add88934 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/reedsolomon/GF256.cpp @@ -0,0 +1,140 @@ +/* + * GF256.cpp + * zxing + * + * Created by Christian Brunschen on 05/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zxing { +using namespace std; + +static inline ArrayRef makeArray(int value) { + ArrayRef valuesRef(new Array (value, 1)); + return valuesRef; +} + +static inline Ref refPoly(GF256 &field, int value) { + ArrayRef values(makeArray(value)); + Ref result(new GF256Poly(field, values)); + return result; +} + +GF256::GF256(int primitive) : + exp_((const int)0, 256), log_((const int)0, 256), zero_(refPoly(*this, 0)), one_(refPoly(*this, 1)) { + int x = 1; + for (int i = 0; i < 256; i++) { + exp_[i] = x; + x <<= 1; + if (x >= 0x100) { + x ^= primitive; + } + } + + // log(0) == 0, but should never be used + log_[0] = 0; + for (int i = 0; i < 255; i++) { + log_[exp_[i]] = i; + } +} + +Ref GF256::getZero() { + return zero_; +} + +Ref GF256::getOne() { + return one_; +} + +Ref GF256::buildMonomial(int degree, int coefficient) { +#ifdef DEBUG + cout << __FUNCTION__ << "\n"; +#endif + if (degree < 0) { + throw IllegalArgumentException("Degree must be non-negative"); + } + if (coefficient == 0) { + return zero_; + } + int nCoefficients = degree + 1; + ArrayRef coefficients(new Array (nCoefficients)); + coefficients[0] = coefficient; + Ref result(new GF256Poly(*this, coefficients)); + return result; +} + +int GF256::addOrSubtract(int a, int b) { + return a ^ b; +} + +int GF256::exp(int a) { + return exp_[a]; +} + +int GF256::log(int a) { + if (a == 0) { + throw IllegalArgumentException("Cannot take the logarithm of 0"); + } + return log_[a]; +} + +int GF256::inverse(int a) { + if (a == 0) { + throw IllegalArgumentException("Cannot calculate the inverse of 0"); + } + return exp_[255 - log_[a]]; +} + +int GF256::multiply(int a, int b) { + if (a == 0 || b == 0) { + return 0; + } + if (a == 1) { + return b; + } + if (b == 1) { + return a; + } + return exp_[(log_[a] + log_[b]) % 255]; +} + +GF256 GF256::QR_CODE_FIELD(0x011D); // x^8 + x^4 + x^3 + x^2 + 1 +GF256 GF256::DATA_MATRIX_FIELD(0x012D); // x^8 + x^5 + x^3 + x^2 + 1 + +ostream& operator<<(ostream& out, const GF256& field) { + out << "Field[\nexp=("; + out << field.exp_[0]; + for (int i = 1; i < 256; i++) { + out << "," << field.exp_[i]; + } + out << "),\nlog=("; + out << field.log_[0]; + for (int i = 1; i < 256; i++) { + out << "," << field.log_[i]; + } + out << ")\n]"; + return out; +} + +} diff --git a/symbian/QQrDecoder/zxing/common/reedsolomon/GF256.h b/symbian/QQrDecoder/zxing/common/reedsolomon/GF256.h new file mode 100644 index 000000000..0930f63bf --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/reedsolomon/GF256.h @@ -0,0 +1,69 @@ +#ifndef __GF256_H__ +#define __GF256_H__ + +/* + * GF256.h + * zxing + * + * Created by Christian Brunschen on 05/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace zxing { +class GF256Poly; + +class GF256 { + /** + *

This class contains utility methods for performing mathematical + * operations over the Galois Field GF(256). Operations use a given + * primitive polynomial in calculations.

+ * + *

Throughout this package, elements of GF(256) are represented as an + * int for convenience and speed (but at the cost of memory). + * Only the bottom 8 bits are really used.

+ * + * @author srowen@google.com (Sean Owen) + * @author christian.brunschen@gmail.com (Christian Brunschen) + */ +private: + std::valarray exp_; + std::valarray log_; + Ref zero_; + Ref one_; + + GF256(int primitive); + +public: + Ref getZero(); + Ref getOne(); + Ref buildMonomial(int degree, int coefficient); + static int addOrSubtract(int a, int b); + int exp(int a); + int log(int a); + int inverse(int a); + int multiply(int a, int b); + + static GF256 QR_CODE_FIELD; + static GF256 DATA_MATRIX_FIELD; + + friend std::ostream& operator<<(std::ostream& out, const GF256& field); +}; +} + +#endif // __GF256_H__ diff --git a/symbian/QQrDecoder/zxing/common/reedsolomon/GF256Poly.cpp b/symbian/QQrDecoder/zxing/common/reedsolomon/GF256Poly.cpp new file mode 100644 index 000000000..2c7f4812e --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/reedsolomon/GF256Poly.cpp @@ -0,0 +1,198 @@ +/* + * GF256Poly.cpp + * zxing + * + * Created by Christian Brunschen on 05/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +namespace zxing { +using namespace std; + +void GF256Poly::fixCoefficients() { + int coefficientsLength = coefficients.size(); + if (coefficientsLength > 1 && coefficients[0] == 0) { + // Leading term must be non-zero for anything except + // the constant polynomial "0" + int firstNonZero = 1; + while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0) { + firstNonZero++; + } + if (firstNonZero == coefficientsLength) { + coefficientsLength = field.getZero()->coefficients.size(); + coefficients.reset(new Array (coefficientsLength)); + *coefficients = *(field.getZero()->coefficients); + } else { + ArrayRef c(coefficients); + coefficientsLength -= firstNonZero; + coefficients.reset(new Array (coefficientsLength)); + for (int i = 0; i < coefficientsLength; i++) { + coefficients[i] = c[i + firstNonZero]; + } + } + } +} + +GF256Poly::GF256Poly(GF256 &f, ArrayRef c) : + Counted(), field(f), coefficients(c) { + fixCoefficients(); +} + +GF256Poly::~GF256Poly() { + +} + +int GF256Poly::getDegree() { + return coefficients.size() - 1; +} + +bool GF256Poly::isZero() { + return coefficients[0] == 0; +} + +int GF256Poly::getCoefficient(int degree) { + return coefficients[coefficients.size() - 1 - degree]; +} + +int GF256Poly::evaluateAt(int a) { + if (a == 0) { + return getCoefficient(0); + } + int size = coefficients.size(); + if (a == 1) { + // Just the sum of the coefficients + int result = 0; + for (int i = 0; i < size; i++) { + result = GF256::addOrSubtract(result, coefficients[i]); + } + return result; + } + int result = coefficients[0]; + for (int i = 1; i < size; i++) { + result = GF256::addOrSubtract(field.multiply(a, result), coefficients[i]); + } + return result; +} + +Ref GF256Poly::addOrSubtract(Ref b) { + if (&field != &b->field) { + throw IllegalArgumentException("Fields must be the same"); + } + if (isZero()) { + return b; + } + if (b->isZero()) { + return Ref(this); + } + + ArrayRef largerCoefficients = coefficients; + ArrayRef smallerCoefficients = b->coefficients; + if (smallerCoefficients.size() > largerCoefficients.size()) { + ArrayRef tmp(smallerCoefficients); + smallerCoefficients = largerCoefficients; + largerCoefficients = tmp; + } + + ArrayRef sumDiff(new Array (largerCoefficients.size())); + + unsigned lengthDiff = largerCoefficients.size() - smallerCoefficients.size(); + for (unsigned i = 0; i < lengthDiff; i++) { + sumDiff[i] = largerCoefficients[i]; + } + for (unsigned i = lengthDiff; i < largerCoefficients.size(); i++) { + sumDiff[i] = GF256::addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); + } + return Ref(new GF256Poly(field, sumDiff)); +} + +Ref GF256Poly::multiply(Ref b) { + if (&field != &b->field) { + throw IllegalArgumentException("Fields must be the same"); + } + if (isZero() || b->isZero()) { + return field.getZero(); + } + ArrayRef aCoefficients = coefficients; + int aLength = aCoefficients.size(); + ArrayRef bCoefficients = b->coefficients; + int bLength = bCoefficients.size(); + int productLength = aLength + bLength - 1; + ArrayRef product(new Array (productLength)); + for (int i = 0; i < aLength; i++) { + int aCoeff = aCoefficients[i]; + for (int j = 0; j < bLength; j++) { + product[i + j] = GF256::addOrSubtract(product[i + j], field.multiply(aCoeff, bCoefficients[j])); + } + } + + return Ref(new GF256Poly(field, product)); +} + +Ref GF256Poly::multiply(int scalar) { + if (scalar == 0) { + return field.getZero(); + } + if (scalar == 1) { + return Ref(this); + } + int size = coefficients.size(); + ArrayRef product(new Array (size)); + for (int i = 0; i < size; i++) { + product[i] = field.multiply(coefficients[i], scalar); + } + return Ref(new GF256Poly(field, product)); +} + +Ref GF256Poly::multiplyByMonomial(int degree, int coefficient) { + if (degree < 0) { + throw IllegalArgumentException("Degree must be non-negative"); + } + if (coefficient == 0) { + return field.getZero(); + } + int size = coefficients.size(); + ArrayRef product(new Array (size + degree)); + for (int i = 0; i < size; i++) { + product[i] = field.multiply(coefficients[i], coefficient); + } + return Ref(new GF256Poly(field, product)); +} + +const char *GF256Poly::description() const { + ostringstream result; + result << *this; + return result.str().c_str(); +} + +ostream& operator<<(ostream& out, const GF256Poly& p) { + GF256Poly &poly = const_cast(p); + out << "Poly[" << poly.coefficients.size() << "]"; + if (poly.coefficients.size() > 0) { + out << "(" << poly.coefficients[0]; + for (unsigned i = 1; i < poly.coefficients.size(); i++) { + out << "," << poly.coefficients[i]; + } + out << ")"; + } + return out; +} + +} diff --git a/symbian/QQrDecoder/zxing/common/reedsolomon/GF256Poly.h b/symbian/QQrDecoder/zxing/common/reedsolomon/GF256Poly.h new file mode 100644 index 000000000..e036f29c0 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/reedsolomon/GF256Poly.h @@ -0,0 +1,54 @@ +#ifndef __GF256_POLY_H__ +#define __GF256_POLY_H__ + +/* + * GF256Poly.h + * zxing + * + * Created by Christian Brunschen on 05/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace zxing { +class GF256; + +class GF256Poly : public Counted { +private: + GF256 &field; + ArrayRef coefficients; + void fixCoefficients(); +public: + GF256Poly(GF256 &field, ArrayRef c); + ~GF256Poly(); + + int getDegree(); + bool isZero(); + int getCoefficient(int degree); + int evaluateAt(int a); + Ref addOrSubtract(Ref other); + Ref multiply(Ref other); + Ref multiply(int scalar); + Ref multiplyByMonomial(int degree, int coefficient); + const char *description() const; + friend std::ostream& operator<<(std::ostream& out, const GF256Poly& poly); + +}; +} + +#endif // __GF256_POLY_H__ diff --git a/symbian/QQrDecoder/zxing/common/reedsolomon/ReedSolomonDecoder.cpp b/symbian/QQrDecoder/zxing/common/reedsolomon/ReedSolomonDecoder.cpp new file mode 100644 index 000000000..58a95a8e1 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/reedsolomon/ReedSolomonDecoder.cpp @@ -0,0 +1,193 @@ +/* + * ReedSolomonDecoder.cpp + * zxing + * + * Created by Christian Brunschen on 05/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace zxing { + +ReedSolomonDecoder::ReedSolomonDecoder(GF256 &fld) : + field(fld) { +} + +ReedSolomonDecoder::~ReedSolomonDecoder() { +} + +void ReedSolomonDecoder::decode(ArrayRef received, int twoS) { + + Ref poly(new GF256Poly(field, received)); + + +#ifdef DEBUG + cout << "decoding with poly " << *poly << "\n"; +#endif + + ArrayRef syndromeCoefficients(new Array (twoS)); + + +#ifdef DEBUG + cout << "syndromeCoefficients array = " << + syndromeCoefficients.array_ << "\n"; +#endif + + bool noError = true; + for (int i = 0; i < twoS; i++) { + int eval = poly->evaluateAt(field.exp(i)); + syndromeCoefficients[syndromeCoefficients->size() - 1 - i] = eval; + if (eval != 0) { + noError = false; + } + } + if (noError) { + return; + } + + Ref syndrome(new GF256Poly(field, syndromeCoefficients)); + Ref monomial(field.buildMonomial(twoS, 1)); + vector > sigmaOmega(runEuclideanAlgorithm(monomial, syndrome, twoS)); + ArrayRef errorLocations = findErrorLocations(sigmaOmega[0]); + ArrayRef errorMagitudes = findErrorMagnitudes(sigmaOmega[1], errorLocations); + for (unsigned i = 0; i < errorLocations->size(); i++) { + int position = received->size() - 1 - field.log(errorLocations[i]); + //TODO: check why the position would be invalid + if (position < 0 || (size_t)position >= received.size()) + throw IllegalArgumentException("Invalid position (ReedSolomonDecoder)"); + received[position] = GF256::addOrSubtract(received[position], errorMagitudes[i]); + } +} + +vector > ReedSolomonDecoder::runEuclideanAlgorithm(Ref a, Ref b, int R) { + // Assume a's degree is >= b's + if (a->getDegree() < b->getDegree()) { + Ref tmp = a; + a = b; + b = tmp; + } + + Ref rLast(a); + Ref r(b); + Ref sLast(field.getOne()); + Ref s(field.getZero()); + Ref tLast(field.getZero()); + Ref t(field.getOne()); + + + // Run Euclidean algorithm until r's degree is less than R/2 + while (r->getDegree() >= R / 2) { + Ref rLastLast(rLast); + Ref sLastLast(sLast); + Ref tLastLast(tLast); + rLast = r; + sLast = s; + tLast = t; + + + // Divide rLastLast by rLast, with quotient q and remainder r + if (rLast->isZero()) { + // Oops, Euclidean algorithm already terminated? + throw ReedSolomonException("r_{i-1} was zero"); + } + r = rLastLast; + Ref q(field.getZero()); + int denominatorLeadingTerm = rLast->getCoefficient(rLast->getDegree()); + int dltInverse = field.inverse(denominatorLeadingTerm); + while (r->getDegree() >= rLast->getDegree() && !r->isZero()) { + int degreeDiff = r->getDegree() - rLast->getDegree(); + int scale = field.multiply(r->getCoefficient(r->getDegree()), dltInverse); + q = q->addOrSubtract(field.buildMonomial(degreeDiff, scale)); + r = r->addOrSubtract(rLast->multiplyByMonomial(degreeDiff, scale)); + } + + s = q->multiply(sLast)->addOrSubtract(sLastLast); + t = q->multiply(tLast)->addOrSubtract(tLastLast); + } + + int sigmaTildeAtZero = t->getCoefficient(0); + if (sigmaTildeAtZero == 0) { + throw ReedSolomonException("sigmaTilde(0) was zero"); + } + + int inverse = field.inverse(sigmaTildeAtZero); + Ref sigma(t->multiply(inverse)); + Ref omega(r->multiply(inverse)); + + +#ifdef DEBUG + cout << "t = " << *t << "\n"; + cout << "r = " << *r << "\n"; + cout << "sigma = " << *sigma << "\n"; + cout << "omega = " << *omega << "\n"; +#endif + + vector > result(2); + result[0] = sigma; + result[1] = omega; + return result; +} + +ArrayRef ReedSolomonDecoder::findErrorLocations(Ref errorLocator) { + // This is a direct application of Chien's search + int numErrors = errorLocator->getDegree(); + if (numErrors == 1) { // shortcut + ArrayRef result(1); + result[0] = errorLocator->getCoefficient(1); + return result; + } + ArrayRef result(numErrors); + int e = 0; + for (int i = 1; i < 256 && e < numErrors; i++) { + // cout << "errorLocator(" << i << ") == " << errorLocator->evaluateAt(i) << "\n"; + if (errorLocator->evaluateAt(i) == 0) { + result[e] = field.inverse(i); + e++; + } + } + if (e != numErrors) { + throw ReedSolomonException("Error locator degree does not match number of roots"); + } + return result; +} + +ArrayRef ReedSolomonDecoder::findErrorMagnitudes(Ref errorEvaluator, ArrayRef errorLocations) { + // This is directly applying Forney's Formula + int s = errorLocations.size(); + ArrayRef result(s); + for (int i = 0; i < s; i++) { + int xiInverse = field.inverse(errorLocations[i]); + int denominator = 1; + for (int j = 0; j < s; j++) { + if (i != j) { + denominator = field.multiply(denominator, GF256::addOrSubtract(1, field.multiply(errorLocations[j], + xiInverse))); + } + } + result[i] = field.multiply(errorEvaluator->evaluateAt(xiInverse), field.inverse(denominator)); + } + return result; +} +} diff --git a/symbian/QQrDecoder/zxing/common/reedsolomon/ReedSolomonDecoder.h b/symbian/QQrDecoder/zxing/common/reedsolomon/ReedSolomonDecoder.h new file mode 100644 index 000000000..f7c534ba7 --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/reedsolomon/ReedSolomonDecoder.h @@ -0,0 +1,47 @@ +#ifndef __REED_SOLOMON_DECODER_H__ +#define __REED_SOLOMON_DECODER_H__ + +/* + * ReedSolomonDecoder.h + * zxing + * + * Created by Christian Brunschen on 05/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +namespace zxing { +class GF256; +class GF256Poly; + +class ReedSolomonDecoder { +private: + GF256 &field; +public: + ReedSolomonDecoder(GF256 &fld); + ~ReedSolomonDecoder(); + void decode(ArrayRef received, int twoS); +private: + std::vector > runEuclideanAlgorithm(Ref a, Ref b, int R); + ArrayRef findErrorLocations(Ref errorLocator); + ArrayRef findErrorMagnitudes(Ref errorEvaluator, ArrayRef errorLocations); +}; +} + +#endif // __REED_SOLOMON_DECODER_H__ diff --git a/symbian/QQrDecoder/zxing/common/reedsolomon/ReedSolomonException.cpp b/symbian/QQrDecoder/zxing/common/reedsolomon/ReedSolomonException.cpp new file mode 100644 index 000000000..20af025bb --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/reedsolomon/ReedSolomonException.cpp @@ -0,0 +1,30 @@ +/* + * ReedSolomonException.cpp + * zxing + * + * Created by Christian Brunschen on 06/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { +ReedSolomonException::ReedSolomonException(const char *msg) throw() : + Exception(msg) { +} +ReedSolomonException::~ReedSolomonException() throw() { +} + +} diff --git a/symbian/QQrDecoder/zxing/common/reedsolomon/ReedSolomonException.h b/symbian/QQrDecoder/zxing/common/reedsolomon/ReedSolomonException.h new file mode 100644 index 000000000..ec0df95ce --- /dev/null +++ b/symbian/QQrDecoder/zxing/common/reedsolomon/ReedSolomonException.h @@ -0,0 +1,34 @@ +#ifndef __REED_SOLOMON_EXCEPTION_H__ +#define __REED_SOLOMON_EXCEPTION_H__ + +/* + * ReedSolomonException.h + * zxing + * + * Created by Christian Brunschen on 06/05/2008. + * Copyright 2008 Google UK. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { +class ReedSolomonException : public Exception { +public: + ReedSolomonException(const char *msg) throw(); + ~ReedSolomonException() throw(); +}; +} + +#endif // __REED_SOLOMON_EXCEPTION_H__ diff --git a/symbian/QQrDecoder/zxing/oned/Code128Reader.cpp b/symbian/QQrDecoder/zxing/oned/Code128Reader.cpp new file mode 100644 index 000000000..943a57481 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/Code128Reader.cpp @@ -0,0 +1,478 @@ +/* + * Code128Reader.cpp + * ZXing + * + * Created by Lukasz Warchol on 10-01-15. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Code128Reader.h" +#include +#include +#include +#include +#include + +namespace zxing { + namespace oned { + + const int CODE_PATTERNS_LENGHT = 107; + const int countersLenght = 6; + static const int CODE_PATTERNS[CODE_PATTERNS_LENGHT][countersLenght] = { + {2, 1, 2, 2, 2, 2}, /* 0 */ + {2, 2, 2, 1, 2, 2}, + {2, 2, 2, 2, 2, 1}, + {1, 2, 1, 2, 2, 3}, + {1, 2, 1, 3, 2, 2}, + {1, 3, 1, 2, 2, 2}, /* 5 */ + {1, 2, 2, 2, 1, 3}, + {1, 2, 2, 3, 1, 2}, + {1, 3, 2, 2, 1, 2}, + {2, 2, 1, 2, 1, 3}, + {2, 2, 1, 3, 1, 2}, /* 10 */ + {2, 3, 1, 2, 1, 2}, + {1, 1, 2, 2, 3, 2}, + {1, 2, 2, 1, 3, 2}, + {1, 2, 2, 2, 3, 1}, + {1, 1, 3, 2, 2, 2}, /* 15 */ + {1, 2, 3, 1, 2, 2}, + {1, 2, 3, 2, 2, 1}, + {2, 2, 3, 2, 1, 1}, + {2, 2, 1, 1, 3, 2}, + {2, 2, 1, 2, 3, 1}, /* 20 */ + {2, 1, 3, 2, 1, 2}, + {2, 2, 3, 1, 1, 2}, + {3, 1, 2, 1, 3, 1}, + {3, 1, 1, 2, 2, 2}, + {3, 2, 1, 1, 2, 2}, /* 25 */ + {3, 2, 1, 2, 2, 1}, + {3, 1, 2, 2, 1, 2}, + {3, 2, 2, 1, 1, 2}, + {3, 2, 2, 2, 1, 1}, + {2, 1, 2, 1, 2, 3}, /* 30 */ + {2, 1, 2, 3, 2, 1}, + {2, 3, 2, 1, 2, 1}, + {1, 1, 1, 3, 2, 3}, + {1, 3, 1, 1, 2, 3}, + {1, 3, 1, 3, 2, 1}, /* 35 */ + {1, 1, 2, 3, 1, 3}, + {1, 3, 2, 1, 1, 3}, + {1, 3, 2, 3, 1, 1}, + {2, 1, 1, 3, 1, 3}, + {2, 3, 1, 1, 1, 3}, /* 40 */ + {2, 3, 1, 3, 1, 1}, + {1, 1, 2, 1, 3, 3}, + {1, 1, 2, 3, 3, 1}, + {1, 3, 2, 1, 3, 1}, + {1, 1, 3, 1, 2, 3}, /* 45 */ + {1, 1, 3, 3, 2, 1}, + {1, 3, 3, 1, 2, 1}, + {3, 1, 3, 1, 2, 1}, + {2, 1, 1, 3, 3, 1}, + {2, 3, 1, 1, 3, 1}, /* 50 */ + {2, 1, 3, 1, 1, 3}, + {2, 1, 3, 3, 1, 1}, + {2, 1, 3, 1, 3, 1}, + {3, 1, 1, 1, 2, 3}, + {3, 1, 1, 3, 2, 1}, /* 55 */ + {3, 3, 1, 1, 2, 1}, + {3, 1, 2, 1, 1, 3}, + {3, 1, 2, 3, 1, 1}, + {3, 3, 2, 1, 1, 1}, + {3, 1, 4, 1, 1, 1}, /* 60 */ + {2, 2, 1, 4, 1, 1}, + {4, 3, 1, 1, 1, 1}, + {1, 1, 1, 2, 2, 4}, + {1, 1, 1, 4, 2, 2}, + {1, 2, 1, 1, 2, 4}, /* 65 */ + {1, 2, 1, 4, 2, 1}, + {1, 4, 1, 1, 2, 2}, + {1, 4, 1, 2, 2, 1}, + {1, 1, 2, 2, 1, 4}, + {1, 1, 2, 4, 1, 2}, /* 70 */ + {1, 2, 2, 1, 1, 4}, + {1, 2, 2, 4, 1, 1}, + {1, 4, 2, 1, 1, 2}, + {1, 4, 2, 2, 1, 1}, + {2, 4, 1, 2, 1, 1}, /* 75 */ + {2, 2, 1, 1, 1, 4}, + {4, 1, 3, 1, 1, 1}, + {2, 4, 1, 1, 1, 2}, + {1, 3, 4, 1, 1, 1}, + {1, 1, 1, 2, 4, 2}, /* 80 */ + {1, 2, 1, 1, 4, 2}, + {1, 2, 1, 2, 4, 1}, + {1, 1, 4, 2, 1, 2}, + {1, 2, 4, 1, 1, 2}, + {1, 2, 4, 2, 1, 1}, /* 85 */ + {4, 1, 1, 2, 1, 2}, + {4, 2, 1, 1, 1, 2}, + {4, 2, 1, 2, 1, 1}, + {2, 1, 2, 1, 4, 1}, + {2, 1, 4, 1, 2, 1}, /* 90 */ + {4, 1, 2, 1, 2, 1}, + {1, 1, 1, 1, 4, 3}, + {1, 1, 1, 3, 4, 1}, + {1, 3, 1, 1, 4, 1}, + {1, 1, 4, 1, 1, 3}, /* 95 */ + {1, 1, 4, 3, 1, 1}, + {4, 1, 1, 1, 1, 3}, + {4, 1, 1, 3, 1, 1}, + {1, 1, 3, 1, 4, 1}, + {1, 1, 4, 1, 3, 1}, /* 100 */ + {3, 1, 1, 1, 4, 1}, + {4, 1, 1, 1, 3, 1}, + {2, 1, 1, 4, 1, 2}, + {2, 1, 1, 2, 1, 4}, + {2, 1, 1, 2, 3, 2}, /* 105 */ + {2, 3, 3, 1, 1, 1} + }; + + + Code128Reader::Code128Reader(){ + } + + int* Code128Reader::findStartPattern(Ref row){ + int width = row->getSize(); + int rowOffset = 0; + while (rowOffset < width) { + if (row->get(rowOffset)) { + break; + } + rowOffset++; + } + + int counterPosition = 0; + int counters[countersLenght] = {0,0,0,0,0,0}; + int patternStart = rowOffset; + bool isWhite = false; + int patternLength = sizeof(counters) / sizeof(int); + + for (int i = rowOffset; i < width; i++) { + bool pixel = row->get(i); + if (pixel ^ isWhite) { + counters[counterPosition]++; + } else { + if (counterPosition == patternLength - 1) { + int bestVariance = MAX_AVG_VARIANCE; + int bestMatch = -1; + for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) { + int variance = patternMatchVariance(counters, sizeof(counters)/sizeof(int), CODE_PATTERNS[startCode], MAX_INDIVIDUAL_VARIANCE); + if (variance < bestVariance) { + bestVariance = variance; + bestMatch = startCode; + } + } + if (bestMatch >= 0) { + // Look for whitespace before start pattern, >= 50% of width of start pattern + if (row->isRange(fmaxl(0, patternStart - (i - patternStart) / 2), patternStart, false)) { + int* resultValue = new int[3]; + resultValue[0] = patternStart; + resultValue[1] = i; + resultValue[2] = bestMatch; + return resultValue; + } + } + patternStart += counters[0] + counters[1]; + for (int y = 2; y < patternLength; y++) { + counters[y - 2] = counters[y]; + } + counters[patternLength - 2] = 0; + counters[patternLength - 1] = 0; + counterPosition--; + } else { + counterPosition++; + } + counters[counterPosition] = 1; + isWhite = !isWhite; + } + } + throw ReaderException(""); + } + + int Code128Reader::decodeCode(Ref row, int counters[], int countersCount, int rowOffset){ + recordPattern(row, rowOffset, counters, countersCount); + int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept + int bestMatch = -1; + for (int d = 0; d < CODE_PATTERNS_LENGHT; d++) { + int pattern[countersLenght]; + + for(int ind = 0; ind< countersLenght; ind++){ + pattern[ind] = CODE_PATTERNS[d][ind]; + } +// memcpy(pattern, CODE_PATTERNS[d], countersLenght); + int variance = patternMatchVariance(counters, countersCount, pattern, MAX_INDIVIDUAL_VARIANCE); + if (variance < bestVariance) { + bestVariance = variance; + bestMatch = d; + } + } + // TODO We're overlooking the fact that the STOP pattern has 7 values, not 6. + if (bestMatch >= 0) { + return bestMatch; + } else { + throw ReaderException(""); + } + } + + Ref Code128Reader::decodeRow(int rowNumber, Ref row){ + + int* startPatternInfo = findStartPattern(row); + int startCode = startPatternInfo[2]; + int codeSet; + switch (startCode) { + case CODE_START_A: + codeSet = CODE_CODE_A; + break; + case CODE_START_B: + codeSet = CODE_CODE_B; + break; + case CODE_START_C: + codeSet = CODE_CODE_C; + break; + default: + throw ReaderException(""); + } + + bool done = false; + bool isNextShifted = false; + + std::string tmpResultString; + + + int lastStart = startPatternInfo[0]; + int nextStart = startPatternInfo[1]; + int counters[countersLenght] = {0,0,0,0,0,0}; + + int lastCode = 0; + int code = 0; + int checksumTotal = startCode; + int multiplier = 0; + bool lastCharacterWasPrintable = true; + + while (!done) { + + bool unshift = isNextShifted; + isNextShifted = false; + + // Save off last code + lastCode = code; + + // Decode another code from image + code = decodeCode(row, counters, sizeof(counters)/sizeof(int), nextStart); + + // Remember whether the last code was printable or not (excluding CODE_STOP) + if (code != CODE_STOP) { + lastCharacterWasPrintable = true; + } + + // Add to checksum computation (if not CODE_STOP of course) + if (code != CODE_STOP) { + multiplier++; + checksumTotal += multiplier * code; + } + + // Advance to where the next code will to start + lastStart = nextStart; + int _countersLenght = sizeof(counters) / sizeof(int); + for (int i = 0; i < _countersLenght; i++) { + nextStart += counters[i]; + } + + // Take care of illegal start codes + switch (code) { + case CODE_START_A: + case CODE_START_B: + case CODE_START_C: + throw ReaderException(""); + } + + switch (codeSet) { + + case CODE_CODE_A: + if (code < 64) { + tmpResultString.append(1, (char) (' ' + code)); + } else if (code < 96) { + tmpResultString.append(1, (char) (code - 64)); + } else { + // Don't let CODE_STOP, which always appears, affect whether whether we think the last + // code was printable or not. + if (code != CODE_STOP) { + lastCharacterWasPrintable = false; + } + switch (code) { + case CODE_FNC_1: + case CODE_FNC_2: + case CODE_FNC_3: + case CODE_FNC_4_A: + // do nothing? + break; + case CODE_SHIFT: + isNextShifted = true; + codeSet = CODE_CODE_B; + break; + case CODE_CODE_B: + codeSet = CODE_CODE_B; + break; + case CODE_CODE_C: + codeSet = CODE_CODE_C; + break; + case CODE_STOP: + done = true; + break; + } + } + break; + case CODE_CODE_B: + if (code < 96) { + tmpResultString.append(1, (char) (' ' + code)); + } else { + if (code != CODE_STOP) { + lastCharacterWasPrintable = false; + } + switch (code) { + case CODE_FNC_1: + case CODE_FNC_2: + case CODE_FNC_3: + case CODE_FNC_4_B: + // do nothing? + break; + case CODE_SHIFT: + isNextShifted = true; + codeSet = CODE_CODE_C; + break; + case CODE_CODE_A: + codeSet = CODE_CODE_A; + break; + case CODE_CODE_C: + codeSet = CODE_CODE_C; + break; + case CODE_STOP: + done = true; + break; + } + } + break; + case CODE_CODE_C: + if (code < 100) { + if (code < 10) { + tmpResultString.append(1, '0'); + } + tmpResultString.append(1, code); + } else { + if (code != CODE_STOP) { + lastCharacterWasPrintable = false; + } + switch (code) { + case CODE_FNC_1: + // do nothing? + break; + case CODE_CODE_A: + codeSet = CODE_CODE_A; + break; + case CODE_CODE_B: + codeSet = CODE_CODE_B; + break; + case CODE_STOP: + done = true; + break; + } + } + break; + } + + // Unshift back to another code set if we were shifted + if (unshift) { + switch (codeSet) { + case CODE_CODE_A: + codeSet = CODE_CODE_C; + break; + case CODE_CODE_B: + codeSet = CODE_CODE_A; + break; + case CODE_CODE_C: + codeSet = CODE_CODE_B; + break; + } + } + + } + + // Check for ample whitespace following pattern, but, to do this we first need to remember that + // we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left + // to read off. Would be slightly better to properly read. Here we just skip it: + int width = row->getSize(); + while (nextStart < width && row->get(nextStart)) { + nextStart++; + } + if (!row->isRange(nextStart, fminl(width, nextStart + (nextStart - lastStart) / 2), false)) { + throw ReaderException(""); + } + + // Pull out from sum the value of the penultimate check code + checksumTotal -= multiplier * lastCode; + // lastCode is the checksum then: + if (checksumTotal % 103 != lastCode) { + throw ReaderException(""); + } + + // Need to pull out the check digits from string + int resultLength = tmpResultString.length(); + // Only bother if the result had at least one character, and if the checksum digit happened to + // be a printable character. If it was just interpreted as a control code, nothing to remove. + if (resultLength > 0 && lastCharacterWasPrintable) { + if (codeSet == CODE_CODE_C) { + tmpResultString.erase(resultLength - 2, resultLength); + } else { + tmpResultString.erase(resultLength - 1, resultLength); + } + } + + Ref resultString(new String(tmpResultString)); +// String resultString(tmpResultString); + + if (tmpResultString.length() == 0) { + // Almost surely a false positive + throw ReaderException(""); + } + + float left = (float) (startPatternInfo[1] + startPatternInfo[0]) / 2.0f; + float right = (float) (nextStart + lastStart) / 2.0f; + + std::vector< Ref > resultPoints(2); + Ref resultPoint1(new OneDResultPoint(left, (float) rowNumber)); + Ref resultPoint2(new OneDResultPoint(right, (float) rowNumber)); + resultPoints[0] = resultPoint1; + resultPoints[1] = resultPoint2; + + ArrayRef resultBytes(1); + + delete [] startPatternInfo; + startPatternInfo = NULL; + + Ref res(new Result(resultString, resultBytes, resultPoints, BarcodeFormat_CODE_128)); + return res; + } + + void Code128Reader::append(char* s, char c){ + int len = strlen(s); + s[len] = c; + s[len + 1] = '\0'; + } + + Code128Reader::~Code128Reader(){ + } + } +} diff --git a/symbian/QQrDecoder/zxing/oned/Code128Reader.h b/symbian/QQrDecoder/zxing/oned/Code128Reader.h new file mode 100644 index 000000000..ad191aa0d --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/Code128Reader.h @@ -0,0 +1,61 @@ +/* + * Code128Reader.h + * ZXing + * + * Created by Lukasz Warchol on 10-01-15. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace zxing { + namespace oned { + class Code128Reader : public OneDReader { + + private: + static const int MAX_AVG_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.25f); + static const int MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.7f); + + static const int CODE_SHIFT = 98; + + static const int CODE_CODE_C = 99; + static const int CODE_CODE_B = 100; + static const int CODE_CODE_A = 101; + + static const int CODE_FNC_1 = 102; + static const int CODE_FNC_2 = 97; + static const int CODE_FNC_3 = 96; + static const int CODE_FNC_4_A = 101; + static const int CODE_FNC_4_B = 100; + + static const int CODE_START_A = 103; + static const int CODE_START_B = 104; + static const int CODE_START_C = 105; + static const int CODE_STOP = 106; + + static int* findStartPattern(Ref row); + static int decodeCode(Ref row, int counters[], int countersCount, int rowOffset); + + void append(char* s, char c); + public: + Ref decodeRow(int rowNumber, Ref row); + Code128Reader(); + ~Code128Reader(); + }; + } +} + diff --git a/symbian/QQrDecoder/zxing/oned/Code39Reader.cpp b/symbian/QQrDecoder/zxing/oned/Code39Reader.cpp new file mode 100644 index 000000000..cb03dd9ac --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/Code39Reader.cpp @@ -0,0 +1,340 @@ +/* + * Code39Reader.cpp + * ZXing + * + * Created by Lukasz Warchol on 10-01-26. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Code39Reader.h" +#include +#include +#include +#include +#include + +namespace zxing { + namespace oned { + + static const char* ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%"; + + + /** + * These represent the encodings of characters, as patterns of wide and narrow bars. + * The 9 least-significant bits of each int correspond to the pattern of wide and narrow, + * with 1s representing "wide" and 0s representing narrow. + */ + const int CHARACTER_ENCODINGS_LEN = 44; + static int CHARACTER_ENCODINGS[CHARACTER_ENCODINGS_LEN] = { + 0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, // 0-9 + 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, // A-J + 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, // K-T + 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x094, // U-* + 0x0A8, 0x0A2, 0x08A, 0x02A // $-% + }; + + static int ASTERISK_ENCODING = 0x094; + + + + /** + * Creates a reader that assumes all encoded data is data, and does not treat the final + * character as a check digit. It will not decoded "extended Code 39" sequences. + */ + Code39Reader::Code39Reader(){ + ALPHABET_STRING = new std::string("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%"); + usingCheckDigit = false; + extendedMode = false; + } + + /** + * Creates a reader that can be configured to check the last character as a check digit. + * It will not decoded "extended Code 39" sequences. + * + * @param usingCheckDigit if true, treat the last data character as a check digit, not + * data, and verify that the checksum passes. + */ + Code39Reader::Code39Reader(bool usingCheckDigit_){ + ALPHABET_STRING = new std::string("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%"); + usingCheckDigit = usingCheckDigit_; + extendedMode = false; + } + + + + Ref Code39Reader::decodeRow(int rowNumber, Ref row){ + int* start = findAsteriskPattern(row); + int nextStart = start[1]; + int end = row->getSize(); + + // Read off white space + while (nextStart < end && !row->get(nextStart)) { + nextStart++; + } + + std::string tmpResultString; + + int countersLen = 9; + int* counters = new int[countersLen]; + for (int i=0; iget(nextStart)) { + nextStart++; + } + } while (decodedChar != '*'); + tmpResultString.erase(tmpResultString.length()-1, 1);// remove asterisk + + // Look for whitespace after pattern: + int lastPatternSize = 0; + for (int i = 0; i < countersLen; i++) { + lastPatternSize += counters[i]; + } + int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize; + // If 50% of last pattern size, following last pattern, is not whitespace, fail + // (but if it's whitespace to the very end of the image, that's OK) + if (nextStart != end && whiteSpaceAfterEnd / 2 < lastPatternSize) { + throw ReaderException("too short end white space"); + } + + if (usingCheckDigit) { + int max = tmpResultString.length() - 1; + int total = 0; + for (int i = 0; i < max; i++) { + total += ALPHABET_STRING->find_first_of(tmpResultString[i], 0); + } + if (total % 43 != ALPHABET_STRING->find_first_of(tmpResultString[max], 0)) { + throw ReaderException(""); + } + tmpResultString.erase(max, 1); + } + + + + + Ref resultString(new String(tmpResultString)); + if (extendedMode) { + delete resultString; + resultString = decodeExtended(tmpResultString); + } + + if (tmpResultString.length() == 0) { + // Almost surely a false positive + throw ReaderException(""); + } + + float left = (float) (start[1] + start[0]) / 2.0f; + float right = (float) (nextStart + lastStart) / 2.0f; + + std::vector< Ref > resultPoints(2); + Ref resultPoint1(new OneDResultPoint(left, (float) rowNumber)); + Ref resultPoint2(new OneDResultPoint(right, (float) rowNumber)); + resultPoints[0] = resultPoint1; + resultPoints[1] = resultPoint2; + + ArrayRef resultBytes(1); + + delete [] start; + + Ref res(new Result(resultString, resultBytes, resultPoints, BarcodeFormat_CODE_39)); + return res; + } + + int* Code39Reader::findAsteriskPattern(Ref row){ + int width = row->getSize(); + int rowOffset = 0; + while (rowOffset < width) { + if (row->get(rowOffset)) { + break; + } + rowOffset++; + } + + int counterPosition = 0; + int countersLen = 9; + int* counters = new int[countersLen]; + for (int i=0; iget(i); + if (pixel ^ isWhite) { + counters[counterPosition]++; + } else { + if (counterPosition == patternLength - 1) { + if (toNarrowWidePattern(counters, countersLen) == ASTERISK_ENCODING) { + // Look for whitespace before start pattern, >= 50% of width of start pattern + if (row->isRange(fmaxl(0, patternStart - (i - patternStart) / 2), patternStart, false)) { + int* resultValue = new int[2]; + resultValue[0] = patternStart; + resultValue[1] = i; + return resultValue; + } + } + patternStart += counters[0] + counters[1]; + for (int y = 2; y < patternLength; y++) { + counters[y - 2] = counters[y]; + } + counters[patternLength - 2] = 0; + counters[patternLength - 1] = 0; + counterPosition--; + } else { + counterPosition++; + } + counters[counterPosition] = 1; + isWhite = !isWhite; + } + } + throw ReaderException(""); + } + + // For efficiency, returns -1 on failure. Not throwing here saved as many as 700 exceptions + // per image when using some of our blackbox images. + int Code39Reader::toNarrowWidePattern(int counters[], int countersLen){ + int numCounters = countersLen; + int maxNarrowCounter = 0; + int wideCounters; + do { + int minCounter = INT_MAX; + for (int i = 0; i < numCounters; i++) { + int counter = counters[i]; + if (counter < minCounter && counter > maxNarrowCounter) { + minCounter = counter; + } + } + maxNarrowCounter = minCounter; + wideCounters = 0; + int totalWideCountersWidth = 0; + int pattern = 0; + for (int i = 0; i < numCounters; i++) { + int counter = counters[i]; + if (counters[i] > maxNarrowCounter) { + pattern |= 1 << (numCounters - 1 - i); + wideCounters++; + totalWideCountersWidth += counter; + } + } + if (wideCounters == 3) { + // Found 3 wide counters, but are they close enough in width? + // We can perform a cheap, conservative check to see if any individual + // counter is more than 1.5 times the average: + for (int i = 0; i < numCounters && wideCounters > 0; i++) { + int counter = counters[i]; + if (counters[i] > maxNarrowCounter) { + wideCounters--; + // totalWideCountersWidth = 3 * average, so this checks if counter >= 3/2 * average + if ((counter << 1) >= totalWideCountersWidth) { + return -1; + } + } + } + return pattern; + } + } while (wideCounters > 3); + return -1; + } + + char Code39Reader::patternToChar(int pattern){ + for (int i = 0; i < CHARACTER_ENCODINGS_LEN; i++) { + if (CHARACTER_ENCODINGS[i] == pattern) { + return ALPHABET[i]; + } + } + throw ReaderException(""); + } + + Ref Code39Reader::decodeExtended(std::string encoded){ + int length = encoded.length(); + std::string tmpDecoded; + for (int i = 0; i < length; i++) { + char c = encoded[i]; + if (c == '+' || c == '$' || c == '%' || c == '/') { + char next = encoded[i + 1]; + char decodedChar = '\0'; + switch (c) { + case '+': + // +A to +Z map to a to z + if (next >= 'A' && next <= 'Z') { + decodedChar = (char) (next + 32); + } else { + throw ReaderException(""); + } + break; + case '$': + // $A to $Z map to control codes SH to SB + if (next >= 'A' && next <= 'Z') { + decodedChar = (char) (next - 64); + } else { + throw ReaderException(""); + } + break; + case '%': + // %A to %E map to control codes ESC to US + if (next >= 'A' && next <= 'E') { + decodedChar = (char) (next - 38); + } else if (next >= 'F' && next <= 'W') { + decodedChar = (char) (next - 11); + } else { + throw ReaderException(""); + } + break; + case '/': + // /A to /O map to ! to , and /Z maps to : + if (next >= 'A' && next <= 'O') { + decodedChar = (char) (next - 32); + } else if (next == 'Z') { + decodedChar = ':'; + } else { + throw ReaderException(""); + } + break; + } + tmpDecoded.append(1, decodedChar); + // bump up i again since we read two characters + i++; + } else { + tmpDecoded.append(1, c); + } + } + Ref decoded(new String(tmpDecoded)); + return decoded; + } + + + Code39Reader::~Code39Reader(){ + delete ALPHABET_STRING; + } + + } +} diff --git a/symbian/QQrDecoder/zxing/oned/Code39Reader.h b/symbian/QQrDecoder/zxing/oned/Code39Reader.h new file mode 100644 index 000000000..1846761a6 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/Code39Reader.h @@ -0,0 +1,57 @@ +/* + * Code39Reader.h + * ZXing + * + * Created by Lukasz Warchol on 10-01-26. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace zxing { + namespace oned { + + /** + *

Decodes Code 39 barcodes. This does not support "Full ASCII Code 39" yet.

+ * Ported form Java (author Sean Owen) + * @author Lukasz Warchol + */ + class Code39Reader : public OneDReader { + + private: + std::string* ALPHABET_STRING; + + bool usingCheckDigit; + bool extendedMode; + + static int* findAsteriskPattern(Ref row); //throws ReaderException + static int toNarrowWidePattern(int counters[], int countersLen); + static char patternToChar(int pattern); //throws ReaderException + static Ref decodeExtended(std::string encoded); //throws ReaderException + + void append(char* s, char c); + public: + Code39Reader(); + Code39Reader(bool usingCheckDigit_); + + Ref decodeRow(int rowNumber, Ref row); + + ~Code39Reader(); + }; + } +} + diff --git a/symbian/QQrDecoder/zxing/oned/EAN13Reader.cpp b/symbian/QQrDecoder/zxing/oned/EAN13Reader.cpp new file mode 100644 index 000000000..0e3de9731 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/EAN13Reader.cpp @@ -0,0 +1,95 @@ +/* + * EAN13Reader.cpp + * ZXing + * + * Created by Lukasz Warchol on 10-01-22. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "EAN13Reader.h" +#include + +namespace zxing { + namespace oned { + + static const int FIRST_DIGIT_ENCODINGS[10] = {0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A}; + + + EAN13Reader::EAN13Reader(){ + decodeMiddleCounters = new int[4]; + for (int i=0; i<4; i++) { + decodeMiddleCounters[i] = 0; + } + } + + int EAN13Reader::decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString){ + int countersLen = 4; + int* counters = decodeMiddleCounters; + counters[0] = 0; + counters[1] = 0; + counters[2] = 0; + counters[3] = 0; + + + int end = row->getSize(); + int rowOffset = startRange[1]; + + int lgPatternFound = 0; + + for (int x = 0; x < 6 && rowOffset < end; x++) { + int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, UPC_EAN_PATTERNS_L_AND_G_PATTERNS); + resultString.append(1, (char) ('0' + bestMatch % 10)); + for (int i = 0; i < countersLen; i++) { + rowOffset += counters[i]; + } + if (bestMatch >= 10) { + lgPatternFound |= 1 << (5 - x); + } + } + + determineFirstDigit(resultString, lgPatternFound); + + int* middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(), getMIDDLE_PATTERN_LEN()); + rowOffset = middleRange[1]; + + for (int x = 0; x < 6 && rowOffset < end; x++) { + int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, UPC_EAN_PATTERNS_L_PATTERNS); + resultString.append(1, (char) ('0' + bestMatch)); + for (int i = 0; i < countersLen; i++) { + rowOffset += counters[i]; + } + } + + return rowOffset; + } + + void EAN13Reader::determineFirstDigit(std::string& resultString, int lgPatternFound){ + for (int d = 0; d < 10; d++) { + if (lgPatternFound == FIRST_DIGIT_ENCODINGS[d]) { + resultString.insert((size_t)0, (size_t)1, (char) ('0' + d)); + return; + } + } + throw ReaderException("determineFirstDigit"); + } + + BarcodeFormat EAN13Reader::getBarcodeFormat(){ + return BarcodeFormat_EAN_13; + } + EAN13Reader::~EAN13Reader(){ + delete [] decodeMiddleCounters; + } + } +} diff --git a/symbian/QQrDecoder/zxing/oned/EAN13Reader.h b/symbian/QQrDecoder/zxing/oned/EAN13Reader.h new file mode 100644 index 000000000..381d6e928 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/EAN13Reader.h @@ -0,0 +1,41 @@ +/* + * EAN13Reader.h + * ZXing + * + * Created by Lukasz Warchol on 10-01-22. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace zxing { + namespace oned { + class EAN13Reader : public UPCEANReader { + + private: + int* decodeMiddleCounters; + static void determineFirstDigit(std::string& resultString, int lgPatternFound); //throws ReaderException + + public: + EAN13Reader(); + + int decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString); //throws ReaderException + + BarcodeFormat getBarcodeFormat(); + ~EAN13Reader(); + }; + } +} diff --git a/symbian/QQrDecoder/zxing/oned/EAN8Reader.cpp b/symbian/QQrDecoder/zxing/oned/EAN8Reader.cpp new file mode 100644 index 000000000..5c34c9fe2 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/EAN8Reader.cpp @@ -0,0 +1,75 @@ +/* + * EAN8Reader.cpp + * ZXing + * + * Created by Lukasz Warchol on 10-01-25. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "EAN8Reader.h" +#include + +namespace zxing { + namespace oned { + + EAN8Reader::EAN8Reader(){ + decodeMiddleCounters = new int[4]; + for (int i=0; i<4; i++) { + decodeMiddleCounters[i] = 0; + } + } + + int EAN8Reader::decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString){ + int countersLen = 4; + int* counters = decodeMiddleCounters; + counters[0] = 0; + counters[1] = 0; + counters[2] = 0; + counters[3] = 0; + + + int end = row->getSize(); + int rowOffset = startRange[1]; + + for (int x = 0; x < 4 && rowOffset < end; x++) { + int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, UPC_EAN_PATTERNS_L_PATTERNS); + resultString.append(1, (char) ('0' + bestMatch)); + for (int i = 0; i < countersLen; i++) { + rowOffset += counters[i]; + } + } + + int* middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(), getMIDDLE_PATTERN_LEN()); + rowOffset = middleRange[1]; + + for (int x = 0; x < 4 && rowOffset < end; x++) { + int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, UPC_EAN_PATTERNS_L_PATTERNS); + resultString.append(1, (char) ('0' + bestMatch)); + for (int i = 0; i < countersLen; i++) { + rowOffset += counters[i]; + } + } + + return rowOffset; + } + + BarcodeFormat EAN8Reader::getBarcodeFormat(){ + return BarcodeFormat_EAN_8; + } + EAN8Reader::~EAN8Reader(){ + delete [] decodeMiddleCounters; + } + } +} diff --git a/symbian/QQrDecoder/zxing/oned/EAN8Reader.h b/symbian/QQrDecoder/zxing/oned/EAN8Reader.h new file mode 100644 index 000000000..f7008562c --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/EAN8Reader.h @@ -0,0 +1,40 @@ +/* + * EAN8Reader.h + * ZXing + * + * Created by Lukasz Warchol on 10-01-25. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace zxing { + namespace oned { + class EAN8Reader : public UPCEANReader { + + private: + int* decodeMiddleCounters; + + public: + EAN8Reader(); + + int decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString); //throws ReaderException + + BarcodeFormat getBarcodeFormat(); + ~EAN8Reader(); + }; + } +} diff --git a/symbian/QQrDecoder/zxing/oned/ITFReader.cpp b/symbian/QQrDecoder/zxing/oned/ITFReader.cpp new file mode 100644 index 000000000..7febab090 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/ITFReader.cpp @@ -0,0 +1,355 @@ +/* + * ITFReader.cpp + * ZXing + * + * Created by Lukasz Warchol on 10-01-26. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ITFReader.h" +#include +#include +#include +#include + +namespace zxing { + namespace oned { + + static const int W = 3; // Pixel width of a wide line + static const int N = 1; // Pixed width of a narrow line + + const int DEFAULT_ALLOWED_LENGTHS[4] = { 6, 10, 14, 44 }; + + /** + * Start/end guard pattern. + * + * Note: The end pattern is reversed because the row is reversed before + * searching for the END_PATTERN + */ + static const int START_PATTERN_LEN = 4; + static const int START_PATTERN[START_PATTERN_LEN] = {N, N, N, N}; + + static const int END_PATTERN_REVERSED_LEN = 3; + static const int END_PATTERN_REVERSED[END_PATTERN_REVERSED_LEN] = {N, N, W}; + + /** + * Patterns of Wide / Narrow lines to indicate each digit + */ + static const int PATTERNS_LEN = 10; + static const int PATTERNS[PATTERNS_LEN][5] = { + {N, N, W, W, N}, // 0 + {W, N, N, N, W}, // 1 + {N, W, N, N, W}, // 2 + {W, W, N, N, N}, // 3 + {N, N, W, N, W}, // 4 + {W, N, W, N, N}, // 5 + {N, W, W, N, N}, // 6 + {N, N, N, W, W}, // 7 + {W, N, N, W, N}, // 8 + {N, W, N, W, N} // 9 + }; + + + ITFReader::ITFReader(){ + narrowLineWidth = -1; + } + + + Ref ITFReader::decodeRow(int rowNumber, Ref row){ + // Find out where the Middle section (payload) starts & ends + int* startRange = decodeStart(row); + int* endRange = decodeEnd(row); + + std::string tmpResult; + decodeMiddle(row, startRange[1], endRange[0], tmpResult); + + // To avoid false positives with 2D barcodes (and other patterns), make + // an assumption that the decoded string must be 6, 10 or 14 digits. + int length = tmpResult.length(); + bool lengthOK = false; + if (length == 6 || length == 10 || length == 14) { + lengthOK = true; + } + if (!lengthOK) { + throw ReaderException("not enought characters count"); + } + + Ref resultString(new String(tmpResult)); + + std::vector< Ref > resultPoints(2); + Ref resultPoint1(new OneDResultPoint(startRange[1], (float) rowNumber)); + Ref resultPoint2(new OneDResultPoint(endRange[0], (float) rowNumber)); + resultPoints[0] = resultPoint1; + resultPoints[1] = resultPoint2; + + ArrayRef resultBytes(1); + + delete [] startRange; + delete [] endRange; + + Ref res(new Result(resultString, resultBytes, resultPoints, BarcodeFormat_ITF)); + return res; + } + + /** + * @param row row of black/white values to search + * @param payloadStart offset of start pattern + * @param resultString {@link StringBuffer} to append decoded chars to + * @throws ReaderException if decoding could not complete successfully + */ + void ITFReader::decodeMiddle(Ref row, int payloadStart, int payloadEnd, std::string& resultString){ + // Digits are interleaved in pairs - 5 black lines for one digit, and the + // 5 + // interleaved white lines for the second digit. + // Therefore, need to scan 10 lines and then + // split these into two arrays + int counterDigitPairLen = 10; + int* counterDigitPair = new int[counterDigitPairLen]; + for (int i=0; i row){ + int endStart = skipWhiteSpace(row); +/// static int* findGuardPattern(Ref row, int rowOffset, bool whiteFirst, const int pattern[], int patternLen); + int* startPattern = findGuardPattern(row, endStart, START_PATTERN, START_PATTERN_LEN); + + // Determine the width of a narrow line in pixels. We can do this by + // getting the width of the start pattern and dividing by 4 because its + // made up of 4 narrow lines. + narrowLineWidth = (startPattern[1] - startPattern[0]) >> 2; + + validateQuietZone(row, startPattern[0]); + + return startPattern; + } + + /** + * Identify where the end of the middle / payload section ends. + * + * @param row row of black/white values to search + * @return Array, containing index of start of 'end block' and end of 'end + * block' + * @throws ReaderException + */ + + int* ITFReader::decodeEnd(Ref row){ + // For convenience, reverse the row and then + // search from 'the start' for the end block + row->reverse(); + try { + int endStart = skipWhiteSpace(row); + int* endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED, END_PATTERN_REVERSED_LEN); + + // The start & end patterns must be pre/post fixed by a quiet zone. This + // zone must be at least 10 times the width of a narrow line. + // ref: http://www.barcode-1.net/i25code.html + validateQuietZone(row, endPattern[0]); + + // Now recalculate the indices of where the 'endblock' starts & stops to + // accommodate + // the reversed nature of the search + int temp = endPattern[0]; + endPattern[0] = row->getSize() - endPattern[1]; + endPattern[1] = row->getSize() - temp; + + return endPattern; + }catch (Exception e) { + row->reverse(); + throw e; + } + } + + /** + * The start & end patterns must be pre/post fixed by a quiet zone. This + * zone must be at least 10 times the width of a narrow line. Scan back until + * we either get to the start of the barcode or match the necessary number of + * quiet zone pixels. + * + * Note: Its assumed the row is reversed when using this method to find + * quiet zone after the end pattern. + * + * ref: http://www.barcode-1.net/i25code.html + * + * @param row bit array representing the scanned barcode. + * @param startPattern index into row of the start or end pattern. + * @throws ReaderException if the quiet zone cannot be found, a ReaderException is thrown. + */ + void ITFReader::validateQuietZone(Ref row, int startPattern){ +#pragma mark needs some corrections +// int quietCount = narrowLineWidth * 10; // expect to find this many pixels of quiet zone +// +// for (int i = startPattern - 1; quietCount > 0 && i >= 0; i--) { +// if (row->get(i)) { +// break; +// } +// quietCount--; +// } +// if (quietCount != 0) { +// // Unable to find the necessary number of quiet zone pixels. +// throw ReaderException("Unable to find the necessary number of quiet zone pixels"); +// } + } + + /** + * Skip all whitespace until we get to the first black line. + * + * @param row row of black/white values to search + * @return index of the first black line. + * @throws ReaderException Throws exception if no black lines are found in the row + */ + int ITFReader::skipWhiteSpace(Ref row){ + int width = row->getSize(); + int endStart = 0; + while (endStart < width) { + if (row->get(endStart)) { + break; + } + endStart++; + } + if (endStart == width) { + throw ReaderException(""); + } + return endStart; + } + + /** + * @param row row of black/white values to search + * @param rowOffset position to start search + * @param pattern pattern of counts of number of black and white pixels that are + * being searched for as a pattern + * @return start/end horizontal offset of guard pattern, as an array of two + * ints + * @throws ReaderException if pattern is not found + */ + + int* ITFReader::findGuardPattern(Ref row, int rowOffset, const int pattern[], int patternLen){ + // TODO: This is very similar to implementation in UPCEANReader. Consider if they can be + // merged to a single method. + int patternLength = patternLen; + int* counters = new int[patternLength]; + for (int i=0; igetSize(); + bool isWhite = false; + + int counterPosition = 0; + int patternStart = rowOffset; + for (int x = rowOffset; x < width; x++) { + bool pixel = row->get(x); + if (pixel ^ isWhite) { + counters[counterPosition]++; + } else { + if (counterPosition == patternLength - 1) { + if (patternMatchVariance(counters, patternLength, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { + int* resultValue = new int[2]; + resultValue[0] = patternStart; + resultValue[1] = x; + return resultValue; + } + patternStart += counters[0] + counters[1]; + for (int y = 2; y < patternLength; y++) { + counters[y - 2] = counters[y]; + } + counters[patternLength - 2] = 0; + counters[patternLength - 1] = 0; + counterPosition--; + } else { + counterPosition++; + } + counters[counterPosition] = 1; + isWhite = !isWhite; + } + } + throw ReaderException(""); + } + + /** + * Attempts to decode a sequence of ITF black/white lines into single + * digit. + * + * @param counters the counts of runs of observed black/white/black/... values + * @return The decoded digit + * @throws ReaderException if digit cannot be decoded + */ + int ITFReader::decodeDigit(int counters[], int countersLen){ + int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept + int bestMatch = -1; + int max = PATTERNS_LEN; + for (int i = 0; i < max; i++) { + //int pattern[countersLen]; + int* pattern = new int(countersLen); + for(int ind = 0; ind= 0) { + return bestMatch; + } else { + throw ReaderException("digit didint found"); + } + } + + + ITFReader::~ITFReader(){ + } + } +} diff --git a/symbian/QQrDecoder/zxing/oned/ITFReader.h b/symbian/QQrDecoder/zxing/oned/ITFReader.h new file mode 100644 index 000000000..759d84144 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/ITFReader.h @@ -0,0 +1,53 @@ +/* + * ITFReader.h + * ZXing + * + * Created by Lukasz Warchol on 10-01-26. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace zxing { + namespace oned { + class ITFReader : public OneDReader { + + private: + static const int MAX_AVG_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.42f); + static const int MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.8f); + + // Stores the actual narrow line width of the image being decoded. + int narrowLineWidth; + + int* decodeStart(Ref row); //throws ReaderException + int* decodeEnd(Ref row); //throws ReaderException + static void decodeMiddle(Ref row, int payloadStart, int payloadEnd, std::string& resultString); //throws ReaderException + void validateQuietZone(Ref row, int startPattern); //throws ReaderException + static int skipWhiteSpace(Ref row); //throws ReaderException + + static int* findGuardPattern(Ref row, int rowOffset, const int pattern[], int patternLen); //throws ReaderException + static int decodeDigit(int counters[], int countersLen); //throws ReaderException + + void append(char* s, char c); + public: + Ref decodeRow(int rowNumber, Ref row); ///throws ReaderException + ITFReader(); + ~ITFReader(); + }; + } +} + diff --git a/symbian/QQrDecoder/zxing/oned/MultiFormatOneDReader.cpp b/symbian/QQrDecoder/zxing/oned/MultiFormatOneDReader.cpp new file mode 100644 index 000000000..245003b1d --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/MultiFormatOneDReader.cpp @@ -0,0 +1,55 @@ +/* + * MultiFormatOneDReader.cpp + * ZXing + * + * Created by Lukasz Warchol on 10-01-25. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MultiFormatOneDReader.h" + +#include +#include +#include +#include +#include + +namespace zxing { + namespace oned { + MultiFormatOneDReader::MultiFormatOneDReader(){ + readers = new std::vector(); + readers->push_back(new MultiFormatUPCEANReader()); + readers->push_back(new Code39Reader()); + readers->push_back(new Code128Reader()); + readers->push_back(new ITFReader()); + } + + Ref MultiFormatOneDReader::decodeRow(int rowNumber, Ref row){ + int size = readers->size(); + for (int i = 0; i < size; i++) { + OneDReader* reader = (*readers)[i]; + try { + return reader->decodeRow(rowNumber, row); + } catch (ReaderException re) { + // continue + } + } + throw ReaderException("No code detected"); + } + MultiFormatOneDReader::~MultiFormatOneDReader(){ + delete readers; + } + } +} diff --git a/symbian/QQrDecoder/zxing/oned/MultiFormatOneDReader.h b/symbian/QQrDecoder/zxing/oned/MultiFormatOneDReader.h new file mode 100644 index 000000000..5320924f6 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/MultiFormatOneDReader.h @@ -0,0 +1,39 @@ +/* + * MultiFormatOneDReader.h + * ZXing + * + * Created by Lukasz Warchol on 10-01-25. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace zxing { + namespace oned { + class MultiFormatOneDReader : public OneDReader { + + private: + std::vector* readers; + public: + MultiFormatOneDReader(); + + Ref decodeRow(int rowNumber, Ref row); + + ~MultiFormatOneDReader(); + }; + } +} diff --git a/symbian/QQrDecoder/zxing/oned/MultiFormatUPCEANReader.cpp b/symbian/QQrDecoder/zxing/oned/MultiFormatUPCEANReader.cpp new file mode 100644 index 000000000..21045e3b1 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/MultiFormatUPCEANReader.cpp @@ -0,0 +1,79 @@ +/* + * MultiFormatUPCEANReader.cpp + * ZXing + * + * Created by Lukasz Warchol on 10-01-25. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "MultiFormatUPCEANReader.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace zxing { + namespace oned { + + MultiFormatUPCEANReader::MultiFormatUPCEANReader(){ + readers = new std::vector(); + readers->push_back(new EAN13Reader()); + // UPC-A is covered by EAN-13 + readers->push_back(new EAN8Reader()); + readers->push_back(new UPCEReader()); + } + + Ref MultiFormatUPCEANReader::decodeRow(int rowNumber, Ref row){ + // Compute this location once and reuse it on multiple implementations + int size = readers->size(); + for (int i = 0; i < size; i++) { + OneDReader* reader = (*readers)[i]; + Ref result; + try { + result = reader->decodeRow(rowNumber, row);//decodeRow(rowNumber, row, startGuardPattern); + } catch (ReaderException re) { + continue; + } + // Special case: a 12-digit code encoded in UPC-A is identical to a "0" + // followed by those 12 digits encoded as EAN-13. Each will recognize such a code, + // UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with "0". + // Individually these are correct and their readers will both read such a code + // and correctly call it EAN-13, or UPC-A, respectively. + // + // In this case, if we've been looking for both types, we'd like to call it + // a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read + // UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A + // result if appropriate. + if (result->getBarcodeFormat() == BarcodeFormat_EAN_13) { + std::string& text = (result->getText())->getText(); + if (text[0] == '0') { + Ref resultString(new String(text.substr(1))); + Ref res(new Result(resultString, result->getRawBytes(), result->getResultPoints(), BarcodeFormat_UPC_A)); + return res; + } + } + return result; + } + throw ReaderException("No EAN code detected"); + } + + MultiFormatUPCEANReader::~MultiFormatUPCEANReader(){ + delete readers; + } + } +} diff --git a/symbian/QQrDecoder/zxing/oned/MultiFormatUPCEANReader.h b/symbian/QQrDecoder/zxing/oned/MultiFormatUPCEANReader.h new file mode 100644 index 000000000..2021bb5f1 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/MultiFormatUPCEANReader.h @@ -0,0 +1,41 @@ +/* + * MultiFormatUPCEANReader.h + * ZXing + * + * Created by Lukasz Warchol on 10-01-25. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +#include +#include +#include + +namespace zxing { + namespace oned { + class MultiFormatUPCEANReader : public OneDReader { + + private: + std::vector* readers; + public: + MultiFormatUPCEANReader(); + + Ref decodeRow(int rowNumber, Ref row); + + ~MultiFormatUPCEANReader(); + }; + } +} diff --git a/symbian/QQrDecoder/zxing/oned/OneDReader.cpp b/symbian/QQrDecoder/zxing/oned/OneDReader.cpp new file mode 100644 index 000000000..0b557d625 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/OneDReader.cpp @@ -0,0 +1,194 @@ +/* + * OneDReader.cpp + * ZXing + * + * Created by Lukasz Warchol on 10-01-15. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "OneDReader.h" +#include +#include +#include + +namespace zxing { + namespace oned { + using namespace std; + + OneDReader::OneDReader() { + } + + Ref OneDReader::decode(Ref image) { + try { + return doDecode(image); + }catch (ReaderException re) { + if (false /*tryHarder && image.isRotateSupported()*/) { + /* + BinaryBitmap rotatedImage = image.rotateCounterClockwise(); + Result result = doDecode(rotatedImage, hints); + // Record that we found it rotated 90 degrees CCW / 270 degrees CW + Hashtable metadata = result.getResultMetadata(); + int orientation = 270; + if (metadata != null && metadata.containsKey(ResultMetadataType.ORIENTATION)) { + // But if we found it reversed in doDecode(), add in that result here: + orientation = (orientation + + ((Integer) metadata.get(ResultMetadataType.ORIENTATION)).intValue()) % 360; + } + result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(orientation)); + // Update result points + ResultPoint[] points = result.getResultPoints(); + int height = rotatedImage.getHeight(); + for (int i = 0; i < points.length; i++) { + points[i] = new ResultPoint(height - points[i].getY() - 1, points[i].getX()); + } + return result; + */ + } else { + throw re; + } + } + } + + Ref OneDReader::doDecode(Ref image){ + int width = image->getWidth(); + int height = image->getHeight(); + Ref row(new BitArray(width)); +// BitArray row = new BitArray(width); + + int middle = height >> 1; + bool tryHarder = true;//hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); + int rowStep = (int)fmax(1, height >> (tryHarder ? 7 : 4)); + int maxLines; + if (tryHarder) { + maxLines = height; // Look at the whole image, not just the center + } else { + maxLines = 9; // Nine rows spaced 1/16 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 (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 (ReaderException re) { + 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) { // trying again? + row->reverse(); // reverse the row and continue + } + try { + // Look for a barcode + Ref 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. + // ResultPoint[] points = result.getResultPoints(); + // points[0] = new ResultPoint(width - points[0].getX() - 1, points[0].getY()); + // points[1] = new ResultPoint(width - points[1].getX() - 1, points[1].getY()); + } + return result; + } catch (ReaderException re) { + // continue -- just couldn't decode this row + } + } + } + throw ReaderException(""); + } + + int OneDReader::patternMatchVariance(int counters[], int countersSize, const int pattern[], int maxIndividualVariance) { + int numCounters = countersSize; + int total = 0; + int patternLength = 0; + for (int i = 0; i < numCounters; i++) { + total += counters[i]; + patternLength += pattern[i]; + } + if (total < patternLength) { + // If we don't even have one pixel per unit of bar width, assume this is too small + // to reliably match, so fail: + return INT_MAX; + } + // We're going to fake floating-point math in integers. We just need to use more bits. + // Scale up patternLength so that intermediate values below like scaledCounter will have + // more "significant digits" + int unitBarWidth = (total << INTEGER_MATH_SHIFT) / patternLength; + maxIndividualVariance = (maxIndividualVariance * unitBarWidth) >> INTEGER_MATH_SHIFT; + + int totalVariance = 0; + for (int x = 0; x < numCounters; x++) { + int counter = counters[x] << INTEGER_MATH_SHIFT; + int scaledPattern = pattern[x] * unitBarWidth; + int variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter; + if (variance > maxIndividualVariance) { + return INT_MAX; + } + totalVariance += variance; + } + return totalVariance / total; + } + + void OneDReader::recordPattern(Ref row, int start, int counters[], int countersCount){ + int numCounters = countersCount;//sizeof(counters) / sizeof(int); + for (int i = 0; i < numCounters; i++) { + counters[i] = 0; + } + int end = row->getSize(); + if (start >= end) { + throw ReaderException("recordPattern: start >= end"); + } + bool isWhite = !row->get(start); + int counterPosition = 0; + int i = start; + while (i < end) { + bool pixel = row->get(i); + if (pixel ^ isWhite) { // that is, exactly one is true + counters[counterPosition]++; + } else { + counterPosition++; + if (counterPosition == numCounters) { + break; + } else { + counters[counterPosition] = 1; + isWhite ^= true; // isWhite = !isWhite; + } + } + i++; + } + // If we read fully the last section of pixels and filled up our counters -- or filled + // the last counter but ran off the side of the image, OK. Otherwise, a problem. + if (!(counterPosition == numCounters || (counterPosition == numCounters - 1 && i == end))) { + throw ReaderException("recordPattern"); + } + } + + OneDReader::~OneDReader() { + } + } +} diff --git a/symbian/QQrDecoder/zxing/oned/OneDReader.h b/symbian/QQrDecoder/zxing/oned/OneDReader.h new file mode 100644 index 000000000..92a7e779b --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/OneDReader.h @@ -0,0 +1,46 @@ +/* + * OneDReader.h + * ZXing + * + * Created by Lukasz Warchol on 10-01-15. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +namespace zxing { + namespace oned { + class OneDReader : public Reader { + private: + static const int INTEGER_MATH_SHIFT = 8; + + Ref doDecode(Ref image); + public: + static const int PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHIFT; + + OneDReader(); + virtual Ref decode(Ref image); + virtual Ref decodeRow(int rowNumber, Ref row) = 0; + + static int patternMatchVariance(int counters[], int countersSize, const int pattern[], int maxIndividualVariance); + static void recordPattern(Ref row, int start, int counters[], int countersCount); + virtual ~OneDReader(); + }; + } +} diff --git a/symbian/QQrDecoder/zxing/oned/OneDResultPoint.cpp b/symbian/QQrDecoder/zxing/oned/OneDResultPoint.cpp new file mode 100644 index 000000000..272319dbf --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/OneDResultPoint.cpp @@ -0,0 +1,39 @@ +/* + * OneDResultPoint.cpp + * ZXing + * + * Created by Lukasz Warchol on 10-01-20. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "OneDResultPoint.h" + +namespace zxing { + namespace oned { + + using namespace std; + + OneDResultPoint::OneDResultPoint(float posX, float posY) : posX_(posX), posY_(posY){ + } + + float OneDResultPoint::getX() { + return posX_; + } + + float OneDResultPoint::getY() { + return posY_; + } + } +} \ No newline at end of file diff --git a/symbian/QQrDecoder/zxing/oned/OneDResultPoint.h b/symbian/QQrDecoder/zxing/oned/OneDResultPoint.h new file mode 100644 index 000000000..1b07b772c --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/OneDResultPoint.h @@ -0,0 +1,37 @@ +/* + * OneDResultPoint.h + * ZXing + * + * Created by Lukasz Warchol on 10-01-20. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +namespace zxing { + namespace oned { + + class OneDResultPoint : public ResultPoint { + private: + float posX_; + float posY_; + + public: + OneDResultPoint(float posX, float posY); + float getX(); + float getY(); + }; + } +} diff --git a/symbian/QQrDecoder/zxing/oned/UPCAReader.cpp b/symbian/QQrDecoder/zxing/oned/UPCAReader.cpp new file mode 100644 index 000000000..8757b2ace --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/UPCAReader.cpp @@ -0,0 +1,64 @@ +/* + * UPCAReader.cpp + * ZXing + * + * Created by Lukasz Warchol on 10-01-25. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "UPCAReader.h" +#include +#include + +namespace zxing { + namespace oned { + UPCAReader::UPCAReader(){ + ean13Reader = new EAN13Reader(); + } + + Ref UPCAReader::decodeRow(int rowNumber, Ref row){ + return maybeReturnResult(ean13Reader->decodeRow(rowNumber, row)); + } + Ref UPCAReader::decodeRow(int rowNumber, Ref row, int startGuardRange[]){ + return maybeReturnResult(ean13Reader->decodeRow(rowNumber, row, startGuardRange)); + } + Ref UPCAReader::decode(Ref image){ + return maybeReturnResult(ean13Reader->decode(image)); + } + + int UPCAReader::decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString){ + return ean13Reader->decodeMiddle(row, startRange, startRangeLen, resultString); + } + + Ref UPCAReader::maybeReturnResult(Ref result){ + std::string& text = (result->getText())->getText(); + if (text[0] == '0') { + Ref resultString(new String(text.substr(1))); + Ref res(new Result(resultString, result->getRawBytes(), result->getResultPoints(), BarcodeFormat_UPC_A)); + return res; + } else { + throw ReaderException("Not UPC-A barcode."); + } + } + + + BarcodeFormat UPCAReader::getBarcodeFormat(){ + return BarcodeFormat_UPC_A; + } + UPCAReader::~UPCAReader(){ + delete ean13Reader; + } + } +} diff --git a/symbian/QQrDecoder/zxing/oned/UPCAReader.h b/symbian/QQrDecoder/zxing/oned/UPCAReader.h new file mode 100644 index 000000000..056295245 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/UPCAReader.h @@ -0,0 +1,45 @@ +/* + * UPCAReader.h + * ZXing + * + * Created by Lukasz Warchol on 10-01-25. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace zxing { + namespace oned { + class UPCAReader : public UPCEANReader { + + private: + UPCEANReader* ean13Reader; + static Ref maybeReturnResult(Ref result); //throws ReaderException + + public: + UPCAReader(); + + int decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString); //throws ReaderException + + Ref decodeRow(int rowNumber, Ref row); //throws ReaderException + Ref decodeRow(int rowNumber, Ref row, int startGuardRange[]); //throws ReaderException + Ref decode(Ref image); + + BarcodeFormat getBarcodeFormat(); + ~UPCAReader(); + }; + } +} diff --git a/symbian/QQrDecoder/zxing/oned/UPCEANReader.cpp b/symbian/QQrDecoder/zxing/oned/UPCEANReader.cpp new file mode 100644 index 000000000..e9bfa1795 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/UPCEANReader.cpp @@ -0,0 +1,316 @@ +/* + * UPCEANReader.cpp + * ZXing + * + * Created by Lukasz Warchol on 10-01-21. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "UPCEANReader.h" +#include +#include +namespace zxing { + namespace oned { + + /** + * Start/end guard pattern. + */ + static const int START_END_PATTERN[3] = {1, 1, 1}; + + /** + * Pattern marking the middle of a UPC/EAN pattern, separating the two halves. + */ + static const int MIDDLE_PATTERN_LEN = 5; + static const int MIDDLE_PATTERN[MIDDLE_PATTERN_LEN] = {1, 1, 1, 1, 1}; + + /** + * "Odd", or "L" patterns used to encode UPC/EAN digits. + */ + const int L_PATTERNS_LEN = 10; + const int L_PATTERNS_SUB_LEN = 4; + const int L_PATTERNS[10][4] = { + {3, 2, 1, 1}, // 0 + {2, 2, 2, 1}, // 1 + {2, 1, 2, 2}, // 2 + {1, 4, 1, 1}, // 3 + {1, 1, 3, 2}, // 4 + {1, 2, 3, 1}, // 5 + {1, 1, 1, 4}, // 6 + {1, 3, 1, 2}, // 7 + {1, 2, 1, 3}, // 8 + {3, 1, 1, 2} // 9 + }; + + /** + * As above but also including the "even", or "G" patterns used to encode UPC/EAN digits. + */ + const int L_AND_G_PATTERNS_LEN = 20; + const int L_AND_G_PATTERNS_SUB_LEN = 4; + const int L_AND_G_PATTERNS[L_AND_G_PATTERNS_LEN][L_AND_G_PATTERNS_SUB_LEN] = { + {3, 2, 1, 1}, // 0 + {2, 2, 2, 1}, // 1 + {2, 1, 2, 2}, // 2 + {1, 4, 1, 1}, // 3 + {1, 1, 3, 2}, // 4 + {1, 2, 3, 1}, // 5 + {1, 1, 1, 4}, // 6 + {1, 3, 1, 2}, // 7 + {1, 2, 1, 3}, // 8 + {3, 1, 1, 2}, // 9 + {1, 1, 2, 3}, // 10 reversed 0 + {1, 2, 2, 2}, // 11 reversed 1 + {2, 2, 1, 2}, // 12 reversed 2 + {1, 1, 4, 1}, // 13 reversed 3 + {2, 3, 1, 1}, // 14 reversed 4 + {1, 3, 2, 1}, // 15 reversed 5 + {4, 1, 1, 1}, // 16 reversed 6 + {2, 1, 3, 1}, // 17 reversed 7 + {3, 1, 2, 1}, // 18 reversed 8 + {2, 1, 1, 3} // 19 reversed 9 + }; + + + const int UPCEANReader::getMIDDLE_PATTERN_LEN(){ + return MIDDLE_PATTERN_LEN; + } + const int* UPCEANReader::getMIDDLE_PATTERN(){ + return MIDDLE_PATTERN; + } + + UPCEANReader::UPCEANReader(){ + } + + + Ref UPCEANReader::decodeRow(int rowNumber, Ref row){ + return decodeRow(rowNumber, row, findStartGuardPattern(row)); + } + Ref UPCEANReader::decodeRow(int rowNumber, Ref row, int startGuardRange[]){ + + std::string tmpResultString; + std::string& tmpResultStringRef = tmpResultString; + int endStart = decodeMiddle(row, startGuardRange, 2 /*reference findGuardPattern*/ , tmpResultStringRef); + + int* endRange = decodeEnd(row, endStart); + +#pragma mark QuietZone needs some change + // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The + // spec might want more whitespace, but in practice this is the maximum we can count on. +// int end = endRange[1]; +// int quietEnd = end + (end - endRange[0]); +// if (quietEnd >= row->getSize() || !row->isRange(end, quietEnd, false)) { +// throw ReaderException("Quiet zone asserrt fail."); +// } + + if (!checkChecksum(tmpResultString)) { + throw ReaderException("Checksum fail."); + } + + Ref resultString(new String(tmpResultString)); + + float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f; + float right = (float) (endRange[1] + endRange[0]) / 2.0f; + + std::vector< Ref > resultPoints(2); + Ref resultPoint1(new OneDResultPoint(left, (float) rowNumber)); + Ref resultPoint2(new OneDResultPoint(right, (float) rowNumber)); + resultPoints[0] = resultPoint1; + resultPoints[1] = resultPoint2; + + ArrayRef resultBytes(1); + + if (startGuardRange!=NULL) { + delete [] startGuardRange; + startGuardRange = NULL; + } + if (endRange!=NULL) { + delete [] endRange; + endRange = NULL; + } + + Ref res(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat())); + return res; + } + + int* UPCEANReader::findStartGuardPattern(Ref row){ + bool foundStart = false; + + int* startRange = NULL; + int nextStart = 0; + while (!foundStart) { + startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN, sizeof(START_END_PATTERN)/sizeof(int)); + int start = startRange[0]; + nextStart = startRange[1]; + // Make sure there is a quiet zone at least as big as the start pattern before the barcode. + // If this check would run off the left edge of the image, do not accept this barcode, + // as it is very likely to be a false positive. + int quietStart = start - (nextStart - start); + if (quietStart >= 0) { + foundStart = row->isRange(quietStart, start, false); + } + } + return startRange; + } + + int* UPCEANReader::findGuardPattern(Ref row, int rowOffset, bool whiteFirst, const int pattern[], int patternLen){ + int patternLength = patternLen; + + //int counters[patternLength]; + int* counters = new int(patternLength); + int countersCount = sizeof(counters)/sizeof(int); + for (int i=0; igetSize(); + bool isWhite = false; + while (rowOffset < width) { + isWhite = !row->get(rowOffset); + if (whiteFirst == isWhite) { + break; + } + rowOffset++; + } + + int counterPosition = 0; + int patternStart = rowOffset; + for (int x = rowOffset; x < width; x++) { + bool pixel = row->get(x); + if (pixel ^ isWhite) { + counters[counterPosition]++; + } else { + if (counterPosition == patternLength - 1) { + if (patternMatchVariance(counters, countersCount, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { + int* resultValue = new int[2]; + resultValue[0] = patternStart; + resultValue[1] = x; + return resultValue; + } + patternStart += counters[0] + counters[1]; + for (int y = 2; y < patternLength; y++) { + counters[y - 2] = counters[y]; + } + counters[patternLength - 2] = 0; + counters[patternLength - 1] = 0; + counterPosition--; + } else { + counterPosition++; + } + counters[counterPosition] = 1; + isWhite = !isWhite; + } + } + delete counters; + throw ReaderException("findGuardPattern"); + } + + int* UPCEANReader::decodeEnd(Ref row, int endStart){ + return findGuardPattern(row, endStart, false, START_END_PATTERN, sizeof(START_END_PATTERN)/sizeof(int)); + } + +// int UPCEANReader::decodeDigit(Ref row, int counters[], int countersLen, int rowOffset, int** patterns/*[][]*/, int paterns1Len, int paterns2Len) + int UPCEANReader::decodeDigit(Ref row, int counters[], int countersLen, int rowOffset, UPC_EAN_PATTERNS paternType){ + recordPattern(row, rowOffset, counters, countersLen); + int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept + int bestMatch = -1; + + int max = 0; + switch (paternType) { + case UPC_EAN_PATTERNS_L_PATTERNS: + max = L_PATTERNS_LEN; + for (int i = 0; i < max; i++) { + //int pattern[countersLen]; + int* pattern = new int(countersLen); + for(int j = 0; j< countersLen; j++){ + pattern[j] = L_PATTERNS[i][j]; + } + + int variance = patternMatchVariance(counters, countersLen, pattern, MAX_INDIVIDUAL_VARIANCE); + if (variance < bestVariance) { + bestVariance = variance; + bestMatch = i; + } + delete pattern; + } + break; + case UPC_EAN_PATTERNS_L_AND_G_PATTERNS: + max = L_AND_G_PATTERNS_LEN; + for (int i = 0; i < max; i++) { + //int pattern[countersLen]; + int* pattern = new int(countersLen); + for(int j = 0; j< countersLen; j++){ + pattern[j] = L_AND_G_PATTERNS[i][j]; + } + + int variance = patternMatchVariance(counters, countersLen, pattern, MAX_INDIVIDUAL_VARIANCE); + if (variance < bestVariance) { + bestVariance = variance; + bestMatch = i; + } + delete pattern; + } + break; + default: + break; + } + if (bestMatch >= 0) { + return bestMatch; + } else { + throw ReaderException("UPCEANReader::decodeDigit: No best mach"); + } + } + + + /** + * @return {@link #checkStandardUPCEANChecksum(String)} + */ + bool UPCEANReader::checkChecksum(std::string s){ + return checkStandardUPCEANChecksum(s); + } + + /** + * Computes the UPC/EAN checksum on a string of digits, and reports + * whether the checksum is correct or not. + * + * @param s string of digits to check + * @return true iff string of digits passes the UPC/EAN checksum algorithm + * @throws ReaderException if the string does not contain only digits + */ + bool UPCEANReader::checkStandardUPCEANChecksum(std::string s){ + int length = s.length(); + if (length == 0) { + return false; + } + + int sum = 0; + for (int i = length - 2; i >= 0; i -= 2) { + int digit = (int) s[i] - (int) '0'; + if (digit < 0 || digit > 9) { + throw ReaderException("checkStandardUPCEANChecksum"); + } + sum += digit; + } + sum *= 3; + for (int i = length - 1; i >= 0; i -= 2) { + int digit = (int) s[i] - (int) '0'; + if (digit < 0 || digit > 9) { + throw ReaderException("checkStandardUPCEANChecksum"); + } + sum += digit; + } + return sum % 10 == 0; + } + UPCEANReader::~UPCEANReader(){ + } + } +} diff --git a/symbian/QQrDecoder/zxing/oned/UPCEANReader.h b/symbian/QQrDecoder/zxing/oned/UPCEANReader.h new file mode 100644 index 000000000..3a39cf9db --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/UPCEANReader.h @@ -0,0 +1,65 @@ +/* + * UPCEANReader.h + * ZXing + * + * Created by Lukasz Warchol on 10-01-21. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +typedef enum UPC_EAN_PATTERNS { + UPC_EAN_PATTERNS_L_PATTERNS = 0, + UPC_EAN_PATTERNS_L_AND_G_PATTERNS +} UPC_EAN_PATTERNS; +namespace zxing { + namespace oned { + class UPCEANReader : public OneDReader { + + private: + static const int MAX_AVG_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.42f); + static const int MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.7f); + + static int* findStartGuardPattern(Ref row); //throws ReaderException + + int* decodeEnd(Ref row, int endStart); //throws ReaderException + + static bool checkStandardUPCEANChecksum(std::string s); //throws ReaderException + protected: + static int* findGuardPattern(Ref row, int rowOffset, bool whiteFirst, const int pattern[], int patternLen); //throws ReaderException + + virtual const int getMIDDLE_PATTERN_LEN(); + virtual const int* getMIDDLE_PATTERN(); + + public: + UPCEANReader(); + + virtual int decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString) = 0; //throws ReaderException + + Ref decodeRow(int rowNumber, Ref row); + Ref decodeRow(int rowNumber, Ref row, int startGuardRange[]); + + static int decodeDigit(Ref row, int counters[], int countersLen, int rowOffset, UPC_EAN_PATTERNS paternType); //throws ReaderException + + bool checkChecksum(std::string s); //throws ReaderException + + virtual BarcodeFormat getBarcodeFormat() = 0; + virtual ~UPCEANReader(); + }; + } +} diff --git a/symbian/QQrDecoder/zxing/oned/UPCEReader.cpp b/symbian/QQrDecoder/zxing/oned/UPCEReader.cpp new file mode 100644 index 000000000..3738d4c6b --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/UPCEReader.cpp @@ -0,0 +1,150 @@ +/* + * UPCEReader.cpp + * ZXing + * + * Created by Lukasz Warchol on 10-01-26. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "UPCEReader.h" +#include + +namespace zxing { + namespace oned { + + /** + * The pattern that marks the middle, and end, of a UPC-E pattern. + * There is no "second half" to a UPC-E barcode. + */ + static const int MIDDLE_END_PATTERN[6] = {1, 1, 1, 1, 1, 1}; + + /** + * See {@link #L_AND_G_PATTERNS}; these values similarly represent patterns of + * even-odd parity encodings of digits that imply both the number system (0 or 1) + * used, and the check digit. + */ + static const int NUMSYS_AND_CHECK_DIGIT_PATTERNS[2][10] = { + {0x38, 0x34, 0x32, 0x31, 0x2C, 0x26, 0x23, 0x2A, 0x29, 0x25}, + {0x07, 0x0B, 0x0D, 0x0E, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A} + }; + + UPCEReader::UPCEReader(){ + decodeMiddleCounters = new int[4]; + for (int i=0; i<4; i++) { + decodeMiddleCounters[i] = 0; + } + } + + int UPCEReader::decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString){ + int countersLen = 4; + int* counters = decodeMiddleCounters; + counters[0] = 0; + counters[1] = 0; + counters[2] = 0; + counters[3] = 0; + + + int end = row->getSize(); + int rowOffset = startRange[1]; + + int lgPatternFound = 0; + + for (int x = 0; x < 6 && rowOffset < end; x++) { + int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, UPC_EAN_PATTERNS_L_AND_G_PATTERNS); + resultString.append(1, (char) ('0' + bestMatch % 10)); + for (int i = 0; i < countersLen; i++) { + rowOffset += counters[i]; + } + if (bestMatch >= 10) { + lgPatternFound |= 1 << (5 - x); + } + } + + determineNumSysAndCheckDigit(resultString, lgPatternFound); + + return rowOffset; + } + + int* UPCEReader::decodeEnd(Ref row, int endStart){ + return findGuardPattern(row, endStart, true, MIDDLE_END_PATTERN, sizeof(MIDDLE_END_PATTERN)/sizeof(int)); + } + + bool UPCEReader::checkChecksum(std::string s){ + return UPCEANReader::checkChecksum(convertUPCEtoUPCA(s)); + } + + + void UPCEReader::determineNumSysAndCheckDigit(std::string& resultString, int lgPatternFound){ + for (int numSys = 0; numSys <= 1; numSys++) { + for (int d = 0; d < 10; d++) { + if (lgPatternFound == NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) { + resultString.insert((size_t)0, (size_t)1, (char) ('0' + numSys)); + resultString.append(1, (char) ('0' + d)); + return; + } + } + } + throw ReaderException("determineNumSysAndCheckDigit exception"); + } + + /** + * Expands a UPC-E value back into its full, equivalent UPC-A code value. + * + * @param upce UPC-E code as string of digits + * @return equivalent UPC-A code as string of digits + */ + std::string& UPCEReader::convertUPCEtoUPCA(std::string upce) { + std::string result; + result.append(1, upce[0]); + char lastChar = upce[6]; + switch (lastChar) { + case '0': + case '1': + case '2': + result.append(upce.substr(1,2)); + result.append(1, lastChar); + result.append("0000"); + result.append(upce.substr(3,3)); + break; + case '3': + result.append(upce.substr(1,3)); + result.append("00000"); + result.append(upce.substr(4,2)); + break; + case '4': + result.append(upce.substr(1,4)); + result.append("00000"); + result.append(1, upce[5]); + break; + default: + result.append(upce.substr(1,5)); + result.append("0000"); + result.append(1, lastChar); + break; + } + result.append(1, upce[7]); + std::string& returnResult = result; + return returnResult; + } + + + BarcodeFormat UPCEReader::getBarcodeFormat(){ + return BarcodeFormat_UPC_E; + } + UPCEReader::~UPCEReader(){ + delete [] decodeMiddleCounters; + } + } +} diff --git a/symbian/QQrDecoder/zxing/oned/UPCEReader.h b/symbian/QQrDecoder/zxing/oned/UPCEReader.h new file mode 100644 index 000000000..7daa87ac9 --- /dev/null +++ b/symbian/QQrDecoder/zxing/oned/UPCEReader.h @@ -0,0 +1,45 @@ +/* + * UPCEReader.h + * ZXing + * + * Created by Lukasz Warchol on 10-01-26. + * Copyright 2010 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace zxing { + namespace oned { + class UPCEReader : public UPCEANReader { + + private: + int* decodeMiddleCounters; + static void determineFirstDigit(std::string& resultString, int lgPatternFound); //throws ReaderException + static void determineNumSysAndCheckDigit(std::string& resultString, int lgPatternFound); //throws ReaderException + protected: + int* decodeEnd(Ref row, int endStart); //throws ReaderException + bool checkChecksum(std::string s); //throws ReaderException + public: + UPCEReader(); + + int decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString); //throws ReaderException + static std::string& convertUPCEtoUPCA(std::string upce); + + BarcodeFormat getBarcodeFormat(); + ~UPCEReader(); + }; + } +} diff --git a/symbian/QQrDecoder/zxing/qrcode/ErrorCorrectionLevel.cpp b/symbian/QQrDecoder/zxing/qrcode/ErrorCorrectionLevel.cpp new file mode 100644 index 000000000..9c610b526 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/ErrorCorrectionLevel.cpp @@ -0,0 +1,49 @@ +/* + * ErrorCorrectionLevel.cpp + * zxing + * + * Created by Christian Brunschen on 15/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { +namespace qrcode { + +ErrorCorrectionLevel::ErrorCorrectionLevel(int ordinal) : + ordinal_(ordinal) { +} + +int ErrorCorrectionLevel::ordinal() { + return ordinal_; +} + +ErrorCorrectionLevel& ErrorCorrectionLevel::forBits(int bits) { + if (bits < 0 || bits >= N_LEVELS) { + throw ReaderException("Ellegal error correction level bits"); + } + return *FOR_BITS[bits]; +} + +ErrorCorrectionLevel ErrorCorrectionLevel::L(0); +ErrorCorrectionLevel ErrorCorrectionLevel::M(1); +ErrorCorrectionLevel ErrorCorrectionLevel::Q(2); +ErrorCorrectionLevel ErrorCorrectionLevel::H(3); +ErrorCorrectionLevel *ErrorCorrectionLevel::FOR_BITS[] = { &M, &L, &H, &Q }; +int ErrorCorrectionLevel::N_LEVELS = 4; + +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/ErrorCorrectionLevel.h b/symbian/QQrDecoder/zxing/qrcode/ErrorCorrectionLevel.h new file mode 100644 index 000000000..426d204cf --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/ErrorCorrectionLevel.h @@ -0,0 +1,47 @@ +#ifndef __ERROR_CORRECTION_LEVEL_H__ +#define __ERROR_CORRECTION_LEVEL_H__ + +/* + * ErrorCorrectionLevel.h + * zxing + * + * Created by Christian Brunschen on 15/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { +namespace qrcode { + +class ErrorCorrectionLevel { +private: + int ordinal_; + ErrorCorrectionLevel(int ordinal); + static ErrorCorrectionLevel *FOR_BITS[]; + static int N_LEVELS; +public: + static ErrorCorrectionLevel L; + static ErrorCorrectionLevel M; + static ErrorCorrectionLevel Q; + static ErrorCorrectionLevel H; + + int ordinal(); + static ErrorCorrectionLevel& forBits(int bits); +}; +} +} + +#endif // __ERROR_CORRECTION_LEVEL_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/FormatInformation.cpp b/symbian/QQrDecoder/zxing/qrcode/FormatInformation.cpp new file mode 100644 index 000000000..41332fb0f --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/FormatInformation.cpp @@ -0,0 +1,108 @@ +/* + * FormatInformation.cpp + * zxing + * + * Created by Christian Brunschen on 18/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace zxing { +namespace qrcode { + +using namespace std; + +int FormatInformation::FORMAT_INFO_MASK_QR = 0x5412; +int FormatInformation::FORMAT_INFO_DECODE_LOOKUP[][2] = { { 0x5412, 0x00 }, { 0x5125, 0x01 }, { 0x5E7C, 0x02 }, { + 0x5B4B, 0x03 }, { 0x45F9, 0x04 }, { 0x40CE, 0x05 }, { 0x4F97, 0x06 }, { 0x4AA0, 0x07 }, { 0x77C4, 0x08 }, { + 0x72F3, 0x09 }, { 0x7DAA, 0x0A }, { 0x789D, 0x0B }, { 0x662F, 0x0C }, { 0x6318, 0x0D }, { 0x6C41, 0x0E }, { + 0x6976, 0x0F }, { 0x1689, 0x10 }, { 0x13BE, 0x11 }, { 0x1CE7, 0x12 }, { 0x19D0, 0x13 }, { 0x0762, 0x14 }, { + 0x0255, 0x15 }, { 0x0D0C, 0x16 }, { 0x083B, 0x17 }, { 0x355F, 0x18 }, { 0x3068, 0x19 }, { 0x3F31, 0x1A }, { + 0x3A06, 0x1B }, { 0x24B4, 0x1C }, { 0x2183, 0x1D }, { 0x2EDA, 0x1E }, { 0x2BED, 0x1F }, +}; +int FormatInformation::N_FORMAT_INFO_DECODE_LOOKUPS = 32; + +int FormatInformation::BITS_SET_IN_HALF_BYTE[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; + +FormatInformation::FormatInformation(int formatInfo) : + errorCorrectionLevel_(ErrorCorrectionLevel::forBits((formatInfo >> 3) & 0x03)), dataMask_( + (unsigned char)(formatInfo & 0x07)) { +} + +ErrorCorrectionLevel& FormatInformation::getErrorCorrectionLevel() { + return errorCorrectionLevel_; +} + +unsigned char FormatInformation::getDataMask() { + return dataMask_; +} + +int FormatInformation::numBitsDiffering(unsigned int a, unsigned int b) { + a ^= b; + return BITS_SET_IN_HALF_BYTE[a & 0x0F] + BITS_SET_IN_HALF_BYTE[(a >> 4 & 0x0F)] + BITS_SET_IN_HALF_BYTE[(a >> 8 + & 0x0F)] + BITS_SET_IN_HALF_BYTE[(a >> 12 & 0x0F)] + BITS_SET_IN_HALF_BYTE[(a >> 16 & 0x0F)] + + BITS_SET_IN_HALF_BYTE[(a >> 20 & 0x0F)] + BITS_SET_IN_HALF_BYTE[(a >> 24 & 0x0F)] + + BITS_SET_IN_HALF_BYTE[(a >> 28 & 0x0F)]; +} + +Ref FormatInformation::decodeFormatInformation(int rawFormatInfo) { + Ref result(doDecodeFormatInformation(rawFormatInfo)); + if (result != 0) { + return result; + } + return doDecodeFormatInformation(rawFormatInfo ^ FORMAT_INFO_MASK_QR); +} +Ref FormatInformation::doDecodeFormatInformation(int rawFormatInfo) { + // Unmask: + int unmaskedFormatInfo = rawFormatInfo ^ FORMAT_INFO_MASK_QR; + // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing + int bestDifference = numeric_limits::max(); + int bestFormatInfo = 0; + for (int i = 0; i < N_FORMAT_INFO_DECODE_LOOKUPS; i++) { + int* decodeInfo = FORMAT_INFO_DECODE_LOOKUP[i]; + int targetInfo = decodeInfo[0]; + if (targetInfo == unmaskedFormatInfo) { + // Found an exact match + Ref result(new FormatInformation(decodeInfo[1])); + return result; + } + int bitsDifference = numBitsDiffering(unmaskedFormatInfo, targetInfo); + if (bitsDifference < bestDifference) { + bestFormatInfo = decodeInfo[1]; + bestDifference = bitsDifference; + } + } + if (bestDifference <= 3) { + Ref result(new FormatInformation(bestFormatInfo)); + return result; + } + Ref result; + return result; +} + +bool operator==(const FormatInformation &a, const FormatInformation &b) { + return &(a.errorCorrectionLevel_) == &(b.errorCorrectionLevel_) && a.dataMask_ == b.dataMask_; +} + +ostream& operator<<(ostream& out, const FormatInformation& fi) { + const FormatInformation *fip = &fi; + out << "FormatInformation @ " << fip; + return out; +} + +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/FormatInformation.h b/symbian/QQrDecoder/zxing/qrcode/FormatInformation.h new file mode 100644 index 000000000..cad027a01 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/FormatInformation.h @@ -0,0 +1,55 @@ +#ifndef __FORMAT_INFORMATION_H__ +#define __FORMAT_INFORMATION_H__ + +/* + * FormatInformation.h + * zxing + * + * Created by Christian Brunschen on 18/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace zxing { +namespace qrcode { + +class FormatInformation : public Counted { +private: + static int FORMAT_INFO_MASK_QR; + static int FORMAT_INFO_DECODE_LOOKUP[][2]; + static int N_FORMAT_INFO_DECODE_LOOKUPS; + static int BITS_SET_IN_HALF_BYTE[]; + + ErrorCorrectionLevel &errorCorrectionLevel_; + unsigned char dataMask_; + + FormatInformation(int formatInfo); + +public: + static int numBitsDiffering(unsigned int a, unsigned int b); + static Ref decodeFormatInformation(int rawFormatInfo); + static Ref doDecodeFormatInformation(int rawFormatInfo); + ErrorCorrectionLevel &getErrorCorrectionLevel(); + unsigned char getDataMask(); + friend bool operator==(const FormatInformation &a, const FormatInformation &b); + friend std::ostream& operator<<(std::ostream& out, const FormatInformation& fi); +}; +} +} + +#endif // __FORMAT_INFORMATION_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/QRCodeReader.cpp b/symbian/QQrDecoder/zxing/qrcode/QRCodeReader.cpp new file mode 100644 index 000000000..f3843eca1 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/QRCodeReader.cpp @@ -0,0 +1,84 @@ +/* + * QRCodeReader.cpp + * zxing + * + * Created by Christian Brunschen on 20/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +namespace zxing { + namespace qrcode { + + using namespace std; + + QRCodeReader::QRCodeReader() :decoder_() { + } + + Ref QRCodeReader::decode(Ref image) { +#ifdef DEBUG + cout << "decoding image " << image.object_ << ":\n" ; +#endif + + Detector detector(image->getBlackMatrix()); + + +#ifdef DEBUG + cout << "(1) created detector " << &detector << "\n" ; +#endif + + Ref detectorResult(detector.detect()); +#ifdef DEBUG + cout << "(2) detected, have detectorResult " << detectorResult.object_ << "\n" ; +#endif + + std::vector > points(detectorResult->getPoints()); + + +#ifdef DEBUG + cout << "(3) extracted points " << &points << "\n"; + cout << "found " << points.size() << " points:\n"; + for (size_t i = 0; i < points.size(); i++) { + cout << " " << points[i]->getX() << "," << points[i]->getY() << "\n"; + } + cout << "bits:\n"; + cout << *(detectorResult->getBits()) << "\n"; +#endif + + Ref decoderResult(decoder_.decode(detectorResult->getBits())); +#ifdef DEBUG + cout << "(4) decoded, have decoderResult " << decoderResult.object_ << "\n" ; +#endif + + Ref result( + new Result(decoderResult->getText(), decoderResult->getRawBytes(), points, BarcodeFormat_QR_CODE)); +#ifdef DEBUG + cout << "(5) created result " << result.object_ << ", returning\n" ; + + cout << "(6) text: " << result->getText()->getText() << std::endl; +#endif + + return result; + } + + QRCodeReader::~QRCodeReader() { + } + + } +} diff --git a/symbian/QQrDecoder/zxing/qrcode/QRCodeReader.h b/symbian/QQrDecoder/zxing/qrcode/QRCodeReader.h new file mode 100644 index 000000000..8257c7a39 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/QRCodeReader.h @@ -0,0 +1,43 @@ +#ifndef __QR_CODE_READER_H__ +#define __QR_CODE_READER_H__ + +/* + * QRCodeReader.h + * zxing + * + * Created by Christian Brunschen on 20/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace zxing { + namespace qrcode { + + class QRCodeReader : public Reader { + private: + Decoder decoder_; + + public: + QRCodeReader(); + virtual Ref decode(Ref image); + virtual ~QRCodeReader(); + + }; + } +} + +#endif // __QR_CODE_READER_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/Version.cpp b/symbian/QQrDecoder/zxing/qrcode/Version.cpp new file mode 100644 index 000000000..5e63c8271 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/Version.cpp @@ -0,0 +1,559 @@ +/* + * Version.cpp + * zxing + * + * Created by Christian Brunschen on 14/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +namespace zxing { +namespace qrcode { +using namespace std; + +ECB::ECB(int count, int dataCodewords) : + count_(count), dataCodewords_(dataCodewords) { +} + +int ECB::getCount() { + return count_; +} + +int ECB::getDataCodewords() { + return dataCodewords_; +} + +ECBlocks::ECBlocks(int ecCodewords, ECB *ecBlocks) : + ecCodewords_(ecCodewords) { + ecBlocks_.push_back(ecBlocks); +} + +ECBlocks::ECBlocks(int ecCodewords, ECB *ecBlocks1, ECB *ecBlocks2) : + ecCodewords_(ecCodewords) { + ecBlocks_.push_back(ecBlocks1); + ecBlocks_.push_back(ecBlocks2); +} + +int ECBlocks::getECCodewords() { + return ecCodewords_; +} + +std::vector& ECBlocks::getECBlocks() { + return ecBlocks_; +} + +ECBlocks::~ECBlocks() { + for (size_t i = 0; i < ecBlocks_.size(); i++) { + delete ecBlocks_[i]; + } +} + +unsigned int Version::VERSION_DECODE_INFO[] = { 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, 0x0C762, 0x0D847, 0x0E60D, + 0x0F928, 0x10B78, 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683, 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB, + 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B, 0x2542E, 0x26A64, + 0x27541, 0x28C69 + }; +int Version::N_VERSION_DECODE_INFOS = 34; +vector > Version::VERSIONS; +static int N_VERSIONS = Version::buildVersions(); + +int Version::getVersionNumber() { + return versionNumber_; +} + +valarray &Version::getAlignmentPatternCenters() { + return alignmentPatternCenters_; +} + +int Version::getTotalCodewords() { + return totalCodewords_; +} + +int Version::getDimensionForVersion() { + return 17 + 4 * versionNumber_; +} + +ECBlocks& Version::getECBlocksForLevel(ErrorCorrectionLevel &ecLevel) { + return *ecBlocks_[ecLevel.ordinal()]; +} + +Version *Version::getProvisionalVersionForDimension(int dimension) { + if (dimension % 4 != 1) { + throw ReaderException("Dimension must be 1 mod 4"); + } + return Version::getVersionForNumber((dimension - 17) >> 2); +} + +Version *Version::getVersionForNumber(int versionNumber) { + if (versionNumber < 1 || versionNumber > 40) { + throw ReaderException("versionNumber must be between 1 and 40"); + } + + return VERSIONS[versionNumber - 1]; +} + +Version::Version(int versionNumber, valarray *alignmentPatternCenters, ECBlocks *ecBlocks1, ECBlocks *ecBlocks2, + ECBlocks *ecBlocks3, ECBlocks *ecBlocks4) : + versionNumber_(versionNumber), alignmentPatternCenters_(*alignmentPatternCenters), ecBlocks_(4) { + ecBlocks_[0] = ecBlocks1; + ecBlocks_[1] = ecBlocks2; + ecBlocks_[2] = ecBlocks3; + ecBlocks_[3] = ecBlocks4; + + int total = 0; + int ecCodewords = ecBlocks1->getECCodewords(); + vector &ecbArray = ecBlocks1->getECBlocks(); + for (size_t i = 0; i < ecbArray.size(); i++) { + ECB *ecBlock = ecbArray[i]; + total += ecBlock->getCount() * (ecBlock->getDataCodewords() + ecCodewords); + } + totalCodewords_ = total; +} + +Version::~Version() { + delete &alignmentPatternCenters_; + for (size_t i = 0; i < ecBlocks_.size(); i++) { + delete ecBlocks_[i]; + } +} + +Version *Version::decodeVersionInformation(unsigned int versionBits) { + int bestDifference = numeric_limits::max(); + size_t bestVersion = 0; + for (int i = 0; i < N_VERSION_DECODE_INFOS; i++) { + unsigned targetVersion = VERSION_DECODE_INFO[i]; + // Do the version info bits match exactly? done. + if (targetVersion == versionBits) { + return getVersionForNumber(i + 7); + } + // Otherwise see if this is the closest to a real version info bit + // string we have seen so far + int bitsDifference = FormatInformation::numBitsDiffering(versionBits, targetVersion); + if (bitsDifference < bestDifference) { + bestVersion = i + 7; + bestDifference = bitsDifference; + } + } + // We can tolerate up to 3 bits of error since no two version info codewords will + // differ in less than 4 bits. + if (bestDifference <= 3) { + return getVersionForNumber(bestVersion); + } + // If we didn't find a close enough match, fail + return 0; +} + +Ref Version::buildFunctionPattern() { + int dimension = getDimensionForVersion(); + Ref functionPattern(new BitMatrix(dimension)); + + + // Top left finder pattern + separator + format + functionPattern->setRegion(0, 0, 9, 9); + // Top right finder pattern + separator + format + functionPattern->setRegion(dimension - 8, 0, 8, 9); + // Bottom left finder pattern + separator + format + functionPattern->setRegion(0, dimension - 8, 9, 8); + + + // Alignment patterns + size_t max = alignmentPatternCenters_.size(); + for (size_t x = 0; x < max; x++) { + int i = alignmentPatternCenters_[x] - 2; + for (size_t y = 0; y < max; y++) { + if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) { + // No alignment patterns near the three finder patterns + continue; + } + functionPattern->setRegion(alignmentPatternCenters_[y] - 2, i, 5, 5); + } + } + + // Vertical timing pattern + functionPattern->setRegion(6, 9, 1, dimension - 17); + // Horizontal timing pattern + functionPattern->setRegion(9, 6, dimension - 17, 1); + + if (versionNumber_ > 6) { + // Version info, top right + functionPattern->setRegion(dimension - 11, 0, 3, 6); + // Version info, bottom left + functionPattern->setRegion(0, dimension - 11, 6, 3); + } + + + //#ifdef DEBUG + // cout << "version " << versionNumber_ << " built function pattern:\n"; + // cout << *functionPattern; + //#endif + + return functionPattern; +} + +static valarray *intArray(size_t n...) { + va_list ap; + va_start(ap, n); + valarray *result = new valarray(n); + for (size_t i = 0; i < n; i++) { + (*result)[i] = va_arg(ap, int); + } + va_end(ap); + return result; +} + +int Version::buildVersions() { + VERSIONS.push_back(Ref(new Version(1, intArray(0), + new ECBlocks(7, new ECB(1, 19)), + new ECBlocks(10, new ECB(1, 16)), + new ECBlocks(13, new ECB(1, 13)), + new ECBlocks(17, new ECB(1, 9))))); + VERSIONS.push_back(Ref(new Version(2, intArray(2, 6, 18), + new ECBlocks(10, new ECB(1, 34)), + new ECBlocks(16, new ECB(1, 28)), + new ECBlocks(22, new ECB(1, 22)), + new ECBlocks(28, new ECB(1, 16))))); + VERSIONS.push_back(Ref(new Version(3, intArray(2, 6, 22), + new ECBlocks(15, new ECB(1, 55)), + new ECBlocks(26, new ECB(1, 44)), + new ECBlocks(18, new ECB(2, 17)), + new ECBlocks(22, new ECB(2, 13))))); + VERSIONS.push_back(Ref(new Version(4, intArray(2, 6, 26), + new ECBlocks(20, new ECB(1, 80)), + new ECBlocks(18, new ECB(2, 32)), + new ECBlocks(26, new ECB(2, 24)), + new ECBlocks(16, new ECB(4, 9))))); + VERSIONS.push_back(Ref(new Version(5, intArray(2, 6, 30), + new ECBlocks(26, new ECB(1, 108)), + new ECBlocks(24, new ECB(2, 43)), + new ECBlocks(18, new ECB(2, 15), + new ECB(2, 16)), + new ECBlocks(22, new ECB(2, 11), + new ECB(2, 12))))); + VERSIONS.push_back(Ref(new Version(6, intArray(2, 6, 34), + new ECBlocks(18, new ECB(2, 68)), + new ECBlocks(16, new ECB(4, 27)), + new ECBlocks(24, new ECB(4, 19)), + new ECBlocks(28, new ECB(4, 15))))); + VERSIONS.push_back(Ref(new Version(7, intArray(3, 6, 22, 38), + new ECBlocks(20, new ECB(2, 78)), + new ECBlocks(18, new ECB(4, 31)), + new ECBlocks(18, new ECB(2, 14), + new ECB(4, 15)), + new ECBlocks(26, new ECB(4, 13), + new ECB(1, 14))))); + VERSIONS.push_back(Ref(new Version(8, intArray(3, 6, 24, 42), + new ECBlocks(24, new ECB(2, 97)), + new ECBlocks(22, new ECB(2, 38), + new ECB(2, 39)), + new ECBlocks(22, new ECB(4, 18), + new ECB(2, 19)), + new ECBlocks(26, new ECB(4, 14), + new ECB(2, 15))))); + VERSIONS.push_back(Ref(new Version(9, intArray(3, 6, 26, 46), + new ECBlocks(30, new ECB(2, 116)), + new ECBlocks(22, new ECB(3, 36), + new ECB(2, 37)), + new ECBlocks(20, new ECB(4, 16), + new ECB(4, 17)), + new ECBlocks(24, new ECB(4, 12), + new ECB(4, 13))))); + VERSIONS.push_back(Ref(new Version(10, intArray(3, 6, 28, 50), + new ECBlocks(18, new ECB(2, 68), + new ECB(2, 69)), + new ECBlocks(26, new ECB(4, 43), + new ECB(1, 44)), + new ECBlocks(24, new ECB(6, 19), + new ECB(2, 20)), + new ECBlocks(28, new ECB(6, 15), + new ECB(2, 16))))); + VERSIONS.push_back(Ref(new Version(11, intArray(3, 6, 30, 54), + new ECBlocks(20, new ECB(4, 81)), + new ECBlocks(30, new ECB(1, 50), + new ECB(4, 51)), + new ECBlocks(28, new ECB(4, 22), + new ECB(4, 23)), + new ECBlocks(24, new ECB(3, 12), + new ECB(8, 13))))); + VERSIONS.push_back(Ref(new Version(12, intArray(3, 6, 32, 58), + new ECBlocks(24, new ECB(2, 92), + new ECB(2, 93)), + new ECBlocks(22, new ECB(6, 36), + new ECB(2, 37)), + new ECBlocks(26, new ECB(4, 20), + new ECB(6, 21)), + new ECBlocks(28, new ECB(7, 14), + new ECB(4, 15))))); + VERSIONS.push_back(Ref(new Version(13, intArray(3, 6, 34, 62), + new ECBlocks(26, new ECB(4, 107)), + new ECBlocks(22, new ECB(8, 37), + new ECB(1, 38)), + new ECBlocks(24, new ECB(8, 20), + new ECB(4, 21)), + new ECBlocks(22, new ECB(12, 11), + new ECB(4, 12))))); + VERSIONS.push_back(Ref(new Version(14, intArray(4, 6, 26, 46, 66), + new ECBlocks(30, new ECB(3, 115), + new ECB(1, 116)), + new ECBlocks(24, new ECB(4, 40), + new ECB(5, 41)), + new ECBlocks(20, new ECB(11, 16), + new ECB(5, 17)), + new ECBlocks(24, new ECB(11, 12), + new ECB(5, 13))))); + VERSIONS.push_back(Ref(new Version(15, intArray(4, 6, 26, 48, 70), + new ECBlocks(22, new ECB(5, 87), + new ECB(1, 88)), + new ECBlocks(24, new ECB(5, 41), + new ECB(5, 42)), + new ECBlocks(30, new ECB(5, 24), + new ECB(7, 25)), + new ECBlocks(24, new ECB(11, 12), + new ECB(7, 13))))); + VERSIONS.push_back(Ref(new Version(16, intArray(4, 6, 26, 50, 74), + new ECBlocks(24, new ECB(5, 98), + new ECB(1, 99)), + new ECBlocks(28, new ECB(7, 45), + new ECB(3, 46)), + new ECBlocks(24, new ECB(15, 19), + new ECB(2, 20)), + new ECBlocks(30, new ECB(3, 15), + new ECB(13, 16))))); + VERSIONS.push_back(Ref(new Version(17, intArray(4, 6, 30, 54, 78), + new ECBlocks(28, new ECB(1, 107), + new ECB(5, 108)), + new ECBlocks(28, new ECB(10, 46), + new ECB(1, 47)), + new ECBlocks(28, new ECB(1, 22), + new ECB(15, 23)), + new ECBlocks(28, new ECB(2, 14), + new ECB(17, 15))))); + VERSIONS.push_back(Ref(new Version(18, intArray(4, 6, 30, 56, 82), + new ECBlocks(30, new ECB(5, 120), + new ECB(1, 121)), + new ECBlocks(26, new ECB(9, 43), + new ECB(4, 44)), + new ECBlocks(28, new ECB(17, 22), + new ECB(1, 23)), + new ECBlocks(28, new ECB(2, 14), + new ECB(19, 15))))); + VERSIONS.push_back(Ref(new Version(19, intArray(4, 6, 30, 58, 86), + new ECBlocks(28, new ECB(3, 113), + new ECB(4, 114)), + new ECBlocks(26, new ECB(3, 44), + new ECB(11, 45)), + new ECBlocks(26, new ECB(17, 21), + new ECB(4, 22)), + new ECBlocks(26, new ECB(9, 13), + new ECB(16, 14))))); + VERSIONS.push_back(Ref(new Version(20, intArray(4, 6, 34, 62, 90), + new ECBlocks(28, new ECB(3, 107), + new ECB(5, 108)), + new ECBlocks(26, new ECB(3, 41), + new ECB(13, 42)), + new ECBlocks(30, new ECB(15, 24), + new ECB(5, 25)), + new ECBlocks(28, new ECB(15, 15), + new ECB(10, 16))))); + VERSIONS.push_back(Ref(new Version(21, intArray(5, 6, 28, 50, 72, 94), + new ECBlocks(28, new ECB(4, 116), + new ECB(4, 117)), + new ECBlocks(26, new ECB(17, 42)), + new ECBlocks(28, new ECB(17, 22), + new ECB(6, 23)), + new ECBlocks(30, new ECB(19, 16), + new ECB(6, 17))))); + VERSIONS.push_back(Ref(new Version(22, intArray(5, 6, 26, 50, 74, 98), + new ECBlocks(28, new ECB(2, 111), + new ECB(7, 112)), + new ECBlocks(28, new ECB(17, 46)), + new ECBlocks(30, new ECB(7, 24), + new ECB(16, 25)), + new ECBlocks(24, new ECB(34, 13))))); + VERSIONS.push_back(Ref(new Version(23, intArray(5, 6, 30, 54, 74, 102), + new ECBlocks(30, new ECB(4, 121), + new ECB(5, 122)), + new ECBlocks(28, new ECB(4, 47), + new ECB(14, 48)), + new ECBlocks(30, new ECB(11, 24), + new ECB(14, 25)), + new ECBlocks(30, new ECB(16, 15), + new ECB(14, 16))))); + VERSIONS.push_back(Ref(new Version(24, intArray(5, 6, 28, 54, 80, 106), + new ECBlocks(30, new ECB(6, 117), + new ECB(4, 118)), + new ECBlocks(28, new ECB(6, 45), + new ECB(14, 46)), + new ECBlocks(30, new ECB(11, 24), + new ECB(16, 25)), + new ECBlocks(30, new ECB(30, 16), + new ECB(2, 17))))); + VERSIONS.push_back(Ref(new Version(25, intArray(5, 6, 32, 58, 84, 110), + new ECBlocks(26, new ECB(8, 106), + new ECB(4, 107)), + new ECBlocks(28, new ECB(8, 47), + new ECB(13, 48)), + new ECBlocks(30, new ECB(7, 24), + new ECB(22, 25)), + new ECBlocks(30, new ECB(22, 15), + new ECB(13, 16))))); + VERSIONS.push_back(Ref(new Version(26, intArray(5, 6, 30, 58, 86, 114), + new ECBlocks(28, new ECB(10, 114), + new ECB(2, 115)), + new ECBlocks(28, new ECB(19, 46), + new ECB(4, 47)), + new ECBlocks(28, new ECB(28, 22), + new ECB(6, 23)), + new ECBlocks(30, new ECB(33, 16), + new ECB(4, 17))))); + VERSIONS.push_back(Ref(new Version(27, intArray(5, 6, 34, 62, 90, 118), + new ECBlocks(30, new ECB(8, 122), + new ECB(4, 123)), + new ECBlocks(28, new ECB(22, 45), + new ECB(3, 46)), + new ECBlocks(30, new ECB(8, 23), + new ECB(26, 24)), + new ECBlocks(30, new ECB(12, 15), + new ECB(28, 16))))); + VERSIONS.push_back(Ref(new Version(28, intArray(6, 6, 26, 50, 74, 98, 122), + new ECBlocks(30, new ECB(3, 117), + new ECB(10, 118)), + new ECBlocks(28, new ECB(3, 45), + new ECB(23, 46)), + new ECBlocks(30, new ECB(4, 24), + new ECB(31, 25)), + new ECBlocks(30, new ECB(11, 15), + new ECB(31, 16))))); + VERSIONS.push_back(Ref(new Version(29, intArray(6, 6, 30, 54, 78, 102, 126), + new ECBlocks(30, new ECB(7, 116), + new ECB(7, 117)), + new ECBlocks(28, new ECB(21, 45), + new ECB(7, 46)), + new ECBlocks(30, new ECB(1, 23), + new ECB(37, 24)), + new ECBlocks(30, new ECB(19, 15), + new ECB(26, 16))))); + VERSIONS.push_back(Ref(new Version(30, intArray(6, 6, 26, 52, 78, 104, 130), + new ECBlocks(30, new ECB(5, 115), + new ECB(10, 116)), + new ECBlocks(28, new ECB(19, 47), + new ECB(10, 48)), + new ECBlocks(30, new ECB(15, 24), + new ECB(25, 25)), + new ECBlocks(30, new ECB(23, 15), + new ECB(25, 16))))); + VERSIONS.push_back(Ref(new Version(31, intArray(6, 6, 30, 56, 82, 108, 134), + new ECBlocks(30, new ECB(13, 115), + new ECB(3, 116)), + new ECBlocks(28, new ECB(2, 46), + new ECB(29, 47)), + new ECBlocks(30, new ECB(42, 24), + new ECB(1, 25)), + new ECBlocks(30, new ECB(23, 15), + new ECB(28, 16))))); + VERSIONS.push_back(Ref(new Version(32, intArray(6, 6, 34, 60, 86, 112, 138), + new ECBlocks(30, new ECB(17, 115)), + new ECBlocks(28, new ECB(10, 46), + new ECB(23, 47)), + new ECBlocks(30, new ECB(10, 24), + new ECB(35, 25)), + new ECBlocks(30, new ECB(19, 15), + new ECB(35, 16))))); + VERSIONS.push_back(Ref(new Version(33, intArray(6, 6, 30, 58, 86, 114, 142), + new ECBlocks(30, new ECB(17, 115), + new ECB(1, 116)), + new ECBlocks(28, new ECB(14, 46), + new ECB(21, 47)), + new ECBlocks(30, new ECB(29, 24), + new ECB(19, 25)), + new ECBlocks(30, new ECB(11, 15), + new ECB(46, 16))))); + VERSIONS.push_back(Ref(new Version(34, intArray(6, 6, 34, 62, 90, 118, 146), + new ECBlocks(30, new ECB(13, 115), + new ECB(6, 116)), + new ECBlocks(28, new ECB(14, 46), + new ECB(23, 47)), + new ECBlocks(30, new ECB(44, 24), + new ECB(7, 25)), + new ECBlocks(30, new ECB(59, 16), + new ECB(1, 17))))); + VERSIONS.push_back(Ref(new Version(35, intArray(7, 6, 30, 54, 78, + 102, 126, 150), + new ECBlocks(30, new ECB(12, 121), + new ECB(7, 122)), + new ECBlocks(28, new ECB(12, 47), + new ECB(26, 48)), + new ECBlocks(30, new ECB(39, 24), + new ECB(14, 25)), + new ECBlocks(30, new ECB(22, 15), + new ECB(41, 16))))); + VERSIONS.push_back(Ref(new Version(36, intArray(7, 6, 24, 50, 76, + 102, 128, 154), + new ECBlocks(30, new ECB(6, 121), + new ECB(14, 122)), + new ECBlocks(28, new ECB(6, 47), + new ECB(34, 48)), + new ECBlocks(30, new ECB(46, 24), + new ECB(10, 25)), + new ECBlocks(30, new ECB(2, 15), + new ECB(64, 16))))); + VERSIONS.push_back(Ref(new Version(37, intArray(7, 6, 28, 54, 80, + 106, 132, 158), + new ECBlocks(30, new ECB(17, 122), + new ECB(4, 123)), + new ECBlocks(28, new ECB(29, 46), + new ECB(14, 47)), + new ECBlocks(30, new ECB(49, 24), + new ECB(10, 25)), + new ECBlocks(30, new ECB(24, 15), + new ECB(46, 16))))); + VERSIONS.push_back(Ref(new Version(38, intArray(7, 6, 32, 58, 84, + 110, 136, 162), + new ECBlocks(30, new ECB(4, 122), + new ECB(18, 123)), + new ECBlocks(28, new ECB(13, 46), + new ECB(32, 47)), + new ECBlocks(30, new ECB(48, 24), + new ECB(14, 25)), + new ECBlocks(30, new ECB(42, 15), + new ECB(32, 16))))); + VERSIONS.push_back(Ref(new Version(39, intArray(7, 6, 26, 54, 82, + 110, 138, 166), + new ECBlocks(30, new ECB(20, 117), + new ECB(4, 118)), + new ECBlocks(28, new ECB(40, 47), + new ECB(7, 48)), + new ECBlocks(30, new ECB(43, 24), + new ECB(22, 25)), + new ECBlocks(30, new ECB(10, 15), + new ECB(67, 16))))); + VERSIONS.push_back(Ref(new Version(40, intArray(7, 6, 30, 58, 86, + 114, 142, 170), + new ECBlocks(30, new ECB(19, 118), + new ECB(6, 119)), + new ECBlocks(28, new ECB(18, 47), + new ECB(31, 48)), + new ECBlocks(30, new ECB(34, 24), + new ECB(34, 25)), + new ECBlocks(30, new ECB(20, 15), + new ECB(61, 16))))); + return VERSIONS.size(); +} +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/Version.h b/symbian/QQrDecoder/zxing/qrcode/Version.h new file mode 100644 index 000000000..181bd98fe --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/Version.h @@ -0,0 +1,87 @@ +#ifndef __VERSION_H__ +#define __VERSION_H__ + +/* + * Version.h + * zxing + * + * Created by Christian Brunschen on 14/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace zxing { +namespace qrcode { + +class ECB { +private: + int count_; + int dataCodewords_; +public: + ECB(int count, int dataCodewords); + int getCount(); + int getDataCodewords(); +}; + +class ECBlocks { +private: + int ecCodewords_; + std::vector ecBlocks_; +public: + ECBlocks(int ecCodewords, ECB *ecBlocks); + ECBlocks(int ecCodewords, ECB *ecBlocks1, ECB *ecBlocks2); + int getECCodewords(); + std::vector& getECBlocks(); + ~ECBlocks(); +}; + +class Version : public Counted { + +private: + int versionNumber_; + std::valarray &alignmentPatternCenters_; + std::vector ecBlocks_; + int totalCodewords_; + Version(int versionNumber, std::valarray *alignmentPatternCenters, ECBlocks *ecBlocks1, ECBlocks *ecBlocks2, + ECBlocks *ecBlocks3, ECBlocks *ecBlocks4); + +public: + static unsigned int VERSION_DECODE_INFO[]; + static int N_VERSION_DECODE_INFOS; + static std::vector > VERSIONS; + + ~Version(); + int getVersionNumber(); + std::valarray &getAlignmentPatternCenters(); + int getTotalCodewords(); + int getDimensionForVersion(); + ECBlocks &getECBlocksForLevel(ErrorCorrectionLevel &ecLevel); + static Version *getProvisionalVersionForDimension(int dimension); + static Version *getVersionForNumber(int versionNumber); + static Version *decodeVersionInformation(unsigned int versionBits); + Ref buildFunctionPattern(); + static int buildVersions(); +}; +} +} + +#endif // __VERSION_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/decoder/BitMatrixParser.cpp b/symbian/QQrDecoder/zxing/qrcode/decoder/BitMatrixParser.cpp new file mode 100644 index 000000000..e4ef5e2d8 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/decoder/BitMatrixParser.cpp @@ -0,0 +1,191 @@ +/* + * BitMatrixParser.cpp + * zxing + * + * Created by Christian Brunschen on 20/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + + +namespace zxing { +namespace qrcode { + +int BitMatrixParser::copyBit(size_t x, size_t y, int versionBits) { + return bitMatrix_->get(x, y) ? (versionBits << 1) | 0x1 : versionBits << 1; +} + +BitMatrixParser::BitMatrixParser(Ref bitMatrix) : + bitMatrix_(bitMatrix), parsedVersion_(0), parsedFormatInfo_() { + size_t dimension = bitMatrix->getDimension(); + if ((dimension < 21) || (dimension & 0x03) != 1) { + throw ReaderException("Dimension must be 1 mod 4 and >= 21"); + } +} + +Ref BitMatrixParser::readFormatInformation() { + if (parsedFormatInfo_ != 0) { + return parsedFormatInfo_; + } + + // Read top-left format info bits + int formatInfoBits = 0; + for (int x = 0; x < 6; x++) { + formatInfoBits = copyBit(x, 8, formatInfoBits); + } + // .. and skip a bit in the timing pattern ... + formatInfoBits = copyBit(7, 8, formatInfoBits); + formatInfoBits = copyBit(8, 8, formatInfoBits); + formatInfoBits = copyBit(8, 7, formatInfoBits); + // .. and skip a bit in the timing pattern ... + for (int y = 5; y >= 0; y--) { + formatInfoBits = copyBit(8, y, formatInfoBits); + } + + parsedFormatInfo_ = FormatInformation::decodeFormatInformation(formatInfoBits); + if (parsedFormatInfo_ != 0) { + return parsedFormatInfo_; + } + + // Hmm, failed. Try the top-right/bottom-left pattern + int dimension = bitMatrix_->getDimension(); + formatInfoBits = 0; + int yMin = dimension - 8; + for (int y = dimension - 1; y >= yMin; y--) { + formatInfoBits = copyBit(8, y, formatInfoBits); + } + for (int x = dimension - 7; x < dimension; x++) { + formatInfoBits = copyBit(x, 8, formatInfoBits); + } + + parsedFormatInfo_ = FormatInformation::decodeFormatInformation(formatInfoBits); + if (parsedFormatInfo_ != 0) { + return parsedFormatInfo_; + } + throw ReaderException("Could not decode format information"); +} + +Version *BitMatrixParser::readVersion() { + if (parsedVersion_ != 0) { + return parsedVersion_; + } + + size_t dimension = bitMatrix_->getDimension(); + + int provisionalVersion = (dimension - 17) >> 2; + if (provisionalVersion <= 6) { + return Version::getVersionForNumber(provisionalVersion); + } + + // Read top-right version info: 3 wide by 6 tall + int versionBits = 0; + for (int y = 5; y >= 0; y--) { + int xMin = dimension - 11; + for (int x = dimension - 9; x >= xMin; x--) { + versionBits = copyBit(x, y, versionBits); + } + } + + parsedVersion_ = Version::decodeVersionInformation(versionBits); + if (parsedVersion_ != 0) { + return parsedVersion_; + } + + // Hmm, failed. Try bottom left: 6 wide by 3 tall + versionBits = 0; + for (int x = 5; x >= 0; x--) { + int yMin = dimension - 11; + for (int y = dimension - 9; y >= yMin; y--) { + versionBits = copyBit(x, y, versionBits); + } + } + + parsedVersion_ = Version::decodeVersionInformation(versionBits); + if (parsedVersion_ != 0) { + return parsedVersion_; + } + throw ReaderException("Could not decode version"); +} + +ArrayRef BitMatrixParser::readCodewords() { + Ref formatInfo = readFormatInformation(); + Version *version = readVersion(); + + + // cerr << *bitMatrix_ << endl; + // cerr << bitMatrix_->getDimension() << endl; + + // Get the data mask for the format used in this QR Code. This will exclude + // some bits from reading as we wind through the bit matrix. + DataMask &dataMask = DataMask::forReference((int)formatInfo->getDataMask()); + // cout << (int)formatInfo->getDataMask() << endl; + int dimension = bitMatrix_->getDimension(); + dataMask.unmaskBitMatrix(*bitMatrix_, dimension); + + + // cerr << *bitMatrix_ << endl; + // cerr << version->getTotalCodewords() << endl; + + Ref functionPattern = version->buildFunctionPattern(); + + + // cout << *functionPattern << endl; + + bool readingUp = true; + ArrayRef result(version->getTotalCodewords()); + int resultOffset = 0; + int currentByte = 0; + int bitsRead = 0; + // Read columns in pairs, from right to left + for (int x = dimension - 1; x > 0; x -= 2) { + if (x == 6) { + // Skip whole column with vertical alignment pattern; + // saves time and makes the other code proceed more cleanly + x--; + } + // Read alternatingly from bottom to top then top to bottom + for (int count = 0; count < dimension; count++) { + int y = readingUp ? dimension - 1 - count : count; + for (int col = 0; col < 2; col++) { + // Ignore bits covered by the function pattern + if (!functionPattern->get(x - col, y)) { + // Read a bit + bitsRead++; + currentByte <<= 1; + if (bitMatrix_->get(x - col, y)) { + currentByte |= 1; + } + // If we've made a whole byte, save it off + if (bitsRead == 8) { + result[resultOffset++] = (unsigned char)currentByte; + bitsRead = 0; + currentByte = 0; + } + } + } + } + readingUp = !readingUp; // switch directions + } + + if (resultOffset != version->getTotalCodewords()) { + throw ReaderException("Did not read all codewords"); + } + return result; +} + +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/decoder/BitMatrixParser.h b/symbian/QQrDecoder/zxing/qrcode/decoder/BitMatrixParser.h new file mode 100644 index 000000000..824556b93 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/decoder/BitMatrixParser.h @@ -0,0 +1,52 @@ +#ifndef __BIT_MATRIX_PARSER_H__ +#define __BIT_MATRIX_PARSER_H__ + +/* + * BitMatrixParser.h + * zxing + * + * Created by Christian Brunschen on 20/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +namespace zxing { +namespace qrcode { + +class BitMatrixParser : public Counted { +private: + Ref bitMatrix_; + Version *parsedVersion_; + Ref parsedFormatInfo_; + + int copyBit(size_t x, size_t y, int versionBits); + +public: + BitMatrixParser(Ref bitMatrix); + Ref readFormatInformation(); + Version *readVersion(); + ArrayRef readCodewords(); +}; + +} +} + +#endif // __BIT_MATRIX_PARSER_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/decoder/DataBlock.cpp b/symbian/QQrDecoder/zxing/qrcode/decoder/DataBlock.cpp new file mode 100644 index 000000000..1ea6602d7 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/decoder/DataBlock.cpp @@ -0,0 +1,118 @@ +/* + * DataBlock.cpp + * zxing + * + * Created by Christian Brunschen on 19/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace zxing { +namespace qrcode { + +using namespace std; + +DataBlock::DataBlock(int numDataCodewords, ArrayRef codewords) : + numDataCodewords_(numDataCodewords), codewords_(codewords) { +} + +int DataBlock::getNumDataCodewords() { + return numDataCodewords_; +} + +ArrayRef DataBlock::getCodewords() { + return codewords_; +} + + +std::vector > DataBlock::getDataBlocks(ArrayRef rawCodewords, Version *version, + ErrorCorrectionLevel &ecLevel) { + + + // Figure out the number and size of data blocks used by this version and + // error correction level + ECBlocks &ecBlocks = version->getECBlocksForLevel(ecLevel); + + + // First count the total number of data blocks + int totalBlocks = 0; + vector ecBlockArray = ecBlocks.getECBlocks(); + for (size_t i = 0; i < ecBlockArray.size(); i++) { + totalBlocks += ecBlockArray[i]->getCount(); + } + + // Now establish DataBlocks of the appropriate size and number of data codewords + std::vector > result(totalBlocks); + int numResultBlocks = 0; + for (size_t j = 0; j < ecBlockArray.size(); j++) { + ECB *ecBlock = ecBlockArray[j]; + for (int i = 0; i < ecBlock->getCount(); i++) { + int numDataCodewords = ecBlock->getDataCodewords(); + int numBlockCodewords = ecBlocks.getECCodewords() + numDataCodewords; + ArrayRef buffer(numBlockCodewords); + Ref blockRef(new DataBlock(numDataCodewords, buffer)); + result[numResultBlocks++] = blockRef; + } + } + + // All blocks have the same amount of data, except that the last n + // (where n may be 0) have 1 more byte. Figure out where these start. + int shorterBlocksTotalCodewords = result[0]->codewords_.size(); + int longerBlocksStartAt = result.size() - 1; + while (longerBlocksStartAt >= 0) { + int numCodewords = result[longerBlocksStartAt]->codewords_.size(); + if (numCodewords == shorterBlocksTotalCodewords) { + break; + } + if (numCodewords != shorterBlocksTotalCodewords + 1) { + throw IllegalArgumentException("Data block sizes differ by more than 1"); + } + longerBlocksStartAt--; + } + longerBlocksStartAt++; + + int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewords(); + // The last elements of result may be 1 element longer; + // first fill out as many elements as all of them have + int rawCodewordsOffset = 0; + for (int i = 0; i < shorterBlocksNumDataCodewords; i++) { + for (int j = 0; j < numResultBlocks; j++) { + result[j]->codewords_[i] = rawCodewords[rawCodewordsOffset++]; + } + } + // Fill out the last data block in the longer ones + for (int j = longerBlocksStartAt; j < numResultBlocks; j++) { + result[j]->codewords_[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++]; + } + // Now add in error correction blocks + int max = result[0]->codewords_.size(); + for (int i = shorterBlocksNumDataCodewords; i < max; i++) { + for (int j = 0; j < numResultBlocks; j++) { + int iOffset = j < longerBlocksStartAt ? i : i + 1; + result[j]->codewords_[iOffset] = rawCodewords[rawCodewordsOffset++]; + } + } + + if ((size_t)rawCodewordsOffset != rawCodewords.size()) { + throw IllegalArgumentException("rawCodewordsOffset != rawCodewords.length"); + } + + return result; +} + +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/decoder/DataBlock.h b/symbian/QQrDecoder/zxing/qrcode/decoder/DataBlock.h new file mode 100644 index 000000000..df536f4d6 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/decoder/DataBlock.h @@ -0,0 +1,52 @@ +#ifndef __DATA_BLOCK_H__ +#define __DATA_BLOCK_H__ + +/* + * DataBlock.h + * zxing + * + * Created by Christian Brunschen on 19/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +namespace zxing { +namespace qrcode { + +class DataBlock : public Counted { +private: + int numDataCodewords_; + ArrayRef codewords_; + + DataBlock(int numDataCodewords, ArrayRef codewords); + +public: + static std::vector > + getDataBlocks(ArrayRef rawCodewords, Version *version, ErrorCorrectionLevel &ecLevel); + + int getNumDataCodewords(); + ArrayRef getCodewords(); +}; + +} +} + +#endif // __DATA_BLOCK_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/decoder/DataMask.cpp b/symbian/QQrDecoder/zxing/qrcode/decoder/DataMask.cpp new file mode 100644 index 000000000..9b293b13c --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/decoder/DataMask.cpp @@ -0,0 +1,159 @@ +/* + * DataMask.cpp + * zxing + * + * Created by Christian Brunschen on 19/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +namespace zxing { +namespace qrcode { + +using namespace std; + +DataMask::DataMask() { +} + +DataMask::~DataMask() { +} + +vector > DataMask::DATA_MASKS; +static int N_DATA_MASKS = DataMask::buildDataMasks(); + +DataMask &DataMask::forReference(int reference) { + if (reference < 0 || reference > 7) { + throw IllegalArgumentException("reference must be between 0 and 7"); + } + return *DATA_MASKS[reference]; +} + +void DataMask::unmaskBitMatrix(BitMatrix& bits, size_t dimension) { + for (size_t y = 0; y < dimension; y++) { + for (size_t x = 0; x < dimension; x++) { + // TODO: check why the coordinates have to be swapped + if (isMasked(y, x)) { + bits.flip(x, y); + } + } + } +} + +/** + * 000: mask bits for which (x + y) mod 2 == 0 + */ +class DataMask000 : public DataMask { +public: + bool isMasked(size_t x, size_t y) { + // return ((x + y) & 0x01) == 0; + return ((x + y) % 2) == 0; + } +}; + +/** + * 001: mask bits for which x mod 2 == 0 + */ +class DataMask001 : public DataMask { +public: + bool isMasked(size_t x, size_t y) { + // return (x & 0x01) == 0; + return (x % 2) == 0; + } +}; + +/** + * 010: mask bits for which y mod 3 == 0 + */ +class DataMask010 : public DataMask { +public: + bool isMasked(size_t x, size_t y) { + return y % 3 == 0; + } +}; + +/** + * 011: mask bits for which (x + y) mod 3 == 0 + */ +class DataMask011 : public DataMask { +public: + bool isMasked(size_t x, size_t y) { + return (x + y) % 3 == 0; + } +}; + +/** + * 100: mask bits for which (x/2 + y/3) mod 2 == 0 + */ +class DataMask100 : public DataMask { +public: + bool isMasked(size_t x, size_t y) { + // return (((x >> 1) + (y / 3)) & 0x01) == 0; + return (((x >> 1) + (y / 3)) % 2) == 0; + } +}; + +/** + * 101: mask bits for which xy mod 2 + xy mod 3 == 0 + */ +class DataMask101 : public DataMask { +public: + bool isMasked(size_t x, size_t y) { + size_t temp = x * y; + // return (temp & 0x01) + (temp % 3) == 0; + return (temp % 2) + (temp % 3) == 0; + + } +}; + +/** + * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0 + */ +class DataMask110 : public DataMask { +public: + bool isMasked(size_t x, size_t y) { + size_t temp = x * y; + // return (((temp & 0x01) + (temp % 3)) & 0x01) == 0; + return (((temp % 2) + (temp % 3)) % 2) == 0; + } +}; + +/** + * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0 + */ +class DataMask111 : public DataMask { +public: + bool isMasked(size_t x, size_t y) { + // return ((((x + y) & 0x01) + ((x * y) % 3)) & 0x01) == 0; + return ((((x + y) % 2) + ((x * y) % 3)) % 2) == 0; + } +}; + +int DataMask::buildDataMasks() { + DATA_MASKS.push_back(Ref (new DataMask000())); + DATA_MASKS.push_back(Ref (new DataMask001())); + DATA_MASKS.push_back(Ref (new DataMask010())); + DATA_MASKS.push_back(Ref (new DataMask011())); + DATA_MASKS.push_back(Ref (new DataMask100())); + DATA_MASKS.push_back(Ref (new DataMask101())); + DATA_MASKS.push_back(Ref (new DataMask110())); + DATA_MASKS.push_back(Ref (new DataMask111())); + return DATA_MASKS.size(); +} + +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/decoder/DataMask.h b/symbian/QQrDecoder/zxing/qrcode/decoder/DataMask.h new file mode 100644 index 000000000..c4a3e0ccf --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/decoder/DataMask.h @@ -0,0 +1,51 @@ +#ifndef __DATA_MASK_H__ +#define __DATA_MASK_H__ + +/* + * DataMask.h + * zxing + * + * Created by Christian Brunschen on 19/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include + +namespace zxing { +namespace qrcode { + +class DataMask : public Counted { +private: + static std::vector > DATA_MASKS; + +protected: + +public: + static int buildDataMasks(); + DataMask(); + virtual ~DataMask(); + void unmaskBitMatrix(BitMatrix& matrix, size_t dimension); + virtual bool isMasked(size_t x, size_t y) = 0; + static DataMask& forReference(int reference); +}; + +} +} + +#endif // __DATA_MASK_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/decoder/DecodedBitStreamParser.cpp b/symbian/QQrDecoder/zxing/qrcode/decoder/DecodedBitStreamParser.cpp new file mode 100644 index 000000000..ab32b2e8c --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/decoder/DecodedBitStreamParser.cpp @@ -0,0 +1,282 @@ +/* + * DecodedBitStreamParser.cpp + * zxing + * + * Created by Christian Brunschen on 20/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +// Required for compatibility. TODO: test on Symbian +#ifdef ZXING_ICONV_CONST +#undef ICONV_CONST +#define ICONV_CONST const +#endif + +#ifndef ICONV_CONST +#define ICONV_CONST /**/ +#endif + +using namespace zxing; + +namespace zxing { +namespace qrcode { + +using namespace std; + +const char DecodedBitStreamParser::ALPHANUMERIC_CHARS[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', + 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', ' ', '$', '%', '*', '+', '-', '.', '/', ':' + }; + +const char *DecodedBitStreamParser::ASCII = "ASCII"; +const char *DecodedBitStreamParser::ISO88591 = "ISO-8859-1"; +const char *DecodedBitStreamParser::UTF8 = "UTF-8"; +const char *DecodedBitStreamParser::SHIFT_JIS = "SHIFT_JIS"; +const char *DecodedBitStreamParser::EUC_JP = "EUC-JP"; + +void DecodedBitStreamParser::append(ostream &ost, const unsigned char *bufIn, size_t nIn, const char *src) { + if (nIn == 0) { + return; + } + + iconv_t cd = iconv_open(UTF8, src); + const int maxOut = 4 * nIn + 1; + unsigned char* bufOut = new unsigned char[maxOut]; + + ICONV_CONST char *fromPtr = (ICONV_CONST char *)bufIn; + size_t nFrom = nIn; + char *toPtr = (char *)bufOut; + size_t nTo = maxOut; + + while (nFrom > 0) { + size_t oneway = iconv(cd, (const char**)&fromPtr, &nFrom, &toPtr, &nTo); + if (oneway == (size_t)(-1)) { + iconv_close(cd); + delete[] bufOut; + throw ReaderException("error converting characters"); + } + } + iconv_close(cd); + + int nResult = maxOut - nTo; + bufOut[nResult] = '\0'; + + ost << bufOut; + delete[] bufOut; +} + +void DecodedBitStreamParser::decodeKanjiSegment(Ref bits, ostringstream &result, int count) { + // Each character will require 2 bytes. Read the characters as 2-byte pairs + // and decode as Shift_JIS afterwards + size_t nBytes = 2 * count; + unsigned char* buffer = new unsigned char[nBytes]; + int offset = 0; + while (count > 0) { + // Each 13 bits encodes a 2-byte character + + int twoBytes = bits->readBits(13); + int assembledTwoBytes = ((twoBytes / 0x0C0) << 8) | (twoBytes % 0x0C0); + if (assembledTwoBytes < 0x01F00) { + // In the 0x8140 to 0x9FFC range + assembledTwoBytes += 0x08140; + } else { + // In the 0xE040 to 0xEBBF range + assembledTwoBytes += 0x0C140; + } + buffer[offset] = (unsigned char)(assembledTwoBytes >> 8); + buffer[offset + 1] = (unsigned char)assembledTwoBytes; + offset += 2; + count--; + } + + append(result, buffer, nBytes, SHIFT_JIS); + delete[] buffer; +} + +void DecodedBitStreamParser::decodeByteSegment(Ref bits, ostringstream &result, int count) { + int nBytes = count; + unsigned char* readBytes = new unsigned char[nBytes]; + if (count << 3 > bits->available()) { + ostringstream s; + s << "Count too large: " << count; + delete[] readBytes; + throw ReaderException(s.str().c_str()); + } + for (int i = 0; i < count; i++) { + readBytes[i] = (unsigned char)bits->readBits(8); + } + // The spec isn't clear on this mode; see + // section 6.4.5: t does not say which encoding to assuming + // upon decoding. I have seen ISO-8859-1 used as well as + // Shift_JIS -- without anything like an ECI designator to + // give a hint. + const char *encoding = guessEncoding(readBytes, nBytes); + append(result, readBytes, nBytes, encoding); + delete[] readBytes; +} + +void DecodedBitStreamParser::decodeNumericSegment(Ref bits, ostringstream &result, int count) { + int nBytes = count; + unsigned char* bytes = new unsigned char[nBytes]; + int i = 0; + // Read three digits at a time + while (count >= 3) { + // Each 10 bits encodes three digits + int threeDigitsBits = bits->readBits(10); + if (threeDigitsBits >= 1000) { + ostringstream s; + s << "Illegal value for 3-digit unit: " << threeDigitsBits; + delete[] bytes; + throw ReaderException(s.str().c_str()); + } + bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits / 100]; + bytes[i++] = ALPHANUMERIC_CHARS[(threeDigitsBits / 10) % 10]; + bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits % 10]; + count -= 3; + } + if (count == 2) { + // Two digits left over to read, encoded in 7 bits + int twoDigitsBits = bits->readBits(7); + if (twoDigitsBits >= 100) { + ostringstream s; + s << "Illegal value for 2-digit unit: " << twoDigitsBits; + delete[] bytes; + throw ReaderException(s.str().c_str()); + } + bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits / 10]; + bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits % 10]; + } else if (count == 1) { + // One digit left over to read + int digitBits = bits->readBits(4); + if (digitBits >= 10) { + ostringstream s; + s << "Illegal value for digit unit: " << digitBits; + delete[] bytes; + throw ReaderException(s.str().c_str()); + } + bytes[i++] = ALPHANUMERIC_CHARS[digitBits]; + } + append(result, bytes, nBytes, ASCII); + delete[] bytes; +} + +void DecodedBitStreamParser::decodeAlphanumericSegment(Ref bits, ostringstream &result, int count) { + int nBytes = count; + unsigned char* bytes = new unsigned char[nBytes]; + int i = 0; + // Read two characters at a time + while (count > 1) { + int nextTwoCharsBits = bits->readBits(11); + bytes[i++] = ALPHANUMERIC_CHARS[nextTwoCharsBits / 45]; + bytes[i++] = ALPHANUMERIC_CHARS[nextTwoCharsBits % 45]; + count -= 2; + } + if (count == 1) { + bytes[i++] = ALPHANUMERIC_CHARS[bits->readBits(6)]; + } + append(result, bytes, nBytes, ASCII); + delete[] bytes; +} + +const char * +DecodedBitStreamParser::guessEncoding(unsigned char *bytes, int length) { + // Does it start with the UTF-8 byte order mark? then guess it's UTF-8 + if (length > 3 && bytes[0] == (unsigned char)0xEF && bytes[1] == (unsigned char)0xBB && bytes[2] + == (unsigned char)0xBF) { + return UTF8; + } + // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS, + // which should be by far the most common encodings. ISO-8859-1 + // should not have bytes in the 0x80 - 0x9F range, while Shift_JIS + // uses this as a first byte of a two-byte character. If we see this + // followed by a valid second byte in Shift_JIS, assume it is Shift_JIS. + // If we see something else in that second byte, we'll make the risky guess + // that it's UTF-8. + bool canBeISO88591 = true; + bool lastWasPossibleDoubleByteStart = false; + for (int i = 0; i < length; i++) { + int value = bytes[i] & 0xFF; + if (value >= 0x80 && value <= 0x9F && i < length - 1) { + canBeISO88591 = false; + // ISO-8859-1 shouldn't use this, but before we decide it is Shift_JIS, + // just double check that it is followed by a byte that's valid in + // the Shift_JIS encoding + if (lastWasPossibleDoubleByteStart) { + // If we just checked this and the last byte for being a valid double-byte + // char, don't check starting on this byte. If the this and the last byte + // formed a valid pair, then this shouldn't be checked to see if it starts + // a double byte pair of course. + lastWasPossibleDoubleByteStart = false; + } else { + // ... otherwise do check to see if this plus the next byte form a valid + // double byte pair encoding a character. + lastWasPossibleDoubleByteStart = true; + int nextValue = bytes[i + 1] & 0xFF; + if ((value & 0x1) == 0) { + // if even, next value should be in [0x9F,0xFC] + // if not, we'll guess UTF-8 + if (nextValue < 0x9F || nextValue > 0xFC) { + return UTF8; + } + } else { + // if odd, next value should be in [0x40,0x9E] + // if not, we'll guess UTF-8 + if (nextValue < 0x40 || nextValue > 0x9E) { + return UTF8; + } + } + } + } + } + return canBeISO88591 ? ISO88591 : SHIFT_JIS; +} + +string DecodedBitStreamParser::decode(ArrayRef bytes, Version *version) { + ostringstream result; + Ref bits(new BitSource(bytes)); + Mode *mode = &Mode::TERMINATOR; + do { + // While still another segment to read... + if (bits->available() < 4) { + // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here + mode = &Mode::TERMINATOR; + } else { + mode = &Mode::forBits(bits->readBits(4)); // mode is encoded by 4 bits + } + if (mode != &Mode::TERMINATOR) { + // How many characters will follow, encoded in this mode? + int count = bits->readBits(mode->getCharacterCountBits(version)); + if (mode == &Mode::NUMERIC) { + decodeNumericSegment(bits, result, count); + } else if (mode == &Mode::ALPHANUMERIC) { + decodeAlphanumericSegment(bits, result, count); + } else if (mode == &Mode::BYTE) { + decodeByteSegment(bits, result, count); + } else if (mode == &Mode::KANJI) { + decodeKanjiSegment(bits, result, count); + } else { + throw ReaderException("Unsupported mode indicator"); + } + } + } while (mode != &Mode::TERMINATOR); + return result.str(); +} + +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/decoder/DecodedBitStreamParser.h b/symbian/QQrDecoder/zxing/qrcode/decoder/DecodedBitStreamParser.h new file mode 100644 index 000000000..8c4ab9bb3 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/decoder/DecodedBitStreamParser.h @@ -0,0 +1,60 @@ +#ifndef __DECODED_BIT_STREAM_PARSER_H__ +#define __DECODED_BIT_STREAM_PARSER_H__ + +/* + * DecodedBitStreamParser.h + * zxing + * + * Created by Christian Brunschen on 20/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + + + +namespace zxing { +namespace qrcode { + +class DecodedBitStreamParser { +private: + static const char ALPHANUMERIC_CHARS[]; + + static const char *ASCII; + static const char *ISO88591; + static const char *UTF8; + static const char *SHIFT_JIS; + static const char *EUC_JP; + + static void decodeKanjiSegment(Ref bits, std::ostringstream &result, int count); + static void decodeByteSegment(Ref bits, std::ostringstream &result, int count); + static void decodeAlphanumericSegment(Ref bits, std::ostringstream &result, int count); + static void decodeNumericSegment(Ref bits, std::ostringstream &result, int count); + static const char *guessEncoding(unsigned char *bytes, int length); + static void append(std::ostream &ost, const unsigned char *bufIn, size_t nIn, const char *src); + +public: + static std::string decode(ArrayRef bytes, Version *version); +}; + +} +} + +#endif // __DECODED_BIT_STREAM_PARSER_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/decoder/Decoder.cpp b/symbian/QQrDecoder/zxing/qrcode/decoder/Decoder.cpp new file mode 100644 index 000000000..13023131d --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/decoder/Decoder.cpp @@ -0,0 +1,103 @@ +/* + * Decoder.cpp + * zxing + * + * Created by Christian Brunschen on 20/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zxing { +namespace qrcode { + +using namespace std; + +Decoder::Decoder() : + rsDecoder_(GF256::QR_CODE_FIELD) { +} + +void Decoder::correctErrors(ArrayRef codewordBytes, int numDataCodewords) { + int numCodewords = codewordBytes->size(); + ArrayRef codewordInts(numCodewords); + for (int i = 0; i < numCodewords; i++) { + codewordInts[i] = codewordBytes[i] & 0xff; + } + int numECCodewords = numCodewords - numDataCodewords; + + try { + rsDecoder_.decode(codewordInts, numECCodewords); + } catch (ReedSolomonException ex) { + ReaderException rex(ex.what()); + throw rex; + } + + for (int i = 0; i < numDataCodewords; i++) { + codewordBytes[i] = (unsigned char)codewordInts[i]; + } +} + +Ref Decoder::decode(Ref bits) { + // Construct a parser and read version, error-correction level + BitMatrixParser parser(bits); + + Version *version = parser.readVersion(); + ErrorCorrectionLevel &ecLevel = parser.readFormatInformation()->getErrorCorrectionLevel(); + + + // Read codewords + ArrayRef codewords(parser.readCodewords()); + + + // Separate into data blocks + std::vector > dataBlocks(DataBlock::getDataBlocks(codewords, version, ecLevel)); + + + // Count total number of data bytes + int totalBytes = 0; + for (size_t i = 0; i < dataBlocks.size(); i++) { + totalBytes += dataBlocks[i]->getNumDataCodewords(); + } + ArrayRef resultBytes(totalBytes); + int resultOffset = 0; + + + // Error-correct and copy data blocks together into a stream of bytes + for (size_t j = 0; j < dataBlocks.size(); j++) { + Ref dataBlock(dataBlocks[j]); + ArrayRef codewordBytes = dataBlock->getCodewords(); + int numDataCodewords = dataBlock->getNumDataCodewords(); + correctErrors(codewordBytes, numDataCodewords); + for (int i = 0; i < numDataCodewords; i++) { + resultBytes[resultOffset++] = codewordBytes[i]; + } + } + + // Decode the contents of that stream of bytes + Ref text(new String(DecodedBitStreamParser::decode(resultBytes, version))); + + Ref result(new DecoderResult(resultBytes, text)); + return result; +} + +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/decoder/Decoder.h b/symbian/QQrDecoder/zxing/qrcode/decoder/Decoder.h new file mode 100644 index 000000000..96e1dc0cc --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/decoder/Decoder.h @@ -0,0 +1,49 @@ +#ifndef __DECODER_H__ +#define __DECODER_H__ + +/* + * Decoder.h + * zxing + * + * Created by Christian Brunschen on 20/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace zxing { +namespace qrcode { + +class Decoder { +private: + ReedSolomonDecoder rsDecoder_; + + void correctErrors(ArrayRef bytes, int numDataCodewords); + +public: + Decoder(); + Ref decode(Ref bits); +}; + +} +} + +#endif // __DECODER_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/decoder/Mode.cpp b/symbian/QQrDecoder/zxing/qrcode/decoder/Mode.cpp new file mode 100644 index 000000000..5a6eb4aa5 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/decoder/Mode.cpp @@ -0,0 +1,73 @@ +/* + * Mode.cpp + * zxing + * + * Created by Christian Brunschen on 19/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +namespace zxing { +namespace qrcode { +using namespace std; + +Mode Mode::TERMINATOR(0, 0, 0); +Mode Mode::NUMERIC(10, 12, 14); +Mode Mode::ALPHANUMERIC(9, 11, 13); +Mode Mode::BYTE(8, 16, 16); +Mode Mode::KANJI(8, 10, 12); + +Mode::Mode(int cbv0_9, int cbv10_26, int cbv27) : + characterCountBitsForVersions0To9_(cbv0_9), characterCountBitsForVersions10To26_(cbv10_26), + characterCountBitsForVersions27AndHigher_(cbv27) { +} + +Mode& Mode::forBits(int bits) { + switch (bits) { + case 0x0: + return TERMINATOR; + case 0x1: + return NUMERIC; + case 0x2: + return ALPHANUMERIC; + case 0x4: + return BYTE; + case 0x8: + return KANJI; + default: + ostringstream s; + s << "Illegal mode bits: " << bits; + throw ReaderException(s.str().c_str()); + } +} + +int Mode::getCharacterCountBits(Version *version) { + int number = version->getVersionNumber(); + if (number <= 9) { + return characterCountBitsForVersions0To9_; + } else if (number <= 26) { + return characterCountBitsForVersions10To26_; + } else { + return characterCountBitsForVersions27AndHigher_; + } +} + +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/decoder/Mode.h b/symbian/QQrDecoder/zxing/qrcode/decoder/Mode.h new file mode 100644 index 000000000..28708a94b --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/decoder/Mode.h @@ -0,0 +1,51 @@ +#ifndef __MODE_H__ +#define __MODE_H__ + +/* + * Mode.h + * zxing + * + * Created by Christian Brunschen on 19/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace zxing { +namespace qrcode { + +class Mode { +private: + int characterCountBitsForVersions0To9_; + int characterCountBitsForVersions10To26_; + int characterCountBitsForVersions27AndHigher_; + + Mode(int cbv0_9, int cbv10_26, int cbv27); + +public: + static Mode TERMINATOR; + static Mode NUMERIC; + static Mode ALPHANUMERIC; + static Mode BYTE; + static Mode KANJI; + + static Mode& forBits(int bits); + int getCharacterCountBits(Version *version); +}; +} +} + +#endif // __MODE_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/AlignmentPattern.cpp b/symbian/QQrDecoder/zxing/qrcode/detector/AlignmentPattern.cpp new file mode 100644 index 000000000..0f6ee592b --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/AlignmentPattern.cpp @@ -0,0 +1,46 @@ +/* + * AlignmentPattern.cpp + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { +namespace qrcode { + +using namespace std; + +AlignmentPattern::AlignmentPattern(float posX, float posY, float estimatedModuleSize) : + posX_(posX), posY_(posY), estimatedModuleSize_(estimatedModuleSize) { +} + +float AlignmentPattern::getX() { + return posX_; +} + +float AlignmentPattern::getY() { + return posY_; +} + +bool AlignmentPattern::aboutEquals(float moduleSize, float i, float j) { + return abs(i - posY_) <= moduleSize && abs(j - posX_) <= moduleSize && (abs(moduleSize - estimatedModuleSize_) + <= 1.0f || abs(moduleSize - estimatedModuleSize_) / estimatedModuleSize_ <= 0.1f); +} + +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/AlignmentPattern.h b/symbian/QQrDecoder/zxing/qrcode/detector/AlignmentPattern.h new file mode 100644 index 000000000..56a683f95 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/AlignmentPattern.h @@ -0,0 +1,46 @@ +#ifndef __ALIGNMENT_PATTERN_H__ +#define __ALIGNMENT_PATTERN_H__ + +/* + * AlignmentPattern.h + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace zxing { + namespace qrcode { + + class AlignmentPattern : public ResultPoint { + private: + float posX_; + float posY_; + float estimatedModuleSize_; + + public: + AlignmentPattern(float posX, float posY, float estimatedModuleSize); + float getX(); + float getY(); + bool aboutEquals(float moduleSize, float i, float j); + }; + + } +} + +#endif // __ALIGNMENT_PATTERN_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/AlignmentPatternFinder.cpp b/symbian/QQrDecoder/zxing/qrcode/detector/AlignmentPatternFinder.cpp new file mode 100644 index 000000000..b3d92d40c --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/AlignmentPatternFinder.cpp @@ -0,0 +1,204 @@ +/* + * AlignmentPatternFinder.cpp + * zxing + * + * Created by Christian Brunschen on 14/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AlignmentPatternFinder.h" +#include +#include +#include +#include + +namespace zxing { +namespace qrcode { + +using namespace std; + +float AlignmentPatternFinder::centerFromEnd(valarray &stateCount, int end) { + return (float)(end - stateCount[2]) - stateCount[1] / 2.0f; +} + +bool AlignmentPatternFinder::foundPatternCross(valarray &stateCount) { + float maxVariance = moduleSize_ / 2.0f; + for (size_t i = 0; i < 3; i++) { + if (abs(moduleSize_ - stateCount[i]) >= maxVariance) { + return false; + } + } + return true; +} + +float AlignmentPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, int maxCount, + int originalStateCountTotal) { + int maxI = image_->getHeight(); + valarray stateCount(0, 3); + + + // Start counting up from center + int i = startI; + while (i >= 0 && image_->get(centerJ, i) && stateCount[1] <= maxCount) { + stateCount[1]++; + i--; + } + // If already too many modules in this state or ran off the edge: + if (i < 0 || stateCount[1] > maxCount) { + return NAN; + } + while (i >= 0 && !image_->get(centerJ, i) && stateCount[0] <= maxCount) { + stateCount[0]++; + i--; + } + if (stateCount[0] > maxCount) { + return NAN; + } + + // Now also count down from center + i = startI + 1; + while (i < maxI && image_->get(centerJ, i) && stateCount[1] <= maxCount) { + stateCount[1]++; + i++; + } + if (i == maxI || stateCount[1] > maxCount) { + return NAN; + } + while (i < maxI && !image_->get(centerJ, i) && stateCount[2] <= maxCount) { + stateCount[2]++; + i++; + } + if (stateCount[2] > maxCount) { + return NAN; + } + + int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2]; + if (5 * abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) { + return NAN; + } + + return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : NAN; +} + +Ref AlignmentPatternFinder::handlePossibleCenter(valarray &stateCount, size_t i, size_t j) { + int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2]; + float centerJ = centerFromEnd(stateCount, j); + float centerI = crossCheckVertical(i, (int)centerJ, 2 * stateCount[1], stateCountTotal); + if (!isnan(centerI)) { + float estimatedModuleSize = (float)(stateCount[0] + stateCount[1] + stateCount[2]) / 3.0f; + int max = possibleCenters_->size(); + for (int index = 0; index < max; index++) { + Ref center((*possibleCenters_)[index]); + // Look for about the same center and module size: + if (center->aboutEquals(estimatedModuleSize, centerI, centerJ)) { + Ref result(new AlignmentPattern(centerJ, centerI, estimatedModuleSize)); + return result; + } + } + AlignmentPattern *tmp = new AlignmentPattern(centerJ, centerI, estimatedModuleSize); + // Hadn't found this before; save it + tmp->retain(); + possibleCenters_->push_back(tmp); + } + Ref result; + return result; +} + +AlignmentPatternFinder::AlignmentPatternFinder(Ref image, size_t startX, size_t startY, size_t width, + size_t height, float moduleSize) : + image_(image), possibleCenters_(new vector ()), startX_(startX), startY_(startY), + width_(width), height_(height), moduleSize_(moduleSize) { +} + +AlignmentPatternFinder::~AlignmentPatternFinder() { + for (size_t i = 0; i < possibleCenters_->size(); i++) { + (*possibleCenters_)[i]->release(); + (*possibleCenters_)[i] = 0; + } + delete possibleCenters_; +} + +Ref AlignmentPatternFinder::find() { + size_t maxJ = startX_ + width_; + size_t middleI = startY_ + (height_ >> 1); + // Ref luminanceRow(new BitArray(width_)); + // We are looking for black/white/black modules in 1:1:1 ratio; + // this tracks the number of black/white/black modules seen so far + valarray stateCount(0, 3); + for (size_t iGen = 0; iGen < height_; iGen++) { + // Search from middle outwards + size_t i = middleI + ((iGen & 0x01) == 0 ? ((iGen + 1) >> 1) : -((iGen + 1) >> 1)); + // image_->getBlackRow(i, luminanceRow, startX_, width_); + stateCount[0] = 0; + stateCount[1] = 0; + stateCount[2] = 0; + size_t j = startX_; + // Burn off leading white pixels before anything else; if we start in the middle of + // a white run, it doesn't make sense to count its length, since we don't know if the + // white run continued to the left of the start point + while (j < maxJ && !image_->get(j, i)) { + j++; + } + int currentState = 0; + while (j < maxJ) { + if (image_->get(j, i)) { + // Black pixel + if (currentState == 1) { // Counting black pixels + stateCount[currentState]++; + } else { // Counting white pixels + if (currentState == 2) { // A winner? + if (foundPatternCross(stateCount)) { // Yes + Ref confirmed(handlePossibleCenter(stateCount, i, j)); + if (confirmed != 0) { + return confirmed; + } + } + stateCount[0] = stateCount[2]; + stateCount[1] = 1; + stateCount[2] = 0; + currentState = 1; + } else { + stateCount[++currentState]++; + } + } + } else { // White pixel + if (currentState == 1) { // Counting black pixels + currentState++; + } + stateCount[currentState]++; + } + j++; + } + if (foundPatternCross(stateCount)) { + Ref confirmed(handlePossibleCenter(stateCount, i, maxJ)); + if (confirmed != 0) { + return confirmed; + } + } + + } + + // Hmm, nothing we saw was observed and confirmed twice. If we had + // any guess at all, return it. + if (possibleCenters_->size() > 0) { + Ref center((*possibleCenters_)[0]); + return center; + } + + throw zxing::ReaderException("Could not find alignment pattern"); +} + +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/AlignmentPatternFinder.h b/symbian/QQrDecoder/zxing/qrcode/detector/AlignmentPatternFinder.h new file mode 100644 index 000000000..266364316 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/AlignmentPatternFinder.h @@ -0,0 +1,62 @@ +#ifndef __ALIGNMENT_PATTERN_FINDER_H__ +#define __ALIGNMENT_PATTERN_FINDER_H__ + +/* + * AlignmentPatternFinder.h + * zxing + * + * Created by Christian Brunschen on 14/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AlignmentPattern.h" +#include +#include +#include + +namespace zxing { +namespace qrcode { + +class AlignmentPatternFinder : public Counted { +private: + static int CENTER_QUORUM; + static int MIN_SKIP; + static int MAX_MODULES; + + Ref image_; + std::vector *possibleCenters_; + size_t startX_; + size_t startY_; + size_t width_; + size_t height_; + float moduleSize_; + + static float centerFromEnd(std::valarray &stateCount, int end); + bool foundPatternCross(std::valarray &stateCount); + + float crossCheckVertical(size_t startI, size_t centerJ, int maxCount, int originalStateCountTotal); + + Ref handlePossibleCenter(std::valarray &stateCount, size_t i, size_t j); + +public: + AlignmentPatternFinder(Ref image, size_t startX, size_t startY, size_t width, size_t height, + float moduleSize); + ~AlignmentPatternFinder(); + Ref find(); +}; +} +} + +#endif // __ALIGNMENT_PATTERN_FINDER_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/Detector.cpp b/symbian/QQrDecoder/zxing/qrcode/detector/Detector.cpp new file mode 100644 index 000000000..dc8090bdf --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/Detector.cpp @@ -0,0 +1,265 @@ +/* + * Detector.cpp + * zxing + * + * Created by Christian Brunschen on 14/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zxing { +namespace qrcode { + +using namespace std; + +Detector::Detector(Ref image) : + image_(image) { +} + +Ref Detector::getImage() { + return image_; +} + +Ref Detector::detect() { + FinderPatternFinder finder(image_); + Ref info(finder.find()); + + Ref topLeft(info->getTopLeft()); + Ref topRight(info->getTopRight()); + Ref bottomLeft(info->getBottomLeft()); + + float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft); + int dimension = computeDimension(topLeft, topRight, bottomLeft, moduleSize); + Version *provisionalVersion = Version::getProvisionalVersionForDimension(dimension); + int modulesBetweenFPCenters = provisionalVersion->getDimensionForVersion() - 7; + + Ref alignmentPattern; + // Anything above version 1 has an alignment pattern + if (provisionalVersion->getAlignmentPatternCenters().size() > 0) { + + + // Guess where a "bottom right" finder pattern would have been + float bottomRightX = topRight->getX() - topLeft->getX() + bottomLeft->getX(); + float bottomRightY = topRight->getY() - topLeft->getY() + bottomLeft->getY(); + + + // Estimate that alignment pattern is closer by 3 modules + // from "bottom right" to known top left location + float correctionToTopLeft = 1.0f - 3.0f / (float)modulesBetweenFPCenters; + int estAlignmentX = (int)(topLeft->getX() + correctionToTopLeft * (bottomRightX - topLeft->getX())); + int estAlignmentY = (int)(topLeft->getY() + correctionToTopLeft * (bottomRightY - topLeft->getY())); + + + // Kind of arbitrary -- expand search radius before giving up + for (int i = 4; i <= 16; i <<= 1) { + try { + alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float)i); + break; + } catch (zxing::ReaderException re) { + // try next round + } + } + if (alignmentPattern == 0) { + // Try anyway + } + + } + + Ref transform = createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension); + Ref bits(sampleGrid(image_, dimension, transform)); + std::vector > points(alignmentPattern == 0 ? 3 : 4); + points[0].reset(bottomLeft); + points[1].reset(topLeft); + points[2].reset(topRight); + if (alignmentPattern != 0) { + points[3].reset(alignmentPattern); + } + + Ref result(new DetectorResult(bits, points, transform)); + return result; +} + +Ref Detector::createTransform(Ref topLeft, Ref topRight, Ref < + ResultPoint > bottomLeft, Ref alignmentPattern, int dimension) { + + float dimMinusThree = (float)dimension - 3.5f; + float bottomRightX; + float bottomRightY; + float sourceBottomRightX; + float sourceBottomRightY; + if (alignmentPattern != 0) { + bottomRightX = alignmentPattern->getX(); + bottomRightY = alignmentPattern->getY(); + sourceBottomRightX = sourceBottomRightY = dimMinusThree - 3.0f; + } else { + // Don't have an alignment pattern, just make up the bottom-right point + bottomRightX = (topRight->getX() - topLeft->getX()) + bottomLeft->getX(); + bottomRightY = (topRight->getY() - topLeft->getY()) + bottomLeft->getY(); + sourceBottomRightX = sourceBottomRightY = dimMinusThree; + } + + Ref transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, sourceBottomRightX, + sourceBottomRightY, 3.5f, dimMinusThree, topLeft->getX(), topLeft->getY(), topRight->getX(), + topRight->getY(), bottomRightX, bottomRightY, bottomLeft->getX(), bottomLeft->getY())); + + return transform; +} + +Ref Detector::sampleGrid(Ref image, int dimension, Ref transform) { + GridSampler &sampler = GridSampler::getInstance(); + return sampler.sampleGrid(image, dimension, transform); +} + +int Detector::computeDimension(Ref topLeft, Ref topRight, Ref bottomLeft, + float moduleSize) { + int tltrCentersDimension = lround(FinderPatternFinder::distance(topLeft, topRight) / moduleSize); + int tlblCentersDimension = lround(FinderPatternFinder::distance(topLeft, bottomLeft) / moduleSize); + int dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7; + switch (dimension & 0x03) { // mod 4 + case 0: + dimension++; + break; + // 1? do nothing + case 2: + dimension--; + break; + case 3: + ostringstream s; + s << "Bad dimension: " << dimension; + throw zxing::ReaderException(s.str().c_str()); + } + return dimension; +} + +float Detector::calculateModuleSize(Ref topLeft, Ref topRight, Ref bottomLeft) { + // Take the average + return (calculateModuleSizeOneWay(topLeft, topRight) + calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f; +} + +float Detector::calculateModuleSizeOneWay(Ref pattern, Ref otherPattern) { + float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int)pattern->getX(), (int)pattern->getY(), + (int)otherPattern->getX(), (int)otherPattern->getY()); + float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int)otherPattern->getX(), (int)otherPattern->getY(), + (int)pattern->getX(), (int)pattern->getY()); + if (isnan(moduleSizeEst1)) { + return moduleSizeEst2; + } + if (isnan(moduleSizeEst2)) { + return moduleSizeEst1; + } + // Average them, and divide by 7 since we've counted the width of 3 black modules, + // and 1 white and 1 black module on either side. Ergo, divide sum by 14. + return (moduleSizeEst1 + moduleSizeEst2) / 14.0f; +} + +float Detector::sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY) { + + float result = sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY); + + + // Now count other way -- don't run off image though of course + int otherToX = fromX - (toX - fromX); + if (otherToX < 0) { + // "to" should the be the first value not included, so, the first value off + // the edge is -1 + otherToX = -1; + } else if (otherToX >= (int)image_->getWidth()) { + otherToX = image_->getWidth(); + } + int otherToY = fromY - (toY - fromY); + if (otherToY < 0) { + otherToY = -1; + } else if (otherToY >= (int)image_->getHeight()) { + otherToY = image_->getHeight(); + } + result += sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY); + return result - 1.0f; // -1 because we counted the middle pixel twice +} + +float Detector::sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY) { + // Mild variant of Bresenham's algorithm; + // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm + bool steep = abs(toY - fromY) > abs(toX - fromX); + if (steep) { + int temp = fromX; + fromX = fromY; + fromY = temp; + temp = toX; + toX = toY; + toY = temp; + } + + int dx = abs(toX - fromX); + int dy = abs(toY - fromY); + int error = -dx >> 1; + int ystep = fromY < toY ? 1 : -1; + int xstep = fromX < toX ? 1 : -1; + int state = 0; // In black pixels, looking for white, first or second time + for (int x = fromX, y = fromY; x != toX; x += xstep) { + + int realX = steep ? y : x; + int realY = steep ? x : y; + if (state == 1) { // In white pixels, looking for black + if (image_->get(realX, realY)) { + state++; + } + } else { + if (!image_->get(realX, realY)) { + state++; + } + } + + if (state == 3) { // Found black, white, black, and stumbled back onto white; done + int diffX = x - fromX; + int diffY = y - fromY; + return (float)sqrt((double)(diffX * diffX + diffY * diffY)); + } + error += dy; + if (error > 0) { + y += ystep; + error -= dx; + } + } + int diffX = toX - fromX; + int diffY = toY - fromY; + return (float)sqrt((double)(diffX * diffX + diffY * diffY)); +} + +Ref Detector::findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY, + float allowanceFactor) { + // Look for an alignment pattern (3 modules in size) around where it + // should be + int allowance = (int)(allowanceFactor * overallEstModuleSize); + int alignmentAreaLeftX = max(0, estAlignmentX - allowance); + int alignmentAreaRightX = min((int)(image_->getWidth() - 1), estAlignmentX + allowance); + int alignmentAreaTopY = max(0, estAlignmentY - allowance); + int alignmentAreaBottomY = min((int)(image_->getHeight() - 1), estAlignmentY + allowance); + + AlignmentPatternFinder alignmentFinder(image_, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX + - alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize); + return alignmentFinder.find(); +} + +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/Detector.h b/symbian/QQrDecoder/zxing/qrcode/detector/Detector.h new file mode 100644 index 000000000..98eed51e9 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/Detector.h @@ -0,0 +1,60 @@ +#ifndef __DETECTOR_H__ +#define __DETECTOR_H__ + +/* + * Detector.h + * zxing + * + * Created by Christian Brunschen on 14/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +namespace zxing { +namespace qrcode { + +class Detector : public Counted { +private: + Ref image_; + +protected: + Ref getImage(); + + static Ref sampleGrid(Ref image, int dimension, Ref); + static int computeDimension(Ref topLeft, Ref topRight, Ref bottomLeft, + float moduleSize); + float calculateModuleSize(Ref topLeft, Ref topRight, Ref bottomLeft); + float calculateModuleSizeOneWay(Ref pattern, Ref otherPattern); + float sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY); + float sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY); + Ref findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY, + float allowanceFactor); +public: + + virtual Ref createTransform(Ref topLeft, Ref topRight, Ref < + ResultPoint > bottomLeft, Ref alignmentPattern, int dimension); + + Detector(Ref image); + Ref detect(); +}; +} +} + +#endif // __DETECTOR_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/FinderPattern.cpp b/symbian/QQrDecoder/zxing/qrcode/detector/FinderPattern.cpp new file mode 100644 index 000000000..531d4e2a1 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/FinderPattern.cpp @@ -0,0 +1,58 @@ +/* + * FinderPattern.cpp + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { + namespace qrcode { + + using namespace std; + + FinderPattern::FinderPattern(float posX, float posY, float estimatedModuleSize) : + posX_(posX), posY_(posY), estimatedModuleSize_(estimatedModuleSize), counter_(1) { + } + + float FinderPattern::getX() { + return posX_; + } + + float FinderPattern::getY() { + return posY_; + } + + int FinderPattern::getCount() { + return counter_; + } + + float FinderPattern::getEstimatedModuleSize() { + return estimatedModuleSize_; + } + + void FinderPattern::incrementCount() { + counter_++; + } + + bool FinderPattern::aboutEquals(float moduleSize, float i, float j) { + return abs(i - posY_) <= moduleSize && abs(j - posX_) <= moduleSize && (abs(moduleSize - estimatedModuleSize_) + <= 1.0f || abs(moduleSize - estimatedModuleSize_) / estimatedModuleSize_ <= 0.1f); + } + + } +} diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/FinderPattern.h b/symbian/QQrDecoder/zxing/qrcode/detector/FinderPattern.h new file mode 100644 index 000000000..0b6615c81 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/FinderPattern.h @@ -0,0 +1,49 @@ +#ifndef __FINDER_PATTERN_H__ +#define __FINDER_PATTERN_H__ + +/* + * FinderPattern.h + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace zxing { + namespace qrcode { + + class FinderPattern : public ResultPoint { + private: + float posX_; + float posY_; + float estimatedModuleSize_; + int counter_; + + public: + FinderPattern(float posX, float posY, float estimatedModuleSize); + float getX(); + float getY(); + int getCount(); + float getEstimatedModuleSize(); + void incrementCount(); + bool aboutEquals(float moduleSize, float i, float j); + }; + } +} + +#endif // __FINDER_PATTERN_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/FinderPatternFinder.cpp b/symbian/QQrDecoder/zxing/qrcode/detector/FinderPatternFinder.cpp new file mode 100644 index 000000000..666c4f210 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/FinderPatternFinder.cpp @@ -0,0 +1,501 @@ +/* + * FinderPatternFinder.cpp + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +namespace zxing { +namespace qrcode { + +using namespace std; + +class ClosestToAverageComparator { +private: + float averageModuleSize_; +public: + ClosestToAverageComparator(float averageModuleSize) : + averageModuleSize_(averageModuleSize) { + } + int operator()(Ref a, Ref b) { + float dA = abs(a->getEstimatedModuleSize() - averageModuleSize_); + float dB = abs(b->getEstimatedModuleSize() - averageModuleSize_); + return dA < dB ? -1 : dA > dB ? 1 : 0; + } +}; + +class CenterComparator { +public: + int operator()(Ref a, Ref b) { + return b->getCount() - a->getCount(); + } +}; + +int FinderPatternFinder::CENTER_QUORUM = 2; +int FinderPatternFinder::MIN_SKIP = 3; +int FinderPatternFinder::MAX_MODULES = 57; + +float FinderPatternFinder::centerFromEnd(int* stateCount, int end) { + return (float)(end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0f; +} + +bool FinderPatternFinder::foundPatternCross(int* stateCount) { + int totalModuleSize = 0; + for (int i = 0; i < 5; i++) { + if (stateCount[i] == 0) { + return false; + } + totalModuleSize += stateCount[i]; + } + if (totalModuleSize < 7) { + return false; + } + float moduleSize = (float)totalModuleSize / 7.0f; + float maxVariance = moduleSize / 2.0f; + // Allow less than 50% variance from 1-1-3-1-1 proportions + return abs(moduleSize - stateCount[0]) < maxVariance && abs(moduleSize - stateCount[1]) < maxVariance && abs(3.0f + * moduleSize - stateCount[2]) < 3.0f * maxVariance && abs(moduleSize - stateCount[3]) < maxVariance && abs( + moduleSize - stateCount[4]) < maxVariance; +} + +float FinderPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, int maxCount, int originalStateCountTotal) { + + int maxI = image_->getHeight(); + int stateCount[5]; + for (int i = 0; i < 5; i++) + stateCount[i] = 0; + + + // Start counting up from center + int i = startI; + while (i >= 0 && image_->get(centerJ, i)) { + stateCount[2]++; + i--; + } + if (i < 0) { + return NAN; + } + while (i >= 0 && !image_->get(centerJ, i) && stateCount[1] <= maxCount) { + stateCount[1]++; + i--; + } + // If already too many modules in this state or ran off the edge: + if (i < 0 || stateCount[1] > maxCount) { + return NAN; + } + while (i >= 0 && image_->get(centerJ, i) && stateCount[0] <= maxCount) { + stateCount[0]++; + i--; + } + if (stateCount[0] > maxCount) { + return NAN; + } + + // Now also count down from center + i = startI + 1; + while (i < maxI && image_->get(centerJ, i)) { + stateCount[2]++; + i++; + } + if (i == maxI) { + return NAN; + } + while (i < maxI && !image_->get(centerJ, i) && stateCount[3] < maxCount) { + stateCount[3]++; + i++; + } + if (i == maxI || stateCount[3] >= maxCount) { + return NAN; + } + while (i < maxI && image_->get(centerJ, i) && stateCount[4] < maxCount) { + stateCount[4]++; + i++; + } + if (stateCount[4] >= maxCount) { + return NAN; + } + + // If we found a finder-pattern-like section, but its size is more than 40% different than + // the original, assume it's a false positive + int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4]; + if (5 * abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) { + return NAN; + } + + return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : NAN; +} + +float FinderPatternFinder::crossCheckHorizontal(size_t startJ, size_t centerI, int maxCount, + int originalStateCountTotal) { + + int maxJ = image_->getWidth(); + int stateCount[5]; + for (int i = 0; i < 5; i++) + stateCount[i] = 0; + + int j = startJ; + while (j >= 0 && image_->get(j, centerI)) { + stateCount[2]++; + j--; + } + if (j < 0) { + return NAN; + } + while (j >= 0 && !image_->get(j, centerI) && stateCount[1] <= maxCount) { + stateCount[1]++; + j--; + } + if (j < 0 || stateCount[1] > maxCount) { + return NAN; + } + while (j >= 0 && image_->get(j, centerI) && stateCount[0] <= maxCount) { + stateCount[0]++; + j--; + } + if (stateCount[0] > maxCount) { + return NAN; + } + + j = startJ + 1; + while (j < maxJ && image_->get(j, centerI)) { + stateCount[2]++; + j++; + } + if (j == maxJ) { + return NAN; + } + while (j < maxJ && !image_->get(j, centerI) && stateCount[3] < maxCount) { + stateCount[3]++; + j++; + } + if (j == maxJ || stateCount[3] >= maxCount) { + return NAN; + } + while (j < maxJ && image_->get(j, centerI) && stateCount[4] < maxCount) { + stateCount[4]++; + j++; + } + if (stateCount[4] >= maxCount) { + return NAN; + } + + // If we found a finder-pattern-like section, but its size is significantly different than + // the original, assume it's a false positive + int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4]; + if (5 * abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) { + return NAN; + } + + return foundPatternCross(stateCount) ? centerFromEnd(stateCount, j) : NAN; +} + +bool FinderPatternFinder::handlePossibleCenter(int* stateCount, size_t i, size_t j) { + int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4]; + float centerJ = centerFromEnd(stateCount, j); + float centerI = crossCheckVertical(i, (size_t)centerJ, stateCount[2], stateCountTotal); + if (!isnan(centerI)) { + // Re-cross check + centerJ = crossCheckHorizontal((size_t)centerJ, (size_t)centerI, stateCount[2], stateCountTotal); + if (!isnan(centerJ)) { + float estimatedModuleSize = (float)stateCountTotal / 7.0f; + bool found = false; + size_t max = possibleCenters_.size(); + for (size_t index = 0; index < max; index++) { + Ref center = possibleCenters_[index]; + // Look for about the same center and module size: + if (center->aboutEquals(estimatedModuleSize, centerI, centerJ)) { + center->incrementCount(); + found = true; + break; + } + } + if (!found) { + Ref newPattern(new FinderPattern(centerJ, centerI, estimatedModuleSize)); + possibleCenters_.push_back(newPattern); + } + return true; + } + } + return false; +} + +int FinderPatternFinder::findRowSkip() { + size_t max = possibleCenters_.size(); + if (max <= 1) { + return 0; + } + Ref firstConfirmedCenter; + for (size_t i = 0; i < max; i++) { + Ref center = possibleCenters_[i]; + if (center->getCount() >= CENTER_QUORUM) { + if (firstConfirmedCenter == 0) { + firstConfirmedCenter = center; + } else { + // We have two confirmed centers + // How far down can we skip before resuming looking for the next + // pattern? In the worst case, only the difference between the + // difference in the x / y coordinates of the two centers. + // This is the case where you find top left first. Draw it out. + hasSkipped_ = true; + return (int)(abs(firstConfirmedCenter->getX() - center->getX()) - abs(firstConfirmedCenter->getY() + - center->getY())); + } + } + } + return 0; +} + +bool FinderPatternFinder::haveMultiplyConfirmedCenters() { + int confirmedCount = 0; + float totalModuleSize = 0.0f; + size_t max = possibleCenters_.size(); + for (size_t i = 0; i < max; i++) { + Ref pattern = possibleCenters_[i]; + if (pattern->getCount() >= CENTER_QUORUM) { + confirmedCount++; + totalModuleSize += pattern->getEstimatedModuleSize(); + } + } + if (confirmedCount < 3) { + return false; + } + // OK, we have at least 3 confirmed centers, but, it's possible that one is a "false positive" + // and that we need to keep looking. We detect this by asking if the estimated module sizes + // vary too much. We arbitrarily say that when the total deviation from average exceeds + // 15% of the total module size estimates, it's too much. + float average = totalModuleSize / max; + float totalDeviation = 0.0f; + for (size_t i = 0; i < max; i++) { + Ref pattern = possibleCenters_[i]; + totalDeviation += abs(pattern->getEstimatedModuleSize() - average); + } + return totalDeviation <= 0.15f * totalModuleSize; +} + +vector > FinderPatternFinder::selectBestPatterns() { + sort(possibleCenters_.begin(), possibleCenters_.end(), CenterComparator()); + size_t size = 0; + size_t max = possibleCenters_.size(); + while (size < max) { + if (possibleCenters_[size]->getCount() < CENTER_QUORUM) { + break; + } + size++; + } + + if (size < 3) { + // Couldn't find enough finder patterns + throw zxing::ReaderException("Could not find three finder patterns"); + } + + if (size == 3) { + // Found just enough -- hope these are good! + vector > result(3); + result[0] = possibleCenters_[0]; + result[1] = possibleCenters_[1]; + result[2] = possibleCenters_[2]; + return result; + } + + // Hmm, multiple found. We need to pick the best three. Find the most + // popular ones whose module size is nearest the average + // This does not work for multiple qr codes in the same image + float averageModuleSize = 0.0f; + for (size_t i = 0; i < size; i++) { + averageModuleSize += possibleCenters_[i]->getEstimatedModuleSize(); + } + averageModuleSize /= (float)size; + + sort(possibleCenters_.begin(), possibleCenters_.end(), ClosestToAverageComparator(averageModuleSize)); + + vector > result(3); + result[0] = possibleCenters_[0]; + result[1] = possibleCenters_[1]; + result[2] = possibleCenters_[2]; + return result; +} + +vector > FinderPatternFinder::orderBestPatterns(vector > patterns) { + // Find distances between pattern centers + float abDistance = distance(patterns[0], patterns[1]); + float bcDistance = distance(patterns[1], patterns[2]); + float acDistance = distance(patterns[0], patterns[2]); + + Ref topLeft; + Ref topRight; + Ref bottomLeft; + // Assume one closest to other two is top left; + // topRight and bottomLeft will just be guesses below at first + if (bcDistance >= abDistance && bcDistance >= acDistance) { + topLeft = patterns[0]; + topRight = patterns[1]; + bottomLeft = patterns[2]; + } else if (acDistance >= bcDistance && acDistance >= abDistance) { + topLeft = patterns[1]; + topRight = patterns[0]; + bottomLeft = patterns[2]; + } else { + topLeft = patterns[2]; + topRight = patterns[0]; + bottomLeft = patterns[1]; + } + + // Use cross product to figure out which of other1/2 is the bottom left + // pattern. The vector "top-left -> bottom-left" x "top-left -> top-right" + // should yield a vector with positive z component + if ((bottomLeft->getY() - topLeft->getY()) * (topRight->getX() - topLeft->getX()) < (bottomLeft->getX() + - topLeft->getX()) * (topRight->getY() - topLeft->getY())) { + Ref temp = topRight; + topRight = bottomLeft; + bottomLeft = temp; + } + + vector > results(3); + results[0] = bottomLeft; + results[1] = topLeft; + results[2] = topRight; + return results; +} + +float FinderPatternFinder::distance(Ref p1, Ref p2) { + float dx = p1->getX() - p2->getX(); + float dy = p1->getY() - p2->getY(); + return (float)sqrt(dx * dx + dy * dy); +} + +FinderPatternFinder::FinderPatternFinder(Ref image) : + image_(image), possibleCenters_(), hasSkipped_(false) { +} + +Ref FinderPatternFinder::find() { + 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 valarray + 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. + size_t 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) { + iSkip = 1; // Go back to examining each line + 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 { + // Advance to next black pixel + do { + j++; + } while (j < maxJ && !image_->get(j, i)); + j--; // back up to that last white pixel + } + // 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 > patternInfo = selectBestPatterns(); + patternInfo = orderBestPatterns(patternInfo); + + Ref result(new FinderPatternInfo(patternInfo)); + return result; +} +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/FinderPatternFinder.h b/symbian/QQrDecoder/zxing/qrcode/detector/FinderPatternFinder.h new file mode 100644 index 000000000..e1fc9ce7f --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/FinderPatternFinder.h @@ -0,0 +1,65 @@ +#ifndef __FINDER_PATTERN_FINDER_H__ +#define __FINDER_PATTERN_FINDER_H__ + +/* + * FinderPatternFinder.h + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +namespace zxing { +namespace qrcode { + +class FinderPatternFinder { +private: + static int CENTER_QUORUM; + static int MIN_SKIP; + static int MAX_MODULES; + + Ref image_; + std::vector > possibleCenters_; + bool hasSkipped_; + + /** stateCount must be int[5] */ + static float centerFromEnd(int* stateCount, int end); + static bool foundPatternCross(int* stateCount); + + float crossCheckVertical(size_t startI, size_t centerJ, int maxCount, int originalStateCountTotal); + float crossCheckHorizontal(size_t startJ, size_t centerI, int maxCount, int originalStateCountTotal); + + /** stateCount must be int[5] */ + bool handlePossibleCenter(int* stateCount, size_t i, size_t j); + int findRowSkip(); + bool haveMultiplyConfirmedCenters(); + std::vector > selectBestPatterns(); + static std::vector > orderBestPatterns(std::vector > patterns); + +public: + static float distance(Ref p1, Ref p2); + FinderPatternFinder(Ref image); + Ref find(); +}; +} +} + +#endif // __FINDER_PATTERN_FINDER_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/FinderPatternInfo.cpp b/symbian/QQrDecoder/zxing/qrcode/detector/FinderPatternInfo.cpp new file mode 100644 index 000000000..088a0e760 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/FinderPatternInfo.cpp @@ -0,0 +1,41 @@ +/* + * FinderPatternInfo.cpp + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace zxing { +namespace qrcode { + +FinderPatternInfo::FinderPatternInfo(std::vector > patternCenters) : + bottomLeft_(patternCenters[0]), topLeft_(patternCenters[1]), topRight_(patternCenters[2]) { +} + +Ref FinderPatternInfo::getBottomLeft() { + return bottomLeft_; +} +Ref FinderPatternInfo::getTopLeft() { + return topLeft_; +} +Ref FinderPatternInfo::getTopRight() { + return topRight_; +} + +} +} diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/FinderPatternInfo.h b/symbian/QQrDecoder/zxing/qrcode/detector/FinderPatternInfo.h new file mode 100644 index 000000000..287a8d17d --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/FinderPatternInfo.h @@ -0,0 +1,48 @@ +#ifndef __FINDER_PATTERN_INFO_H__ +#define __FINDER_PATTERN_INFO_H__ + +/* + * FinderPatternInfo.h + * zxing + * + * Created by Christian Brunschen on 13/05/2008. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +namespace zxing { +namespace qrcode { + +class FinderPatternInfo : public Counted { +private: + Ref bottomLeft_; + Ref topLeft_; + Ref topRight_; + +public: + FinderPatternInfo(std::vector > patternCenters); + + Ref getBottomLeft(); + Ref getTopLeft(); + Ref getTopRight(); +}; +} +} + +#endif // __FINDER_PATTERN_INFO_H__ diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/QREdgeDetector.cpp b/symbian/QQrDecoder/zxing/qrcode/detector/QREdgeDetector.cpp new file mode 100644 index 000000000..18affe6e1 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/QREdgeDetector.cpp @@ -0,0 +1,168 @@ +/* + * QREdgeDetector.cpp + * zxing + * + * Created by Ralf Kistner on 7/12/2009. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +using namespace std; + +namespace zxing { +namespace qrcode { + +static const float patternEdgeThreshold = 2; +static const int patternEdgeWidth = 3; +static const float patternEdgeSearchRatio = 1.1; +static const int patternEdgeSkip = 2; + +static const float accurateEdgeThreshold = 3.3; +static const int accurateEdgeWidth = 7; +static const int accurateEdgeSkip = 2; + +static Point guessLastPattern(Point topLeft, Point topRight, Point bottomLeft) { + return Point(topRight.x - topLeft.x + bottomLeft.x, topRight.y - topLeft.y + bottomLeft.y); +} + +static Point rp(Ref rp) { + return Point(rp->getX(), rp->getY()); +} + +QREdgeDetector::QREdgeDetector(Ref image) : Detector(image) { } + +Ref QREdgeDetector::createTransform(Ref topLeft, Ref topRight, Ref < + ResultPoint > bottomLeft, Ref alignmentPattern, int dimension) { + + if(alignmentPattern == NULL) { + Point corner = findCorner(*Detector::getImage(), rp(topLeft), rp(topRight), rp(bottomLeft), dimension); + return get1CornerTransform(rp(topLeft), rp(topRight), rp(bottomLeft), corner, dimension); + } else { + return Detector::createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension); + } +} + + + + +Point QREdgeDetector::findCorner(const BitMatrix& image, Point topLeft, Point topRight, Point bottomLeft, int dimension) { + Point bottomRight = guessLastPattern(topLeft, topRight, bottomLeft); + + Line bottomEst = findPatternEdge(image, bottomLeft, topLeft, bottomRight, false); + Line rightEst = findPatternEdge(image, topRight, topLeft, bottomRight, true); + + //return EdgeDetector::intersection(bottomEst, rightEst); + + Line bottom = EdgeDetector::findLine(image, bottomEst, false, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip); + Line right = EdgeDetector::findLine(image, rightEst, true, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip); + + + return EdgeDetector::intersection(bottom, right); +} + +Line QREdgeDetector::findPatternEdge(const BitMatrix& image, Point pattern, Point opposite, Point direction, bool invert) { + Point start = endOfReverseBlackWhiteBlackRun(image, pattern, opposite); + + float dx = pattern.x - start.x; + float dy = pattern.y - start.y; + float dist = sqrt(dx*dx + dy*dy); + + float dirX = direction.x - pattern.x; + float dirY = direction.y - pattern.y; + float dirSize = sqrt(dirX*dirX + dirY*dirY); + + float nx = dirX/dirSize; + float ny = dirY/dirSize; + + float search = dist * patternEdgeSearchRatio; + Point a(start.x + nx*search, start.y + ny*search); + Point b(start.x - nx*search, start.y - ny*search); + + return EdgeDetector::findLine(image, Line(a, b), invert, patternEdgeWidth, patternEdgeThreshold, patternEdgeSkip); +} + + +Ref QREdgeDetector::get1CornerTransform(Point topLeft, Point topRight, Point bottomLeft, Point corner, int dimension) { + float dimMinusThree = (float) dimension - 3.5f; + + Ref transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, dimension, + dimension, 3.5f, dimMinusThree, topLeft.x, topLeft.y, topRight.x, + topRight.y, corner.x, corner.y, bottomLeft.x, bottomLeft.y)); + + return transform; +} + +// Adapted from "sizeOfBlackWhiteBlackRun" in zxing::qrcode::Detector +Point QREdgeDetector::endOfReverseBlackWhiteBlackRun(const BitMatrix& image, Point from, Point to) { + int fromX = (int)from.x; + int fromY = (int)from.y; + int toX = (int)to.x; + int toY = (int)to.y; + + bool steep = abs(toY - fromY) > abs(toX - fromX); + if (steep) { + int temp = fromX; + fromX = fromY; + fromY = temp; + temp = toX; + toX = toY; + toY = temp; + } + + int dx = abs(toX - fromX); + int dy = abs(toY - fromY); + int error = -dx >> 1; + int ystep = fromY < toY ? -1 : 1; + int xstep = fromX < toX ? -1 : 1; + int state = 0; // In black pixels, looking for white, first or second time + + // In case there are no points, prepopulate to from + int realX = fromX; + int realY = fromY; + for (int x = fromX, y = fromY; x != toX; x += xstep) { + realX = steep ? y : x; + realY = steep ? x : y; + + if(realX < 0 || realY < 0 || realX >= (int)image.getWidth() || realY >= (int)image.getHeight()) + break; + + if (state == 1) { // In white pixels, looking for black + if (image.get(realX, realY)) { + state++; + } + } else { + if (!image.get(realX, realY)) { + state++; + } + } + + if (state == 3) { // Found black, white, black, and stumbled back onto white; done + return Point(realX, realY); + } + error += dy; + if (error > 0) { + y += ystep; + error -= dx; + } + } + + // B-W-B run not found, return the last point visited. + return Point(realX, realY); +} + +} // namespace qrcode +} // namespace zxing diff --git a/symbian/QQrDecoder/zxing/qrcode/detector/QREdgeDetector.h b/symbian/QQrDecoder/zxing/qrcode/detector/QREdgeDetector.h new file mode 100644 index 000000000..f5cdc89e3 --- /dev/null +++ b/symbian/QQrDecoder/zxing/qrcode/detector/QREdgeDetector.h @@ -0,0 +1,48 @@ +/* + * QREdgeDetector.h + * zxing + * + * Created by Ralf Kistner on 7/12/2009. + * Copyright 2008 ZXing authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef QREDGEDETECTOR_H_ +#define QREDGEDETECTOR_H_ + +#include +#include + +namespace zxing { +namespace qrcode { + +class QREdgeDetector : public Detector { +public: + QREdgeDetector(Ref image); + + virtual Ref createTransform(Ref topLeft, Ref topRight, Ref < + ResultPoint > bottomLeft, Ref alignmentPattern, int dimension); + +private: + Point findCorner(const BitMatrix& image, Point topLeft, Point topRight, Point bottomLeft, int dimension); + Line findPatternEdge(const BitMatrix& image, Point pattern, Point opposite, Point direction, bool invert); + + Point endOfReverseBlackWhiteBlackRun(const BitMatrix& image, Point from, Point to); + + Ref get1CornerTransform(Point topLeft, Point topRight, Point bottomLeft, Point corner, int dimension); +}; + +} +} +#endif // QREDGEDETECTOR_H_ diff --git a/symbian/QQrDecoder_tutorial.txt b/symbian/QQrDecoder_tutorial.txt new file mode 100644 index 000000000..d7f6cfb4c --- /dev/null +++ b/symbian/QQrDecoder_tutorial.txt @@ -0,0 +1,58 @@ +This project is the same as ZXingBarcodeReader. The difference is that the GUI is +developed using Qt framework. This means that it can easily be ported to other platforms +supported by Qt by simply changing the camera operations implemented in "QCameraControllerWidget" +which is Symbian specific code. + +Also the advantage of this implementation over "ZXingBarcodeReader" is that the code written is +more readable and familiar to users that have never used Qt framework or Symbian C++ before. + +== Prerequisities == + +* Have at least one S60 SDK. One of the SDKs can be obtained from here: + http://www.forum.nokia.com/info/sw.nokia.com/id/ec866fab-4b76-49f6-b5a5-af0631419e9c/S60_All_in_One_SDKs.html + +* After installing S60 SDK you have to install OpenC++. + http://www.forum.nokia.com/info/sw.nokia.com/id/91d89929-fb8c-4d66-bea0-227e42df9053/Open_C_SDK_Plug-In.html + +* Next step, have "Qt for Symbian" installed. It under LGLP licence. + http://qt.nokia.com/downloads/symbian-cpp + +* (Optional) You can use Carbide C++ as IDE which makes the life a bit easier on creating applications for Symbian. + An alternative approach is to compile the program in command line but i am afraid i can help you here because i + have no idea :P +or + You can use Qt Creator (see its tutorials on how to use it) + http://qt.nokia.com/products/developer-tools/developer-tools + +== Create project == +If you have Carbide C++ IDE then go "File->Import->Qt->Qt Project", +click "Browse" and find and select file "QQrDecoder\QQrDecoder.pro". +Next step you select the S60 SDK to be compiled to and you are ready. + +== Build project == +Since the project is created, we can proceed to build it. + +First in "QQrDecoder\camerawrapper" folder there is a folder named "epoc32". +Copy this folder and paste it to the root folder of the S60 SDK that you are going to use +(in my case: C:\S60\devices\S60_5th_Edition_SDK_v1.0). This step is important in order +to use a Plug-In API for the easier manipulation of the camera. + +Now we are ready to compile. Since the camera is not supported in the Symbian emulator we +will build the project directly to be installed on a devidce. +Select "QQrDecoder" project in the "Project Explorer" view in Carbide, right click on it +and select "Properties". Expand "Carbide.c++" field and select "Build Configurations". +Being in the "SIS Builder" tab, select as Active Configuration the "Phone Degug (GCCE)". +Then press "Add" button, and to select a PKG file click "Browse" button. Go to "QQrDecoder" +folder and select "QQrDecoder_template.pkg" file. Make sure that "Self sign sis file" radio +button is selected and press OK. + +Now go "Project->Build Project" and if everything goes right, you will have 2 installation files +in "QQrDecoder" folder. Install the .sisx file to your device and you are ready. + +== Additional information == +For afew more details about the implementation you can see the following page: +http://wiki.forum.nokia.com/index.php/Qr_Decoder_in_Qt + +== The same project in Symbian C++ == + +In case you are interested in using this project with only Symbian C++, take a look at ZXingBarcodeReader folder. \ No newline at end of file diff --git a/symbian/ZXingBarcodeReader_tutorial.txt b/symbian/ZXingBarcodeReader_tutorial.txt new file mode 100644 index 000000000..254f50df3 --- /dev/null +++ b/symbian/ZXingBarcodeReader_tutorial.txt @@ -0,0 +1,46 @@ +The whole ZXingBarcodeReader folder is a Carbide project build and tested on both +S60 5th Edition SDK and S60 3rd Edition FP2. (currently only Qr Codes can be detected) + +== Prerequisities == + +* Have at least one S60 SDK. One of the SDKs can be obtained from here: + http://www.forum.nokia.com/info/sw.nokia.com/id/ec866fab-4b76-49f6-b5a5-af0631419e9c/S60_All_in_One_SDKs.html + +* After installing S60 SDK you have to install OpenC++. + http://www.forum.nokia.com/info/sw.nokia.com/id/91d89929-fb8c-4d66-bea0-227e42df9053/Open_C_SDK_Plug-In.html + +* (Optional) You can use Carbide C++ as IDE which makes the life a bit easier on creating applications for Symbian. + An alternative approach is to compile the program in command line but i am afraid i can help you here because i + have no idea :P + +== Create project == +If you have Carbide C++ IDE then go "File->Import->Symbian OS->Symbian OS Bld.inf file", +click "Browse" and find and select file "ZXingBarcodeReader\group\bld.inf". +Next step you select the S60 SDK to be compiled to and you are ready. + +== Build project == +Since the project is created, we can proceed to build it. + +First in "ZXingBarcodeReader\camerawrapper" folder there is a folder named "epoc32". +Copy this folder and paste it to the root folder of the S60 SDK that you are going to use +(in my case: C:\S60\devices\S60_5th_Edition_SDK_v1.0). This step is important in order +to use a Plug-In API for the easier manipulation of the camera. + +Now we are ready to compile. Since the camera is not supported in the Symbian emulator we +will build the project directly to be installed on a devidce. +Select "ZXingBarcodeReader" project in the "Project Explorer" view in Carbide, right click on it +and select "Properties". Expand "Carbide.c++" field and select "Build Configurations". +Being in the "SIS Builder" tab, select as Active Configuration the "Phone Degug (GCCE)". +Then press "Add" button, and to select a PKG file click "Browse" button. Go to "ZXingBarcodeReader\sis" +folder and select "ZXingBarcodeReader_S60.pkg" file. Make sure that "Self sign sis file" radio +button is selected and press OK. + +Now go "Project->Build Project" and if everything goes right, you will have 2 installation files +in "ZXingBarcodeReader\sis" folder. Install the .sisx file to your device and you are ready. + +== The same project in Qt == + +In case you are interested in using this project with Qt on Symbian, take a look at QQrDecoder folder. + + +