Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fxbarcode / src / BC_QRCoderDecoder.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "barcode.h"\r
8 #include "include/BC_ReedSolomonDecoder.h"\r
9 #include "include/BC_CommonBitMatrix.h"\r
10 #include "include/BC_CommonDecoderResult.h"\r
11 #include "include/BC_QRBitMatrixParser.h"\r
12 #include "include/BC_QRDataBlock.h"\r
13 #include "include/BC_QRDecodedBitStreamParser.h"\r
14 #include "include/BC_QRCoderVersion.h"\r
15 #include "include/BC_QRCoderFormatInformation.h"\r
16 #include "include/BC_ReedSolomonGF256.h"\r
17 #include "include/BC_QRCoderDecoder.h"\r
18 CBC_QRCoderDecoder::CBC_QRCoderDecoder()\r
19 {\r
20     m_rsDecoder = NULL;\r
21 }\r
22 \r
23 void CBC_QRCoderDecoder::Init()\r
24 {\r
25     m_rsDecoder = FX_NEW CBC_ReedSolomonDecoder(CBC_ReedSolomonGF256::QRCodeFild);\r
26 }\r
27 CBC_QRCoderDecoder::~CBC_QRCoderDecoder()\r
28 {\r
29     if(m_rsDecoder != NULL) {\r
30         delete m_rsDecoder;\r
31     }\r
32     m_rsDecoder = NULL;\r
33 }\r
34 CBC_CommonDecoderResult* CBC_QRCoderDecoder::Decode(FX_BOOL* image, FX_INT32 width, FX_INT32 height, FX_INT32 &e)\r
35 {\r
36     CBC_CommonBitMatrix  bits;\r
37     bits.Init(width);\r
38     for(FX_INT32 i = 0; i < width; i++) {\r
39         for(FX_INT32 j = 0; j < height; j++) {\r
40             if(image[i * width + j]) {\r
41                 bits.Set(j, i);\r
42             }\r
43         }\r
44     }\r
45     CBC_CommonDecoderResult* cdr = Decode(&bits, height, e);\r
46     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
47     return cdr;\r
48 }\r
49 CBC_CommonDecoderResult* CBC_QRCoderDecoder::Decode(CBC_CommonBitMatrix* bits, FX_INT32 byteModeDecode, FX_INT32 &e)\r
50 {\r
51     CBC_QRBitMatrixParser parser;\r
52     parser.Init(bits, e);\r
53     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
54     CBC_QRCoderVersion *version = parser.ReadVersion(e);\r
55     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
56     CBC_QRCoderFormatInformation* temp = parser.ReadFormatInformation(e);\r
57     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
58     CBC_QRCoderErrorCorrectionLevel* ecLevel = temp->GetErrorCorrectionLevel();\r
59     CFX_ByteArray* ba = parser.ReadCodewords(e);\r
60     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
61     CBC_AutoPtr<CFX_ByteArray > codewords(ba);\r
62     CFX_PtrArray *dataBlocks = CBC_QRDataBlock::GetDataBlocks(codewords.get(), version, ecLevel, e);\r
63     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
64     FX_INT32 totalBytes = 0;\r
65     for (FX_INT32 i = 0; i < dataBlocks->GetSize(); i++) {\r
66         totalBytes += ((CBC_QRDataBlock*) ((*dataBlocks)[i]))->GetNumDataCodewords();\r
67     }\r
68     CFX_ByteArray resultBytes;\r
69     FX_INT32 resultOffset = 0;\r
70     for (FX_INT32 j = 0; j < dataBlocks->GetSize(); j++) {\r
71         CBC_QRDataBlock *dataBlock = (CBC_QRDataBlock *)((*dataBlocks)[j]);\r
72         CFX_ByteArray* codewordBytes = dataBlock->GetCodewords();\r
73         FX_INT32 numDataCodewords = dataBlock->GetNumDataCodewords();\r
74         CorrectErrors(codewordBytes, numDataCodewords, e);\r
75         if (e != BCExceptionNO) {\r
76             for(FX_INT32 k = 0; k < dataBlocks->GetSize(); k++) {\r
77                 delete (CBC_QRDataBlock*)(*dataBlocks)[k];\r
78             }\r
79             dataBlocks->RemoveAll();\r
80             delete dataBlocks;\r
81             dataBlocks = NULL;\r
82             return NULL;\r
83         }\r
84         for(FX_INT32 i = 0; i < numDataCodewords; i++) {\r
85             resultBytes.Add((*codewordBytes)[i]);\r
86         }\r
87     }\r
88     for(FX_INT32 k = 0; k < dataBlocks->GetSize(); k++) {\r
89         delete  (CBC_QRDataBlock*)(*dataBlocks)[k] ;\r
90     }\r
91     dataBlocks->RemoveAll();\r
92     delete dataBlocks;\r
93     dataBlocks = NULL;\r
94     CBC_CommonDecoderResult* cdr = CBC_QRDecodedBitStreamParser::Decode(&resultBytes, version, ecLevel, byteModeDecode, e);\r
95     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
96     return cdr;\r
97 }\r
98 void CBC_QRCoderDecoder::CorrectErrors(CFX_ByteArray* codewordBytes, FX_INT32 numDataCodewords, FX_INT32 &e)\r
99 {\r
100     FX_INT32 numCodewords = codewordBytes->GetSize();\r
101     CFX_Int32Array codewordsInts;\r
102     codewordsInts.SetSize(numCodewords);\r
103     for(FX_INT32 i = 0; i < numCodewords; i++) {\r
104         codewordsInts[i] = (FX_INT32)((*codewordBytes)[i] & 0xff);\r
105     }\r
106     FX_INT32 numECCodewords = codewordBytes->GetSize() - numDataCodewords;\r
107     m_rsDecoder->Decode(&codewordsInts, numECCodewords, e);\r
108     BC_EXCEPTION_CHECK_ReturnVoid(e);\r
109     for(FX_INT32 k = 0; k < numDataCodewords; k++) {\r
110         (*codewordBytes)[k] = (FX_BYTE) codewordsInts[k];\r
111     }\r
112 }\r