Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions common/reedsolomon/reedsolomon_decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ func NewReedSolomonDecoder(field *GenericGF) *ReedSolomonDecoder {
}

func (this *ReedSolomonDecoder) Decode(received []int, twoS int) ReedSolomonException {
_, e := this.DecodeWithECCount(received, twoS)
return e
}

func (this *ReedSolomonDecoder) DecodeWithECCount(received []int, twoS int) (int, ReedSolomonException) {
poly, e := NewGenericGFPoly(this.field, received)
if e != nil {
return WrapReedSolomonException(e)
return 0, WrapReedSolomonException(e)
}
syndromeCoefficients := make([]int, twoS)
noError := true
Expand All @@ -27,40 +32,40 @@ func (this *ReedSolomonDecoder) Decode(received []int, twoS int) ReedSolomonExce
}
}
if noError {
return nil
return 0, nil
}
syndrome, e := NewGenericGFPoly(this.field, syndromeCoefficients)
if e != nil {
return WrapReedSolomonException(e)
return 0, WrapReedSolomonException(e)
}
monomial, e := this.field.BuildMonomial(twoS, 1)
if e != nil {
return WrapReedSolomonException(e)
return 0, WrapReedSolomonException(e)
}
sigma, omega, e := this.runEuclideanAlgorithm(monomial, syndrome, twoS)
if e != nil {
return WrapReedSolomonException(e)
return 0, WrapReedSolomonException(e)
}
errorLocations, e := this.findErrorLocations(sigma)
if e != nil {
return WrapReedSolomonException(e)
return 0, WrapReedSolomonException(e)
}
errorMagnitudes, e := this.findErrorMagnitudes(omega, errorLocations)
if e != nil {
return WrapReedSolomonException(e)
return 0, WrapReedSolomonException(e)
}
for i := 0; i < len(errorLocations); i++ {
log, e := this.field.Log(errorLocations[i])
if e != nil {
return WrapReedSolomonException(e)
return 0, WrapReedSolomonException(e)
}
position := len(received) - 1 - log
if position < 0 {
return NewReedSolomonException("Bad error location")
return 0, NewReedSolomonException("Bad error location")
}
received[position] = GenericGF_addOrSubtract(received[position], errorMagnitudes[i])
}
return nil
return len(errorLocations), nil
}

func (this *ReedSolomonDecoder) runEuclideanAlgorithm(a, b *GenericGFPoly, R int) (sigma, omega *GenericGFPoly, e error) {
Expand Down
21 changes: 15 additions & 6 deletions qrcode/decoder/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,12 @@ func (this *Decoder) decode(parser *BitMatrixParser, hints map[gozxing.DecodeHin
resultOffset := 0

// Error-correct and copy data blocks together into a stream of bytes
errorsCorrected := 0
for _, dataBlock := range dataBlocks {
codewordBytes := dataBlock.GetCodewords()
numDataCodewords := dataBlock.GetNumDataCodewords()
e := this.correctErrors(codewordBytes, numDataCodewords)
c, e := this.correctErrors(codewordBytes, numDataCodewords)
errorsCorrected += c
if e != nil {
return nil, e
}
Expand All @@ -144,25 +146,32 @@ func (this *Decoder) decode(parser *BitMatrixParser, hints map[gozxing.DecodeHin
}

// Decode the contents of that stream of bytes
return DecodedBitStreamParser_Decode(resultBytes, version, ecLevel, hints)
result, e := DecodedBitStreamParser_Decode(resultBytes, version, ecLevel, hints)
if e != nil {
return result, e
}
result.SetErrorsCorrected(errorsCorrected)
return result, nil
}

func (this *Decoder) correctErrors(codewordBytes []byte, numDataCodewords int) error {
func (this *Decoder) correctErrors(codewordBytes []byte, numDataCodewords int) (int, error) {
numCodewords := len(codewordBytes)
// First read into an array of ints
codewordsInts := make([]int, numCodewords)
for i := 0; i < numCodewords; i++ {
codewordsInts[i] = int(codewordBytes[i] & 0xFF)
}

e := this.rsDecoder.Decode(codewordsInts, numCodewords-numDataCodewords)
errorsCorrected := 0

errorsCorrected, e := this.rsDecoder.DecodeWithECCount(codewordsInts, numCodewords-numDataCodewords)
if e != nil {
return gozxing.WrapChecksumException(e)
return 0, gozxing.WrapChecksumException(e)
}
// Copy back into array of bytes -- only need to worry about the bytes that were data
// We don't care about errors in the error-correction codewords
for i := 0; i < numDataCodewords; i++ {
codewordBytes[i] = byte(codewordsInts[i])
}
return nil
return errorsCorrected, nil
}
1 change: 1 addition & 0 deletions qrcode/qrcode_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ func (this *QRCodeReader) Decode(image *gozxing.BinaryBitmap, hints map[gozxing.
gozxing.ResultMetadataType_STRUCTURED_APPEND_PARITY,
decoderResult.GetStructuredAppendParity())
}
result.PutMetadata(gozxing.ResultMetadataType_ERRORS_CORRECTED, decoderResult.GetErrorsCorrected())
result.PutMetadata(
gozxing.ResultMetadataType_SYMBOLOGY_IDENTIFIER, "]Q"+strconv.Itoa(decoderResult.GetSymbologyModifier()))
return result, nil
Expand Down
7 changes: 7 additions & 0 deletions result_metadata_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ const (
*/
ResultMetadataType_ERROR_CORRECTION_LEVEL

/**
* The number of errors corrected. If applicable, maps to an {@link Integer} of value greater than or equal to zero.
*/
ResultMetadataType_ERRORS_CORRECTED

/**
* For some periodicals, indicates the issue number as an {@link Integer}.
*/
Expand Down Expand Up @@ -91,6 +96,8 @@ func (t ResultMetadataType) String() string {
return "BYTE_SEGMENTS"
case ResultMetadataType_ERROR_CORRECTION_LEVEL:
return "ERROR_CORRECTION_LEVEL"
case ResultMetadataType_ERRORS_CORRECTED:
return "ERRORS_CORRECTED"
case ResultMetadataType_ISSUE_NUMBER:
return "ISSUE_NUMBER"
case ResultMetadataType_SUGGESTED_PRICE:
Expand Down